From ff786d9139280b36f0214cb71afa18affb676095 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Wed, 28 May 2025 15:07:51 -0400 Subject: abort --- js/src/server/server.ts | 39 +++++++++++++++++++++++++++++++++++++++ js/src/session/session.ts | 24 +++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) (limited to 'js/src') diff --git a/js/src/server/server.ts b/js/src/server/server.ts index ea70cd5ef..11262f4fd 100644 --- a/js/src/server/server.ts +++ b/js/src/server/server.ts @@ -158,8 +158,47 @@ export namespace Server { return c.json(sessions); }, ) + .post( + "/session_abort", + describeRoute({ + description: "Abort a session", + responses: { + 200: { + description: "Aborted session", + content: { + "application/json": { + schema: resolver(z.boolean()), + }, + }, + }, + }, + }), + zValidator( + "json", + z.object({ + sessionID: z.string(), + }), + ), + async (c) => { + const body = c.req.valid("json"); + return c.json(Session.abort(body.sessionID)); + }, + ) .post( "/session_chat", + describeRoute({ + description: "Chat with a model", + responses: { + 200: { + description: "Chat with a model", + content: { + "application/json": { + schema: resolver(SessionMessage), + }, + }, + }, + }, + }), zValidator( "json", z.object({ diff --git a/js/src/session/session.ts b/js/src/session/session.ts index 406ab27f8..011519048 100644 --- a/js/src/session/session.ts +++ b/js/src/session/session.ts @@ -129,6 +129,16 @@ export namespace Session { } } + const pending = new Map(); + + export function abort(sessionID: string) { + const controller = pending.get(sessionID); + if (!controller) return false; + controller.abort(); + pending.delete(sessionID); + return true; + } + export async function chat(input: { sessionID: string; providerID: string; @@ -225,6 +235,8 @@ export namespace Session { tool: {}, }, }; + const controller = new AbortController(); + pending.set(input.sessionID, controller); const result = streamText({ onStepFinish: (step) => { update(input.sessionID, (draft) => { @@ -240,6 +252,8 @@ export namespace Session { .toNumber(); }); }, + abortSignal: controller.signal, + maxRetries: 6, stopWhen: stepCountIs(1000), messages: convertToModelMessages(msgs), temperature: 0, @@ -251,7 +265,14 @@ export namespace Session { let text: TextUIPart | undefined; const reader = result.toUIMessageStream().getReader(); while (true) { - const { done, value } = await reader.read(); + const result = await reader.read().catch((e) => { + if (e instanceof DOMException && e.name === "AbortError") { + return; + } + throw e; + }); + if (!result) break; + const { done, value } = result; if (done) break; l.info("part", { type: value.type, @@ -316,6 +337,7 @@ export namespace Session { } await write(next); } + pending.delete(input.sessionID); next.metadata!.time.completed = Date.now(); await write(next); return next; -- cgit v1.2.3