Return structured curator handoffs

This commit is contained in:
Sai-karthik
2026-06-15 11:08:29 +00:00
parent 3fecfdc403
commit 2ccc0ea48d

View File

@@ -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,
};
}