summaryrefslogtreecommitdiffhomepage
path: root/packages/core/src/tools
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-05-22 20:54:19 +0900
committerAdam Malczewski <[email protected]>2026-05-22 20:54:19 +0900
commitc47346cc6237044ecb60ff22c4011d89744af581 (patch)
tree2359a25e687e1290ba5180fd60eae83b03b53a23 /packages/core/src/tools
parent288b21cec98421fda57028a0c8c9d835cfbb14b0 (diff)
downloaddispatch-c47346cc6237044ecb60ff22c4011d89744af581.tar.gz
dispatch-c47346cc6237044ecb60ff22c4011d89744af581.zip
feat: message queue/interrupt system, CORS fix, mobile fixes, chat splitting
- Add message queue allowing users to send messages while agent is running - Queue messages are injected into tool results as [USER INTERRUPT] - Retrieve tool interrupted via Promise.race when user message arrives - Queued messages show with 'queued' badge and cancel button - Consumed messages repositioned and chat splits at interrupt point - New assistant message block created after interrupt for clean flow - Add POST /chat/cancel endpoint for cancelling queued messages - Fix CORS to allow any origin (Tailscale/LAN access) - Fix crypto.randomUUID fallback for non-secure contexts (HTTP) - Fix frontend API URL derivation from page hostname - Auto-create DB tab if missing on processMessage (foreign key fix) - Add error logging to processMessage catch block - Fix working directory input sync on agent switch - Fix agent mode button to re-apply agent settings
Diffstat (limited to 'packages/core/src/tools')
-rw-r--r--packages/core/src/tools/retrieve.ts28
1 files changed, 25 insertions, 3 deletions
diff --git a/packages/core/src/tools/retrieve.ts b/packages/core/src/tools/retrieve.ts
index 93f4c89..8e14a96 100644
--- a/packages/core/src/tools/retrieve.ts
+++ b/packages/core/src/tools/retrieve.ts
@@ -1,5 +1,5 @@
import { z } from "zod";
-import type { ToolDefinition } from "../types/index.js";
+import type { ToolDefinition, ToolExecuteContext } from "../types/index.js";
export interface RetrieveCallbacks {
getResult(
@@ -24,11 +24,33 @@ export function createRetrieveTool(callbacks: RetrieveCallbacks): ToolDefinition
parameters: z.object({
agent_id: z.string().describe("The agent_id returned by a previous summon call."),
}),
- execute: async (args: Record<string, unknown>): Promise<string> => {
+ execute: async (args: Record<string, unknown>, context?: ToolExecuteContext): Promise<string> => {
const agentId = args.agent_id as string;
+ const queueCallbacks = context?.queueCallbacks;
try {
- const outcome = await callbacks.getResult(agentId);
+ let outcome: { status: "done"; result: string } | { status: "error"; error: string };
+
+ if (queueCallbacks) {
+ const childPromise = callbacks.getResult(agentId);
+ const { promise: queuePromise, cancel: cancelQueueWait } = queueCallbacks.waitForQueuedMessage();
+ const queueSignal = queuePromise.then(() => "QUEUE_INTERRUPT" as const);
+
+ const raceResult = await Promise.race([childPromise, queueSignal]);
+
+ if (raceResult === "QUEUE_INTERRUPT") {
+ const queuedMsgs = queueCallbacks.dequeueMessages();
+ const userMessages = queuedMsgs.map((m) => m.message).join("\n---\n");
+ return `The subagent (agent_id: ${agentId}) has not completed its task yet. You will need to call retrieve with this agent_id again later to get the result.\n\n[USER INTERRUPT]\nThe user has sent you message(s) while you were working. You MUST address these before continuing with your current task:\n\n${userMessages}`;
+ }
+
+ // Child finished first — clean up the queue listener
+ cancelQueueWait();
+ outcome = raceResult;
+ } else {
+ outcome = await callbacks.getResult(agentId);
+ }
+
if (outcome.status === "done") {
return ["<agent_result>", outcome.result, "</agent_result>"].join("\n");
}