Revert "feat(core): publish terminal session run failures"
This reverts commit fd07e58384.
This commit is contained in:
parent
fd07e58384
commit
93ca32f41a
6 changed files with 8 additions and 76 deletions
|
|
@ -119,23 +119,6 @@ export namespace PromptLifecycle {
|
||||||
export type Promoted = typeof Promoted.Type
|
export type Promoted = typeof Promoted.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace Run {
|
|
||||||
export const Failed = EventV2.define({
|
|
||||||
type: "session.next.run.failed",
|
|
||||||
...options,
|
|
||||||
schema: {
|
|
||||||
...Base,
|
|
||||||
reason: Schema.Literals(["execution-failed", "step-limit-exceeded", "unknown"]),
|
|
||||||
input: Schema.Struct({
|
|
||||||
messageID: SessionMessageID.ID,
|
|
||||||
admittedSeq: NonNegativeInt,
|
|
||||||
promotedSeq: NonNegativeInt.pipe(Schema.optional),
|
|
||||||
}).pipe(Schema.optional),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
export type Failed = typeof Failed.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InterruptRequested = EventV2.define({
|
export const InterruptRequested = EventV2.define({
|
||||||
type: "session.next.interrupt.requested",
|
type: "session.next.interrupt.requested",
|
||||||
...options,
|
...options,
|
||||||
|
|
@ -493,7 +476,6 @@ const DurableDefinitions = [
|
||||||
Prompted,
|
Prompted,
|
||||||
PromptLifecycle.Admitted,
|
PromptLifecycle.Admitted,
|
||||||
PromptLifecycle.Promoted,
|
PromptLifecycle.Promoted,
|
||||||
Run.Failed,
|
|
||||||
InterruptRequested,
|
InterruptRequested,
|
||||||
ContextUpdated,
|
ContextUpdated,
|
||||||
Synthetic,
|
Synthetic,
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,10 @@
|
||||||
import { Cause, DateTime, Effect, Layer, Option } from "effect"
|
import { Effect, Layer } from "effect"
|
||||||
import { LLMError } from "@opencode-ai/llm"
|
|
||||||
import { Database } from "../../database/database"
|
|
||||||
import { EventV2 } from "../../event"
|
|
||||||
import { LocationServiceMap } from "../../location-layer"
|
import { LocationServiceMap } from "../../location-layer"
|
||||||
import { SessionRunCoordinator } from "../run-coordinator"
|
import { SessionRunCoordinator } from "../run-coordinator"
|
||||||
import { SessionRunner } from "../runner"
|
import { SessionRunner } from "../runner"
|
||||||
import { SessionSchema } from "../schema"
|
import { SessionSchema } from "../schema"
|
||||||
import { SessionStore } from "../store"
|
import { SessionStore } from "../store"
|
||||||
import { SessionExecution } from "../execution"
|
import { SessionExecution } from "../execution"
|
||||||
import { SessionEvent } from "../event"
|
|
||||||
import { SessionInput } from "../input"
|
|
||||||
|
|
||||||
/** Current-process routing for implicit-local Locations. Future remote placement belongs here. */
|
/** Current-process routing for implicit-local Locations. Future remote placement belongs here. */
|
||||||
export const layer = Layer.effect(
|
export const layer = Layer.effect(
|
||||||
|
|
@ -17,8 +12,6 @@ export const layer = Layer.effect(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const store = yield* SessionStore.Service
|
const store = yield* SessionStore.Service
|
||||||
const locations = yield* LocationServiceMap
|
const locations = yield* LocationServiceMap
|
||||||
const database = yield* Database.Service
|
|
||||||
const events = yield* EventV2.Service
|
|
||||||
const coordinator = yield* SessionRunCoordinator.make<SessionSchema.ID, void, SessionRunner.RunError>({
|
const coordinator = yield* SessionRunCoordinator.make<SessionSchema.ID, void, SessionRunner.RunError>({
|
||||||
drain: Effect.fnUntraced(function* (sessionID: SessionSchema.ID, mode) {
|
drain: Effect.fnUntraced(function* (sessionID: SessionSchema.ID, mode) {
|
||||||
const session = yield* store.get(sessionID)
|
const session = yield* store.get(sessionID)
|
||||||
|
|
@ -27,34 +20,11 @@ export const layer = Layer.effect(
|
||||||
Effect.provide(locations.get(session.location)),
|
Effect.provide(locations.get(session.location)),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
onFailure: (sessionID, cause, context) =>
|
onFailure: (sessionID, cause) =>
|
||||||
Effect.gen(function* () {
|
Effect.logError("Failed to drain Session").pipe(
|
||||||
yield* Effect.logError("Failed to drain Session").pipe(
|
Effect.annotateLogs("sessionID", sessionID),
|
||||||
Effect.annotateLogs("sessionID", sessionID),
|
Effect.annotateLogs("cause", cause),
|
||||||
Effect.annotateLogs("cause", cause),
|
),
|
||||||
)
|
|
||||||
if (Cause.hasInterruptsOnly(cause)) return
|
|
||||||
const error = Option.getOrUndefined(Cause.findErrorOption(cause))
|
|
||||||
// Provider failures already publish Step.Failed before escaping the runner.
|
|
||||||
if (error instanceof LLMError) return
|
|
||||||
const input = context.seq === undefined
|
|
||||||
? undefined
|
|
||||||
: yield* SessionInput.findByAdmittedSeq(database.db, sessionID, context.seq)
|
|
||||||
yield* events.publish(SessionEvent.Run.Failed, {
|
|
||||||
sessionID,
|
|
||||||
timestamp: yield* DateTime.now,
|
|
||||||
reason: error instanceof SessionRunner.StepLimitExceededError ? "step-limit-exceeded" : "execution-failed",
|
|
||||||
...(input === undefined
|
|
||||||
? {}
|
|
||||||
: {
|
|
||||||
input: {
|
|
||||||
messageID: input.id,
|
|
||||||
admittedSeq: input.admittedSeq,
|
|
||||||
...(input.promotedSeq === undefined ? {} : { promotedSeq: input.promotedSeq }),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return SessionExecution.Service.of({
|
return SessionExecution.Service.of({
|
||||||
|
|
|
||||||
|
|
@ -47,20 +47,6 @@ export const find = Effect.fn("SessionInput.find")(function* (db: DatabaseServic
|
||||||
return row === undefined ? undefined : fromRow(row)
|
return row === undefined ? undefined : fromRow(row)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const findByAdmittedSeq = Effect.fn("SessionInput.findByAdmittedSeq")(function* (
|
|
||||||
db: DatabaseService,
|
|
||||||
sessionID: SessionSchema.ID,
|
|
||||||
admittedSeq: number,
|
|
||||||
) {
|
|
||||||
const row = yield* db
|
|
||||||
.select()
|
|
||||||
.from(SessionInputTable)
|
|
||||||
.where(and(eq(SessionInputTable.session_id, sessionID), eq(SessionInputTable.admitted_seq, admittedSeq)))
|
|
||||||
.get()
|
|
||||||
.pipe(Effect.orDie)
|
|
||||||
return row === undefined ? undefined : fromRow(row)
|
|
||||||
})
|
|
||||||
|
|
||||||
export class LifecycleConflict extends Schema.TaggedErrorClass<LifecycleConflict>()("SessionInput.LifecycleConflict", {
|
export class LifecycleConflict extends Schema.TaggedErrorClass<LifecycleConflict>()("SessionInput.LifecycleConflict", {
|
||||||
id: SessionMessage.ID,
|
id: SessionMessage.ID,
|
||||||
}) {}
|
}) {}
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,6 @@ export function update(adapter: Adapter, event: SessionEvent.Event) {
|
||||||
},
|
},
|
||||||
"session.next.prompt.admitted": () => Effect.void,
|
"session.next.prompt.admitted": () => Effect.void,
|
||||||
"session.next.prompt.promoted": () => Effect.void,
|
"session.next.prompt.promoted": () => Effect.void,
|
||||||
"session.next.run.failed": () => Effect.void,
|
|
||||||
"session.next.interrupt.requested": () => Effect.void,
|
"session.next.interrupt.requested": () => Effect.void,
|
||||||
"session.next.context.updated": (event) =>
|
"session.next.context.updated": (event) =>
|
||||||
adapter.appendMessage(
|
adapter.appendMessage(
|
||||||
|
|
|
||||||
|
|
@ -410,7 +410,6 @@ export const layer = Layer.effectDiscard(
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
yield* events.project(SessionEvent.Run.Failed, () => Effect.void)
|
|
||||||
yield* events.project(SessionEvent.InterruptRequested, () => Effect.void)
|
yield* events.project(SessionEvent.InterruptRequested, () => Effect.void)
|
||||||
yield* events.project(SessionEvent.ContextUpdated, (event) => {
|
yield* events.project(SessionEvent.ContextUpdated, (event) => {
|
||||||
if (!event.replay || event.seq === undefined) return run(db, event)
|
if (!event.replay || event.seq === undefined) return run(db, event)
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,7 @@ const maxSeq = (left: number | undefined, right: number | undefined) => {
|
||||||
/** Constructs a scoped coordinator. Every in-memory transition is synchronous. */
|
/** Constructs a scoped coordinator. Every in-memory transition is synchronous. */
|
||||||
export const make = <Key, A, E>(options: {
|
export const make = <Key, A, E>(options: {
|
||||||
readonly drain: (key: Key, mode: Mode) => Effect.Effect<A, E>
|
readonly drain: (key: Key, mode: Mode) => Effect.Effect<A, E>
|
||||||
readonly onFailure?: (
|
readonly onFailure?: (key: Key, cause: Cause.Cause<E>) => Effect.Effect<void>
|
||||||
key: Key,
|
|
||||||
cause: Cause.Cause<E>,
|
|
||||||
context: { readonly mode: "wake"; readonly seq?: number },
|
|
||||||
) => Effect.Effect<void>
|
|
||||||
}): Effect.Effect<Coordinator<Key, A, E>, never, Scope.Scope> =>
|
}): Effect.Effect<Coordinator<Key, A, E>, never, Scope.Scope> =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const active = new Map<Key, Entry<A, E>>()
|
const active = new Map<Key, Entry<A, E>>()
|
||||||
|
|
@ -170,7 +166,7 @@ export const make = <Key, A, E>(options: {
|
||||||
successor === undefined &&
|
successor === undefined &&
|
||||||
options.onFailure !== undefined
|
options.onFailure !== undefined
|
||||||
) {
|
) {
|
||||||
report(Effect.suspend(() => options.onFailure!(key, exit.cause, { mode: "wake", seq: demand.seq })))
|
report(Effect.suspend(() => options.onFailure!(key, exit.cause)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue