Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions packages/opencode/src/control-plane/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,13 @@ export const layer = Layer.effect(

if (target.type === "remote") {
yield* syncHistory(previous, target.url, target.headers).pipe(
Effect.catch((error) => Effect.sync(() => {})),
Effect.catch((error) =>
Effect.logWarning("session warp final source sync failed", {
workspaceID: previous.id,
sessionID: input.sessionID,
error: errorData(error),
}),
),
)
} else {
yield* prompt.cancel(input.sessionID)
Expand Down Expand Up @@ -739,9 +745,7 @@ export const layer = Layer.effect(
([type, adapter]) =>
WorkspaceAdapterRuntime.list(adapter).pipe(
Effect.catchCause((error) =>
Effect.sync(() => {
return []
}),
Effect.logWarning("workspace adapter list failed", { type, error }).pipe(Effect.as([])),
),
),
{ concurrency: "unbounded" },
Expand Down Expand Up @@ -817,7 +821,7 @@ export const layer = Layer.effect(
Effect.gen(function* () {
yield* WorkspaceAdapterRuntime.remove(info)
}),
() => Effect.sync(() => {}),
() => Effect.logError("adapter not available when removing workspace", { type: row.type }),
)

yield* db.delete(WorkspaceTable).where(eq(WorkspaceTable.id, id)).run().pipe(Effect.orDie)
Expand Down
20 changes: 19 additions & 1 deletion packages/opencode/src/mcp/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ function fetchFromClient<T extends { name: string }>(
return e
},
}).pipe(
Effect.tapError((error) =>
Effect.logWarning(`failed to get ${label}`, {
clientName,
error: error instanceof Error ? error.message : String(error),
}),
),
Effect.map((items) => {
const out: Record<string, T & { client: string }> = {}
const sanitizedClient = sanitize(clientName)
Expand Down Expand Up @@ -529,6 +535,7 @@ export const layer = Layer.effect(
([key, mcp]) =>
Effect.gen(function* () {
if (!isMcpConfigured(mcp)) {
yield* Effect.logError("Ignoring MCP config entry without type", { key })
return
}

Expand Down Expand Up @@ -679,6 +686,7 @@ export const layer = Layer.effect(

const listed = s.defs[clientName]
if (!listed) {
yield* Effect.logWarning("missing cached tools for connected server", { clientName })
return
}

Expand Down Expand Up @@ -744,14 +752,24 @@ export const layer = Layer.effect(
const s = yield* InstanceState.get(state)
const client = s.clients[clientName]
if (!client) {
yield* Effect.logWarning(`client not found for ${label}`, { clientName })
return undefined
}
return yield* Effect.tryPromise({
try: () => fn(client),
catch: (e: any) => {
return e
},
}).pipe(Effect.orElseSucceed(() => undefined))
}).pipe(
Effect.tapError((error) =>
Effect.logError(`failed to ${label}`, {
clientName,
...meta,
error: error instanceof Error ? error.message : String(error),
}),
),
Effect.orElseSucceed(() => undefined),
)
})

const getPrompt = Effect.fn("MCP.getPrompt")(function* (
Expand Down
17 changes: 13 additions & 4 deletions packages/opencode/src/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,13 @@ export const layer = Layer.effect(
for (const plugin of flags.disableDefaultPlugins ? [] : internalPlugins(flags)) {
const init = yield* Effect.tryPromise({
try: () => plugin(input),
catch: (err) => {},
}).pipe(Effect.option)
catch: errorMessage,
}).pipe(
Effect.tapError((error) =>
Effect.logError("failed to load internal plugin", { name: plugin.name, error }),
),
Effect.option,
)
if (init._tag === "Some") hooks.push(init.value)
}

Expand Down Expand Up @@ -217,6 +222,7 @@ export const layer = Layer.effect(
return message
},
}).pipe(
Effect.tapError((error) => Effect.logError("failed to load plugin", { path: load.spec, error })),
Effect.catch(() => {
// TODO: make proper events for this
// events.publish(Session.Event.Error, {
Expand Down Expand Up @@ -256,8 +262,11 @@ export const layer = Layer.effect(
(hook) =>
Effect.tryPromise({
try: () => Promise.resolve(hook.dispose?.()),
catch: (error) => {},
}).pipe(Effect.ignore),
catch: errorMessage,
}).pipe(
Effect.tapError((error) => Effect.logError("plugin dispose hook failed", { error })),
Effect.ignore,
),
{ discard: true },
),
)
Expand Down
15 changes: 14 additions & 1 deletion packages/opencode/src/session/llm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ const live: Layer.Layer<
// Wire up toolExecutor for DWS workflow models so that tool calls
// from the workflow service are executed via opencode's tool system
// and results sent back over the WebSocket.
const bridge = yield* EffectBridge.make()
if (language instanceof GitLabWorkflowLanguageModel) {
const workflowModel = language as GitLabWorkflowLanguageModel & {
sessionID?: string
Expand Down Expand Up @@ -149,7 +150,6 @@ const live: Layer.Layer<
return !match || match.action !== "ask"
})

const bridge = yield* EffectBridge.make()
const approvedToolsForSession = new Set<string>()
workflowModel.approvalHandler = bridge.bind(async (approvalTools) => {
const uniqueNames = [...new Set(approvalTools.map((t: { name: string }) => t.name))] as string[]
Expand Down Expand Up @@ -276,6 +276,19 @@ const live: Layer.Layer<
return {
type: "ai-sdk" as const,
result: streamText({
onError(error) {
bridge.fork(
Effect.logError("stream error", {
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,
error,
}),
)
},
// Copilot returns the authoritative billed amount only in provider-specific response fields.
includeRawChunks: input.model.providerID.includes("github-copilot"),
async experimental_repairToolCall(failed) {
Expand Down
Loading