mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-21 23:43:29 +00:00
105 lines
4.4 KiB
TypeScript
105 lines
4.4 KiB
TypeScript
export * as SessionGenerateNode from "./generate-node.js"
|
|
|
|
import { LLM, LLMClient, Message, SystemPart } from "@opencode-ai/ai"
|
|
import { Effect, Layer } from "effect"
|
|
import { Database } from "../database/database.js"
|
|
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
|
|
import { App } from "../app.js"
|
|
import { llmClient } from "../effect/app-node-platform.js"
|
|
import { PluginHooks } from "../plugin/hooks.js"
|
|
import { SessionContext } from "./context.js"
|
|
import { SessionGenerate } from "./generate.js"
|
|
import { SessionHistory } from "./history.js"
|
|
import { SessionModelHeaders } from "./model-headers.js"
|
|
import { SessionModelHook } from "./model-hook.js"
|
|
import { SessionModelHttp } from "./model-http.js"
|
|
import { SessionPromptCacheKey } from "./prompt-cache-key.js"
|
|
import { SessionRunnerModel } from "./runner/model.js"
|
|
import { SessionSystemPrompt } from "./system-prompt.js"
|
|
import { toLLMMessages } from "./runner/to-llm-message.js"
|
|
|
|
export const layer = Layer.effect(
|
|
SessionGenerate.Service,
|
|
Effect.gen(function* () {
|
|
const context = yield* SessionContext.Service
|
|
const database = yield* Database.Service
|
|
const hooks = yield* PluginHooks.Service
|
|
const llm = yield* LLMClient.Service
|
|
const models = yield* SessionRunnerModel.Service
|
|
const app = yield* App.Metadata
|
|
|
|
return SessionGenerate.Service.of({
|
|
generate: Effect.fn("SessionGenerate.generate")(function* (input) {
|
|
const selection = yield* context.select(input.sessionID)
|
|
const model = yield* models.resolve(selection.session)
|
|
const history = yield* SessionHistory.preview(database.db, selection.session.id, selection.instructions)
|
|
const providerMetadataKey = model.model.route.providerMetadataKey ?? model.model.provider
|
|
const tools = selection.tools
|
|
const toolDefinitions = tools.definitions
|
|
const toolsByName = new Map(toolDefinitions.map((tool) => [tool.name, tool]))
|
|
const contextEvent = yield* hooks.trigger("session", "context", {
|
|
sessionID: selection.session.id,
|
|
agent: selection.agent.id,
|
|
model: model.ref,
|
|
system: [
|
|
selection.agent.info.system
|
|
? selection.agent.info.system
|
|
: SessionSystemPrompt.make(toolDefinitions.map((tool) => tool.name)),
|
|
history.initial,
|
|
]
|
|
.filter((part) => part.length > 0)
|
|
.map(SystemPart.make),
|
|
messages: [
|
|
...toLLMMessages(history.messages, model.ref, providerMetadataKey),
|
|
...(history.instructionUpdate ? [Message.system(history.instructionUpdate)] : []),
|
|
Message.user(input.prompt),
|
|
],
|
|
tools: Object.fromEntries(
|
|
toolDefinitions.map((tool) => [
|
|
tool.name,
|
|
{ description: tool.description, input: { ...tool.inputSchema } },
|
|
]),
|
|
),
|
|
})
|
|
const hookedTools = Object.entries(contextEvent.tools).flatMap(([name, tool]) => {
|
|
const registered = toolsByName.get(name)
|
|
return registered
|
|
? [Object.assign({}, registered, { description: tool.description, inputSchema: tool.input })]
|
|
: []
|
|
})
|
|
yield* Effect.logInfo("sending session generation request", {
|
|
sessionID: selection.session.id,
|
|
providerID: model.ref.providerID,
|
|
modelID: model.ref.id,
|
|
})
|
|
const request = yield* SessionModelHook.apply(
|
|
hooks,
|
|
{ sessionID: selection.session.id, agent: selection.agent.id, model: model.ref },
|
|
LLM.request({
|
|
model: model.model,
|
|
http: { headers: SessionModelHeaders.make(selection.session, app) },
|
|
promptCacheKey: SessionPromptCacheKey.make(selection.session.id),
|
|
system: contextEvent.system,
|
|
messages: contextEvent.messages,
|
|
tools: hookedTools,
|
|
}),
|
|
)
|
|
const response = yield* llm.generate(request, {
|
|
http: SessionModelHttp.middleware(hooks, {
|
|
sessionID: selection.session.id,
|
|
agent: selection.agent.id,
|
|
model: model.ref,
|
|
}),
|
|
})
|
|
yield* Effect.logInfo("session generation usage diagnostic", { usage: response.usage })
|
|
return response.text
|
|
}),
|
|
})
|
|
}),
|
|
)
|
|
|
|
export const node = makeLocationNode({
|
|
service: SessionGenerate.Service,
|
|
layer,
|
|
deps: [SessionContext.node, Database.node, PluginHooks.node, SessionRunnerModel.node, App.node, llmClient],
|
|
})
|