fix(core): preserve session failure causes
This commit is contained in:
parent
1025540fcc
commit
53ff1b57c9
@ -25,6 +25,7 @@ import { fromRow } from "./session/info"
|
||||
import { SessionRunner } from "./session/runner/index"
|
||||
import { SessionStore } from "./session/store"
|
||||
import { SessionExecution } from "./session/execution"
|
||||
import { logFailure } from "./session/logging"
|
||||
import { MessageDecodeError } from "./session/error"
|
||||
import { SessionEvent } from "./session/event"
|
||||
import { SessionInput } from "./session/input"
|
||||
@ -177,10 +178,7 @@ export const layer = Layer.effect(
|
||||
Effect.tapCause((cause) =>
|
||||
Cause.hasInterruptsOnly(cause)
|
||||
? Effect.void
|
||||
: Effect.logError("Failed to wake Session").pipe(
|
||||
Effect.annotateLogs("sessionID", admitted.sessionID),
|
||||
Effect.annotateLogs("cause", cause),
|
||||
),
|
||||
: logFailure("Failed to wake Session", admitted.sessionID, cause),
|
||||
),
|
||||
Effect.ignore,
|
||||
Effect.forkIn(scope, { startImmediately: true }),
|
||||
|
||||
@ -5,6 +5,7 @@ import { SessionRunner } from "../runner"
|
||||
import { SessionSchema } from "../schema"
|
||||
import { SessionStore } from "../store"
|
||||
import { SessionExecution } from "../execution"
|
||||
import { logFailure } from "../logging"
|
||||
|
||||
/** Current-process routing for implicit-local Locations. Future remote placement belongs here. */
|
||||
export const layer = Layer.effect(
|
||||
@ -20,11 +21,7 @@ export const layer = Layer.effect(
|
||||
Effect.provide(locations.get(session.location)),
|
||||
)
|
||||
}),
|
||||
onFailure: (sessionID, cause) =>
|
||||
Effect.logError("Failed to drain Session").pipe(
|
||||
Effect.annotateLogs("sessionID", sessionID),
|
||||
Effect.annotateLogs("cause", cause),
|
||||
),
|
||||
onFailure: (sessionID, cause) => logFailure("Failed to drain Session", sessionID, cause),
|
||||
})
|
||||
|
||||
return SessionExecution.Service.of({
|
||||
|
||||
8
packages/core/src/session/logging.ts
Normal file
8
packages/core/src/session/logging.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Cause, Effect } from "effect"
|
||||
import { SessionSchema } from "./schema"
|
||||
|
||||
export const logFailure = (
|
||||
message: "Failed to drain Session" | "Failed to wake Session",
|
||||
sessionID: SessionSchema.ID,
|
||||
cause: Cause.Cause<unknown>,
|
||||
) => Effect.logError(message, cause).pipe(Effect.annotateLogs("sessionID", sessionID))
|
||||
@ -2,6 +2,7 @@ export * as SessionRunCoordinator from "./run-coordinator"
|
||||
|
||||
import { Cause, Context, Deferred, Effect, Exit, Fiber, FiberSet, Layer, Scope } from "effect"
|
||||
import { SessionRunner } from "./runner"
|
||||
import { logFailure } from "./logging"
|
||||
import { SessionSchema } from "./schema"
|
||||
|
||||
export type Mode = "run" | "wake"
|
||||
@ -275,11 +276,7 @@ export const layer = Layer.effect(
|
||||
Effect.flatMap((runner) =>
|
||||
make<SessionSchema.ID, void, SessionRunner.RunError>({
|
||||
drain: (sessionID, mode) => runner.run({ sessionID, force: mode === "run" }),
|
||||
onFailure: (sessionID, cause) =>
|
||||
Effect.logError("Failed to drain Session").pipe(
|
||||
Effect.annotateLogs("sessionID", sessionID),
|
||||
Effect.annotateLogs("cause", cause),
|
||||
),
|
||||
onFailure: (sessionID, cause) => logFailure("Failed to drain Session", sessionID, cause),
|
||||
}),
|
||||
),
|
||||
Effect.map(Service.of),
|
||||
|
||||
30
packages/core/test/session-logging.test.ts
Normal file
30
packages/core/test/session-logging.test.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { Cause, Effect, Logger } from "effect"
|
||||
import { logFailure } from "@opencode-ai/core/session/logging"
|
||||
import { SessionSchema } from "@opencode-ai/core/session/schema"
|
||||
|
||||
describe("Session logging", () => {
|
||||
for (const message of ["Failed to drain Session", "Failed to wake Session"] as const) {
|
||||
test(`renders the cause for ${message}`, async () => {
|
||||
const entries: Array<ReturnType<typeof Logger.formatStructured.log>> = []
|
||||
const logger = Logger.formatStructured.pipe(
|
||||
Logger.map((entry): void => {
|
||||
entries.push(entry)
|
||||
}),
|
||||
)
|
||||
|
||||
await logFailure(
|
||||
message,
|
||||
SessionSchema.ID.make("session-123"),
|
||||
Cause.fail({ _tag: "SessionFailure", detail: { code: "nested-code" } }),
|
||||
).pipe(Effect.provide(Logger.layer([logger])), Effect.runPromise)
|
||||
|
||||
expect(entries).toHaveLength(1)
|
||||
expect(entries[0]?.message).toBe(message)
|
||||
expect(entries[0]?.annotations).toEqual({ sessionID: "session-123" })
|
||||
expect(entries[0]?.cause).toContain("SessionFailure")
|
||||
expect(entries[0]?.cause).toContain("nested-code")
|
||||
expect(entries[0]?.cause).not.toContain("[Object")
|
||||
})
|
||||
}
|
||||
})
|
||||
Loading…
Reference in New Issue
Block a user