mirror of
https://github.com/anomalyco/opencode.git
synced 2026-03-11 00:54:19 +00:00
Compare commits
1 Commits
dev
...
fix/interr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8084f9dfd8 |
@@ -376,7 +376,7 @@ export const SessionRoutes = lazy(() =>
|
||||
}),
|
||||
),
|
||||
async (c) => {
|
||||
SessionPrompt.cancel(c.req.valid("param").sessionID)
|
||||
SessionPrompt.cancel(c.req.valid("param").sessionID, "aborted")
|
||||
return c.json(true)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -381,7 +381,10 @@ export namespace SessionProcessor {
|
||||
sessionID: input.assistantMessage.sessionID,
|
||||
error: input.assistantMessage.error,
|
||||
})
|
||||
SessionStatus.set(input.sessionID, { type: "idle" })
|
||||
SessionStatus.set(input.sessionID, {
|
||||
type: "idle",
|
||||
reason: error.name === "MessageAbortedError" ? "aborted" : "error",
|
||||
})
|
||||
}
|
||||
}
|
||||
if (snapshot) {
|
||||
|
||||
@@ -254,17 +254,21 @@ export namespace SessionPrompt {
|
||||
return s[sessionID].abort.signal
|
||||
}
|
||||
|
||||
export function cancel(sessionID: string) {
|
||||
export function cancel(sessionID: string, reason: SessionStatus.IdleReason = "aborted") {
|
||||
log.info("cancel", { sessionID })
|
||||
const idle = () => {
|
||||
if (SessionStatus.get(sessionID).type === "idle") return
|
||||
SessionStatus.set(sessionID, { type: "idle", reason })
|
||||
}
|
||||
const s = state()
|
||||
const match = s[sessionID]
|
||||
if (!match) {
|
||||
SessionStatus.set(sessionID, { type: "idle" })
|
||||
idle()
|
||||
return
|
||||
}
|
||||
match.abort.abort()
|
||||
delete s[sessionID]
|
||||
SessionStatus.set(sessionID, { type: "idle" })
|
||||
idle()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -283,7 +287,8 @@ export namespace SessionPrompt {
|
||||
})
|
||||
}
|
||||
|
||||
using _ = defer(() => cancel(sessionID))
|
||||
let reason: SessionStatus.IdleReason = "completed"
|
||||
using _ = defer(() => cancel(sessionID, reason))
|
||||
|
||||
// Structured output state
|
||||
// Note: On session resumption, state is reset but outputFormat is preserved
|
||||
@@ -295,7 +300,10 @@ export namespace SessionPrompt {
|
||||
while (true) {
|
||||
SessionStatus.set(sessionID, { type: "busy" })
|
||||
log.info("loop", { step, sessionID })
|
||||
if (abort.aborted) break
|
||||
if (abort.aborted) {
|
||||
reason = "aborted"
|
||||
break
|
||||
}
|
||||
let msgs = await MessageV2.filterCompacted(MessageV2.stream(sessionID))
|
||||
|
||||
let lastUser: MessageV2.User | undefined
|
||||
@@ -536,7 +544,10 @@ export namespace SessionPrompt {
|
||||
auto: task.auto,
|
||||
overflow: task.overflow,
|
||||
})
|
||||
if (result === "stop") break
|
||||
if (result === "stop") {
|
||||
reason = abort.aborted ? "aborted" : "completed"
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -698,11 +709,19 @@ export namespace SessionPrompt {
|
||||
retries: 0,
|
||||
}).toObject()
|
||||
await Session.updateMessage(processor.message)
|
||||
reason = "error"
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (result === "stop") break
|
||||
if (result === "stop") {
|
||||
if (processor.message.error?.name === "MessageAbortedError") {
|
||||
reason = "aborted"
|
||||
} else if (processor.message.error) {
|
||||
reason = "error"
|
||||
}
|
||||
break
|
||||
}
|
||||
if (result === "compact") {
|
||||
await SessionCompaction.create({
|
||||
sessionID,
|
||||
|
||||
@@ -4,10 +4,14 @@ import { Instance } from "@/project/instance"
|
||||
import z from "zod"
|
||||
|
||||
export namespace SessionStatus {
|
||||
export const IdleReason = z.enum(["completed", "aborted", "error"])
|
||||
export type IdleReason = z.infer<typeof IdleReason>
|
||||
|
||||
export const Info = z
|
||||
.union([
|
||||
z.object({
|
||||
type: z.literal("idle"),
|
||||
reason: IdleReason.optional(),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("retry"),
|
||||
@@ -65,9 +69,11 @@ export namespace SessionStatus {
|
||||
})
|
||||
if (status.type === "idle") {
|
||||
// deprecated
|
||||
Bus.publish(Event.Idle, {
|
||||
sessionID,
|
||||
})
|
||||
if (!status.reason || status.reason === "completed") {
|
||||
Bus.publish(Event.Idle, {
|
||||
sessionID,
|
||||
})
|
||||
}
|
||||
delete state()[sessionID]
|
||||
return
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ export const TaskTool = Tool.define("task", async (ctx) => {
|
||||
const messageID = Identifier.ascending("message")
|
||||
|
||||
function cancel() {
|
||||
SessionPrompt.cancel(session.id)
|
||||
SessionPrompt.cancel(session.id, "aborted")
|
||||
}
|
||||
ctx.abort.addEventListener("abort", cancel)
|
||||
using _ = defer(() => ctx.abort.removeEventListener("abort", cancel))
|
||||
|
||||
@@ -453,6 +453,7 @@ export type EventPermissionReplied = {
|
||||
export type SessionStatus =
|
||||
| {
|
||||
type: "idle"
|
||||
reason?: "completed" | "aborted" | "error"
|
||||
}
|
||||
| {
|
||||
type: "retry"
|
||||
|
||||
@@ -581,6 +581,7 @@ export type EventPermissionReplied = {
|
||||
export type SessionStatus =
|
||||
| {
|
||||
type: "idle"
|
||||
reason?: "completed" | "aborted" | "error"
|
||||
}
|
||||
| {
|
||||
type: "retry"
|
||||
|
||||
Reference in New Issue
Block a user