mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-18 23:23:30 +00:00
refactor(core): handle form cancellation in runner
This commit is contained in:
parent
a2136dd0f0
commit
5deef980dd
3 changed files with 9 additions and 10 deletions
|
|
@ -63,6 +63,8 @@ export class InvalidFormError extends Schema.TaggedErrorClass<InvalidFormError>(
|
|||
message: Schema.String,
|
||||
}) {}
|
||||
|
||||
export class CancelledError extends Schema.TaggedErrorClass<CancelledError>()("Form.CancelledError", {}) {}
|
||||
|
||||
export type CreateInput =
|
||||
| (Omit<Form.FormInfo, "id"> & { readonly id?: ID })
|
||||
| (Omit<Form.UrlInfo, "id"> & { readonly id?: ID })
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { Config } from "../../config"
|
|||
import { Database } from "../../database/database"
|
||||
import { EventV2 } from "../../event"
|
||||
import { Location } from "../../location"
|
||||
import { QuestionV2 } from "../../question"
|
||||
import { Form } from "../../form"
|
||||
import { SystemContext } from "../../system-context/index"
|
||||
import { SystemContextBuiltIns } from "../../system-context/builtins"
|
||||
import { InstructionContext } from "../../instruction-context"
|
||||
|
|
@ -149,9 +149,8 @@ const layer = Layer.effect(
|
|||
const awaitToolFibers = (fibers: FiberSet.FiberSet<void, ToolOutputStore.Error>) =>
|
||||
Effect.raceFirst(FiberSet.join(fibers), FiberSet.awaitEmpty(fibers))
|
||||
|
||||
// Match V1: dismissing a question halts the loop instead of becoming model-facing tool output.
|
||||
const isQuestionRejected = (cause: Cause.Cause<unknown>) =>
|
||||
cause.reasons.some((reason) => Cause.isDieReason(reason) && reason.defect instanceof QuestionV2.RejectedError)
|
||||
const isFormCancelled = (cause: Cause.Cause<unknown>) =>
|
||||
cause.reasons.some((reason) => Cause.isDieReason(reason) && reason.defect instanceof Form.CancelledError)
|
||||
|
||||
const loadSystemContext = (agent: AgentV2.Selection, sessionID: SessionSchema.ID) =>
|
||||
Effect.all(
|
||||
|
|
@ -341,14 +340,13 @@ const layer = Layer.effect(
|
|||
if (streamInterrupted) yield* FiberSet.clear(toolFibers)
|
||||
const settled = yield* restore(awaitToolFibers(toolFibers)).pipe(Effect.exit)
|
||||
const toolsInterrupted = settled._tag === "Failure" && Cause.hasInterrupts(settled.cause)
|
||||
const questionDismissed = settled._tag === "Failure" && isQuestionRejected(settled.cause)
|
||||
const formCancelled = settled._tag === "Failure" && isFormCancelled(settled.cause)
|
||||
|
||||
if (questionDismissed || streamInterrupted || toolsInterrupted) {
|
||||
if (formCancelled || streamInterrupted || toolsInterrupted) {
|
||||
yield* FiberSet.clear(toolFibers)
|
||||
yield* serialized(publisher.failUnsettledTools("Tool execution interrupted"))
|
||||
yield* serialized(publisher.failAssistant("Step interrupted"))
|
||||
// Match V1: dismissing a question halts the loop like an interruption.
|
||||
if (questionDismissed) return yield* Effect.interrupt
|
||||
if (formCancelled) return yield* Effect.interrupt
|
||||
}
|
||||
// A settled tool fiber failure is one of two things. A defect from a tool
|
||||
// implementation becomes a failed tool call the model can read, and the step still
|
||||
|
|
|
|||
|
|
@ -94,8 +94,7 @@ export const Plugin = {
|
|||
.pipe(Effect.orDie),
|
||||
),
|
||||
Effect.flatMap((state) => {
|
||||
// The runner halts the loop on this exact defect (session/runner/llm.ts).
|
||||
if (state.status !== "answered") return Effect.die(new QuestionV2.RejectedError())
|
||||
if (state.status !== "answered") return Effect.die(new Form.CancelledError())
|
||||
return Effect.succeed({
|
||||
answers: input.questions.map((_, index): QuestionV2.Answer => {
|
||||
const value = state.answer[`q${index}`]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue