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