@rtrvr-ai/rover 1.1.2 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -5
- package/dist/embed.js +578 -16
- package/dist/index.d.ts +20 -0
- package/dist/rover.js +2478 -275
- package/dist/worker/rover-worker.js +708 -252
- package/package.json +3 -2
|
@@ -758,13 +758,13 @@ function isAllowedByRules(url, rules) {
|
|
|
758
758
|
if (!host)
|
|
759
759
|
return { allowed: false, reason: "invalid_url" };
|
|
760
760
|
if (rules.denyDomains.some((rule) => matchesDomainRule(host, rule))) {
|
|
761
|
-
return { allowed: false, reason:
|
|
761
|
+
return { allowed: false, reason: "deny_rule" };
|
|
762
762
|
}
|
|
763
763
|
if (!rules.allowDomains.length)
|
|
764
764
|
return { allowed: true };
|
|
765
765
|
if (rules.allowDomains.some((rule) => matchesDomainRule(host, rule)))
|
|
766
766
|
return { allowed: true };
|
|
767
|
-
return { allowed: false, reason:
|
|
767
|
+
return { allowed: false, reason: "not_in_allowlist" };
|
|
768
768
|
}
|
|
769
769
|
function normalizeRuntimeExternalTabs(input) {
|
|
770
770
|
if (!Array.isArray(input))
|
|
@@ -1456,6 +1456,61 @@ async function processActionResponse({ request, response, tabId, prevSteps, thou
|
|
|
1456
1456
|
return { needsRetry: false, data };
|
|
1457
1457
|
}
|
|
1458
1458
|
if (Array.isArray(functionCalls) && functionCalls.length > 0) {
|
|
1459
|
+
const askUserCall = functionCalls.find((call) => String(call?.name || "").trim().toLowerCase() === "ask_user");
|
|
1460
|
+
if (askUserCall) {
|
|
1461
|
+
const questions = normalizeAskUserQuestions(askUserCall?.args?.questions_to_ask);
|
|
1462
|
+
if (!questions.length) {
|
|
1463
|
+
prevSteps.push({
|
|
1464
|
+
accTreeId,
|
|
1465
|
+
thought,
|
|
1466
|
+
modelParts,
|
|
1467
|
+
fail: "ask_user called with invalid or empty 'questions_to_ask'",
|
|
1468
|
+
functions: [
|
|
1469
|
+
{
|
|
1470
|
+
name: "ask_user",
|
|
1471
|
+
args: askUserCall?.args || {},
|
|
1472
|
+
response: {
|
|
1473
|
+
status: "Failure",
|
|
1474
|
+
error: "Missing/invalid 'questions_to_ask'",
|
|
1475
|
+
allowFallback: false
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
]
|
|
1479
|
+
});
|
|
1480
|
+
limitPrevSteps(prevSteps);
|
|
1481
|
+
onPrevStepsUpdate?.(prevSteps);
|
|
1482
|
+
return { needsRetry: true };
|
|
1483
|
+
}
|
|
1484
|
+
prevSteps.push({
|
|
1485
|
+
accTreeId,
|
|
1486
|
+
thought,
|
|
1487
|
+
modelParts,
|
|
1488
|
+
functions: [
|
|
1489
|
+
{
|
|
1490
|
+
name: "ask_user",
|
|
1491
|
+
args: {
|
|
1492
|
+
questions_to_ask: questions.map((question) => ({ key: question.key, query: question.query }))
|
|
1493
|
+
},
|
|
1494
|
+
response: {
|
|
1495
|
+
status: "Success",
|
|
1496
|
+
output: {
|
|
1497
|
+
status: "waiting_input",
|
|
1498
|
+
needsUserInput: true,
|
|
1499
|
+
questions
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
]
|
|
1504
|
+
});
|
|
1505
|
+
limitPrevSteps(prevSteps);
|
|
1506
|
+
onPrevStepsUpdate?.(prevSteps);
|
|
1507
|
+
onStatusUpdate?.("Need user clarification to continue", thought, "verify");
|
|
1508
|
+
return {
|
|
1509
|
+
needsRetry: false,
|
|
1510
|
+
needsUserInput: true,
|
|
1511
|
+
questions
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1459
1514
|
const systemCalls = [];
|
|
1460
1515
|
const externalCalls = [];
|
|
1461
1516
|
for (const call of functionCalls) {
|
|
@@ -1538,6 +1593,39 @@ async function processActionResponse({ request, response, tabId, prevSteps, thou
|
|
|
1538
1593
|
onPrevStepsUpdate?.(prevSteps);
|
|
1539
1594
|
return { needsRetry: true };
|
|
1540
1595
|
}
|
|
1596
|
+
function normalizeAskUserQuestions(rawQuestions) {
|
|
1597
|
+
if (!Array.isArray(rawQuestions))
|
|
1598
|
+
return [];
|
|
1599
|
+
const out = [];
|
|
1600
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
1601
|
+
for (const item of rawQuestions) {
|
|
1602
|
+
if (!item || typeof item !== "object")
|
|
1603
|
+
continue;
|
|
1604
|
+
const rawKey = String(item.key || "").trim();
|
|
1605
|
+
const query = resolveQuestionText(item);
|
|
1606
|
+
if (!rawKey || !query)
|
|
1607
|
+
continue;
|
|
1608
|
+
if (seenKeys.has(rawKey))
|
|
1609
|
+
continue;
|
|
1610
|
+
seenKeys.add(rawKey);
|
|
1611
|
+
out.push({
|
|
1612
|
+
key: rawKey,
|
|
1613
|
+
query,
|
|
1614
|
+
...typeof item.question === "string" && item.question.trim() ? { question: String(item.question).trim() } : {},
|
|
1615
|
+
...typeof item.id === "string" && item.id.trim() ? { id: String(item.id).trim() } : {},
|
|
1616
|
+
...Array.isArray(item.choices) ? { choices: item.choices } : {}
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
return out.slice(0, 6);
|
|
1620
|
+
}
|
|
1621
|
+
function resolveQuestionText(raw) {
|
|
1622
|
+
if (!raw || typeof raw !== "object")
|
|
1623
|
+
return "";
|
|
1624
|
+
const question = String(raw.query || raw.question || "").trim();
|
|
1625
|
+
if (!question)
|
|
1626
|
+
return "";
|
|
1627
|
+
return question;
|
|
1628
|
+
}
|
|
1541
1629
|
function limitPrevSteps(prevSteps) {
|
|
1542
1630
|
if (prevSteps.length <= MAX_PREV_STEPS)
|
|
1543
1631
|
return;
|
|
@@ -1838,6 +1926,17 @@ async function executeAgenticSeek(options) {
|
|
|
1838
1926
|
warnings: allWarnings
|
|
1839
1927
|
};
|
|
1840
1928
|
}
|
|
1929
|
+
if (processResult.needsUserInput && Array.isArray(processResult.questions) && processResult.questions.length > 0) {
|
|
1930
|
+
managePrevStepsSize(accumulatedPrevSteps);
|
|
1931
|
+
onPrevStepsUpdate?.(accumulatedPrevSteps);
|
|
1932
|
+
return {
|
|
1933
|
+
prevSteps: accumulatedPrevSteps,
|
|
1934
|
+
creditsUsed: totalCreditsUsed,
|
|
1935
|
+
warnings: allWarnings,
|
|
1936
|
+
needsUserInput: true,
|
|
1937
|
+
questions: processResult.questions
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1841
1940
|
if (processResult.functionCalls?.length) {
|
|
1842
1941
|
const functionCallsWithIds = processResult.functionCalls.map((fc, index) => ({
|
|
1843
1942
|
...fc,
|
|
@@ -2592,8 +2691,7 @@ function resolvePath(obj, path) {
|
|
|
2592
2691
|
}
|
|
2593
2692
|
|
|
2594
2693
|
// dist/agent/toolExecutor.js
|
|
2595
|
-
var MAX_AGENT_CHATLOG_ENTRIES =
|
|
2596
|
-
var MAX_AGENT_CHATLOG_MESSAGE_CHARS = 1e3;
|
|
2694
|
+
var MAX_AGENT_CHATLOG_ENTRIES = 12;
|
|
2597
2695
|
function unsupportedToolResult(toolName, message) {
|
|
2598
2696
|
return {
|
|
2599
2697
|
error: message,
|
|
@@ -2624,17 +2722,31 @@ function buildStructuredErrorOutput(envelope) {
|
|
|
2624
2722
|
function normalizeAgentLog(agentLog) {
|
|
2625
2723
|
const prevSteps = Array.isArray(agentLog?.prevSteps) ? agentLog.prevSteps : [];
|
|
2626
2724
|
const sanitizeMessage = (value) => {
|
|
2627
|
-
|
|
2628
|
-
if (!normalized)
|
|
2629
|
-
return "";
|
|
2630
|
-
if (normalized.length <= MAX_AGENT_CHATLOG_MESSAGE_CHARS)
|
|
2631
|
-
return normalized;
|
|
2632
|
-
return `${normalized.slice(0, MAX_AGENT_CHATLOG_MESSAGE_CHARS - 1)}\u2026`;
|
|
2725
|
+
return String(value || "").replace(/\s+/g, " ").trim();
|
|
2633
2726
|
};
|
|
2634
|
-
const
|
|
2727
|
+
const normalizedChatLog = Array.isArray(agentLog?.chatLog) ? agentLog.chatLog.map((entry) => ({
|
|
2635
2728
|
role: entry?.role === "user" ? "user" : "model",
|
|
2636
2729
|
message: typeof entry?.message === "string" ? sanitizeMessage(entry.message) : ""
|
|
2637
|
-
})).filter((entry) => !!entry.message)
|
|
2730
|
+
})).filter((entry) => !!entry.message) : [];
|
|
2731
|
+
const dedupedChatLog = [];
|
|
2732
|
+
for (const entry of normalizedChatLog) {
|
|
2733
|
+
const previous = dedupedChatLog[dedupedChatLog.length - 1];
|
|
2734
|
+
if (previous && previous.role === entry.role && previous.message === entry.message)
|
|
2735
|
+
continue;
|
|
2736
|
+
dedupedChatLog.push(entry);
|
|
2737
|
+
}
|
|
2738
|
+
const firstUser = dedupedChatLog.find((entry) => entry.role === "user");
|
|
2739
|
+
const tailBudget = firstUser ? Math.max(1, MAX_AGENT_CHATLOG_ENTRIES - 1) : MAX_AGENT_CHATLOG_ENTRIES;
|
|
2740
|
+
let chatLog = dedupedChatLog.slice(-tailBudget);
|
|
2741
|
+
if (firstUser) {
|
|
2742
|
+
const hasAnchor = chatLog.some((entry) => entry.role === "user" && entry.message === firstUser.message);
|
|
2743
|
+
if (!hasAnchor) {
|
|
2744
|
+
chatLog = [firstUser, ...chatLog];
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
if (chatLog.length > MAX_AGENT_CHATLOG_ENTRIES) {
|
|
2748
|
+
chatLog = chatLog.slice(-MAX_AGENT_CHATLOG_ENTRIES);
|
|
2749
|
+
}
|
|
2638
2750
|
return { prevSteps, chatLog };
|
|
2639
2751
|
}
|
|
2640
2752
|
async function executeToolFromPlan(context) {
|
|
@@ -2667,7 +2779,12 @@ async function executeToolFromPlan(context) {
|
|
|
2667
2779
|
ctx: effectiveCtx,
|
|
2668
2780
|
onPrevStepsUpdate
|
|
2669
2781
|
});
|
|
2670
|
-
|
|
2782
|
+
const actOutput = actResult.data ?? (actResult.needsUserInput ? {
|
|
2783
|
+
status: "waiting_input",
|
|
2784
|
+
needsUserInput: true,
|
|
2785
|
+
questions: Array.isArray(actResult.questions) ? actResult.questions : []
|
|
2786
|
+
} : void 0);
|
|
2787
|
+
return { ...actResult, output: actOutput };
|
|
2671
2788
|
}
|
|
2672
2789
|
case PLANNER_FUNCTION_CALLS.EXTRACT: {
|
|
2673
2790
|
const prompt = toolArgs?.user_input || toolArgs?.prompt || toolArgs?.task_instruction || userInput;
|
|
@@ -3452,18 +3569,34 @@ async function executeCustomToolGenerator({ userInput, plannerPrevSteps, files,
|
|
|
3452
3569
|
|
|
3453
3570
|
// dist/agent/plannerAgent.js
|
|
3454
3571
|
var MAX_PLANNER_DEPTH = 15;
|
|
3455
|
-
var MAX_CHATLOG_ENTRIES =
|
|
3456
|
-
var MAX_CHATLOG_MESSAGE_CHARS = 1e3;
|
|
3572
|
+
var MAX_CHATLOG_ENTRIES = 12;
|
|
3457
3573
|
function normalizeChatLog(entries) {
|
|
3458
3574
|
if (!Array.isArray(entries) || !entries.length)
|
|
3459
3575
|
return [];
|
|
3460
|
-
|
|
3576
|
+
const normalized = entries.map((entry) => ({
|
|
3461
3577
|
role: entry?.role === "user" ? "user" : "model",
|
|
3462
3578
|
message: String(entry?.message || "").replace(/\s+/g, " ").trim()
|
|
3463
|
-
})).filter((entry) => !!entry.message)
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3579
|
+
})).filter((entry) => !!entry.message);
|
|
3580
|
+
const deduped = [];
|
|
3581
|
+
for (const entry of normalized) {
|
|
3582
|
+
const previous = deduped[deduped.length - 1];
|
|
3583
|
+
if (previous && previous.role === entry.role && previous.message === entry.message)
|
|
3584
|
+
continue;
|
|
3585
|
+
deduped.push(entry);
|
|
3586
|
+
}
|
|
3587
|
+
const firstUser = deduped.find((entry) => entry.role === "user");
|
|
3588
|
+
const tailBudget = firstUser ? Math.max(1, MAX_CHATLOG_ENTRIES - 1) : MAX_CHATLOG_ENTRIES;
|
|
3589
|
+
let selected = deduped.slice(-tailBudget);
|
|
3590
|
+
if (firstUser) {
|
|
3591
|
+
const hasAnchor = selected.some((entry) => entry.role === "user" && entry.message === firstUser.message);
|
|
3592
|
+
if (!hasAnchor) {
|
|
3593
|
+
selected = [firstUser, ...selected];
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
3596
|
+
if (selected.length > MAX_CHATLOG_ENTRIES) {
|
|
3597
|
+
selected = selected.slice(-MAX_CHATLOG_ENTRIES);
|
|
3598
|
+
}
|
|
3599
|
+
return selected;
|
|
3467
3600
|
}
|
|
3468
3601
|
async function executePlanner(options) {
|
|
3469
3602
|
const { userInput, tabs, previousMessages = [], trajectoryId: trajectoryId2, previousSteps = [], files, continuePlanning = false, recordingContext, driveAuthToken, agentLog, lastToolPreviousSteps, ctx, bridgeRpc: bridgeRpc2, functionDeclarations } = options;
|
|
@@ -4163,20 +4296,19 @@ var bridgeRpc = null;
|
|
|
4163
4296
|
var toolRegistry = new ToolRegistry();
|
|
4164
4297
|
var plannerHistory = [];
|
|
4165
4298
|
var agentPrevSteps = [];
|
|
4299
|
+
var pendingAskUser;
|
|
4166
4300
|
var trajectoryId = crypto.randomUUID();
|
|
4167
4301
|
var tabularStore = null;
|
|
4168
4302
|
var PLANNER_TOOL_NAME_SET = new Set(Object.values(PLANNER_FUNCTION_CALLS));
|
|
4169
4303
|
var activeRun = null;
|
|
4170
|
-
var
|
|
4304
|
+
var cancelledRunIds = /* @__PURE__ */ new Set();
|
|
4171
4305
|
var activeAbortController = null;
|
|
4172
4306
|
var lastStatusKey = "";
|
|
4173
4307
|
var seenStatusKeys = /* @__PURE__ */ new Set();
|
|
4174
|
-
var
|
|
4175
|
-
var completedRunOutcomes = /* @__PURE__ */ new Map();
|
|
4308
|
+
var terminalRuns = /* @__PURE__ */ new Map();
|
|
4176
4309
|
var RPC_TIMEOUT_MS = 3e4;
|
|
4177
4310
|
var DETACHED_EXTERNAL_TAB_MAX_AGE_MS = 9e4;
|
|
4178
|
-
var MAX_CHATLOG_ENTRIES2 =
|
|
4179
|
-
var MAX_CHATLOG_MESSAGE_CHARS2 = 1e3;
|
|
4311
|
+
var MAX_CHATLOG_ENTRIES2 = 12;
|
|
4180
4312
|
function resolveAgentName(config2) {
|
|
4181
4313
|
const raw = String(config2?.ui?.agent?.name || "").trim();
|
|
4182
4314
|
if (!raw)
|
|
@@ -4392,11 +4524,6 @@ function postStatus(message, thought, stage) {
|
|
|
4392
4524
|
self.postMessage({ type: "status", message, thought, stage: resolvedStage, compactThought: compact, runId: activeRun?.runId });
|
|
4393
4525
|
postStateSnapshot();
|
|
4394
4526
|
}
|
|
4395
|
-
function truncateText(value, max = 8e3) {
|
|
4396
|
-
if (value.length <= max)
|
|
4397
|
-
return value;
|
|
4398
|
-
return `${value.slice(0, max)}\u2026`;
|
|
4399
|
-
}
|
|
4400
4527
|
function cloneUnknown(value) {
|
|
4401
4528
|
if (value == null)
|
|
4402
4529
|
return value;
|
|
@@ -4439,6 +4566,90 @@ function sanitizeAgentPrevStepsForPersist(input) {
|
|
|
4439
4566
|
}
|
|
4440
4567
|
return out;
|
|
4441
4568
|
}
|
|
4569
|
+
function normalizePlannerQuestion(input, index) {
|
|
4570
|
+
if (!input || typeof input !== "object")
|
|
4571
|
+
return void 0;
|
|
4572
|
+
const keyCandidate = String(input.key || input.id || "").trim();
|
|
4573
|
+
const queryCandidate = String(input.query || input.question || "").trim();
|
|
4574
|
+
const key = keyCandidate || `clarification_${index + 1}`;
|
|
4575
|
+
if (!queryCandidate)
|
|
4576
|
+
return void 0;
|
|
4577
|
+
return {
|
|
4578
|
+
key,
|
|
4579
|
+
query: queryCandidate,
|
|
4580
|
+
...typeof input.id === "string" && input.id.trim() ? { id: input.id.trim() } : {},
|
|
4581
|
+
...typeof input.question === "string" && input.question.trim() ? { question: input.question.trim() } : {},
|
|
4582
|
+
...Array.isArray(input.choices) ? { choices: input.choices } : {}
|
|
4583
|
+
};
|
|
4584
|
+
}
|
|
4585
|
+
function normalizePlannerQuestions(input) {
|
|
4586
|
+
if (!Array.isArray(input))
|
|
4587
|
+
return [];
|
|
4588
|
+
const out = [];
|
|
4589
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4590
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
4591
|
+
const question = normalizePlannerQuestion(input[i], i);
|
|
4592
|
+
if (!question)
|
|
4593
|
+
continue;
|
|
4594
|
+
const key = `${question.key}::${question.query}`.toLowerCase();
|
|
4595
|
+
if (seen.has(key))
|
|
4596
|
+
continue;
|
|
4597
|
+
seen.add(key);
|
|
4598
|
+
out.push(question);
|
|
4599
|
+
}
|
|
4600
|
+
return out.slice(0, 6);
|
|
4601
|
+
}
|
|
4602
|
+
function questionToDisplayText(question) {
|
|
4603
|
+
return String(question.query || question.question || "").trim();
|
|
4604
|
+
}
|
|
4605
|
+
function normalizeAskUserAnswerMeta(raw, questions, fallbackText) {
|
|
4606
|
+
const validKeys = new Set(questions.map((question) => question.key));
|
|
4607
|
+
const answersByKey = {};
|
|
4608
|
+
if (raw?.answersByKey && typeof raw.answersByKey === "object") {
|
|
4609
|
+
for (const [key, value] of Object.entries(raw.answersByKey)) {
|
|
4610
|
+
if (!validKeys.has(key))
|
|
4611
|
+
continue;
|
|
4612
|
+
const normalizedValue = String(value || "").trim();
|
|
4613
|
+
if (!normalizedValue)
|
|
4614
|
+
continue;
|
|
4615
|
+
answersByKey[key] = normalizedValue;
|
|
4616
|
+
}
|
|
4617
|
+
}
|
|
4618
|
+
const fallback = String(fallbackText || "").trim();
|
|
4619
|
+
if (Object.keys(answersByKey).length === 0 && fallback) {
|
|
4620
|
+
if (questions.length === 1) {
|
|
4621
|
+
answersByKey[questions[0].key] = fallback;
|
|
4622
|
+
} else {
|
|
4623
|
+
const lines = fallback.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
4624
|
+
for (const line of lines) {
|
|
4625
|
+
const splitIndex = line.indexOf(":");
|
|
4626
|
+
if (splitIndex <= 0)
|
|
4627
|
+
continue;
|
|
4628
|
+
const key = line.slice(0, splitIndex).trim();
|
|
4629
|
+
const value = line.slice(splitIndex + 1).trim();
|
|
4630
|
+
if (!key || !value || !validKeys.has(key))
|
|
4631
|
+
continue;
|
|
4632
|
+
answersByKey[key] = value;
|
|
4633
|
+
}
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
const rawText = String(raw?.rawText || fallback || "").trim();
|
|
4637
|
+
if (!rawText && Object.keys(answersByKey).length === 0)
|
|
4638
|
+
return void 0;
|
|
4639
|
+
return { answersByKey, rawText };
|
|
4640
|
+
}
|
|
4641
|
+
function buildAskUserAnswerContext(questions, answers) {
|
|
4642
|
+
const lines = ["[ASK_USER_ANSWERS]"];
|
|
4643
|
+
for (const question of questions) {
|
|
4644
|
+
const answer = String(answers.answersByKey[question.key] || "").trim();
|
|
4645
|
+
lines.push(`${question.key}: ${answer || "(no answer provided)"}`);
|
|
4646
|
+
}
|
|
4647
|
+
if (answers.rawText) {
|
|
4648
|
+
lines.push("[RAW_USER_REPLY]");
|
|
4649
|
+
lines.push(answers.rawText);
|
|
4650
|
+
}
|
|
4651
|
+
return lines.join("\n");
|
|
4652
|
+
}
|
|
4442
4653
|
function buildPersistedState() {
|
|
4443
4654
|
const safePrevSteps = sanitizeAgentPrevStepsForPersist(Array.isArray(agentPrevSteps) ? agentPrevSteps : []);
|
|
4444
4655
|
return {
|
|
@@ -4446,7 +4657,12 @@ function buildPersistedState() {
|
|
|
4446
4657
|
history: sanitizeHistoryForPersist(history),
|
|
4447
4658
|
plannerHistory: sanitizePlannerHistoryForPersist(Array.isArray(plannerHistory) ? plannerHistory : []),
|
|
4448
4659
|
agentPrevSteps: safePrevSteps,
|
|
4449
|
-
lastToolPreviousSteps: safePrevSteps
|
|
4660
|
+
lastToolPreviousSteps: safePrevSteps,
|
|
4661
|
+
pendingAskUser: pendingAskUser ? {
|
|
4662
|
+
questions: normalizePlannerQuestions(pendingAskUser.questions),
|
|
4663
|
+
source: pendingAskUser.source,
|
|
4664
|
+
askedAt: Number(pendingAskUser.askedAt) || Date.now()
|
|
4665
|
+
} : void 0
|
|
4450
4666
|
};
|
|
4451
4667
|
}
|
|
4452
4668
|
function postStateSnapshot() {
|
|
@@ -4479,6 +4695,16 @@ function hydrateState(raw) {
|
|
|
4479
4695
|
} else if (Array.isArray(snapshot.lastToolPreviousSteps)) {
|
|
4480
4696
|
agentPrevSteps = sanitizeAgentPrevStepsForPersist(snapshot.lastToolPreviousSteps);
|
|
4481
4697
|
}
|
|
4698
|
+
const hydratedQuestions = normalizePlannerQuestions(snapshot.pendingAskUser?.questions);
|
|
4699
|
+
if (hydratedQuestions.length > 0) {
|
|
4700
|
+
pendingAskUser = {
|
|
4701
|
+
questions: hydratedQuestions,
|
|
4702
|
+
source: snapshot.pendingAskUser?.source === "planner" ? "planner" : "act",
|
|
4703
|
+
askedAt: Number(snapshot.pendingAskUser?.askedAt) || Date.now()
|
|
4704
|
+
};
|
|
4705
|
+
} else {
|
|
4706
|
+
pendingAskUser = void 0;
|
|
4707
|
+
}
|
|
4482
4708
|
if (typeof snapshot.trajectoryId === "string" && snapshot.trajectoryId.trim()) {
|
|
4483
4709
|
trajectoryId = snapshot.trajectoryId.trim();
|
|
4484
4710
|
}
|
|
@@ -4487,146 +4713,131 @@ function hydrateState(raw) {
|
|
|
4487
4713
|
}
|
|
4488
4714
|
postStateSnapshot();
|
|
4489
4715
|
}
|
|
4490
|
-
function
|
|
4491
|
-
if (
|
|
4492
|
-
return
|
|
4493
|
-
const
|
|
4494
|
-
const
|
|
4495
|
-
|
|
4496
|
-
return "";
|
|
4497
|
-
return clean.length <= max ? clean : `${clean.slice(0, max - 1)}\u2026`;
|
|
4498
|
-
}
|
|
4499
|
-
function formatInlineValue(value) {
|
|
4500
|
-
if (value == null)
|
|
4501
|
-
return "";
|
|
4502
|
-
if (typeof value === "string")
|
|
4503
|
-
return shortText(value, 200);
|
|
4504
|
-
if (typeof value === "number" || typeof value === "boolean")
|
|
4505
|
-
return String(value);
|
|
4506
|
-
if (Array.isArray(value))
|
|
4507
|
-
return `${value.length} item(s)`;
|
|
4508
|
-
if (typeof value === "object") {
|
|
4509
|
-
if (typeof value.message === "string")
|
|
4510
|
-
return shortText(value.message, 200);
|
|
4511
|
-
const keys = Object.keys(value);
|
|
4512
|
-
if (!keys.length)
|
|
4513
|
-
return "{}";
|
|
4514
|
-
return `{ ${keys.slice(0, 4).join(", ")}${keys.length > 4 ? ", \u2026" : ""} }`;
|
|
4515
|
-
}
|
|
4516
|
-
return shortText(value, 200);
|
|
4517
|
-
}
|
|
4518
|
-
function formatObjectBlock(value) {
|
|
4519
|
-
const preferredKeys = [
|
|
4520
|
-
"message",
|
|
4521
|
-
"summary",
|
|
4522
|
-
"status",
|
|
4523
|
-
"result",
|
|
4524
|
-
"url",
|
|
4525
|
-
"title",
|
|
4526
|
-
"name",
|
|
4527
|
-
"count",
|
|
4528
|
-
"total",
|
|
4529
|
-
"next_action"
|
|
4530
|
-
];
|
|
4531
|
-
const entries = Object.entries(value).filter(([, v]) => v !== void 0 && v !== null && !(typeof v === "string" && !v.trim()));
|
|
4532
|
-
if (!entries.length)
|
|
4533
|
-
return "";
|
|
4534
|
-
const sorted = entries.sort((a, b) => {
|
|
4535
|
-
const ai = preferredKeys.indexOf(a[0]);
|
|
4536
|
-
const bi = preferredKeys.indexOf(b[0]);
|
|
4537
|
-
const ar = ai === -1 ? preferredKeys.length : ai;
|
|
4538
|
-
const br = bi === -1 ? preferredKeys.length : bi;
|
|
4539
|
-
return ar - br;
|
|
4540
|
-
});
|
|
4541
|
-
const lines = [];
|
|
4542
|
-
const limit = 7;
|
|
4543
|
-
const CONTENT_KEYS = /* @__PURE__ */ new Set(["response", "message", "summary", "result", "output", "text", "content", "description"]);
|
|
4544
|
-
const URL_KEYS = /* @__PURE__ */ new Set(["url", "href", "link", "sheetUrl", "downloadUrl", "storageUrl"]);
|
|
4545
|
-
for (const [key, raw] of sorted.slice(0, limit)) {
|
|
4546
|
-
const isContent = CONTENT_KEYS.has(key);
|
|
4547
|
-
const isUrl = URL_KEYS.has(key) || typeof raw === "string" && /^https?:\/\/.+/.test(raw.trim());
|
|
4548
|
-
let rendered;
|
|
4549
|
-
if (typeof raw === "string" && isUrl) {
|
|
4550
|
-
const url = raw.trim();
|
|
4551
|
-
rendered = `[${url}](${url})`;
|
|
4552
|
-
} else if (typeof raw === "string" && isContent) {
|
|
4553
|
-
rendered = shortText(raw, 2e3);
|
|
4554
|
-
} else {
|
|
4555
|
-
rendered = formatInlineValue(raw);
|
|
4556
|
-
}
|
|
4557
|
-
if (!rendered)
|
|
4558
|
-
continue;
|
|
4559
|
-
lines.push(`**${key}:** ${rendered}`);
|
|
4560
|
-
}
|
|
4561
|
-
if (sorted.length > limit) {
|
|
4562
|
-
lines.push(`\u2026 ${sorted.length - limit} more field(s)`);
|
|
4563
|
-
}
|
|
4564
|
-
return lines.join("\n");
|
|
4565
|
-
}
|
|
4566
|
-
function formatArrayBlock(value) {
|
|
4567
|
-
if (!value.length)
|
|
4568
|
-
return "";
|
|
4569
|
-
const lines = [];
|
|
4570
|
-
const limit = 6;
|
|
4571
|
-
for (const item of value.slice(0, limit)) {
|
|
4572
|
-
if (typeof item === "string") {
|
|
4573
|
-
const text = shortText(item, 260);
|
|
4574
|
-
if (text)
|
|
4575
|
-
lines.push(`- ${text}`);
|
|
4716
|
+
function sanitizeAssistantBlocks(input) {
|
|
4717
|
+
if (!Array.isArray(input))
|
|
4718
|
+
return void 0;
|
|
4719
|
+
const out = [];
|
|
4720
|
+
for (const raw of input) {
|
|
4721
|
+
if (!raw || typeof raw !== "object")
|
|
4576
4722
|
continue;
|
|
4577
|
-
|
|
4578
|
-
if (
|
|
4579
|
-
const
|
|
4580
|
-
if (
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
lines.push(block);
|
|
4584
|
-
}
|
|
4723
|
+
const type = raw.type;
|
|
4724
|
+
if (type === "text") {
|
|
4725
|
+
const text = String(raw.text || "").trim();
|
|
4726
|
+
if (!text)
|
|
4727
|
+
continue;
|
|
4728
|
+
out.push({ type: "text", text });
|
|
4585
4729
|
continue;
|
|
4586
4730
|
}
|
|
4587
|
-
if (
|
|
4588
|
-
|
|
4731
|
+
if (type === "tool_output" || type === "json") {
|
|
4732
|
+
out.push({
|
|
4733
|
+
type,
|
|
4734
|
+
data: cloneUnknown(raw.data),
|
|
4735
|
+
label: typeof raw.label === "string" ? raw.label : void 0,
|
|
4736
|
+
toolName: typeof raw.toolName === "string" ? raw.toolName : void 0
|
|
4737
|
+
});
|
|
4589
4738
|
}
|
|
4590
4739
|
}
|
|
4591
|
-
|
|
4592
|
-
lines.push(`- \u2026 ${value.length - limit} more item(s)`);
|
|
4593
|
-
}
|
|
4594
|
-
return lines.join("\n");
|
|
4740
|
+
return out.length ? out : void 0;
|
|
4595
4741
|
}
|
|
4596
|
-
function
|
|
4742
|
+
function summarizeOutputText(output) {
|
|
4597
4743
|
if (output == null)
|
|
4598
|
-
return
|
|
4744
|
+
return void 0;
|
|
4599
4745
|
if (typeof output === "string") {
|
|
4600
4746
|
const clean = output.trim();
|
|
4601
|
-
return clean
|
|
4747
|
+
return clean || void 0;
|
|
4602
4748
|
}
|
|
4603
4749
|
if (typeof output === "number" || typeof output === "boolean") {
|
|
4604
4750
|
return String(output);
|
|
4605
4751
|
}
|
|
4606
4752
|
if (Array.isArray(output)) {
|
|
4607
|
-
const
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
}
|
|
4618
|
-
const block = formatObjectBlock(output);
|
|
4619
|
-
if (block)
|
|
4620
|
-
return truncateText(block, 12e3);
|
|
4753
|
+
const lines = [];
|
|
4754
|
+
for (const item of output.slice(0, 4)) {
|
|
4755
|
+
const candidate = summarizeOutputText(item);
|
|
4756
|
+
if (candidate)
|
|
4757
|
+
lines.push(candidate);
|
|
4758
|
+
if (lines.length >= 3)
|
|
4759
|
+
break;
|
|
4760
|
+
}
|
|
4761
|
+
if (lines.length)
|
|
4762
|
+
return lines.join("\n");
|
|
4763
|
+
return `Received ${output.length} item(s).`;
|
|
4621
4764
|
}
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4765
|
+
if (typeof output === "object") {
|
|
4766
|
+
const preferredKeys = ["response", "message", "summary", "text", "content", "result", "description"];
|
|
4767
|
+
for (const key of preferredKeys) {
|
|
4768
|
+
const value = output[key];
|
|
4769
|
+
if (typeof value === "string" && value.trim()) {
|
|
4770
|
+
return value.trim();
|
|
4771
|
+
}
|
|
4772
|
+
}
|
|
4773
|
+
const keys = Object.keys(output);
|
|
4774
|
+
if (!keys.length)
|
|
4775
|
+
return void 0;
|
|
4776
|
+
return `Received ${keys.length} field(s).`;
|
|
4626
4777
|
}
|
|
4778
|
+
return void 0;
|
|
4627
4779
|
}
|
|
4628
|
-
function
|
|
4629
|
-
|
|
4780
|
+
function isSingleTextWrapperObject(value) {
|
|
4781
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
4782
|
+
return false;
|
|
4783
|
+
const entries = Object.entries(value).filter(([, v]) => v !== void 0 && v !== null);
|
|
4784
|
+
if (entries.length !== 1)
|
|
4785
|
+
return false;
|
|
4786
|
+
const [key, raw] = entries[0];
|
|
4787
|
+
if (typeof raw !== "string" || !raw.trim())
|
|
4788
|
+
return false;
|
|
4789
|
+
const textKeys = /* @__PURE__ */ new Set(["response", "message", "summary", "text", "content", "result", "description"]);
|
|
4790
|
+
return textKeys.has(key);
|
|
4791
|
+
}
|
|
4792
|
+
function shouldAttachStructuredBlock(output, summaryText) {
|
|
4793
|
+
if (output == null)
|
|
4794
|
+
return false;
|
|
4795
|
+
if (typeof output === "string") {
|
|
4796
|
+
const clean = output.trim();
|
|
4797
|
+
if (!clean)
|
|
4798
|
+
return false;
|
|
4799
|
+
return !summaryText || clean !== summaryText.trim();
|
|
4800
|
+
}
|
|
4801
|
+
if (Array.isArray(output)) {
|
|
4802
|
+
const meaningful = output.filter((item) => item !== void 0 && item !== null);
|
|
4803
|
+
if (meaningful.length === 1) {
|
|
4804
|
+
const first = meaningful[0];
|
|
4805
|
+
if (typeof first === "string" || typeof first === "number" || typeof first === "boolean") {
|
|
4806
|
+
return false;
|
|
4807
|
+
}
|
|
4808
|
+
if (isSingleTextWrapperObject(first)) {
|
|
4809
|
+
return false;
|
|
4810
|
+
}
|
|
4811
|
+
}
|
|
4812
|
+
return true;
|
|
4813
|
+
}
|
|
4814
|
+
if (isSingleTextWrapperObject(output)) {
|
|
4815
|
+
return false;
|
|
4816
|
+
}
|
|
4817
|
+
return true;
|
|
4818
|
+
}
|
|
4819
|
+
function buildAssistantPayloadFromToolOutput(output, options) {
|
|
4820
|
+
const summaryText = summarizeOutputText(output);
|
|
4821
|
+
const text = summaryText || options?.fallbackText || "Done.";
|
|
4822
|
+
const blocks = [];
|
|
4823
|
+
if (shouldAttachStructuredBlock(output, summaryText)) {
|
|
4824
|
+
blocks.push({
|
|
4825
|
+
type: "tool_output",
|
|
4826
|
+
label: options?.label,
|
|
4827
|
+
toolName: options?.toolName,
|
|
4828
|
+
data: cloneUnknown(output)
|
|
4829
|
+
});
|
|
4830
|
+
}
|
|
4831
|
+
return { text, blocks: blocks.length ? blocks : void 0 };
|
|
4832
|
+
}
|
|
4833
|
+
function postAssistantMessage(payload) {
|
|
4834
|
+
const text = typeof payload === "string" ? String(payload || "").trim() : String(payload?.text || "").trim();
|
|
4835
|
+
const blocks = typeof payload === "string" ? void 0 : sanitizeAssistantBlocks(payload.blocks);
|
|
4836
|
+
const firstTextBlock = blocks?.find((block) => block.type === "text");
|
|
4837
|
+
const firstStructuredBlock = blocks?.find((block) => block.type === "tool_output" || block.type === "json");
|
|
4838
|
+
const resolvedText = text || firstTextBlock?.text || summarizeOutputText(firstStructuredBlock?.data) || "Done.";
|
|
4839
|
+
self.postMessage({ type: "assistant", text: resolvedText, blocks, runId: activeRun?.runId });
|
|
4840
|
+
return resolvedText;
|
|
4630
4841
|
}
|
|
4631
4842
|
function dedupeFunctionDeclarations(declarations) {
|
|
4632
4843
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -4664,11 +4875,6 @@ function toStructuredErrorPayload(err, fallbackMessage = "Operation failed") {
|
|
|
4664
4875
|
};
|
|
4665
4876
|
return payload;
|
|
4666
4877
|
}
|
|
4667
|
-
function formatStructuredErrorForAssistant(payload) {
|
|
4668
|
-
const summary = `${payload.error.code}: ${payload.error.message}`;
|
|
4669
|
-
return `${summary}
|
|
4670
|
-
${JSON.stringify(payload, null, 2)}`;
|
|
4671
|
-
}
|
|
4672
4878
|
function extractStructuredErrorFromToolResult(result) {
|
|
4673
4879
|
if (!result || typeof result !== "object")
|
|
4674
4880
|
return void 0;
|
|
@@ -4711,25 +4917,13 @@ function maybePostNavigationGuardrailFromToolResult(toolResult) {
|
|
|
4711
4917
|
});
|
|
4712
4918
|
}
|
|
4713
4919
|
function buildChatLogFromHistory(input, currentUserInput) {
|
|
4714
|
-
const sanitizeChatText = (raw
|
|
4715
|
-
|
|
4716
|
-
if (!text)
|
|
4717
|
-
return "";
|
|
4718
|
-
if (role === "assistant") {
|
|
4719
|
-
if (/^\w[\w_]*:\s*\{/.test(text) || /^\[error\]/i.test(text) || /"success":\s*false/.test(text)) {
|
|
4720
|
-
const firstSentence = text.split(/(?<=\.)\s+/)[0] || text;
|
|
4721
|
-
text = firstSentence.trim();
|
|
4722
|
-
}
|
|
4723
|
-
}
|
|
4724
|
-
if (text.length > MAX_CHATLOG_MESSAGE_CHARS2) {
|
|
4725
|
-
text = `${text.slice(0, MAX_CHATLOG_MESSAGE_CHARS2 - 1)}\u2026`;
|
|
4726
|
-
}
|
|
4727
|
-
return text;
|
|
4920
|
+
const sanitizeChatText = (raw) => {
|
|
4921
|
+
return String(raw || "").replace(/\s+/g, " ").trim();
|
|
4728
4922
|
};
|
|
4729
|
-
const normalizedCurrentUserInput = currentUserInput ? sanitizeChatText(currentUserInput
|
|
4923
|
+
const normalizedCurrentUserInput = currentUserInput ? sanitizeChatText(currentUserInput) : "";
|
|
4730
4924
|
const entries = input.filter((message) => message.role === "user" || message.role === "assistant").map((message) => ({
|
|
4731
4925
|
role: message.role,
|
|
4732
|
-
content: sanitizeChatText(String(message.content || "")
|
|
4926
|
+
content: sanitizeChatText(String(message.content || ""))
|
|
4733
4927
|
})).filter((message) => !!message.content);
|
|
4734
4928
|
if (normalizedCurrentUserInput) {
|
|
4735
4929
|
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
@@ -4746,11 +4940,25 @@ function buildChatLogFromHistory(input, currentUserInput) {
|
|
|
4746
4940
|
continue;
|
|
4747
4941
|
deduped.push(entry);
|
|
4748
4942
|
}
|
|
4749
|
-
const
|
|
4750
|
-
|
|
4751
|
-
|
|
4943
|
+
const firstUser = deduped.find((message) => message.role === "user");
|
|
4944
|
+
const tailBudget = firstUser ? Math.max(1, MAX_CHATLOG_ENTRIES2 - 1) : MAX_CHATLOG_ENTRIES2;
|
|
4945
|
+
let selected = deduped.slice(-tailBudget);
|
|
4946
|
+
if (firstUser) {
|
|
4947
|
+
const hasAnchor = selected.some((message) => message.role === "user" && message.content === firstUser.content);
|
|
4948
|
+
if (!hasAnchor) {
|
|
4949
|
+
selected = [firstUser, ...selected];
|
|
4950
|
+
}
|
|
4951
|
+
}
|
|
4952
|
+
if (selected.length > MAX_CHATLOG_ENTRIES2) {
|
|
4953
|
+
selected = selected.slice(-MAX_CHATLOG_ENTRIES2);
|
|
4752
4954
|
}
|
|
4753
|
-
|
|
4955
|
+
if (selected.length > 1 && selected[0]?.role !== "user") {
|
|
4956
|
+
const firstUserIndex = selected.findIndex((message) => message.role === "user");
|
|
4957
|
+
if (firstUserIndex > 0) {
|
|
4958
|
+
selected = selected.slice(firstUserIndex);
|
|
4959
|
+
}
|
|
4960
|
+
}
|
|
4961
|
+
return selected.map((message) => ({
|
|
4754
4962
|
role: message.role === "user" ? "user" : "model",
|
|
4755
4963
|
message: message.content
|
|
4756
4964
|
}));
|
|
@@ -4799,33 +5007,65 @@ function extractArtifactLinks(toolResult) {
|
|
|
4799
5007
|
}
|
|
4800
5008
|
return links;
|
|
4801
5009
|
}
|
|
4802
|
-
function
|
|
4803
|
-
if (!Array.isArray(toolResults) || toolResults.length
|
|
4804
|
-
return
|
|
4805
|
-
const
|
|
5010
|
+
function buildPlannerToolResultBlocks(toolResults) {
|
|
5011
|
+
if (!Array.isArray(toolResults) || !toolResults.length)
|
|
5012
|
+
return void 0;
|
|
5013
|
+
const blocks = [];
|
|
4806
5014
|
for (let i = 0; i < toolResults.length; i += 1) {
|
|
4807
5015
|
const result = toolResults[i];
|
|
4808
5016
|
if (!result)
|
|
4809
5017
|
continue;
|
|
5018
|
+
const stepLabel = `Step ${i + 1}`;
|
|
4810
5019
|
const output = result.output ?? result.generatedContentRef ?? result.schemaHeaderSheetInfo;
|
|
4811
|
-
const
|
|
5020
|
+
const summary = summarizeOutputText(output);
|
|
5021
|
+
if (output !== void 0 && shouldAttachStructuredBlock(output, summary)) {
|
|
5022
|
+
blocks.push({
|
|
5023
|
+
type: "tool_output",
|
|
5024
|
+
label: result.toolName ? `${stepLabel}: ${result.toolName}` : stepLabel,
|
|
5025
|
+
toolName: typeof result.toolName === "string" ? result.toolName : void 0,
|
|
5026
|
+
data: cloneUnknown(output)
|
|
5027
|
+
});
|
|
5028
|
+
}
|
|
5029
|
+
if (result.error || result.errorDetails) {
|
|
5030
|
+
blocks.push({
|
|
5031
|
+
type: "json",
|
|
5032
|
+
label: `${stepLabel} error`,
|
|
5033
|
+
data: cloneUnknown({
|
|
5034
|
+
error: result.error,
|
|
5035
|
+
errorDetails: result.errorDetails
|
|
5036
|
+
})
|
|
5037
|
+
});
|
|
5038
|
+
}
|
|
4812
5039
|
const links = extractArtifactLinks(result);
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
5040
|
+
if (links.length) {
|
|
5041
|
+
blocks.push({
|
|
5042
|
+
type: "text",
|
|
5043
|
+
text: `${stepLabel} artifacts:
|
|
5044
|
+
${links.map((link) => `- ${link}`).join("\n")}`
|
|
5045
|
+
});
|
|
5046
|
+
}
|
|
5047
|
+
}
|
|
5048
|
+
return blocks.length ? blocks : void 0;
|
|
5049
|
+
}
|
|
5050
|
+
function summarizePlannerToolResults(toolResults) {
|
|
5051
|
+
if (!Array.isArray(toolResults) || !toolResults.length)
|
|
5052
|
+
return void 0;
|
|
5053
|
+
const lines = [];
|
|
5054
|
+
for (let i = 0; i < toolResults.length; i += 1) {
|
|
5055
|
+
const result = toolResults[i];
|
|
5056
|
+
if (!result)
|
|
4822
5057
|
continue;
|
|
4823
|
-
|
|
4824
|
-
|
|
5058
|
+
const output = result.output ?? result.generatedContentRef ?? result.schemaHeaderSheetInfo;
|
|
5059
|
+
const summary = summarizeOutputText(output);
|
|
5060
|
+
if (summary) {
|
|
5061
|
+
lines.push(summary);
|
|
5062
|
+
if (lines.length >= 3)
|
|
5063
|
+
break;
|
|
5064
|
+
}
|
|
4825
5065
|
}
|
|
4826
|
-
if (!
|
|
4827
|
-
return
|
|
4828
|
-
return
|
|
5066
|
+
if (!lines.length)
|
|
5067
|
+
return void 0;
|
|
5068
|
+
return lines.join("\n\n");
|
|
4829
5069
|
}
|
|
4830
5070
|
function extractLatestPrevStepsFromPlanner(toolResults) {
|
|
4831
5071
|
if (!Array.isArray(toolResults) || !toolResults.length)
|
|
@@ -4871,16 +5111,48 @@ function detectOpenedTabFromToolResult(result) {
|
|
|
4871
5111
|
}
|
|
4872
5112
|
return void 0;
|
|
4873
5113
|
}
|
|
5114
|
+
function extractQuestionsFromResult(result) {
|
|
5115
|
+
if (!result || typeof result !== "object")
|
|
5116
|
+
return void 0;
|
|
5117
|
+
const topLevel = normalizePlannerQuestions(result.questions);
|
|
5118
|
+
if (topLevel.length)
|
|
5119
|
+
return topLevel;
|
|
5120
|
+
const output = result.output;
|
|
5121
|
+
const outputQuestions = normalizePlannerQuestions(output?.questions);
|
|
5122
|
+
if (outputQuestions.length)
|
|
5123
|
+
return outputQuestions;
|
|
5124
|
+
return void 0;
|
|
5125
|
+
}
|
|
5126
|
+
function extractPlannerQuestionsFromToolResults(toolResults) {
|
|
5127
|
+
if (!Array.isArray(toolResults) || toolResults.length === 0)
|
|
5128
|
+
return [];
|
|
5129
|
+
const combined = [];
|
|
5130
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5131
|
+
for (const toolResult of toolResults) {
|
|
5132
|
+
const questions = extractQuestionsFromResult(toolResult);
|
|
5133
|
+
if (!questions || !questions.length)
|
|
5134
|
+
continue;
|
|
5135
|
+
for (const question of questions) {
|
|
5136
|
+
const key = `${question.key}::${question.query}`.toLowerCase();
|
|
5137
|
+
if (seen.has(key))
|
|
5138
|
+
continue;
|
|
5139
|
+
seen.add(key);
|
|
5140
|
+
combined.push(question);
|
|
5141
|
+
}
|
|
5142
|
+
}
|
|
5143
|
+
return combined.slice(0, 6);
|
|
5144
|
+
}
|
|
4874
5145
|
function deriveDirectToolRunOutcome(result) {
|
|
4875
5146
|
if (!result || typeof result !== "object") {
|
|
4876
5147
|
return { taskComplete: false };
|
|
4877
5148
|
}
|
|
5149
|
+
const questions = extractQuestionsFromResult(result);
|
|
4878
5150
|
const topLevelStatus = String(result.status || "").trim().toLowerCase();
|
|
4879
5151
|
if (topLevelStatus === "failure" || topLevelStatus === "failed" || topLevelStatus === "error") {
|
|
4880
5152
|
return { taskComplete: false };
|
|
4881
5153
|
}
|
|
4882
5154
|
if (topLevelStatus === "waiting_input" || topLevelStatus === "needs_input" || topLevelStatus === "pending_user_input") {
|
|
4883
|
-
return { taskComplete: false, needsUserInput: true };
|
|
5155
|
+
return { taskComplete: false, needsUserInput: true, questions };
|
|
4884
5156
|
}
|
|
4885
5157
|
if (result.error) {
|
|
4886
5158
|
return { taskComplete: false };
|
|
@@ -4891,10 +5163,10 @@ function deriveDirectToolRunOutcome(result) {
|
|
|
4891
5163
|
return { taskComplete: true };
|
|
4892
5164
|
}
|
|
4893
5165
|
if (output.needsUserInput === true || output.waitingForUserInput === true) {
|
|
4894
|
-
return { taskComplete: false, needsUserInput: true };
|
|
5166
|
+
return { taskComplete: false, needsUserInput: true, questions };
|
|
4895
5167
|
}
|
|
4896
5168
|
if (Array.isArray(output.questions) && output.questions.length > 0) {
|
|
4897
|
-
return { taskComplete: false, needsUserInput: true };
|
|
5169
|
+
return { taskComplete: false, needsUserInput: true, questions };
|
|
4898
5170
|
}
|
|
4899
5171
|
if (output.error) {
|
|
4900
5172
|
return { taskComplete: false };
|
|
@@ -4927,7 +5199,7 @@ function deriveDirectToolRunOutcome(result) {
|
|
|
4927
5199
|
if (output != null) {
|
|
4928
5200
|
return { taskComplete: true };
|
|
4929
5201
|
}
|
|
4930
|
-
return { taskComplete:
|
|
5202
|
+
return { taskComplete: true };
|
|
4931
5203
|
}
|
|
4932
5204
|
function normalizeRunOutcome(outcome) {
|
|
4933
5205
|
if (!outcome || typeof outcome !== "object") {
|
|
@@ -4935,16 +5207,37 @@ function normalizeRunOutcome(outcome) {
|
|
|
4935
5207
|
}
|
|
4936
5208
|
const needsUserInput = outcome.needsUserInput === true;
|
|
4937
5209
|
const taskComplete = outcome.taskComplete === true && !needsUserInput;
|
|
5210
|
+
const questions = normalizePlannerQuestions(outcome.questions);
|
|
4938
5211
|
return {
|
|
4939
5212
|
route: outcome.route,
|
|
4940
5213
|
taskComplete,
|
|
4941
|
-
needsUserInput
|
|
5214
|
+
needsUserInput,
|
|
5215
|
+
questions: questions.length ? questions : void 0
|
|
4942
5216
|
};
|
|
4943
5217
|
}
|
|
5218
|
+
function rememberTerminalRun(runId, result) {
|
|
5219
|
+
terminalRuns.set(runId, result);
|
|
5220
|
+
while (terminalRuns.size > 80) {
|
|
5221
|
+
const oldest = terminalRuns.keys().next().value;
|
|
5222
|
+
if (!oldest)
|
|
5223
|
+
break;
|
|
5224
|
+
terminalRuns.delete(oldest);
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
function rememberCancelledRun(runId) {
|
|
5228
|
+
cancelledRunIds.add(runId);
|
|
5229
|
+
while (cancelledRunIds.size > 80) {
|
|
5230
|
+
const oldest = cancelledRunIds.values().next().value;
|
|
5231
|
+
if (!oldest)
|
|
5232
|
+
break;
|
|
5233
|
+
cancelledRunIds.delete(oldest);
|
|
5234
|
+
}
|
|
5235
|
+
}
|
|
4944
5236
|
function clearTaskScopedContextAfterCompletion() {
|
|
4945
5237
|
history.length = 0;
|
|
4946
5238
|
plannerHistory = [];
|
|
4947
5239
|
agentPrevSteps = [];
|
|
5240
|
+
pendingAskUser = void 0;
|
|
4948
5241
|
}
|
|
4949
5242
|
async function maybeWaitForNewTab(result) {
|
|
4950
5243
|
const logicalTabId = detectOpenedTabFromToolResult(result);
|
|
@@ -4964,6 +5257,34 @@ async function handleUserMessage(text, options) {
|
|
|
4964
5257
|
history.push({ role: "user", content: text });
|
|
4965
5258
|
postStateSnapshot();
|
|
4966
5259
|
}
|
|
5260
|
+
let effectiveUserInput = text;
|
|
5261
|
+
if (pendingAskUser?.questions?.length) {
|
|
5262
|
+
const normalizedAnswers = normalizeAskUserAnswerMeta(options?.askUserAnswers, pendingAskUser.questions, text);
|
|
5263
|
+
if (normalizedAnswers) {
|
|
5264
|
+
const answerContext = buildAskUserAnswerContext(pendingAskUser.questions, normalizedAnswers);
|
|
5265
|
+
effectiveUserInput = answerContext;
|
|
5266
|
+
plannerHistory = sanitizePlannerHistoryForPersist([
|
|
5267
|
+
...plannerHistory,
|
|
5268
|
+
{
|
|
5269
|
+
thought: "User provided clarification answers.",
|
|
5270
|
+
questionsAsked: pendingAskUser.questions,
|
|
5271
|
+
userAnswers: normalizedAnswers.answersByKey
|
|
5272
|
+
}
|
|
5273
|
+
]);
|
|
5274
|
+
applyAgentPrevSteps([
|
|
5275
|
+
...agentPrevSteps,
|
|
5276
|
+
{
|
|
5277
|
+
thought: "User provided clarification answers.",
|
|
5278
|
+
data: JSON.stringify({
|
|
5279
|
+
ask_user_answers: normalizedAnswers.answersByKey,
|
|
5280
|
+
raw_user_reply: normalizedAnswers.rawText
|
|
5281
|
+
})
|
|
5282
|
+
}
|
|
5283
|
+
], { snapshot: false });
|
|
5284
|
+
pendingAskUser = void 0;
|
|
5285
|
+
postStateSnapshot();
|
|
5286
|
+
}
|
|
5287
|
+
}
|
|
4967
5288
|
const tabs = await getKnownTabs();
|
|
4968
5289
|
const fallbackTabs = tabs.length > 0 ? tabs : [
|
|
4969
5290
|
{
|
|
@@ -5010,7 +5331,7 @@ async function handleUserMessage(text, options) {
|
|
|
5010
5331
|
}
|
|
5011
5332
|
}, bridgeRpc, tabularStore);
|
|
5012
5333
|
const currentRunId = activeRun?.runId;
|
|
5013
|
-
ctx.isCancelled = () =>
|
|
5334
|
+
ctx.isCancelled = () => !!(currentRunId && cancelledRunIds.has(currentRunId));
|
|
5014
5335
|
const functionDeclarations = dedupeFunctionDeclarations(removePlannerNameCollisions(toolRegistry.getFunctionDeclarations()));
|
|
5015
5336
|
const toolFunctions = toolRegistry.getToolFunctions();
|
|
5016
5337
|
const chatLog = buildChatLogFromHistory(history, text);
|
|
@@ -5021,7 +5342,7 @@ async function handleUserMessage(text, options) {
|
|
|
5021
5342
|
plannerHistory = sanitizePlannerHistoryForPersist(Array.isArray(steps) ? steps : []);
|
|
5022
5343
|
postStateSnapshot();
|
|
5023
5344
|
};
|
|
5024
|
-
const result = await handleSendMessageWithFunctions(
|
|
5345
|
+
const result = await handleSendMessageWithFunctions(effectiveUserInput, {
|
|
5025
5346
|
tabs: tabsForRun,
|
|
5026
5347
|
previousMessages: history,
|
|
5027
5348
|
trajectoryId,
|
|
@@ -5035,7 +5356,7 @@ async function handleUserMessage(text, options) {
|
|
|
5035
5356
|
chatLog
|
|
5036
5357
|
},
|
|
5037
5358
|
lastToolPreviousSteps: agentPrevSteps,
|
|
5038
|
-
taskRouting: config.taskRouting,
|
|
5359
|
+
taskRouting: options?.routing ? { ...config.taskRouting, mode: options.routing } : config.taskRouting,
|
|
5039
5360
|
ctx,
|
|
5040
5361
|
bridgeRpc,
|
|
5041
5362
|
functionDeclarations,
|
|
@@ -5047,8 +5368,16 @@ async function handleUserMessage(text, options) {
|
|
|
5047
5368
|
if (errorPayload.error.requires_api_key) {
|
|
5048
5369
|
postAuthRequired(errorPayload.error);
|
|
5049
5370
|
}
|
|
5050
|
-
const errorMsg =
|
|
5051
|
-
|
|
5371
|
+
const errorMsg = postAssistantMessage({
|
|
5372
|
+
text: `${errorPayload.error.code}: ${errorPayload.error.message}`,
|
|
5373
|
+
blocks: [
|
|
5374
|
+
{
|
|
5375
|
+
type: "json",
|
|
5376
|
+
label: "Error details",
|
|
5377
|
+
data: cloneUnknown(errorPayload)
|
|
5378
|
+
}
|
|
5379
|
+
]
|
|
5380
|
+
});
|
|
5052
5381
|
history.push({ role: "assistant", content: errorMsg });
|
|
5053
5382
|
postStatus("Execution failed", errorPayload.error.message, "complete");
|
|
5054
5383
|
postStateSnapshot();
|
|
@@ -5058,12 +5387,31 @@ async function handleUserMessage(text, options) {
|
|
|
5058
5387
|
for (const fn of result.executedFunctions) {
|
|
5059
5388
|
applyAgentPrevSteps(fn.prevSteps, { snapshot: false });
|
|
5060
5389
|
}
|
|
5061
|
-
const
|
|
5062
|
-
|
|
5063
|
-
|
|
5390
|
+
const blocks = [];
|
|
5391
|
+
const lines = [];
|
|
5392
|
+
for (const fn of result.executedFunctions) {
|
|
5393
|
+
const summary = summarizeOutputText(fn.result);
|
|
5394
|
+
if (fn.result !== void 0 && shouldAttachStructuredBlock(fn.result, summary)) {
|
|
5395
|
+
blocks.push({
|
|
5396
|
+
type: "tool_output",
|
|
5397
|
+
toolName: fn.name,
|
|
5398
|
+
label: `${fn.name} output`,
|
|
5399
|
+
data: cloneUnknown(fn.result)
|
|
5400
|
+
});
|
|
5401
|
+
}
|
|
5402
|
+
if (fn.error) {
|
|
5403
|
+
blocks.push({
|
|
5404
|
+
type: "json",
|
|
5405
|
+
label: `${fn.name} error`,
|
|
5406
|
+
data: cloneUnknown({ error: fn.error })
|
|
5407
|
+
});
|
|
5408
|
+
}
|
|
5409
|
+
lines.push(summary ? `@${fn.name}: ${summary}` : `@${fn.name}: ${fn.error || "ok"}`);
|
|
5410
|
+
}
|
|
5411
|
+
const msg = postAssistantMessage({
|
|
5412
|
+
text: lines.join("\n") || "Done.",
|
|
5413
|
+
blocks
|
|
5064
5414
|
});
|
|
5065
|
-
const msg = lines.join("\n");
|
|
5066
|
-
postAssistantMessage(msg);
|
|
5067
5415
|
history.push({ role: "assistant", content: msg });
|
|
5068
5416
|
postStatus("Execution completed", "Function calls finished", "complete");
|
|
5069
5417
|
postStateSnapshot();
|
|
@@ -5074,55 +5422,121 @@ async function handleUserMessage(text, options) {
|
|
|
5074
5422
|
postStatus("Verifying result", void 0, "verify");
|
|
5075
5423
|
maybePostNavigationGuardrailFromToolResult(result.directToolResult);
|
|
5076
5424
|
applyAgentPrevSteps(result.directToolResult.prevSteps, { snapshot: false });
|
|
5425
|
+
const outcome = deriveDirectToolRunOutcome(result.directToolResult);
|
|
5426
|
+
const questions = normalizePlannerQuestions(outcome.questions);
|
|
5427
|
+
if (outcome.needsUserInput && questions.length > 0) {
|
|
5428
|
+
pendingAskUser = {
|
|
5429
|
+
questions,
|
|
5430
|
+
source: "act",
|
|
5431
|
+
askedAt: Date.now()
|
|
5432
|
+
};
|
|
5433
|
+
plannerHistory = sanitizePlannerHistoryForPersist([
|
|
5434
|
+
...plannerHistory,
|
|
5435
|
+
{
|
|
5436
|
+
thought: "Need user clarification before continuing act workflow.",
|
|
5437
|
+
questionsAsked: questions
|
|
5438
|
+
}
|
|
5439
|
+
]);
|
|
5440
|
+
const qText = questions.map((question) => `- ${question.key}: ${questionToDisplayText(question)}`).join("\n");
|
|
5441
|
+
const msg2 = postAssistantMessage(`I need a bit more info before continuing:
|
|
5442
|
+
${qText}`);
|
|
5443
|
+
history.push({ role: "assistant", content: msg2 });
|
|
5444
|
+
postStatus("Need more input to continue", void 0, "verify");
|
|
5445
|
+
postStateSnapshot();
|
|
5446
|
+
return {
|
|
5447
|
+
route: result.route,
|
|
5448
|
+
taskComplete: false,
|
|
5449
|
+
needsUserInput: true,
|
|
5450
|
+
questions
|
|
5451
|
+
};
|
|
5452
|
+
}
|
|
5453
|
+
pendingAskUser = void 0;
|
|
5077
5454
|
const output = result.directToolResult.output ?? result.directToolResult.generatedContentRef ?? result.directToolResult.schemaHeaderSheetInfo;
|
|
5078
|
-
const formattedOutput = output ? formatToolOutput(output) : null;
|
|
5079
5455
|
const structuredError = extractStructuredErrorFromToolResult(result.directToolResult);
|
|
5080
5456
|
if (structuredError?.error.requires_api_key) {
|
|
5081
5457
|
postAuthRequired(structuredError.error);
|
|
5082
5458
|
}
|
|
5083
|
-
const msg = structuredError ?
|
|
5084
|
-
|
|
5459
|
+
const msg = structuredError ? postAssistantMessage({
|
|
5460
|
+
text: `${structuredError.error.code}: ${structuredError.error.message}`,
|
|
5461
|
+
blocks: [
|
|
5462
|
+
{
|
|
5463
|
+
type: "json",
|
|
5464
|
+
label: "Error details",
|
|
5465
|
+
data: cloneUnknown(structuredError)
|
|
5466
|
+
}
|
|
5467
|
+
]
|
|
5468
|
+
}) : postAssistantMessage(buildAssistantPayloadFromToolOutput(output, {
|
|
5469
|
+
label: "Tool output",
|
|
5470
|
+
fallbackText: "Done."
|
|
5471
|
+
}));
|
|
5085
5472
|
history.push({ role: "assistant", content: msg });
|
|
5086
5473
|
postStatus("Execution completed", structuredError?.error.message, "complete");
|
|
5087
5474
|
postStateSnapshot();
|
|
5088
|
-
const outcome = deriveDirectToolRunOutcome(result.directToolResult);
|
|
5089
5475
|
return {
|
|
5090
5476
|
route: result.route,
|
|
5091
5477
|
taskComplete: outcome.taskComplete,
|
|
5092
|
-
needsUserInput: outcome.needsUserInput
|
|
5478
|
+
needsUserInput: outcome.needsUserInput,
|
|
5479
|
+
questions: normalizePlannerQuestions(outcome.questions)
|
|
5093
5480
|
};
|
|
5094
5481
|
}
|
|
5095
5482
|
if (result.plannerResponse) {
|
|
5096
5483
|
postStatus("Verifying planner output", void 0, "verify");
|
|
5097
5484
|
const response = result.plannerResponse.response;
|
|
5485
|
+
const toolResults = result.plannerResponse.toolResults || [];
|
|
5098
5486
|
if (result.plannerResponse.previousSteps) {
|
|
5099
5487
|
plannerHistory = result.plannerResponse.previousSteps;
|
|
5100
5488
|
postStateSnapshot();
|
|
5101
5489
|
}
|
|
5102
|
-
const latestToolPrevSteps = extractLatestPrevStepsFromPlanner(
|
|
5490
|
+
const latestToolPrevSteps = extractLatestPrevStepsFromPlanner(toolResults);
|
|
5103
5491
|
applyAgentPrevSteps(latestToolPrevSteps, { snapshot: false });
|
|
5104
|
-
|
|
5105
|
-
|
|
5492
|
+
const responseQuestions = normalizePlannerQuestions(response.questions);
|
|
5493
|
+
const fallbackQuestions = responseQuestions.length ? [] : extractPlannerQuestionsFromToolResults(toolResults);
|
|
5494
|
+
const plannerQuestions = responseQuestions.length ? responseQuestions : fallbackQuestions;
|
|
5495
|
+
if (plannerQuestions.length) {
|
|
5496
|
+
const questions = plannerQuestions;
|
|
5497
|
+
pendingAskUser = questions.length ? {
|
|
5498
|
+
questions,
|
|
5499
|
+
source: "planner",
|
|
5500
|
+
askedAt: Date.now()
|
|
5501
|
+
} : void 0;
|
|
5502
|
+
const qText = questions.map((question) => `- ${question.key}: ${questionToDisplayText(question)}`).join("\n");
|
|
5106
5503
|
const msg2 = `I need a bit more info:
|
|
5107
5504
|
${qText}`;
|
|
5108
5505
|
postAssistantMessage(msg2);
|
|
5109
5506
|
history.push({ role: "assistant", content: msg2 });
|
|
5110
5507
|
postStatus("Planner needs user input", void 0, "verify");
|
|
5111
5508
|
postStateSnapshot();
|
|
5112
|
-
return {
|
|
5509
|
+
return {
|
|
5510
|
+
route: result.route,
|
|
5511
|
+
taskComplete: false,
|
|
5512
|
+
needsUserInput: true,
|
|
5513
|
+
questions
|
|
5514
|
+
};
|
|
5113
5515
|
}
|
|
5114
|
-
|
|
5516
|
+
pendingAskUser = void 0;
|
|
5115
5517
|
for (const toolResult of toolResults) {
|
|
5116
5518
|
await maybeWaitForNewTab(toolResult);
|
|
5117
5519
|
maybePostNavigationGuardrailFromToolResult(toolResult);
|
|
5118
5520
|
}
|
|
5119
|
-
const
|
|
5521
|
+
const toolBlocks = buildPlannerToolResultBlocks(toolResults);
|
|
5120
5522
|
const responseError = response.error || response.errorDetails ? toStructuredErrorPayload(response.errorDetails || { message: response.error }, "Planner failed") : void 0;
|
|
5121
5523
|
if (responseError?.error.requires_api_key) {
|
|
5122
5524
|
postAuthRequired(responseError.error);
|
|
5123
5525
|
}
|
|
5124
|
-
const msg =
|
|
5125
|
-
|
|
5526
|
+
const msg = responseError ? postAssistantMessage({
|
|
5527
|
+
text: `${responseError.error.code}: ${responseError.error.message}`,
|
|
5528
|
+
blocks: [
|
|
5529
|
+
{
|
|
5530
|
+
type: "json",
|
|
5531
|
+
label: "Planner error",
|
|
5532
|
+
data: cloneUnknown(responseError)
|
|
5533
|
+
},
|
|
5534
|
+
...toolBlocks || []
|
|
5535
|
+
]
|
|
5536
|
+
}) : postAssistantMessage({
|
|
5537
|
+
text: String(response.overallThought || summarizePlannerToolResults(toolResults) || "Done."),
|
|
5538
|
+
blocks: toolBlocks
|
|
5539
|
+
});
|
|
5126
5540
|
history.push({ role: "assistant", content: msg });
|
|
5127
5541
|
postStatus("Planner execution completed", response.overallThought, "complete");
|
|
5128
5542
|
postStateSnapshot();
|
|
@@ -5132,24 +5546,37 @@ ${qText}`;
|
|
|
5132
5546
|
needsUserInput: false
|
|
5133
5547
|
};
|
|
5134
5548
|
}
|
|
5135
|
-
postAssistantMessage("Done.");
|
|
5136
|
-
history.push({ role: "assistant", content:
|
|
5549
|
+
const doneMsg = postAssistantMessage("Done.");
|
|
5550
|
+
history.push({ role: "assistant", content: doneMsg });
|
|
5137
5551
|
postStatus("Completed", void 0, "complete");
|
|
5138
5552
|
postStateSnapshot();
|
|
5139
5553
|
return { route: result.route, taskComplete: true };
|
|
5140
5554
|
}
|
|
5141
5555
|
async function runUserMessage(text, meta) {
|
|
5142
5556
|
const runId = meta?.runId || crypto.randomUUID();
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5557
|
+
const terminal = terminalRuns.get(runId);
|
|
5558
|
+
if (terminal) {
|
|
5559
|
+
if (terminal.ok) {
|
|
5560
|
+
const cachedOutcome = normalizeRunOutcome(terminal.outcome);
|
|
5561
|
+
self.postMessage({
|
|
5562
|
+
type: "run_completed",
|
|
5563
|
+
runId,
|
|
5564
|
+
ok: true,
|
|
5565
|
+
route: cachedOutcome.route,
|
|
5566
|
+
taskComplete: cachedOutcome.taskComplete,
|
|
5567
|
+
needsUserInput: cachedOutcome.needsUserInput,
|
|
5568
|
+
questions: cachedOutcome.questions
|
|
5569
|
+
});
|
|
5570
|
+
} else {
|
|
5571
|
+
self.postMessage({
|
|
5572
|
+
type: "run_completed",
|
|
5573
|
+
runId,
|
|
5574
|
+
ok: false,
|
|
5575
|
+
error: terminal.error,
|
|
5576
|
+
taskComplete: false,
|
|
5577
|
+
needsUserInput: false
|
|
5578
|
+
});
|
|
5579
|
+
}
|
|
5153
5580
|
return;
|
|
5154
5581
|
}
|
|
5155
5582
|
if (activeRun && activeRun.runId === runId) {
|
|
@@ -5158,20 +5585,26 @@ async function runUserMessage(text, meta) {
|
|
|
5158
5585
|
const resume = !!meta?.resume;
|
|
5159
5586
|
lastStatusKey = "";
|
|
5160
5587
|
seenStatusKeys = /* @__PURE__ */ new Set();
|
|
5588
|
+
cancelledRunIds.delete(runId);
|
|
5161
5589
|
activeAbortController = new AbortController();
|
|
5162
5590
|
activeRun = { runId, text, startedAt: Date.now(), resume };
|
|
5163
5591
|
self.postMessage({ type: "run_started", runId, text, resume });
|
|
5164
5592
|
postStateSnapshot();
|
|
5165
5593
|
try {
|
|
5166
|
-
const outcome = normalizeRunOutcome(await handleUserMessage(text, {
|
|
5167
|
-
|
|
5594
|
+
const outcome = normalizeRunOutcome(await handleUserMessage(text, {
|
|
5595
|
+
resume,
|
|
5596
|
+
routing: meta?.routing,
|
|
5597
|
+
askUserAnswers: meta?.askUserAnswers
|
|
5598
|
+
}));
|
|
5599
|
+
rememberTerminalRun(runId, { ok: true, outcome });
|
|
5168
5600
|
self.postMessage({
|
|
5169
5601
|
type: "run_completed",
|
|
5170
5602
|
runId,
|
|
5171
5603
|
ok: true,
|
|
5172
5604
|
route: outcome.route,
|
|
5173
5605
|
taskComplete: outcome.taskComplete,
|
|
5174
|
-
needsUserInput: outcome.needsUserInput
|
|
5606
|
+
needsUserInput: outcome.needsUserInput,
|
|
5607
|
+
questions: outcome.questions
|
|
5175
5608
|
});
|
|
5176
5609
|
if (outcome.taskComplete && !outcome.needsUserInput) {
|
|
5177
5610
|
clearTaskScopedContextAfterCompletion();
|
|
@@ -5179,6 +5612,12 @@ async function runUserMessage(text, meta) {
|
|
|
5179
5612
|
}
|
|
5180
5613
|
} catch (error) {
|
|
5181
5614
|
if (error?.name === "AbortError") {
|
|
5615
|
+
rememberTerminalRun(runId, {
|
|
5616
|
+
ok: false,
|
|
5617
|
+
error: "Run cancelled",
|
|
5618
|
+
taskComplete: false,
|
|
5619
|
+
needsUserInput: false
|
|
5620
|
+
});
|
|
5182
5621
|
self.postMessage({
|
|
5183
5622
|
type: "run_completed",
|
|
5184
5623
|
runId,
|
|
@@ -5188,6 +5627,12 @@ async function runUserMessage(text, meta) {
|
|
|
5188
5627
|
needsUserInput: false
|
|
5189
5628
|
});
|
|
5190
5629
|
} else {
|
|
5630
|
+
rememberTerminalRun(runId, {
|
|
5631
|
+
ok: false,
|
|
5632
|
+
error: error?.message || String(error),
|
|
5633
|
+
taskComplete: false,
|
|
5634
|
+
needsUserInput: false
|
|
5635
|
+
});
|
|
5191
5636
|
self.postMessage({
|
|
5192
5637
|
type: "run_completed",
|
|
5193
5638
|
runId,
|
|
@@ -5201,14 +5646,6 @@ async function runUserMessage(text, meta) {
|
|
|
5201
5646
|
} finally {
|
|
5202
5647
|
activeAbortController = null;
|
|
5203
5648
|
activeRun = null;
|
|
5204
|
-
completedRunIds.add(runId);
|
|
5205
|
-
if (completedRunIds.size > 50) {
|
|
5206
|
-
const oldest = completedRunIds.values().next().value;
|
|
5207
|
-
if (oldest) {
|
|
5208
|
-
completedRunIds.delete(oldest);
|
|
5209
|
-
completedRunOutcomes.delete(oldest);
|
|
5210
|
-
}
|
|
5211
|
-
}
|
|
5212
5649
|
postStateSnapshot();
|
|
5213
5650
|
}
|
|
5214
5651
|
}
|
|
@@ -5256,6 +5693,9 @@ self.onmessage = async (ev) => {
|
|
|
5256
5693
|
trajectoryId = partial.sessionId.trim();
|
|
5257
5694
|
plannerHistory = [];
|
|
5258
5695
|
agentPrevSteps = [];
|
|
5696
|
+
pendingAskUser = void 0;
|
|
5697
|
+
terminalRuns.clear();
|
|
5698
|
+
cancelledRunIds.clear();
|
|
5259
5699
|
tabularStore = new TabularStore(`rover-${trajectoryId}`);
|
|
5260
5700
|
}
|
|
5261
5701
|
const tools = partial.tools;
|
|
@@ -5279,29 +5719,45 @@ self.onmessage = async (ev) => {
|
|
|
5279
5719
|
if (!config)
|
|
5280
5720
|
throw new Error("Worker not initialized");
|
|
5281
5721
|
const nextTaskId = typeof data.taskId === "string" && data.taskId.trim() ? data.taskId.trim() : crypto.randomUUID();
|
|
5722
|
+
activeAbortController?.abort();
|
|
5282
5723
|
history.length = 0;
|
|
5283
5724
|
plannerHistory = [];
|
|
5284
5725
|
agentPrevSteps = [];
|
|
5726
|
+
pendingAskUser = void 0;
|
|
5727
|
+
terminalRuns.clear();
|
|
5728
|
+
cancelledRunIds.clear();
|
|
5285
5729
|
trajectoryId = nextTaskId;
|
|
5286
5730
|
tabularStore = new TabularStore(`rover-${trajectoryId}`);
|
|
5287
5731
|
activeRun = null;
|
|
5732
|
+
activeAbortController = null;
|
|
5288
5733
|
postStateSnapshot();
|
|
5289
5734
|
self.postMessage({ type: "task_started", taskId: nextTaskId });
|
|
5290
5735
|
return;
|
|
5291
5736
|
}
|
|
5292
5737
|
if (data.type === "cancel_run") {
|
|
5293
5738
|
if (typeof data.runId === "string" && data.runId) {
|
|
5294
|
-
|
|
5739
|
+
rememberCancelledRun(data.runId);
|
|
5295
5740
|
activeAbortController?.abort();
|
|
5296
5741
|
}
|
|
5742
|
+
pendingAskUser = void 0;
|
|
5743
|
+
postStateSnapshot();
|
|
5297
5744
|
return;
|
|
5298
5745
|
}
|
|
5299
5746
|
if (data.type === "run") {
|
|
5300
|
-
await runUserMessage(String(data.text || ""), {
|
|
5747
|
+
await runUserMessage(String(data.text || ""), {
|
|
5748
|
+
runId: data.runId,
|
|
5749
|
+
resume: !!data.resume,
|
|
5750
|
+
routing: data.routing,
|
|
5751
|
+
askUserAnswers: data.askUserAnswers
|
|
5752
|
+
});
|
|
5301
5753
|
return;
|
|
5302
5754
|
}
|
|
5303
5755
|
if (data.type === "user") {
|
|
5304
|
-
await runUserMessage(String(data.text || ""), {
|
|
5756
|
+
await runUserMessage(String(data.text || ""), {
|
|
5757
|
+
runId: data.runId,
|
|
5758
|
+
resume: !!data.resume,
|
|
5759
|
+
askUserAnswers: data.askUserAnswers
|
|
5760
|
+
});
|
|
5305
5761
|
return;
|
|
5306
5762
|
}
|
|
5307
5763
|
} catch (err) {
|