refactor(core): replace legacy logger with Effect logging (#31310)
This commit is contained in:
@@ -5,7 +5,6 @@ import { SessionID, MessageID, PartID } from "./schema"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { Token } from "@/util/token"
|
||||
import { Log } from "@opencode-ai/core/util/log"
|
||||
import { SessionProcessor } from "./processor"
|
||||
import { Agent } from "@/agent/agent"
|
||||
import { Plugin } from "@/plugin"
|
||||
@@ -26,8 +25,6 @@ import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { EventV2 } from "@opencode-ai/core/event"
|
||||
import { buildPrompt } from "@opencode-ai/core/session/compaction"
|
||||
|
||||
const log = Log.create({ service: "session.compaction" })
|
||||
|
||||
export const Event = {
|
||||
Compacted: EventV2.define({
|
||||
type: "session.compacted",
|
||||
@@ -237,7 +234,9 @@ export const layer = Layer.effect(
|
||||
estimate,
|
||||
})
|
||||
if (split) keep = split
|
||||
else if (!keep) log.info("tail fallback", { budget, size, total })
|
||||
else if (!keep) {
|
||||
yield* Effect.logInfo("tail fallback", { budget, size, total })
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
@@ -253,7 +252,7 @@ export const layer = Layer.effect(
|
||||
const prune = Effect.fn("SessionCompaction.prune")(function* (input: { sessionID: SessionID }) {
|
||||
const cfg = yield* config.get()
|
||||
if (!cfg.compaction?.prune) return
|
||||
log.info("pruning")
|
||||
yield* Effect.logInfo("pruning")
|
||||
|
||||
const msgs = yield* session
|
||||
.messages({ sessionID: input.sessionID })
|
||||
@@ -284,7 +283,7 @@ export const layer = Layer.effect(
|
||||
}
|
||||
}
|
||||
|
||||
log.info("found", { pruned, total })
|
||||
yield* Effect.logInfo("found", { pruned, total })
|
||||
if (pruned > PRUNE_MINIMUM) {
|
||||
for (const part of toPrune) {
|
||||
if (part.state.status === "completed") {
|
||||
@@ -292,7 +291,7 @@ export const layer = Layer.effect(
|
||||
yield* session.updatePart(part)
|
||||
}
|
||||
}
|
||||
log.info("pruned", { count: toPrune.length })
|
||||
yield* Effect.logInfo("pruned", { count: toPrune.length })
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import { PermissionV1 } from "@opencode-ai/core/v1/permission"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { SessionV1 } from "@opencode-ai/core/v1/session"
|
||||
import { serviceUse } from "@opencode-ai/core/effect/service-use"
|
||||
import { Log } from "@opencode-ai/core/util/log"
|
||||
import { Context, Effect, Layer } from "effect"
|
||||
import * as Stream from "effect/Stream"
|
||||
import { streamText, wrapLanguageModel, type ModelMessage, type Tool } from "ai"
|
||||
@@ -29,7 +28,6 @@ import { LLMAISDK } from "./llm/ai-sdk"
|
||||
import { LLMNativeRuntime } from "./llm/native-runtime"
|
||||
import { LLMRequestPrep } from "./llm/request"
|
||||
|
||||
const log = Log.create({ service: "llm" })
|
||||
export const OUTPUT_TOKEN_MAX = ProviderTransform.OUTPUT_TOKEN_MAX
|
||||
|
||||
export type StreamInput = {
|
||||
@@ -83,17 +81,13 @@ const live: Layer.Layer<
|
||||
const flags = yield* RuntimeFlags.Service
|
||||
|
||||
const run = Effect.fn("LLM.run")(function* (input: StreamRequest) {
|
||||
const l = log
|
||||
.clone()
|
||||
.tag("providerID", input.model.providerID)
|
||||
.tag("modelID", input.model.id)
|
||||
.tag("session.id", input.sessionID)
|
||||
.tag("small", (input.small ?? false).toString())
|
||||
.tag("agent", input.agent.name)
|
||||
.tag("mode", input.agent.mode)
|
||||
l.info("stream", {
|
||||
modelID: input.model.id,
|
||||
yield* Effect.logInfo("stream", {
|
||||
providerID: input.model.providerID,
|
||||
modelID: input.model.id,
|
||||
"session.id": input.sessionID,
|
||||
small: (input.small ?? false).toString(),
|
||||
agent: input.agent.name,
|
||||
mode: input.agent.mode,
|
||||
})
|
||||
|
||||
const [language, cfg, item, info] = yield* Effect.all(
|
||||
@@ -245,36 +239,38 @@ const live: Layer.Layer<
|
||||
abort: input.abort,
|
||||
})
|
||||
if (native.type === "supported") {
|
||||
yield* Effect.logInfo("llm runtime selected").pipe(
|
||||
Effect.annotateLogs({
|
||||
"llm.runtime": "native",
|
||||
"llm.provider": input.model.providerID,
|
||||
"llm.model": input.model.id,
|
||||
}),
|
||||
)
|
||||
yield* Effect.logInfo("llm runtime selected", {
|
||||
"llm.runtime": "native",
|
||||
"llm.provider": input.model.providerID,
|
||||
"llm.model": input.model.id,
|
||||
})
|
||||
return {
|
||||
type: "native" as const,
|
||||
stream: native.stream,
|
||||
}
|
||||
}
|
||||
yield* Effect.logInfo("llm runtime selected").pipe(
|
||||
Effect.annotateLogs({
|
||||
"llm.runtime": "ai-sdk",
|
||||
"llm.provider": input.model.providerID,
|
||||
"llm.model": input.model.id,
|
||||
"llm.native_unsupported_reason": native.reason,
|
||||
}),
|
||||
)
|
||||
l.info("native runtime unavailable; falling back to ai-sdk", { reason: native.reason })
|
||||
}
|
||||
|
||||
yield* Effect.logInfo("llm runtime selected").pipe(
|
||||
Effect.annotateLogs({
|
||||
yield* Effect.logInfo("llm runtime selected", {
|
||||
"llm.runtime": "ai-sdk",
|
||||
"llm.provider": input.model.providerID,
|
||||
"llm.model": input.model.id,
|
||||
}),
|
||||
)
|
||||
"llm.native_unsupported_reason": native.reason,
|
||||
})
|
||||
yield* Effect.logInfo("native runtime unavailable; falling back to ai-sdk", {
|
||||
providerID: input.model.providerID,
|
||||
modelID: input.model.id,
|
||||
"session.id": input.sessionID,
|
||||
small: (input.small ?? false).toString(),
|
||||
agent: input.agent.name,
|
||||
mode: input.agent.mode,
|
||||
reason: native.reason,
|
||||
})
|
||||
}
|
||||
|
||||
yield* Effect.logInfo("llm runtime selected", {
|
||||
"llm.runtime": "ai-sdk",
|
||||
"llm.provider": input.model.providerID,
|
||||
"llm.model": input.model.id,
|
||||
})
|
||||
// Default runtime path: AI SDK owns provider execution and tool dispatch;
|
||||
// LLMAISDK.toLLMEvents below normalizes fullStream parts for the processor.
|
||||
return {
|
||||
@@ -282,18 +278,9 @@ const live: Layer.Layer<
|
||||
result: streamText({
|
||||
// Copilot returns the authoritative billed amount only in provider-specific response fields.
|
||||
includeRawChunks: input.model.providerID.includes("github-copilot"),
|
||||
onError(error) {
|
||||
l.error("stream error", {
|
||||
error,
|
||||
})
|
||||
},
|
||||
async experimental_repairToolCall(failed) {
|
||||
const lower = failed.toolCall.toolName.toLowerCase()
|
||||
if (lower !== failed.toolCall.toolName && prepared.tools[lower]) {
|
||||
l.info("repairing tool call", {
|
||||
tool: failed.toolCall.toolName,
|
||||
repaired: lower,
|
||||
})
|
||||
return {
|
||||
...failed.toolCall,
|
||||
toolName: lower,
|
||||
|
||||
@@ -37,7 +37,6 @@ import { isMedia } from "@/util/media"
|
||||
import type { SystemError } from "bun"
|
||||
import type { Provider } from "@/provider/provider"
|
||||
import { Effect, Schema } from "effect"
|
||||
import * as EffectLogger from "@opencode-ai/core/effect/logger"
|
||||
|
||||
/** Error shape thrown by Bun's fetch() when gzip/br decompression fails mid-stream */
|
||||
interface FetchDecompressionError extends Error {
|
||||
@@ -431,7 +430,7 @@ export function toModelMessages(
|
||||
model: Provider.Model,
|
||||
options?: { stripMedia?: boolean; toolOutputMaxChars?: number },
|
||||
): Promise<ModelMessage[]> {
|
||||
return Effect.runPromise(toModelMessagesEffect(input, model, options).pipe(Effect.provide(EffectLogger.layer)))
|
||||
return Effect.runPromise(toModelMessagesEffect(input, model, options))
|
||||
}
|
||||
|
||||
export const page = Effect.fn("MessageV2.page")(function* (input: {
|
||||
|
||||
@@ -20,7 +20,6 @@ import { SessionSummary } from "./summary"
|
||||
import type { Provider } from "@/provider/provider"
|
||||
import { Question } from "@/question"
|
||||
import { errorMessage } from "@/util/error"
|
||||
import { Log } from "@opencode-ai/core/util/log"
|
||||
import { isRecord } from "@/util/record"
|
||||
import { EventV2Bridge } from "@/event-v2-bridge"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
@@ -34,8 +33,6 @@ import { toolFileSourceFromUri, Usage, type LLMEvent } from "@opencode-ai/llm"
|
||||
import { ToolOutput } from "@opencode-ai/core/tool-output"
|
||||
|
||||
const DOOM_LOOP_THRESHOLD = 3
|
||||
const log = Log.create({ service: "session.processor" })
|
||||
|
||||
export type Result = "compact" | "stop" | "continue"
|
||||
|
||||
export interface Handle {
|
||||
@@ -131,7 +128,6 @@ export const layer = Layer.effect(
|
||||
}
|
||||
const mirrorAssistant = flags.experimentalEventSystem && !input.assistantMessage.summary
|
||||
let aborted = false
|
||||
const slog = log.clone().tag("session.id", input.sessionID).tag("messageID", input.assistantMessage.id)
|
||||
|
||||
const parse = (e: unknown) =>
|
||||
MessageV2.fromError(e, {
|
||||
@@ -918,7 +914,12 @@ export const layer = Layer.effect(
|
||||
})
|
||||
|
||||
const halt = Effect.fn("SessionProcessor.halt")(function* (e: unknown) {
|
||||
slog.error("process", { error: errorMessage(e), stack: e instanceof Error ? e.stack : undefined })
|
||||
yield* Effect.logError("process", {
|
||||
"session.id": input.sessionID,
|
||||
messageID: input.assistantMessage.id,
|
||||
error: errorMessage(e),
|
||||
stack: e instanceof Error ? e.stack : undefined,
|
||||
})
|
||||
const error = parse(e)
|
||||
yield* flushV2Fragments()
|
||||
if (SessionV1.ContextOverflowError.isInstance(error)) {
|
||||
@@ -956,7 +957,10 @@ export const layer = Layer.effect(
|
||||
})
|
||||
|
||||
const process = Effect.fn("SessionProcessor.process")(function* (streamInput: LLM.StreamInput) {
|
||||
slog.info("process")
|
||||
yield* Effect.logInfo("process", {
|
||||
"session.id": input.sessionID,
|
||||
messageID: input.assistantMessage.id,
|
||||
})
|
||||
ctx.needsCompaction = false
|
||||
ctx.shouldBreak = (yield* config.get()).experimental?.continue_loop_on_deny !== true
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import { SessionV1 } from "@opencode-ai/core/v1/session"
|
||||
import os from "os"
|
||||
import { SessionID, MessageID, PartID } from "./schema"
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { Log } from "@opencode-ai/core/util/log"
|
||||
import { SessionRevert } from "./revert"
|
||||
import { Session } from "./session"
|
||||
import { Agent } from "../agent/agent"
|
||||
@@ -43,7 +42,6 @@ import { Image } from "@/image/image"
|
||||
import { decodeDataUrl } from "@/util/data-url"
|
||||
import { Process } from "@/util/process"
|
||||
import { Cause, Effect, Exit, Latch, Layer, Option, Scope, Context, Schema, Types } from "effect"
|
||||
import * as EffectLogger from "@opencode-ai/core/effect/logger"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
import { TaskTool, type TaskPromptOps } from "@/tool/task"
|
||||
import { SessionRunState } from "./run-state"
|
||||
@@ -80,9 +78,6 @@ IMPORTANT:
|
||||
|
||||
const STRUCTURED_OUTPUT_SYSTEM_PROMPT = `IMPORTANT: The user has requested structured output. You MUST use the StructuredOutput tool to provide your final response. Do NOT respond with plain text - you MUST call the StructuredOutput tool with your answer formatted according to the schema.`
|
||||
|
||||
const log = Log.create({ service: "session.prompt" })
|
||||
const elog = EffectLogger.create({ service: "session.prompt" })
|
||||
|
||||
function isOrphanedInterruptedTool(part: SessionV1.ToolPart) {
|
||||
// cleanup() marks abandoned tool_use blocks this way after retries/aborts.
|
||||
// They are not pending work and must not trigger an assistant-prefill request.
|
||||
@@ -141,7 +136,7 @@ export const layer = Layer.effect(
|
||||
})
|
||||
|
||||
const cancel = Effect.fn("SessionPrompt.cancel")(function* (sessionID: SessionID) {
|
||||
yield* elog.info("cancel", { sessionID })
|
||||
yield* Effect.logInfo("cancel", { "session.id": sessionID })
|
||||
yield* state.cancel(sessionID)
|
||||
})
|
||||
|
||||
@@ -282,7 +277,7 @@ export const layer = Layer.effect(
|
||||
const t = cleaned.length > 100 ? cleaned.substring(0, 97) + "..." : cleaned
|
||||
yield* sessions
|
||||
.setTitle({ sessionID: input.session.id, title: t })
|
||||
.pipe(Effect.catchCause((cause) => elog.error("failed to generate title", { error: Cause.squash(cause) })))
|
||||
.pipe(Effect.catchCause((cause) => Effect.logError("failed to generate title", { error: Cause.squash(cause) })))
|
||||
})
|
||||
|
||||
const handleSubtask = Effect.fn("SessionPrompt.handleSubtask")(function* (input: {
|
||||
@@ -384,8 +379,11 @@ export const layer = Layer.effect(
|
||||
Effect.catchCause((cause) => {
|
||||
const defect = Cause.squash(cause)
|
||||
error = defect instanceof Error ? defect : new Error(String(defect))
|
||||
log.error("subtask execution failed", { error, agent: task.agent, description: task.description })
|
||||
return Effect.void
|
||||
return Effect.logError("subtask execution failed", {
|
||||
error,
|
||||
agent: task.agent,
|
||||
description: task.description,
|
||||
})
|
||||
}),
|
||||
Effect.onInterrupt(() =>
|
||||
Effect.gen(function* () {
|
||||
@@ -761,7 +759,7 @@ export const layer = Layer.effect(
|
||||
if (part.type === "file") {
|
||||
if (part.source?.type === "resource") {
|
||||
const { clientName, uri } = part.source
|
||||
log.info("mcp resource", { clientName, uri, mime: part.mime })
|
||||
yield* Effect.logInfo("mcp resource", { clientName, uri, mime: part.mime })
|
||||
const pieces: Draft<SessionV1.Part>[] = [
|
||||
{
|
||||
messageID: info.id,
|
||||
@@ -799,7 +797,7 @@ export const layer = Layer.effect(
|
||||
pieces.push({ ...part, messageID: info.id, sessionID: input.sessionID })
|
||||
} else {
|
||||
const error = Cause.squash(exit.cause)
|
||||
log.error("failed to read MCP resource", { error, clientName, uri })
|
||||
yield* Effect.logError("failed to read MCP resource", { error, clientName, uri })
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
pieces.push({
|
||||
messageID: info.id,
|
||||
@@ -835,7 +833,7 @@ export const layer = Layer.effect(
|
||||
}
|
||||
break
|
||||
case "file:": {
|
||||
log.info("file", { mime: part.mime })
|
||||
yield* Effect.logInfo("file", { mime: part.mime })
|
||||
const filepath = fileURLToPath(part.url)
|
||||
const mime = (yield* fsys.isDir(filepath)) ? "application/x-directory" : part.mime
|
||||
|
||||
@@ -918,7 +916,7 @@ export const layer = Layer.effect(
|
||||
}
|
||||
} else {
|
||||
const error = Cause.squash(exit.cause)
|
||||
log.error("failed to read file", { error })
|
||||
yield* Effect.logError("failed to read file", { error, filepath })
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
yield* events.publish(Session.Event.Error, {
|
||||
sessionID: input.sessionID,
|
||||
@@ -940,7 +938,7 @@ export const layer = Layer.effect(
|
||||
const exit = yield* execRead(args).pipe(Effect.exit)
|
||||
if (Exit.isFailure(exit)) {
|
||||
const error = Cause.squash(exit.cause)
|
||||
log.error("failed to read directory", { error })
|
||||
yield* Effect.logError("failed to read directory", { error, filepath })
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
yield* events.publish(Session.Event.Error, {
|
||||
sessionID: input.sessionID,
|
||||
@@ -1065,7 +1063,7 @@ export const layer = Layer.effect(
|
||||
|
||||
const parsed = decodeMessageInfo(info, { errors: "all", propertyOrder: "original" })
|
||||
if (Exit.isFailure(parsed)) {
|
||||
log.error("invalid user message before save", {
|
||||
yield* Effect.logError("invalid user message before save", {
|
||||
sessionID: input.sessionID,
|
||||
messageID: info.id,
|
||||
agent: info.agent,
|
||||
@@ -1073,10 +1071,10 @@ export const layer = Layer.effect(
|
||||
cause: Cause.pretty(parsed.cause),
|
||||
})
|
||||
}
|
||||
parts.forEach((part, index) => {
|
||||
for (const [index, part] of parts.entries()) {
|
||||
const p = decodeMessagePart(part, { errors: "all", propertyOrder: "original" })
|
||||
if (Exit.isSuccess(p)) return
|
||||
log.error("invalid user part before save", {
|
||||
if (Exit.isSuccess(p)) continue
|
||||
yield* Effect.logError("invalid user part before save", {
|
||||
sessionID: input.sessionID,
|
||||
messageID: info.id,
|
||||
partID: part.id,
|
||||
@@ -1085,7 +1083,7 @@ export const layer = Layer.effect(
|
||||
cause: Cause.pretty(p.cause),
|
||||
part,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
yield* sessions.updateMessage(info)
|
||||
for (const part of parts) yield* sessions.updatePart(part)
|
||||
@@ -1217,14 +1215,13 @@ export const layer = Layer.effect(
|
||||
const runLoop: (sessionID: SessionID) => Effect.Effect<SessionV1.WithParts> = Effect.fn("SessionPrompt.run")(
|
||||
function* (sessionID: SessionID) {
|
||||
const ctx = yield* InstanceState.context
|
||||
const slog = elog.with({ sessionID })
|
||||
let structured: unknown
|
||||
let step = 0
|
||||
const session = yield* sessions.get(sessionID).pipe(Effect.orDie)
|
||||
|
||||
while (true) {
|
||||
yield* status.set(sessionID, { type: "busy" })
|
||||
yield* slog.info("loop", { step })
|
||||
yield* Effect.logInfo("loop", { "session.id": sessionID, step })
|
||||
|
||||
let msgs = yield* MessageV2.filterCompactedEffect(sessionID).pipe(
|
||||
Effect.provideService(Database.Service, database),
|
||||
@@ -1255,13 +1252,14 @@ export const layer = Layer.effect(
|
||||
(part): part is SessionV1.ToolPart => part.type === "tool" && isOrphanedInterruptedTool(part),
|
||||
)
|
||||
if (orphan) {
|
||||
yield* slog.warn("loop exit with orphaned interrupted tool", {
|
||||
yield* Effect.logWarning("loop exit with orphaned interrupted tool", {
|
||||
"session.id": sessionID,
|
||||
messageID: lastAssistant.id,
|
||||
tool: orphan.tool,
|
||||
callID: orphan.callID,
|
||||
})
|
||||
}
|
||||
yield* slog.info("exiting loop")
|
||||
yield* Effect.logInfo("exiting loop", { "session.id": sessionID })
|
||||
break
|
||||
}
|
||||
|
||||
@@ -1486,7 +1484,11 @@ export const layer = Layer.effect(
|
||||
})
|
||||
|
||||
const command = Effect.fn("SessionPrompt.command")(function* (input: CommandInput) {
|
||||
yield* elog.info("command", { sessionID: input.sessionID, command: input.command, agent: input.agent })
|
||||
yield* Effect.logInfo("command", {
|
||||
"session.id": input.sessionID,
|
||||
command: input.command,
|
||||
agent: input.agent,
|
||||
})
|
||||
const cmd = yield* commands.get(input.command)
|
||||
if (!cmd) {
|
||||
const available = (yield* commands.list()).map((c) => c.name)
|
||||
|
||||
@@ -3,15 +3,12 @@ import { SessionV1 } from "@opencode-ai/core/v1/session"
|
||||
import { EventV2Bridge } from "@/event-v2-bridge"
|
||||
import { Snapshot } from "../snapshot"
|
||||
import { Storage } from "@/storage/storage"
|
||||
import { Log } from "@opencode-ai/core/util/log"
|
||||
import { Session } from "./session"
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { SessionID, MessageID, PartID } from "./schema"
|
||||
import { SessionRunState } from "./run-state"
|
||||
import { SessionSummary } from "./summary"
|
||||
|
||||
const log = Log.create({ service: "session.revert" })
|
||||
|
||||
export const RevertInput = Schema.Struct({
|
||||
sessionID: SessionID,
|
||||
messageID: MessageID,
|
||||
@@ -90,7 +87,7 @@ export const layer = Layer.effect(
|
||||
})
|
||||
|
||||
const unrevert = Effect.fn("SessionRevert.unrevert")(function* (input: { sessionID: SessionID }) {
|
||||
log.info("unreverting", input)
|
||||
yield* Effect.logInfo("unreverting", { sessionID: input.sessionID })
|
||||
yield* state.assertNotBusy(input.sessionID)
|
||||
const session = yield* sessions.get(input.sessionID).pipe(Effect.orDie)
|
||||
if (!session.revert) return session
|
||||
|
||||
@@ -28,7 +28,6 @@ import { or } from "drizzle-orm"
|
||||
import type { SQL } from "drizzle-orm"
|
||||
import { PartTable, SessionTable } from "@opencode-ai/core/session/sql"
|
||||
import { ProjectTable } from "@opencode-ai/core/project/sql"
|
||||
import { Log } from "@opencode-ai/core/util/log"
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import type { InstanceContext } from "../project/instance-context"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
@@ -46,7 +45,6 @@ import { RuntimeFlags } from "@/effect/runtime-flags"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
|
||||
const log = Log.create({ service: "session" })
|
||||
const runtime = makeRuntime(Database.Service, Database.defaultLayer)
|
||||
|
||||
const parentTitlePrefix = "New session - "
|
||||
@@ -573,7 +571,7 @@ export const layer: Layer.Layer<
|
||||
updated: Date.now(),
|
||||
},
|
||||
}
|
||||
log.info("created", result)
|
||||
yield* Effect.logInfo("created", result)
|
||||
|
||||
yield* events.publish(SessionV1.Event.Created, { sessionID: result.id, info: result })
|
||||
|
||||
@@ -664,8 +662,8 @@ export const layer: Layer.Layer<
|
||||
|
||||
yield* events.publish(SessionV1.Event.Deleted, { sessionID, info: session })
|
||||
yield* events.remove(sessionID)
|
||||
} catch (e) {
|
||||
log.error(e)
|
||||
} catch (error) {
|
||||
yield* Effect.logError("failed to remove session", { sessionID, error })
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -17,13 +17,10 @@ import { MessageV2 } from "./message-v2"
|
||||
import { Session } from "./session"
|
||||
import { SessionProcessor } from "./processor"
|
||||
import { PartID } from "./schema"
|
||||
import { Log } from "@opencode-ai/core/util/log"
|
||||
import { EffectBridge } from "@/effect/bridge"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
|
||||
const log = Log.create({ service: "session.tools" })
|
||||
|
||||
export const resolve = Effect.fn("SessionTools.resolve")(function* (input: {
|
||||
agent: Agent.Info
|
||||
model: Provider.Model
|
||||
@@ -33,7 +30,6 @@ export const resolve = Effect.fn("SessionTools.resolve")(function* (input: {
|
||||
messages: SessionV1.WithParts[]
|
||||
promptOps: TaskPromptOps
|
||||
}) {
|
||||
using _ = log.time("resolveTools")
|
||||
const tools: Record<string, AITool> = {}
|
||||
const run = yield* EffectBridge.make()
|
||||
const plugin = yield* Plugin.Service
|
||||
|
||||
Reference in New Issue
Block a user