From 2ccc0ea48d0276dd2fe293275c2cebc9be6d2a8f Mon Sep 17 00:00:00 2001 From: Sai-karthik Date: Mon, 15 Jun 2026 11:08:29 +0000 Subject: [PATCH] Return structured curator handoffs --- src/v1/curator/curator-agent.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/v1/curator/curator-agent.ts b/src/v1/curator/curator-agent.ts index f33cddb..bf719da 100644 --- a/src/v1/curator/curator-agent.ts +++ b/src/v1/curator/curator-agent.ts @@ -8,6 +8,7 @@ import { generateConversationResponse, getConversationModel } from "../../actors import { buildCuratorTasks, todayIsoDate } from "./curator-store.js"; import { emitCuratorEvent } from "./curator-events.js"; import type { CuratorChatResponse, CuratorSubtaskStatusUpdate } from "./curator-types.js"; +import { prepareHandoffForTask } from "./curator-tools.js"; const chatExtractSchema = z.object({ summary: z.string(), @@ -45,13 +46,21 @@ function sanitize(text: string) { const trimmed = line.trim(); if (!trimmed) return true; if (/^(date|curator task id|focused subtask|curator task title|curator task context|curator task subtasks|curator service|expected completion events|captured task memory|task title|task service|task context|all task subtasks|visible history):/i.test(trimmed)) return false; + if (/setup route|mission instance id|curator task id|access the setup at/i.test(trimmed)) return false; + if (/\/agents\/(interview|roleplay|resume|qscore)|\/analytics\?|\/social\?|\/pathways\?/i.test(trimmed)) return false; if (/^```/.test(trimmed)) return false; return true; }) .join("\n") .trim(); const withoutJsonEnvelope = withoutControlLines.replace(/^\s*\{[\s\S]*"reply"\s*:\s*"([^"]+)"[\s\S]*\}\s*$/i, "$1"); - return withoutJsonEnvelope + const withoutRoutes = withoutJsonEnvelope + .replace(/\b(?:Interview|Roleplay|Resume|Q Score)?\s*setup route:\s*\/\S+/gi, "") + .replace(/\/agents\/(?:interview|roleplay|resume|qscore)\/?\S*/gi, "") + .replace(/\/analytics\?\S*/gi, "") + .replace(/\/social\?\S*/gi, "") + .replace(/\/pathways\?\S*/gi, ""); + return withoutRoutes .replace(/[\u2013\u2014]/g, "-") .replace(/[\u2018\u2019]/g, "'") .replace(/[\u201C\u201D]/g, '"') @@ -398,13 +407,17 @@ export async function runCuratorChat(input: { if (task?.serviceId && isExplicitHandoffRequest(latest)) { statusUpdate = { status: "handoff_ready", - summary: `${task.serviceName} handoff is ready.`, + summary: `${task.serviceName} setup is ready. Use the action below to open it.`, confidence: Math.max(statusUpdate.confidence, 0.9), }; } + const handoff = task?.serviceId && statusUpdate.status === "handoff_ready" + ? await prepareHandoffForTask(input.userId, task, task.serviceId) + : undefined; + if (statusUpdate.status !== "needs_more_context") { - if (reply.includes("?")) { + if (reply.includes("?") || handoff) { reply = sanitize(statusUpdate.summary); } @@ -435,5 +448,6 @@ export async function runCuratorChat(input: { reply, messages: visibleCuratorMessages(await listMessagesPg(input.userId, conversation.id)), statusUpdate, + handoff, }; }