@rtrvr-ai/rover 1.3.1 → 1.3.2
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/dist/embed.js +37 -18
- package/dist/rover.js +903 -150
- package/dist/worker/rover-worker.js +586 -141
- package/package.json +1 -1
package/dist/rover.js
CHANGED
|
@@ -11385,10 +11385,9 @@ var Bridge = class {
|
|
|
11385
11385
|
}
|
|
11386
11386
|
const clickTargetUrl = this.getClickTargetUrl(args);
|
|
11387
11387
|
if (clickTargetUrl) {
|
|
11388
|
-
this.
|
|
11389
|
-
this.
|
|
11390
|
-
|
|
11391
|
-
this.notifyAgentNavigation(window.location.href);
|
|
11388
|
+
const intent = this.buildNavigationIntent(clickTargetUrl);
|
|
11389
|
+
this.notifyAgentNavigation(intent);
|
|
11390
|
+
this.notifyCrossHostNavigation(intent);
|
|
11392
11391
|
}
|
|
11393
11392
|
}
|
|
11394
11393
|
if (toolName === SystemToolNames.describe_images) {
|
|
@@ -11527,8 +11526,9 @@ var Bridge = class {
|
|
|
11527
11526
|
}
|
|
11528
11527
|
return this.domainScopeBlockedResponse(targetUrl, reason);
|
|
11529
11528
|
}
|
|
11530
|
-
this.
|
|
11531
|
-
this.
|
|
11529
|
+
const intent = this.buildNavigationIntent(targetUrl);
|
|
11530
|
+
this.notifyAgentNavigation(intent);
|
|
11531
|
+
this.notifyCrossHostNavigation(intent);
|
|
11532
11532
|
window.location.href = targetUrl;
|
|
11533
11533
|
return { success: true, output: { url: targetUrl, navigation: "same_tab" } };
|
|
11534
11534
|
}
|
|
@@ -11557,23 +11557,24 @@ var Bridge = class {
|
|
|
11557
11557
|
}
|
|
11558
11558
|
return this.domainScopeBlockedResponse(targetUrl, reason);
|
|
11559
11559
|
}
|
|
11560
|
-
this.
|
|
11561
|
-
this.
|
|
11560
|
+
const intent = this.buildNavigationIntent(targetUrl);
|
|
11561
|
+
this.notifyAgentNavigation(intent);
|
|
11562
|
+
this.notifyCrossHostNavigation(intent);
|
|
11562
11563
|
window.location.href = targetUrl;
|
|
11563
11564
|
return { success: true, output: { url: targetUrl, navigation: "same_tab" } };
|
|
11564
11565
|
}
|
|
11565
11566
|
case SystemToolNames.go_back: {
|
|
11566
|
-
this.notifyAgentNavigation(window.location.href);
|
|
11567
|
+
this.notifyAgentNavigation(this.buildNavigationIntent(window.location.href, { isCrossHost: false }));
|
|
11567
11568
|
window.history.back();
|
|
11568
11569
|
return { success: true };
|
|
11569
11570
|
}
|
|
11570
11571
|
case SystemToolNames.go_forward: {
|
|
11571
|
-
this.notifyAgentNavigation(window.location.href);
|
|
11572
|
+
this.notifyAgentNavigation(this.buildNavigationIntent(window.location.href, { isCrossHost: false }));
|
|
11572
11573
|
window.history.forward();
|
|
11573
11574
|
return { success: true };
|
|
11574
11575
|
}
|
|
11575
11576
|
case SystemToolNames.refresh_page: {
|
|
11576
|
-
this.notifyAgentNavigation(window.location.href);
|
|
11577
|
+
this.notifyAgentNavigation(this.buildNavigationIntent(window.location.href, { isCrossHost: false }));
|
|
11577
11578
|
window.location.reload();
|
|
11578
11579
|
return { success: true };
|
|
11579
11580
|
}
|
|
@@ -11585,8 +11586,9 @@ var Bridge = class {
|
|
|
11585
11586
|
if (!targetUrl)
|
|
11586
11587
|
return { success: false, error: `open_new_tab: invalid url "${rawUrl}"`, allowFallback: true };
|
|
11587
11588
|
if (this.shouldConvertOpenNewTabToSameTab(targetUrl)) {
|
|
11588
|
-
this.
|
|
11589
|
-
this.
|
|
11589
|
+
const intent = this.buildNavigationIntent(targetUrl);
|
|
11590
|
+
this.notifyAgentNavigation(intent);
|
|
11591
|
+
this.notifyCrossHostNavigation(intent);
|
|
11590
11592
|
window.location.assign(targetUrl);
|
|
11591
11593
|
return {
|
|
11592
11594
|
success: true,
|
|
@@ -11681,16 +11683,33 @@ var Bridge = class {
|
|
|
11681
11683
|
return false;
|
|
11682
11684
|
return isUrlAllowedByDomains(targetUrl, this.allowedDomains);
|
|
11683
11685
|
}
|
|
11684
|
-
|
|
11686
|
+
buildNavigationIntent(targetUrl, options) {
|
|
11687
|
+
let handoffId = "";
|
|
11685
11688
|
try {
|
|
11686
|
-
|
|
11689
|
+
handoffId = crypto.randomUUID();
|
|
11687
11690
|
} catch {
|
|
11691
|
+
handoffId = `handoff_${Date.now()}_${Math.floor(Math.random() * 1e5)}`;
|
|
11688
11692
|
}
|
|
11693
|
+
return {
|
|
11694
|
+
handoffId,
|
|
11695
|
+
targetUrl,
|
|
11696
|
+
sourceRuntimeId: this.runtimeId,
|
|
11697
|
+
sourceLogicalTabId: this.actionGateContext.localLogicalTabId,
|
|
11698
|
+
runId: options?.runId,
|
|
11699
|
+
isCrossHost: options?.isCrossHost ?? this.isCrossHostInScopeNavigation(targetUrl),
|
|
11700
|
+
ts: Date.now()
|
|
11701
|
+
};
|
|
11689
11702
|
}
|
|
11690
|
-
|
|
11691
|
-
|
|
11703
|
+
notifyAgentNavigation(event) {
|
|
11704
|
+
try {
|
|
11705
|
+
this.onBeforeAgentNavigation?.(event);
|
|
11706
|
+
} catch {
|
|
11707
|
+
}
|
|
11708
|
+
}
|
|
11709
|
+
notifyCrossHostNavigation(event) {
|
|
11710
|
+
if (event.isCrossHost) {
|
|
11692
11711
|
try {
|
|
11693
|
-
this.onBeforeCrossHostNavigation?.(
|
|
11712
|
+
this.onBeforeCrossHostNavigation?.(event);
|
|
11694
11713
|
} catch {
|
|
11695
11714
|
}
|
|
11696
11715
|
}
|
|
@@ -14084,12 +14103,29 @@ function mountWidget(opts) {
|
|
|
14084
14103
|
display: flex;
|
|
14085
14104
|
justify-content: flex-end;
|
|
14086
14105
|
align-items: center;
|
|
14106
|
+
gap: 8px;
|
|
14087
14107
|
position: sticky;
|
|
14088
14108
|
bottom: 0;
|
|
14089
14109
|
padding-top: 2px;
|
|
14090
14110
|
background: linear-gradient(to bottom, rgba(255, 247, 242, 0), rgba(255, 247, 242, 0.94) 40%);
|
|
14091
14111
|
}
|
|
14092
14112
|
|
|
14113
|
+
.questionPromptCancel {
|
|
14114
|
+
border: 1px solid var(--rv-border-strong);
|
|
14115
|
+
background: rgba(255, 255, 255, 0.88);
|
|
14116
|
+
color: var(--rv-text-secondary);
|
|
14117
|
+
border-radius: var(--rv-radius-sm);
|
|
14118
|
+
font-size: 12px;
|
|
14119
|
+
font-weight: 700;
|
|
14120
|
+
letter-spacing: 0.01em;
|
|
14121
|
+
padding: 6px 10px;
|
|
14122
|
+
cursor: pointer;
|
|
14123
|
+
}
|
|
14124
|
+
|
|
14125
|
+
.questionPromptCancel:hover {
|
|
14126
|
+
background: rgba(242, 246, 250, 0.95);
|
|
14127
|
+
}
|
|
14128
|
+
|
|
14093
14129
|
.questionPromptSubmit {
|
|
14094
14130
|
border: 1px solid var(--rv-accent-border);
|
|
14095
14131
|
background: var(--rv-accent-soft);
|
|
@@ -14860,6 +14896,11 @@ function mountWidget(opts) {
|
|
|
14860
14896
|
questionPromptForm.appendChild(questionPromptList);
|
|
14861
14897
|
const questionPromptActions = document.createElement("div");
|
|
14862
14898
|
questionPromptActions.className = "questionPromptActions";
|
|
14899
|
+
const questionPromptCancel = document.createElement("button");
|
|
14900
|
+
questionPromptCancel.type = "button";
|
|
14901
|
+
questionPromptCancel.className = "questionPromptCancel";
|
|
14902
|
+
questionPromptCancel.textContent = "Cancel";
|
|
14903
|
+
questionPromptActions.appendChild(questionPromptCancel);
|
|
14863
14904
|
const questionPromptSubmit = document.createElement("button");
|
|
14864
14905
|
questionPromptSubmit.type = "submit";
|
|
14865
14906
|
questionPromptSubmit.className = "questionPromptSubmit";
|
|
@@ -15219,6 +15260,7 @@ function mountWidget(opts) {
|
|
|
15219
15260
|
function syncComposerDisabledState() {
|
|
15220
15261
|
const disabled = currentMode2 === "observer" && !canComposeInObserver;
|
|
15221
15262
|
inputEl.disabled = disabled;
|
|
15263
|
+
questionPromptCancel.disabled = disabled;
|
|
15222
15264
|
questionPromptSubmit.disabled = disabled;
|
|
15223
15265
|
for (const node of Array.from(questionPromptForm.querySelectorAll(".questionPromptInput"))) {
|
|
15224
15266
|
node.disabled = disabled;
|
|
@@ -15616,6 +15658,7 @@ function mountWidget(opts) {
|
|
|
15616
15658
|
if (!value) {
|
|
15617
15659
|
input.classList.remove("invalid");
|
|
15618
15660
|
delete questionDraftAnswers[question.key];
|
|
15661
|
+
rawLines.push(`${question.key}: (no answer provided)`);
|
|
15619
15662
|
continue;
|
|
15620
15663
|
}
|
|
15621
15664
|
input.classList.remove("invalid");
|
|
@@ -15628,7 +15671,7 @@ function mountWidget(opts) {
|
|
|
15628
15671
|
return;
|
|
15629
15672
|
}
|
|
15630
15673
|
const keys = currentQuestionPrompt.questions.map((question) => question.key);
|
|
15631
|
-
const rawText = rawLines.join("\n");
|
|
15674
|
+
const rawText = rawLines.length ? rawLines.join("\n") : keys.map((key) => `${key}: (no answer provided)`).join("\n");
|
|
15632
15675
|
opts.onSend(rawText, {
|
|
15633
15676
|
askUserAnswers: {
|
|
15634
15677
|
answersByKey,
|
|
@@ -15636,7 +15679,15 @@ function mountWidget(opts) {
|
|
|
15636
15679
|
keys
|
|
15637
15680
|
}
|
|
15638
15681
|
});
|
|
15639
|
-
|
|
15682
|
+
});
|
|
15683
|
+
questionPromptCancel.addEventListener("click", () => {
|
|
15684
|
+
if (inputEl.disabled)
|
|
15685
|
+
return;
|
|
15686
|
+
if (opts.onCancelQuestionFlow) {
|
|
15687
|
+
opts.onCancelQuestionFlow();
|
|
15688
|
+
return;
|
|
15689
|
+
}
|
|
15690
|
+
opts.onCancelRun?.();
|
|
15640
15691
|
});
|
|
15641
15692
|
inputEl.addEventListener("keydown", (e) => {
|
|
15642
15693
|
if (e.key === "Enter" && !e.shiftKey && !e.isComposing) {
|
|
@@ -15751,7 +15802,9 @@ var SHARED_VERSION = 2;
|
|
|
15751
15802
|
var SHARED_KEY_PREFIX = "rover:shared:";
|
|
15752
15803
|
var SHARED_CHANNEL_PREFIX = "rover:channel:";
|
|
15753
15804
|
var STALE_DETACHED_EXTERNAL_TAB_MS = 2 * 6e4;
|
|
15754
|
-
var STALE_DETACHED_TAB_MS =
|
|
15805
|
+
var STALE_DETACHED_TAB_MS = 9e4;
|
|
15806
|
+
var STALE_NAVIGATION_HANDOFF_TAB_MS = 45e3;
|
|
15807
|
+
var STALE_PENDING_ATTACH_TAB_MS = 2e4;
|
|
15755
15808
|
var STALE_RUNTIME_TAB_MS = 45e3;
|
|
15756
15809
|
function now() {
|
|
15757
15810
|
return Date.now();
|
|
@@ -15773,13 +15826,6 @@ function normalizeUrl2(raw) {
|
|
|
15773
15826
|
return text;
|
|
15774
15827
|
}
|
|
15775
15828
|
}
|
|
15776
|
-
function extractHostname2(url) {
|
|
15777
|
-
try {
|
|
15778
|
-
return new URL(url).hostname.toLowerCase();
|
|
15779
|
-
} catch {
|
|
15780
|
-
return "";
|
|
15781
|
-
}
|
|
15782
|
-
}
|
|
15783
15829
|
function sanitizeSharedTask(raw) {
|
|
15784
15830
|
if (!raw || typeof raw !== "object")
|
|
15785
15831
|
return void 0;
|
|
@@ -15866,6 +15912,12 @@ function sanitizeSharedWorkerContext(raw) {
|
|
|
15866
15912
|
choices: Array.isArray(question?.choices) ? question.choices : void 0
|
|
15867
15913
|
};
|
|
15868
15914
|
}).filter((question) => !!question).slice(0, 6) : [];
|
|
15915
|
+
const pendingStepRefRaw = raw.pendingAskUser?.stepRef;
|
|
15916
|
+
const pendingStepRef = pendingStepRefRaw && Number.isFinite(Number(pendingStepRefRaw.stepIndex)) && Number(pendingStepRefRaw.stepIndex) >= 0 && Number.isFinite(Number(pendingStepRefRaw.functionIndex)) && Number(pendingStepRefRaw.functionIndex) >= 0 ? {
|
|
15917
|
+
stepIndex: Number(pendingStepRefRaw.stepIndex),
|
|
15918
|
+
functionIndex: Number(pendingStepRefRaw.functionIndex),
|
|
15919
|
+
...typeof pendingStepRefRaw.accTreeId === "string" && pendingStepRefRaw.accTreeId.trim() ? { accTreeId: pendingStepRefRaw.accTreeId.trim() } : {}
|
|
15920
|
+
} : void 0;
|
|
15869
15921
|
const normalizeEntries = (items) => items.slice(-80).map((item) => ({
|
|
15870
15922
|
role: typeof item?.role === "string" ? item.role : "assistant",
|
|
15871
15923
|
content: typeof item?.content === "string" ? item.content : ""
|
|
@@ -15873,15 +15925,20 @@ function sanitizeSharedWorkerContext(raw) {
|
|
|
15873
15925
|
const history2 = Array.isArray(raw.history) ? normalizeEntries(raw.history) : [];
|
|
15874
15926
|
const plannerHistory = cloneUnknownArrayTail(raw.plannerHistory, 40);
|
|
15875
15927
|
const agentPrevSteps = cloneUnknownArrayTail(raw.agentPrevSteps, 80);
|
|
15928
|
+
const rootUserInput = typeof raw.rootUserInput === "string" ? raw.rootUserInput.trim() : "";
|
|
15876
15929
|
return {
|
|
15877
15930
|
trajectoryId: typeof raw.trajectoryId === "string" ? raw.trajectoryId : void 0,
|
|
15931
|
+
taskBoundaryId: typeof raw.taskBoundaryId === "string" && raw.taskBoundaryId.trim() ? raw.taskBoundaryId.trim() : void 0,
|
|
15932
|
+
rootUserInput: rootUserInput || void 0,
|
|
15878
15933
|
history: history2,
|
|
15879
15934
|
plannerHistory,
|
|
15880
15935
|
agentPrevSteps,
|
|
15881
15936
|
pendingAskUser: pendingQuestions.length ? {
|
|
15882
15937
|
questions: pendingQuestions,
|
|
15883
15938
|
source: raw.pendingAskUser?.source === "planner" ? "planner" : "act",
|
|
15884
|
-
askedAt: Number(raw.pendingAskUser?.askedAt) || now()
|
|
15939
|
+
askedAt: Number(raw.pendingAskUser?.askedAt) || now(),
|
|
15940
|
+
boundaryId: typeof raw.pendingAskUser?.boundaryId === "string" && raw.pendingAskUser.boundaryId.trim() ? raw.pendingAskUser.boundaryId.trim() : void 0,
|
|
15941
|
+
...pendingStepRef ? { stepRef: pendingStepRef } : {}
|
|
15885
15942
|
} : void 0,
|
|
15886
15943
|
updatedAt: Number(raw.updatedAt) || now()
|
|
15887
15944
|
};
|
|
@@ -15926,7 +15983,13 @@ function sanitizeSharedState(raw, siteId, sessionId) {
|
|
|
15926
15983
|
openedAt: Number(entry?.openedAt) || now(),
|
|
15927
15984
|
updatedAt: Number(entry?.updatedAt) || now(),
|
|
15928
15985
|
external: !!entry?.external,
|
|
15929
|
-
openerRuntimeId: typeof entry?.openerRuntimeId === "string" ? entry.openerRuntimeId : void 0
|
|
15986
|
+
openerRuntimeId: typeof entry?.openerRuntimeId === "string" ? entry.openerRuntimeId : void 0,
|
|
15987
|
+
detachedAt: Number(entry?.detachedAt) || void 0,
|
|
15988
|
+
detachedReason: entry?.detachedReason === "navigation_handoff" || entry?.detachedReason === "tab_close" || entry?.detachedReason === "opened_pending_attach" || entry?.detachedReason === "unknown" ? entry.detachedReason : void 0,
|
|
15989
|
+
handoffId: typeof entry?.handoffId === "string" ? entry.handoffId : void 0,
|
|
15990
|
+
handoffRunId: typeof entry?.handoffRunId === "string" ? entry.handoffRunId : void 0,
|
|
15991
|
+
handoffTargetUrl: typeof entry?.handoffTargetUrl === "string" ? entry.handoffTargetUrl : void 0,
|
|
15992
|
+
handoffCreatedAt: Number(entry?.handoffCreatedAt) || void 0
|
|
15930
15993
|
})).filter((entry) => !!entry.logicalTabId) : [],
|
|
15931
15994
|
nextLogicalTabId: Math.max(1, Number(raw.nextLogicalTabId) || 1),
|
|
15932
15995
|
activeLogicalTabId: Number(raw.activeLogicalTabId) || void 0,
|
|
@@ -16012,35 +16075,176 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16012
16075
|
lastNotifiedRole;
|
|
16013
16076
|
roleChangeTimer = null;
|
|
16014
16077
|
static ROLE_CHANGE_DEBOUNCE_MS = 200;
|
|
16078
|
+
tabFreshnessTs(tab) {
|
|
16079
|
+
return Math.max(Number(tab.updatedAt) || 0, Number(tab.openedAt) || 0, Number(tab.detachedAt) || 0);
|
|
16080
|
+
}
|
|
16081
|
+
isBetterTabCandidate(next, current) {
|
|
16082
|
+
if (!current)
|
|
16083
|
+
return true;
|
|
16084
|
+
const nextFreshness = this.tabFreshnessTs(next);
|
|
16085
|
+
const currentFreshness = this.tabFreshnessTs(current);
|
|
16086
|
+
if (nextFreshness !== currentFreshness)
|
|
16087
|
+
return nextFreshness > currentFreshness;
|
|
16088
|
+
if (!!next.runtimeId !== !!current.runtimeId)
|
|
16089
|
+
return !!next.runtimeId;
|
|
16090
|
+
return next.logicalTabId < current.logicalTabId;
|
|
16091
|
+
}
|
|
16092
|
+
isRuntimeTabFresh(tab, nowMs2) {
|
|
16093
|
+
if (!tab.runtimeId)
|
|
16094
|
+
return false;
|
|
16095
|
+
if (tab.runtimeId === this.runtimeId)
|
|
16096
|
+
return true;
|
|
16097
|
+
return nowMs2 - this.tabFreshnessTs(tab) <= STALE_RUNTIME_TAB_MS;
|
|
16098
|
+
}
|
|
16099
|
+
isTabVisibleInScope(tab, nowMs2, scope) {
|
|
16100
|
+
if (tab.runtimeId) {
|
|
16101
|
+
return this.isRuntimeTabFresh(tab, nowMs2);
|
|
16102
|
+
}
|
|
16103
|
+
if (tab.external) {
|
|
16104
|
+
return nowMs2 - this.tabFreshnessTs(tab) <= STALE_DETACHED_EXTERNAL_TAB_MS;
|
|
16105
|
+
}
|
|
16106
|
+
if (tab.detachedReason === "opened_pending_attach") {
|
|
16107
|
+
return nowMs2 - this.tabFreshnessTs(tab) <= STALE_PENDING_ATTACH_TAB_MS;
|
|
16108
|
+
}
|
|
16109
|
+
if (scope === "context") {
|
|
16110
|
+
return false;
|
|
16111
|
+
}
|
|
16112
|
+
if (tab.detachedReason === "navigation_handoff") {
|
|
16113
|
+
return nowMs2 - this.tabFreshnessTs(tab) <= STALE_NAVIGATION_HANDOFF_TAB_MS;
|
|
16114
|
+
}
|
|
16115
|
+
return nowMs2 - this.tabFreshnessTs(tab) <= STALE_DETACHED_TAB_MS;
|
|
16116
|
+
}
|
|
16117
|
+
normalizeDraftTabs(draft) {
|
|
16118
|
+
const byLogicalTabId = /* @__PURE__ */ new Map();
|
|
16119
|
+
for (const tab of draft.tabs) {
|
|
16120
|
+
if (!Number.isFinite(Number(tab.logicalTabId)) || Number(tab.logicalTabId) <= 0)
|
|
16121
|
+
continue;
|
|
16122
|
+
const existing = byLogicalTabId.get(tab.logicalTabId);
|
|
16123
|
+
if (this.isBetterTabCandidate(tab, existing)) {
|
|
16124
|
+
byLogicalTabId.set(tab.logicalTabId, tab);
|
|
16125
|
+
}
|
|
16126
|
+
}
|
|
16127
|
+
const dedupedByLogical = [];
|
|
16128
|
+
const emittedLogical = /* @__PURE__ */ new Set();
|
|
16129
|
+
for (const tab of draft.tabs) {
|
|
16130
|
+
if (emittedLogical.has(tab.logicalTabId))
|
|
16131
|
+
continue;
|
|
16132
|
+
const chosen = byLogicalTabId.get(tab.logicalTabId);
|
|
16133
|
+
if (!chosen)
|
|
16134
|
+
continue;
|
|
16135
|
+
if (chosen === tab) {
|
|
16136
|
+
dedupedByLogical.push(chosen);
|
|
16137
|
+
emittedLogical.add(chosen.logicalTabId);
|
|
16138
|
+
}
|
|
16139
|
+
}
|
|
16140
|
+
for (const [logicalTabId, tab] of byLogicalTabId.entries()) {
|
|
16141
|
+
if (emittedLogical.has(logicalTabId))
|
|
16142
|
+
continue;
|
|
16143
|
+
dedupedByLogical.push(tab);
|
|
16144
|
+
emittedLogical.add(logicalTabId);
|
|
16145
|
+
}
|
|
16146
|
+
const byRuntimeId = /* @__PURE__ */ new Map();
|
|
16147
|
+
for (const tab of dedupedByLogical) {
|
|
16148
|
+
if (!tab.runtimeId)
|
|
16149
|
+
continue;
|
|
16150
|
+
const existing = byRuntimeId.get(tab.runtimeId);
|
|
16151
|
+
if (this.isBetterTabCandidate(tab, existing)) {
|
|
16152
|
+
byRuntimeId.set(tab.runtimeId, tab);
|
|
16153
|
+
}
|
|
16154
|
+
}
|
|
16155
|
+
draft.tabs = dedupedByLogical.filter((tab) => !tab.runtimeId || byRuntimeId.get(tab.runtimeId) === tab).sort((a, b) => a.logicalTabId - b.logicalTabId);
|
|
16156
|
+
if (!draft.tabs.length) {
|
|
16157
|
+
draft.activeLogicalTabId = void 0;
|
|
16158
|
+
draft.nextLogicalTabId = 1;
|
|
16159
|
+
return;
|
|
16160
|
+
}
|
|
16161
|
+
const nowMs2 = now();
|
|
16162
|
+
const currentActive = draft.activeLogicalTabId ? draft.tabs.find((tab) => tab.logicalTabId === draft.activeLogicalTabId) : void 0;
|
|
16163
|
+
const localAttached = draft.tabs.find((tab) => tab.runtimeId === this.runtimeId);
|
|
16164
|
+
const liveTabs = draft.tabs.filter((tab) => this.isRuntimeTabFresh(tab, nowMs2));
|
|
16165
|
+
const freshestLiveTab = [...liveTabs].sort((a, b) => this.tabFreshnessTs(b) - this.tabFreshnessTs(a))[0];
|
|
16166
|
+
let nextActiveLogicalTabId = currentActive?.logicalTabId;
|
|
16167
|
+
if (!currentActive) {
|
|
16168
|
+
nextActiveLogicalTabId = localAttached?.logicalTabId || freshestLiveTab?.logicalTabId || draft.tabs[0]?.logicalTabId;
|
|
16169
|
+
} else if (!currentActive.runtimeId || !this.isRuntimeTabFresh(currentActive, nowMs2)) {
|
|
16170
|
+
nextActiveLogicalTabId = localAttached?.logicalTabId || freshestLiveTab?.logicalTabId || currentActive.logicalTabId;
|
|
16171
|
+
}
|
|
16172
|
+
draft.activeLogicalTabId = nextActiveLogicalTabId;
|
|
16173
|
+
const maxLogicalTabId = draft.tabs.reduce((max, tab) => Math.max(max, tab.logicalTabId), 0);
|
|
16174
|
+
draft.nextLogicalTabId = Math.max(Number(draft.nextLogicalTabId) || 1, maxLogicalTabId + 1);
|
|
16175
|
+
}
|
|
16015
16176
|
pruneDetachedTabs(draft, options) {
|
|
16016
16177
|
const dropRuntimeDetached = !!options?.dropRuntimeDetached;
|
|
16017
16178
|
const dropAllDetachedExternal = !!options?.dropAllDetachedExternal;
|
|
16179
|
+
const keepOnlyActiveLiveTab = !!options?.keepOnlyActiveLiveTab;
|
|
16180
|
+
const keepRecentExternalPlaceholders = !!options?.keepRecentExternalPlaceholders;
|
|
16018
16181
|
const nowMs2 = now();
|
|
16019
|
-
const before = draft.tabs.length;
|
|
16020
16182
|
draft.tabs = draft.tabs.filter((tab) => {
|
|
16021
16183
|
if (tab.runtimeId) {
|
|
16022
|
-
|
|
16023
|
-
return true;
|
|
16024
|
-
return nowMs2 - Math.max(tab.updatedAt || 0, tab.openedAt || 0) <= STALE_RUNTIME_TAB_MS;
|
|
16184
|
+
return this.isRuntimeTabFresh(tab, nowMs2);
|
|
16025
16185
|
}
|
|
16026
|
-
if (dropRuntimeDetached && tab.openerRuntimeId === this.runtimeId) {
|
|
16186
|
+
if (dropRuntimeDetached && !tab.external && tab.openerRuntimeId === this.runtimeId) {
|
|
16027
16187
|
return false;
|
|
16028
16188
|
}
|
|
16029
16189
|
if (tab.external) {
|
|
16030
16190
|
if (dropAllDetachedExternal)
|
|
16031
16191
|
return false;
|
|
16032
|
-
return nowMs2 -
|
|
16192
|
+
return nowMs2 - this.tabFreshnessTs(tab) <= STALE_DETACHED_EXTERNAL_TAB_MS;
|
|
16033
16193
|
}
|
|
16034
|
-
|
|
16035
|
-
|
|
16036
|
-
|
|
16037
|
-
if (draft.activeLogicalTabId && !draft.tabs.some((tab) => tab.logicalTabId === draft.activeLogicalTabId)) {
|
|
16038
|
-
draft.activeLogicalTabId = this.localLogicalTabId || draft.tabs[0]?.logicalTabId;
|
|
16194
|
+
const ageMs = nowMs2 - this.tabFreshnessTs(tab);
|
|
16195
|
+
if (tab.detachedReason === "navigation_handoff") {
|
|
16196
|
+
return ageMs <= STALE_NAVIGATION_HANDOFF_TAB_MS;
|
|
16039
16197
|
}
|
|
16040
|
-
if (
|
|
16041
|
-
|
|
16198
|
+
if (tab.detachedReason === "opened_pending_attach") {
|
|
16199
|
+
return ageMs <= STALE_PENDING_ATTACH_TAB_MS;
|
|
16042
16200
|
}
|
|
16201
|
+
return ageMs <= STALE_DETACHED_TAB_MS;
|
|
16202
|
+
});
|
|
16203
|
+
if (keepOnlyActiveLiveTab) {
|
|
16204
|
+
this.normalizeDraftTabs(draft);
|
|
16205
|
+
const liveTabs = draft.tabs.filter((tab) => this.isRuntimeTabFresh(tab, nowMs2));
|
|
16206
|
+
const activeLiveTab = liveTabs.find((tab) => tab.logicalTabId === draft.activeLogicalTabId);
|
|
16207
|
+
const localLiveTab = liveTabs.find((tab) => tab.runtimeId === this.runtimeId);
|
|
16208
|
+
const fallbackLiveTab = [...liveTabs].sort((a, b) => this.tabFreshnessTs(b) - this.tabFreshnessTs(a))[0];
|
|
16209
|
+
const keepLiveTabId = activeLiveTab?.logicalTabId || localLiveTab?.logicalTabId || fallbackLiveTab?.logicalTabId;
|
|
16210
|
+
draft.tabs = draft.tabs.filter((tab) => {
|
|
16211
|
+
if (tab.runtimeId) {
|
|
16212
|
+
return !!keepLiveTabId && tab.logicalTabId === keepLiveTabId;
|
|
16213
|
+
}
|
|
16214
|
+
if (tab.external) {
|
|
16215
|
+
return keepRecentExternalPlaceholders && nowMs2 - this.tabFreshnessTs(tab) <= STALE_DETACHED_EXTERNAL_TAB_MS;
|
|
16216
|
+
}
|
|
16217
|
+
return false;
|
|
16218
|
+
});
|
|
16219
|
+
draft.activeLogicalTabId = keepLiveTabId || draft.tabs.find((tab) => tab.runtimeId)?.logicalTabId || draft.tabs[0]?.logicalTabId;
|
|
16043
16220
|
}
|
|
16221
|
+
this.normalizeDraftTabs(draft);
|
|
16222
|
+
}
|
|
16223
|
+
resetDraftToSingleCurrentTab(draft, url, title) {
|
|
16224
|
+
const nowTs = now();
|
|
16225
|
+
const normalizedUrl = normalizeUrl2(url);
|
|
16226
|
+
const existingLocal = draft.tabs.find((tab) => tab.runtimeId === this.runtimeId);
|
|
16227
|
+
const openedAt = Number(existingLocal?.openedAt) || nowTs;
|
|
16228
|
+
draft.tabs = [
|
|
16229
|
+
{
|
|
16230
|
+
logicalTabId: 1,
|
|
16231
|
+
runtimeId: this.runtimeId,
|
|
16232
|
+
url: normalizedUrl || existingLocal?.url || "",
|
|
16233
|
+
title: title || existingLocal?.title,
|
|
16234
|
+
openedAt,
|
|
16235
|
+
updatedAt: nowTs,
|
|
16236
|
+
external: false,
|
|
16237
|
+
detachedAt: void 0,
|
|
16238
|
+
detachedReason: void 0
|
|
16239
|
+
}
|
|
16240
|
+
];
|
|
16241
|
+
draft.activeLogicalTabId = 1;
|
|
16242
|
+
draft.nextLogicalTabId = 2;
|
|
16243
|
+
draft.lease = {
|
|
16244
|
+
holderRuntimeId: this.runtimeId,
|
|
16245
|
+
expiresAt: nowTs + this.leaseMs,
|
|
16246
|
+
updatedAt: nowTs
|
|
16247
|
+
};
|
|
16044
16248
|
}
|
|
16045
16249
|
constructor(options) {
|
|
16046
16250
|
this.siteId = options.siteId;
|
|
@@ -16056,15 +16260,16 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16056
16260
|
this.key = `${SHARED_KEY_PREFIX}${this.siteId}:${this.sessionId}`;
|
|
16057
16261
|
this.channelName = `${SHARED_CHANNEL_PREFIX}${this.siteId}:${this.sessionId}`;
|
|
16058
16262
|
this.state = this.loadState();
|
|
16263
|
+
this.normalizeDraftTabs(this.state);
|
|
16059
16264
|
}
|
|
16060
|
-
start() {
|
|
16265
|
+
start(initialHandoff) {
|
|
16061
16266
|
if (this.started)
|
|
16062
16267
|
return;
|
|
16063
16268
|
this.started = true;
|
|
16064
16269
|
this.mutate("local", (draft) => {
|
|
16065
16270
|
this.pruneDetachedTabs(draft, { dropRuntimeDetached: true, dropAllDetachedExternal: true });
|
|
16066
16271
|
});
|
|
16067
|
-
this.registerCurrentTab(window.location.href, document.title || void 0);
|
|
16272
|
+
this.registerCurrentTab(window.location.href, document.title || void 0, initialHandoff);
|
|
16068
16273
|
this.claimLease(false);
|
|
16069
16274
|
if (!this.state.task) {
|
|
16070
16275
|
this.mutate("local", (draft) => {
|
|
@@ -16227,25 +16432,23 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16227
16432
|
}
|
|
16228
16433
|
return true;
|
|
16229
16434
|
}
|
|
16230
|
-
listTabs() {
|
|
16435
|
+
listTabs(options) {
|
|
16436
|
+
const scope = options?.scope === "all" ? "all" : "context";
|
|
16231
16437
|
const nowMs2 = now();
|
|
16232
|
-
return this.state.tabs.filter((tab) =>
|
|
16233
|
-
if (tab.runtimeId) {
|
|
16234
|
-
if (tab.runtimeId === this.runtimeId)
|
|
16235
|
-
return true;
|
|
16236
|
-
return nowMs2 - Math.max(tab.updatedAt || 0, tab.openedAt || 0) <= STALE_RUNTIME_TAB_MS;
|
|
16237
|
-
}
|
|
16238
|
-
if (tab.external) {
|
|
16239
|
-
return nowMs2 - Math.max(tab.updatedAt || 0, tab.openedAt || 0) <= STALE_DETACHED_EXTERNAL_TAB_MS;
|
|
16240
|
-
}
|
|
16241
|
-
return nowMs2 - Math.max(tab.updatedAt || 0, tab.openedAt || 0) <= STALE_DETACHED_TAB_MS;
|
|
16242
|
-
});
|
|
16438
|
+
return this.state.tabs.filter((tab) => this.isTabVisibleInScope(tab, nowMs2, scope));
|
|
16243
16439
|
}
|
|
16244
16440
|
pruneTabs(options) {
|
|
16245
16441
|
this.mutate("local", (draft) => {
|
|
16246
16442
|
this.pruneDetachedTabs(draft, options);
|
|
16247
16443
|
});
|
|
16248
16444
|
}
|
|
16445
|
+
resetTabsToCurrent(url, title) {
|
|
16446
|
+
this.mutate("local", (draft) => {
|
|
16447
|
+
this.resetDraftToSingleCurrentTab(draft, url, title);
|
|
16448
|
+
});
|
|
16449
|
+
this.notifyRoleChange();
|
|
16450
|
+
return this.localLogicalTabId || 1;
|
|
16451
|
+
}
|
|
16249
16452
|
startNewTask(task) {
|
|
16250
16453
|
const startedAt = Number(task.startedAt) || now();
|
|
16251
16454
|
const nextTask = {
|
|
@@ -16265,7 +16468,7 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16265
16468
|
draft.uiStatus = void 0;
|
|
16266
16469
|
draft.activeRun = void 0;
|
|
16267
16470
|
draft.workerContext = void 0;
|
|
16268
|
-
this.
|
|
16471
|
+
this.resetDraftToSingleCurrentTab(draft, window.location.href, document.title || void 0);
|
|
16269
16472
|
});
|
|
16270
16473
|
return nextTask;
|
|
16271
16474
|
}
|
|
@@ -16405,28 +16608,56 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16405
16608
|
requestControl() {
|
|
16406
16609
|
return this.claimLease(true);
|
|
16407
16610
|
}
|
|
16408
|
-
registerCurrentTab(url, title) {
|
|
16611
|
+
registerCurrentTab(url, title, handoff) {
|
|
16409
16612
|
const normalizedUrl = normalizeUrl2(url);
|
|
16613
|
+
const handoffId = typeof handoff?.handoffId === "string" ? handoff.handoffId.trim() : "";
|
|
16614
|
+
const handoffTabId = Number(handoff?.sourceLogicalTabId);
|
|
16410
16615
|
let nextLocalTabId;
|
|
16411
16616
|
this.mutate("local", (draft) => {
|
|
16617
|
+
const nowTs = now();
|
|
16618
|
+
const leaseValid = !!(draft.lease && draft.lease.expiresAt > nowTs);
|
|
16619
|
+
const controllerRuntimeId = leaseValid ? draft.lease?.holderRuntimeId : void 0;
|
|
16620
|
+
const shouldPreferLocalAsActive = !controllerRuntimeId || controllerRuntimeId === this.runtimeId;
|
|
16412
16621
|
const existing = draft.tabs.find((tab) => tab.runtimeId === this.runtimeId);
|
|
16413
16622
|
if (existing) {
|
|
16414
16623
|
existing.url = normalizedUrl || existing.url;
|
|
16415
16624
|
existing.title = title || existing.title;
|
|
16416
|
-
existing.updatedAt =
|
|
16625
|
+
existing.updatedAt = nowTs;
|
|
16626
|
+
existing.detachedAt = void 0;
|
|
16627
|
+
existing.detachedReason = void 0;
|
|
16628
|
+
existing.handoffId = void 0;
|
|
16629
|
+
existing.handoffRunId = void 0;
|
|
16630
|
+
existing.handoffTargetUrl = void 0;
|
|
16631
|
+
existing.handoffCreatedAt = void 0;
|
|
16417
16632
|
nextLocalTabId = existing.logicalTabId;
|
|
16418
16633
|
} else {
|
|
16419
|
-
let adopted
|
|
16634
|
+
let adopted;
|
|
16635
|
+
if (handoffId) {
|
|
16636
|
+
adopted = draft.tabs.find((tab) => {
|
|
16637
|
+
if (tab.runtimeId)
|
|
16638
|
+
return false;
|
|
16639
|
+
if (String(tab.handoffId || "").trim() !== handoffId)
|
|
16640
|
+
return false;
|
|
16641
|
+
if (Number.isFinite(handoffTabId) && handoffTabId > 0 && tab.logicalTabId !== handoffTabId)
|
|
16642
|
+
return false;
|
|
16643
|
+
const ageMs = nowTs - Number(tab.handoffCreatedAt || tab.updatedAt || tab.openedAt || 0);
|
|
16644
|
+
return ageMs >= 0 && ageMs <= 3e4;
|
|
16645
|
+
});
|
|
16646
|
+
}
|
|
16420
16647
|
if (!adopted) {
|
|
16421
|
-
|
|
16422
|
-
const candidates = draft.tabs.filter((tab) => !tab.runtimeId && currentHost && extractHostname2(tab.url) === currentHost && now() - tab.updatedAt < 1e4).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
16423
|
-
adopted = candidates[0];
|
|
16648
|
+
adopted = draft.tabs.find((tab) => !tab.runtimeId && !tab.external && tab.url === normalizedUrl && nowTs - tab.openedAt < 18e4);
|
|
16424
16649
|
}
|
|
16425
16650
|
if (adopted) {
|
|
16426
16651
|
adopted.runtimeId = this.runtimeId;
|
|
16427
16652
|
adopted.url = normalizedUrl || adopted.url;
|
|
16428
16653
|
adopted.title = title || adopted.title;
|
|
16429
|
-
adopted.updatedAt =
|
|
16654
|
+
adopted.updatedAt = nowTs;
|
|
16655
|
+
adopted.detachedAt = void 0;
|
|
16656
|
+
adopted.detachedReason = void 0;
|
|
16657
|
+
adopted.handoffId = void 0;
|
|
16658
|
+
adopted.handoffRunId = void 0;
|
|
16659
|
+
adopted.handoffTargetUrl = void 0;
|
|
16660
|
+
adopted.handoffCreatedAt = void 0;
|
|
16430
16661
|
nextLocalTabId = adopted.logicalTabId;
|
|
16431
16662
|
} else {
|
|
16432
16663
|
const logicalTabId = draft.nextLogicalTabId++;
|
|
@@ -16435,14 +16666,17 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16435
16666
|
runtimeId: this.runtimeId,
|
|
16436
16667
|
url: normalizedUrl,
|
|
16437
16668
|
title,
|
|
16438
|
-
openedAt:
|
|
16439
|
-
updatedAt:
|
|
16440
|
-
external: false
|
|
16669
|
+
openedAt: nowTs,
|
|
16670
|
+
updatedAt: nowTs,
|
|
16671
|
+
external: false,
|
|
16672
|
+
detachedAt: void 0,
|
|
16673
|
+
detachedReason: void 0
|
|
16441
16674
|
});
|
|
16442
16675
|
nextLocalTabId = logicalTabId;
|
|
16443
16676
|
}
|
|
16444
16677
|
}
|
|
16445
|
-
|
|
16678
|
+
const activeEntry = draft.activeLogicalTabId ? draft.tabs.find((tab) => tab.logicalTabId === draft.activeLogicalTabId) : void 0;
|
|
16679
|
+
if (!activeEntry || !activeEntry.runtimeId || activeEntry.logicalTabId === nextLocalTabId || shouldPreferLocalAsActive) {
|
|
16446
16680
|
draft.activeLogicalTabId = nextLocalTabId;
|
|
16447
16681
|
}
|
|
16448
16682
|
});
|
|
@@ -16453,11 +16687,14 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16453
16687
|
const normalizedUrl = normalizeUrl2(payload.url);
|
|
16454
16688
|
let logicalTabId = 0;
|
|
16455
16689
|
this.mutate("local", (draft) => {
|
|
16690
|
+
const nowTs = now();
|
|
16456
16691
|
const existing = draft.tabs.find((tab) => !tab.runtimeId && !!tab.external === !!payload.external && tab.url === normalizedUrl);
|
|
16457
16692
|
if (existing) {
|
|
16458
16693
|
existing.title = payload.title || existing.title;
|
|
16459
|
-
existing.updatedAt =
|
|
16694
|
+
existing.updatedAt = nowTs;
|
|
16460
16695
|
existing.openerRuntimeId = payload.openerRuntimeId || existing.openerRuntimeId;
|
|
16696
|
+
existing.detachedAt = existing.detachedAt || nowTs;
|
|
16697
|
+
existing.detachedReason = "opened_pending_attach";
|
|
16461
16698
|
logicalTabId = existing.logicalTabId;
|
|
16462
16699
|
return;
|
|
16463
16700
|
}
|
|
@@ -16467,10 +16704,12 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16467
16704
|
runtimeId: void 0,
|
|
16468
16705
|
url: normalizedUrl,
|
|
16469
16706
|
title: payload.title,
|
|
16470
|
-
openedAt:
|
|
16471
|
-
updatedAt:
|
|
16707
|
+
openedAt: nowTs,
|
|
16708
|
+
updatedAt: nowTs,
|
|
16472
16709
|
external: !!payload.external,
|
|
16473
|
-
openerRuntimeId: payload.openerRuntimeId
|
|
16710
|
+
openerRuntimeId: payload.openerRuntimeId,
|
|
16711
|
+
detachedAt: nowTs,
|
|
16712
|
+
detachedReason: "opened_pending_attach"
|
|
16474
16713
|
});
|
|
16475
16714
|
});
|
|
16476
16715
|
return { logicalTabId };
|
|
@@ -16554,21 +16793,32 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16554
16793
|
title
|
|
16555
16794
|
});
|
|
16556
16795
|
}
|
|
16557
|
-
broadcastClosing() {
|
|
16796
|
+
broadcastClosing(handoff) {
|
|
16558
16797
|
this.closing = true;
|
|
16559
|
-
if (!this.channel)
|
|
16560
|
-
return;
|
|
16561
16798
|
this.mutate("local", (draft) => {
|
|
16799
|
+
const nowTs = now();
|
|
16562
16800
|
const localTab = draft.tabs.find((t) => t.runtimeId === this.runtimeId);
|
|
16563
16801
|
if (localTab) {
|
|
16564
16802
|
localTab.runtimeId = void 0;
|
|
16565
|
-
localTab.updatedAt =
|
|
16803
|
+
localTab.updatedAt = nowTs;
|
|
16804
|
+
localTab.detachedAt = nowTs;
|
|
16805
|
+
localTab.detachedReason = handoff ? "navigation_handoff" : "tab_close";
|
|
16806
|
+
localTab.handoffId = typeof handoff?.handoffId === "string" ? handoff.handoffId : void 0;
|
|
16807
|
+
localTab.handoffRunId = typeof handoff?.runId === "string" ? handoff.runId : void 0;
|
|
16808
|
+
localTab.handoffTargetUrl = typeof handoff?.targetUrl === "string" ? handoff.targetUrl : void 0;
|
|
16809
|
+
localTab.handoffCreatedAt = Number(handoff?.ts) || nowTs;
|
|
16810
|
+
}
|
|
16811
|
+
if (draft.lease?.holderRuntimeId === this.runtimeId) {
|
|
16812
|
+
draft.lease = void 0;
|
|
16566
16813
|
}
|
|
16567
16814
|
});
|
|
16815
|
+
if (!this.channel)
|
|
16816
|
+
return;
|
|
16568
16817
|
this.channel.postMessage({
|
|
16569
16818
|
type: "tab_closing",
|
|
16570
16819
|
runtimeId: this.runtimeId,
|
|
16571
|
-
logicalTabId: this.localLogicalTabId
|
|
16820
|
+
logicalTabId: this.localLogicalTabId,
|
|
16821
|
+
handoff
|
|
16572
16822
|
});
|
|
16573
16823
|
}
|
|
16574
16824
|
isTabAlive(logicalTabId) {
|
|
@@ -16694,8 +16944,24 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16694
16944
|
}
|
|
16695
16945
|
handleRemoteTabClosing(payload) {
|
|
16696
16946
|
const { runtimeId: closingRuntimeId } = payload;
|
|
16947
|
+
const handoff = payload?.handoff;
|
|
16948
|
+
const handoffId = typeof handoff?.handoffId === "string" && handoff.handoffId.trim() ? handoff.handoffId.trim() : void 0;
|
|
16949
|
+
const handoffRunId = typeof handoff?.runId === "string" && handoff.runId.trim() ? handoff.runId.trim() : void 0;
|
|
16950
|
+
const handoffTargetUrl = typeof handoff?.targetUrl === "string" && handoff.targetUrl.trim() ? handoff.targetUrl.trim() : void 0;
|
|
16951
|
+
const handoffCreatedAt = Number(handoff?.ts) || now();
|
|
16697
16952
|
this.mutate("local", (draft) => {
|
|
16698
|
-
|
|
16953
|
+
const nowTs = now();
|
|
16954
|
+
const tab = draft.tabs.find((t) => t.runtimeId === closingRuntimeId);
|
|
16955
|
+
if (tab) {
|
|
16956
|
+
tab.runtimeId = void 0;
|
|
16957
|
+
tab.updatedAt = nowTs;
|
|
16958
|
+
tab.detachedAt = nowTs;
|
|
16959
|
+
tab.detachedReason = handoffId ? "navigation_handoff" : "tab_close";
|
|
16960
|
+
tab.handoffId = handoffId;
|
|
16961
|
+
tab.handoffRunId = handoffRunId;
|
|
16962
|
+
tab.handoffTargetUrl = handoffTargetUrl;
|
|
16963
|
+
tab.handoffCreatedAt = handoffCreatedAt;
|
|
16964
|
+
}
|
|
16699
16965
|
if (draft.lease?.holderRuntimeId === closingRuntimeId) {
|
|
16700
16966
|
draft.lease = void 0;
|
|
16701
16967
|
}
|
|
@@ -16706,7 +16972,7 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16706
16972
|
draft.activeRun = void 0;
|
|
16707
16973
|
}
|
|
16708
16974
|
if (draft.activeLogicalTabId && !draft.tabs.some((t) => t.logicalTabId === draft.activeLogicalTabId)) {
|
|
16709
|
-
draft.activeLogicalTabId =
|
|
16975
|
+
draft.activeLogicalTabId = this.localLogicalTabId || draft.tabs[0]?.logicalTabId;
|
|
16710
16976
|
}
|
|
16711
16977
|
});
|
|
16712
16978
|
this.notifyRoleChange();
|
|
@@ -16722,21 +16988,32 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16722
16988
|
currentTab.url = currentUrl || currentTab.url;
|
|
16723
16989
|
currentTab.title = currentTitle || currentTab.title;
|
|
16724
16990
|
currentTab.updatedAt = now();
|
|
16991
|
+
currentTab.detachedAt = void 0;
|
|
16992
|
+
currentTab.detachedReason = void 0;
|
|
16725
16993
|
} else {
|
|
16994
|
+
const nowTs = now();
|
|
16726
16995
|
const logicalTabId = draft.nextLogicalTabId++;
|
|
16727
16996
|
draft.tabs.push({
|
|
16728
16997
|
logicalTabId,
|
|
16729
16998
|
runtimeId: this.runtimeId,
|
|
16730
16999
|
url: currentUrl,
|
|
16731
17000
|
title: currentTitle,
|
|
16732
|
-
openedAt:
|
|
16733
|
-
updatedAt:
|
|
16734
|
-
external: false
|
|
17001
|
+
openedAt: nowTs,
|
|
17002
|
+
updatedAt: nowTs,
|
|
17003
|
+
external: false,
|
|
17004
|
+
detachedAt: void 0,
|
|
17005
|
+
detachedReason: void 0
|
|
16735
17006
|
});
|
|
16736
17007
|
}
|
|
16737
17008
|
const lease = draft.lease;
|
|
16738
17009
|
const leaseExpired = !lease || lease.expiresAt <= now();
|
|
16739
|
-
|
|
17010
|
+
const remoteHolderRuntimeId = lease && lease.holderRuntimeId !== this.runtimeId && lease.expiresAt > now() ? lease.holderRuntimeId : void 0;
|
|
17011
|
+
const remoteHolderTab = remoteHolderRuntimeId ? draft.tabs.find((tab) => tab.runtimeId === remoteHolderRuntimeId) : void 0;
|
|
17012
|
+
const remoteHolderAlive = !!(remoteHolderTab && remoteHolderTab.updatedAt > now() - 2 * this.heartbeatMs);
|
|
17013
|
+
const hasRemoteActiveRun2 = !!(draft.activeRun?.runtimeId && draft.activeRun.runtimeId !== this.runtimeId);
|
|
17014
|
+
const hasRemoteWorkflowLock = !!(draft.workflowLock && draft.workflowLock.runtimeId !== this.runtimeId && draft.workflowLock.expiresAt > now());
|
|
17015
|
+
const shouldReclaimFromObserver = !!(remoteHolderRuntimeId && !remoteHolderAlive && !hasRemoteActiveRun2 && !hasRemoteWorkflowLock);
|
|
17016
|
+
if (leaseExpired || lease?.holderRuntimeId === this.runtimeId || shouldReclaimFromObserver) {
|
|
16740
17017
|
draft.lease = {
|
|
16741
17018
|
holderRuntimeId: this.runtimeId,
|
|
16742
17019
|
expiresAt: now() + this.leaseMs,
|
|
@@ -16755,6 +17032,7 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16755
17032
|
}
|
|
16756
17033
|
reloadFromStorage() {
|
|
16757
17034
|
const fresh = this.loadState();
|
|
17035
|
+
this.normalizeDraftTabs(fresh);
|
|
16758
17036
|
if (fresh.seq > this.state.seq || fresh.seq === this.state.seq && fresh.updatedAt > this.state.updatedAt) {
|
|
16759
17037
|
this.state = fresh;
|
|
16760
17038
|
this.syncLocalLogicalTabId();
|
|
@@ -16822,6 +17100,7 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16822
17100
|
}
|
|
16823
17101
|
const draft = sanitizeSharedState(this.state, this.siteId, this.sessionId);
|
|
16824
17102
|
updater(draft);
|
|
17103
|
+
this.normalizeDraftTabs(draft);
|
|
16825
17104
|
draft.seq = Math.max(1, Number(draft.seq) || 1) + (source === "local" ? 1 : 0);
|
|
16826
17105
|
draft.updatedAt = now();
|
|
16827
17106
|
this.state = draft;
|
|
@@ -16842,6 +17121,7 @@ var SessionCoordinator = class _SessionCoordinator {
|
|
|
16842
17121
|
if (incoming.seq === this.state.seq && incoming.updatedAt <= this.state.updatedAt)
|
|
16843
17122
|
return;
|
|
16844
17123
|
this.pruneDetachedTabs(incoming);
|
|
17124
|
+
this.normalizeDraftTabs(incoming);
|
|
16845
17125
|
this.state = incoming;
|
|
16846
17126
|
this.syncLocalLogicalTabId();
|
|
16847
17127
|
this.onStateChange?.(this.state, "remote");
|
|
@@ -17340,6 +17620,47 @@ function clearCrossDomainResumeCookie(siteId) {
|
|
|
17340
17620
|
}
|
|
17341
17621
|
}
|
|
17342
17622
|
|
|
17623
|
+
// dist/taskBoundaryGuards.js
|
|
17624
|
+
function normalizeTaskBoundaryId(input) {
|
|
17625
|
+
const normalized = String(input || "").trim();
|
|
17626
|
+
return normalized || void 0;
|
|
17627
|
+
}
|
|
17628
|
+
function shouldAdoptIncomingBoundary(params) {
|
|
17629
|
+
const incoming = normalizeTaskBoundaryId(params.incomingBoundaryId);
|
|
17630
|
+
const current = normalizeTaskBoundaryId(params.currentBoundaryId);
|
|
17631
|
+
if (!incoming)
|
|
17632
|
+
return false;
|
|
17633
|
+
if (incoming === current)
|
|
17634
|
+
return false;
|
|
17635
|
+
if (!current)
|
|
17636
|
+
return params.allowBootstrapAdoption !== false;
|
|
17637
|
+
if (params.taskEpochAdvanced === true && params.hasPendingRun !== true) {
|
|
17638
|
+
return true;
|
|
17639
|
+
}
|
|
17640
|
+
return false;
|
|
17641
|
+
}
|
|
17642
|
+
function shouldAcceptWorkerSnapshot(params) {
|
|
17643
|
+
const incoming = normalizeTaskBoundaryId(params.incomingBoundaryId);
|
|
17644
|
+
const current = normalizeTaskBoundaryId(params.currentBoundaryId);
|
|
17645
|
+
if (incoming && current && incoming === current) {
|
|
17646
|
+
return { accept: true, reason: "match" };
|
|
17647
|
+
}
|
|
17648
|
+
if (!incoming) {
|
|
17649
|
+
if (!current && params.allowBootstrapAdoption !== false) {
|
|
17650
|
+
return { accept: true, reason: "bootstrap_adopt" };
|
|
17651
|
+
}
|
|
17652
|
+
return { accept: false, reason: "missing_incoming" };
|
|
17653
|
+
}
|
|
17654
|
+
if (shouldAdoptIncomingBoundary(params)) {
|
|
17655
|
+
return {
|
|
17656
|
+
accept: true,
|
|
17657
|
+
adoptedBoundaryId: incoming,
|
|
17658
|
+
reason: current ? "epoch_adopt" : "bootstrap_adopt"
|
|
17659
|
+
};
|
|
17660
|
+
}
|
|
17661
|
+
return { accept: false, reason: "mismatch" };
|
|
17662
|
+
}
|
|
17663
|
+
|
|
17343
17664
|
// dist/taskLifecycleGuards.js
|
|
17344
17665
|
function shouldStartFreshTask(taskStatus) {
|
|
17345
17666
|
return taskStatus === "completed" || taskStatus === "ended";
|
|
@@ -17368,7 +17689,13 @@ function shouldClearPendingFromSharedState(params) {
|
|
|
17368
17689
|
return false;
|
|
17369
17690
|
}
|
|
17370
17691
|
function shouldIgnoreRunScopedMessage(params) {
|
|
17371
|
-
const { type, messageRunId, pendingRunId, sharedActiveRunId, taskStatus, ignoredRunIds: ignoredRunIds2 } = params;
|
|
17692
|
+
const { type, messageRunId, messageTaskBoundaryId, currentTaskBoundaryId: currentTaskBoundaryId2, pendingRunId, sharedActiveRunId, taskStatus, ignoredRunIds: ignoredRunIds2 } = params;
|
|
17693
|
+
const currentBoundary = normalizeTaskBoundaryId(currentTaskBoundaryId2);
|
|
17694
|
+
const messageBoundary = normalizeTaskBoundaryId(messageTaskBoundaryId);
|
|
17695
|
+
if ((type === "run_started" || type === "run_completed") && currentBoundary) {
|
|
17696
|
+
if (!messageBoundary || messageBoundary !== currentBoundary)
|
|
17697
|
+
return true;
|
|
17698
|
+
}
|
|
17372
17699
|
if (!messageRunId && type !== "run_started")
|
|
17373
17700
|
return false;
|
|
17374
17701
|
if (messageRunId && ignoredRunIds2?.has(messageRunId))
|
|
@@ -17451,6 +17778,8 @@ var suppressCheckpointSync = false;
|
|
|
17451
17778
|
var currentMode = "controller";
|
|
17452
17779
|
var workerReady = false;
|
|
17453
17780
|
var autoResumeAttempted = false;
|
|
17781
|
+
var agentNavigationPending = false;
|
|
17782
|
+
var currentTaskBoundaryId = "";
|
|
17454
17783
|
var runSafetyTimer = null;
|
|
17455
17784
|
var unloadHandlerInstalled = false;
|
|
17456
17785
|
var pendingTaskSuggestion = null;
|
|
@@ -17503,6 +17832,106 @@ function createId2(prefix) {
|
|
|
17503
17832
|
return `${prefix}-${Date.now()}-${Math.floor(Math.random() * 1e5)}`;
|
|
17504
17833
|
}
|
|
17505
17834
|
}
|
|
17835
|
+
function createTaskBoundaryId() {
|
|
17836
|
+
return createId2("task-boundary");
|
|
17837
|
+
}
|
|
17838
|
+
function sanitizeNavigationHandoff(input) {
|
|
17839
|
+
if (!input || typeof input !== "object")
|
|
17840
|
+
return void 0;
|
|
17841
|
+
const handoffId = typeof input.handoffId === "string" ? input.handoffId.trim() : "";
|
|
17842
|
+
const targetUrl = typeof input.targetUrl === "string" ? input.targetUrl.trim() : "";
|
|
17843
|
+
if (!handoffId || !targetUrl)
|
|
17844
|
+
return void 0;
|
|
17845
|
+
const sourceLogicalTabId = Number(input.sourceLogicalTabId);
|
|
17846
|
+
return {
|
|
17847
|
+
handoffId,
|
|
17848
|
+
targetUrl,
|
|
17849
|
+
sourceLogicalTabId: Number.isFinite(sourceLogicalTabId) && sourceLogicalTabId > 0 ? sourceLogicalTabId : void 0,
|
|
17850
|
+
runId: typeof input.runId === "string" && input.runId.trim() ? input.runId.trim() : void 0,
|
|
17851
|
+
createdAt: Number(input.createdAt) || Date.now(),
|
|
17852
|
+
consumed: input.consumed === true
|
|
17853
|
+
};
|
|
17854
|
+
}
|
|
17855
|
+
function toSharedNavigationHandoff(input) {
|
|
17856
|
+
if (!input)
|
|
17857
|
+
return void 0;
|
|
17858
|
+
return {
|
|
17859
|
+
handoffId: input.handoffId,
|
|
17860
|
+
targetUrl: input.targetUrl,
|
|
17861
|
+
sourceLogicalTabId: input.sourceLogicalTabId,
|
|
17862
|
+
runId: input.runId,
|
|
17863
|
+
ts: input.createdAt
|
|
17864
|
+
};
|
|
17865
|
+
}
|
|
17866
|
+
function toPersistedNavigationHandoff(intent) {
|
|
17867
|
+
return {
|
|
17868
|
+
handoffId: intent.handoffId,
|
|
17869
|
+
targetUrl: intent.targetUrl,
|
|
17870
|
+
sourceLogicalTabId: intent.sourceLogicalTabId,
|
|
17871
|
+
runId: intent.runId,
|
|
17872
|
+
createdAt: Number(intent.ts) || Date.now(),
|
|
17873
|
+
consumed: false
|
|
17874
|
+
};
|
|
17875
|
+
}
|
|
17876
|
+
function resolveExistingTaskBoundaryIdFromState(state) {
|
|
17877
|
+
const pendingCandidate = typeof state?.pendingRun?.taskBoundaryId === "string" ? state.pendingRun.taskBoundaryId : void 0;
|
|
17878
|
+
if (pendingCandidate)
|
|
17879
|
+
return normalizeTaskBoundaryId(pendingCandidate);
|
|
17880
|
+
const workerCandidate = typeof state?.workerState?.taskBoundaryId === "string" ? state.workerState.taskBoundaryId : void 0;
|
|
17881
|
+
if (workerCandidate)
|
|
17882
|
+
return normalizeTaskBoundaryId(workerCandidate);
|
|
17883
|
+
return void 0;
|
|
17884
|
+
}
|
|
17885
|
+
function resolveTaskBoundaryIdFromState(state) {
|
|
17886
|
+
const existing = resolveExistingTaskBoundaryIdFromState(state);
|
|
17887
|
+
if (existing)
|
|
17888
|
+
return existing;
|
|
17889
|
+
return createTaskBoundaryId();
|
|
17890
|
+
}
|
|
17891
|
+
function resolveCurrentTaskBoundaryCandidate() {
|
|
17892
|
+
return normalizeTaskBoundaryId(currentTaskBoundaryId) || resolveExistingTaskBoundaryIdFromState(runtimeState);
|
|
17893
|
+
}
|
|
17894
|
+
function shouldAcceptIncomingWorkerBoundary(params) {
|
|
17895
|
+
const decision = shouldAcceptWorkerSnapshot({
|
|
17896
|
+
source: params.source,
|
|
17897
|
+
incomingBoundaryId: params.incomingBoundaryId,
|
|
17898
|
+
currentBoundaryId: resolveCurrentTaskBoundaryCandidate(),
|
|
17899
|
+
taskEpochAdvanced: params.taskEpochAdvanced,
|
|
17900
|
+
hasPendingRun: !!runtimeState?.pendingRun,
|
|
17901
|
+
taskStatus: runtimeState?.activeTask?.status,
|
|
17902
|
+
allowBootstrapAdoption: params.allowBootstrapAdoption
|
|
17903
|
+
});
|
|
17904
|
+
if (!decision.accept)
|
|
17905
|
+
return false;
|
|
17906
|
+
if (decision.adoptedBoundaryId) {
|
|
17907
|
+
currentTaskBoundaryId = decision.adoptedBoundaryId;
|
|
17908
|
+
}
|
|
17909
|
+
return true;
|
|
17910
|
+
}
|
|
17911
|
+
function getUnconsumedNavigationHandoff(maxAgeMs = 12e4) {
|
|
17912
|
+
const handoff = sanitizeNavigationHandoff(runtimeState?.lastNavigationHandoff);
|
|
17913
|
+
if (!handoff || handoff.consumed === true)
|
|
17914
|
+
return void 0;
|
|
17915
|
+
const ageMs = Date.now() - Number(handoff.createdAt || 0);
|
|
17916
|
+
if (!Number.isFinite(ageMs) || ageMs < -5e3 || ageMs > maxAgeMs)
|
|
17917
|
+
return void 0;
|
|
17918
|
+
return handoff;
|
|
17919
|
+
}
|
|
17920
|
+
function syncCurrentTaskBoundaryId(options) {
|
|
17921
|
+
const pendingBoundary = sanitizePendingRun(runtimeState?.pendingRun)?.taskBoundaryId;
|
|
17922
|
+
if (pendingBoundary) {
|
|
17923
|
+
currentTaskBoundaryId = pendingBoundary;
|
|
17924
|
+
return;
|
|
17925
|
+
}
|
|
17926
|
+
const workerBoundary = sanitizeWorkerState(runtimeState?.workerState)?.taskBoundaryId;
|
|
17927
|
+
if (workerBoundary) {
|
|
17928
|
+
currentTaskBoundaryId = workerBoundary;
|
|
17929
|
+
return;
|
|
17930
|
+
}
|
|
17931
|
+
if (!currentTaskBoundaryId || options?.rotateIfMissing) {
|
|
17932
|
+
currentTaskBoundaryId = createTaskBoundaryId();
|
|
17933
|
+
}
|
|
17934
|
+
}
|
|
17506
17935
|
function getOrCreateRuntimeId(siteId) {
|
|
17507
17936
|
const key = `${RUNTIME_ID_PREFIX}${siteId}`;
|
|
17508
17937
|
try {
|
|
@@ -17673,6 +18102,7 @@ function createDefaultRuntimeState(sessionId, rid) {
|
|
|
17673
18102
|
executionMode: "controller",
|
|
17674
18103
|
workerState: void 0,
|
|
17675
18104
|
pendingRun: void 0,
|
|
18105
|
+
lastNavigationHandoff: void 0,
|
|
17676
18106
|
taskEpoch: 1,
|
|
17677
18107
|
activeTask: createDefaultTaskState(),
|
|
17678
18108
|
lastRoutingDecision: void 0,
|
|
@@ -18054,9 +18484,12 @@ function shouldIgnoreRunScopedWorkerMessage(msg) {
|
|
|
18054
18484
|
if (!RUN_SCOPED_WORKER_MESSAGE_TYPES.has(type))
|
|
18055
18485
|
return false;
|
|
18056
18486
|
const messageRunId = typeof msg?.runId === "string" && msg.runId ? msg.runId : void 0;
|
|
18487
|
+
const messageTaskBoundaryId = typeof msg?.taskBoundaryId === "string" && msg.taskBoundaryId ? msg.taskBoundaryId : void 0;
|
|
18057
18488
|
return shouldIgnoreRunScopedMessage({
|
|
18058
18489
|
type,
|
|
18059
18490
|
messageRunId,
|
|
18491
|
+
messageTaskBoundaryId,
|
|
18492
|
+
currentTaskBoundaryId: resolveCurrentTaskBoundaryCandidate(),
|
|
18060
18493
|
pendingRunId: getPendingRunId(),
|
|
18061
18494
|
sharedActiveRunId: sessionCoordinator?.getState()?.activeRun?.runId,
|
|
18062
18495
|
taskStatus: runtimeState?.activeTask?.status,
|
|
@@ -18097,14 +18530,66 @@ function normalizeAskUserQuestions(input) {
|
|
|
18097
18530
|
}
|
|
18098
18531
|
return out.slice(0, 6);
|
|
18099
18532
|
}
|
|
18533
|
+
function buildAskUserDispatchText(text, askUserAnswers) {
|
|
18534
|
+
const trimmed = String(text || "").trim();
|
|
18535
|
+
if (trimmed)
|
|
18536
|
+
return trimmed;
|
|
18537
|
+
if (!askUserAnswers || typeof askUserAnswers !== "object")
|
|
18538
|
+
return "";
|
|
18539
|
+
const answersByKey = askUserAnswers.answersByKey && typeof askUserAnswers.answersByKey === "object" ? askUserAnswers.answersByKey : {};
|
|
18540
|
+
const pendingQuestions = normalizeAskUserQuestions(runtimeState?.workerState?.pendingAskUser?.questions);
|
|
18541
|
+
const rawKeys = Array.isArray(askUserAnswers.keys) ? askUserAnswers.keys : [];
|
|
18542
|
+
const resolvedKeys = rawKeys.map((key) => String(key || "").trim()).filter(Boolean);
|
|
18543
|
+
if (resolvedKeys.length === 0) {
|
|
18544
|
+
for (const question of pendingQuestions) {
|
|
18545
|
+
const key = String(question.key || "").trim();
|
|
18546
|
+
if (key)
|
|
18547
|
+
resolvedKeys.push(key);
|
|
18548
|
+
}
|
|
18549
|
+
}
|
|
18550
|
+
if (resolvedKeys.length === 0) {
|
|
18551
|
+
for (const key of Object.keys(answersByKey)) {
|
|
18552
|
+
const normalizedKey = String(key || "").trim();
|
|
18553
|
+
if (normalizedKey)
|
|
18554
|
+
resolvedKeys.push(normalizedKey);
|
|
18555
|
+
}
|
|
18556
|
+
}
|
|
18557
|
+
const lines = [];
|
|
18558
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18559
|
+
for (const key of resolvedKeys) {
|
|
18560
|
+
const normalizedKey = String(key || "").trim();
|
|
18561
|
+
if (!normalizedKey || seen.has(normalizedKey))
|
|
18562
|
+
continue;
|
|
18563
|
+
seen.add(normalizedKey);
|
|
18564
|
+
const value = String(answersByKey[normalizedKey] || "").trim();
|
|
18565
|
+
lines.push(`${normalizedKey}: ${value || "(no answer provided)"}`);
|
|
18566
|
+
}
|
|
18567
|
+
if (lines.length > 0) {
|
|
18568
|
+
return lines.join("\n");
|
|
18569
|
+
}
|
|
18570
|
+
return String(askUserAnswers.rawText || "").trim();
|
|
18571
|
+
}
|
|
18100
18572
|
function normalizeRunCompletionState(msg) {
|
|
18101
18573
|
if (!msg || typeof msg !== "object") {
|
|
18102
|
-
return {
|
|
18574
|
+
return {
|
|
18575
|
+
taskComplete: false,
|
|
18576
|
+
needsUserInput: false,
|
|
18577
|
+
terminalState: "in_progress",
|
|
18578
|
+
contextResetRecommended: false
|
|
18579
|
+
};
|
|
18103
18580
|
}
|
|
18581
|
+
const incomingTerminal = String(msg.terminalState || "").trim().toLowerCase();
|
|
18104
18582
|
const needsUserInput = msg.needsUserInput === true;
|
|
18105
|
-
const
|
|
18583
|
+
const inferredTerminalState = incomingTerminal === "waiting_input" || incomingTerminal === "in_progress" || incomingTerminal === "completed" || incomingTerminal === "failed" ? incomingTerminal : needsUserInput ? "waiting_input" : msg.taskComplete === true ? "completed" : msg.ok === false ? "failed" : "in_progress";
|
|
18584
|
+
const taskComplete = inferredTerminalState === "completed" || msg.taskComplete === true && inferredTerminalState !== "waiting_input";
|
|
18106
18585
|
const questions = normalizeAskUserQuestions(msg.questions);
|
|
18107
|
-
return {
|
|
18586
|
+
return {
|
|
18587
|
+
taskComplete,
|
|
18588
|
+
needsUserInput: inferredTerminalState === "waiting_input" || needsUserInput,
|
|
18589
|
+
terminalState: inferredTerminalState,
|
|
18590
|
+
contextResetRecommended: msg.contextResetRecommended === true || inferredTerminalState === "completed",
|
|
18591
|
+
...questions.length ? { questions } : {}
|
|
18592
|
+
};
|
|
18108
18593
|
}
|
|
18109
18594
|
function getLatestAssistantText(runId) {
|
|
18110
18595
|
if (runId && latestAssistantByRunId.has(runId)) {
|
|
@@ -18318,6 +18803,7 @@ function sanitizeTimelineEvents(input) {
|
|
|
18318
18803
|
function sanitizeWorkerState(input) {
|
|
18319
18804
|
if (!input || typeof input !== "object")
|
|
18320
18805
|
return void 0;
|
|
18806
|
+
const taskBoundaryIdCandidate = String(input.taskBoundaryId || "").trim();
|
|
18321
18807
|
const historyRaw = Array.isArray(input.history) ? input.history : [];
|
|
18322
18808
|
const plannerRaw = Array.isArray(input.plannerHistory) ? input.plannerHistory : [];
|
|
18323
18809
|
const agentPrevStepsRaw = Array.isArray(input.agentPrevSteps) ? input.agentPrevSteps : Array.isArray(input.lastToolPreviousSteps) ? input.lastToolPreviousSteps : [];
|
|
@@ -18325,13 +18811,24 @@ function sanitizeWorkerState(input) {
|
|
|
18325
18811
|
const plannerHistory = cloneUnknownArrayTail2(plannerRaw, MAX_WORKER_STEPS);
|
|
18326
18812
|
const agentPrevSteps = cloneUnknownArrayTail2(agentPrevStepsRaw, MAX_WORKER_STEPS * 2);
|
|
18327
18813
|
const pendingQuestions = normalizeAskUserQuestions(input?.pendingAskUser?.questions);
|
|
18814
|
+
const pendingStepRefRaw = input?.pendingAskUser?.stepRef;
|
|
18815
|
+
const pendingStepRef = pendingStepRefRaw && Number.isFinite(Number(pendingStepRefRaw.stepIndex)) && Number(pendingStepRefRaw.stepIndex) >= 0 && Number.isFinite(Number(pendingStepRefRaw.functionIndex)) && Number(pendingStepRefRaw.functionIndex) >= 0 ? {
|
|
18816
|
+
stepIndex: Number(pendingStepRefRaw.stepIndex),
|
|
18817
|
+
functionIndex: Number(pendingStepRefRaw.functionIndex),
|
|
18818
|
+
...typeof pendingStepRefRaw.accTreeId === "string" && pendingStepRefRaw.accTreeId.trim() ? { accTreeId: pendingStepRefRaw.accTreeId.trim() } : {}
|
|
18819
|
+
} : void 0;
|
|
18328
18820
|
const pendingAskUser = pendingQuestions.length ? {
|
|
18329
18821
|
questions: pendingQuestions,
|
|
18330
18822
|
source: input?.pendingAskUser?.source === "planner" ? "planner" : "act",
|
|
18331
|
-
askedAt: Number(input?.pendingAskUser?.askedAt) || Date.now()
|
|
18823
|
+
askedAt: Number(input?.pendingAskUser?.askedAt) || Date.now(),
|
|
18824
|
+
boundaryId: typeof input?.pendingAskUser?.boundaryId === "string" && input.pendingAskUser.boundaryId.trim() ? input.pendingAskUser.boundaryId.trim() : void 0,
|
|
18825
|
+
...pendingStepRef ? { stepRef: pendingStepRef } : {}
|
|
18332
18826
|
} : void 0;
|
|
18827
|
+
const rootUserInput = typeof input.rootUserInput === "string" ? input.rootUserInput.trim() : "";
|
|
18333
18828
|
return {
|
|
18334
18829
|
trajectoryId: typeof input.trajectoryId === "string" ? input.trajectoryId : void 0,
|
|
18830
|
+
taskBoundaryId: taskBoundaryIdCandidate || void 0,
|
|
18831
|
+
rootUserInput: rootUserInput || void 0,
|
|
18335
18832
|
history: history2,
|
|
18336
18833
|
plannerHistory,
|
|
18337
18834
|
agentPrevSteps,
|
|
@@ -18360,6 +18857,7 @@ function normalizePersistedState(raw, sessionId, rid) {
|
|
|
18360
18857
|
executionMode: raw.executionMode === "observer" || raw.executionMode === "controller" ? raw.executionMode : "controller",
|
|
18361
18858
|
workerState: sanitizeWorkerState(raw.workerState),
|
|
18362
18859
|
pendingRun,
|
|
18860
|
+
lastNavigationHandoff: sanitizeNavigationHandoff(raw.lastNavigationHandoff),
|
|
18363
18861
|
taskEpoch: Math.max(1, Number(raw.taskEpoch) || 1),
|
|
18364
18862
|
activeTask: parsedTask,
|
|
18365
18863
|
lastRoutingDecision: raw.lastRoutingDecision && (raw.lastRoutingDecision.mode === "act" || raw.lastRoutingDecision.mode === "planner") ? {
|
|
@@ -18395,13 +18893,23 @@ function toSharedWorkerContext(state) {
|
|
|
18395
18893
|
const pendingQuestions = normalizeAskUserQuestions(state.pendingAskUser?.questions);
|
|
18396
18894
|
return {
|
|
18397
18895
|
trajectoryId: state.trajectoryId,
|
|
18896
|
+
taskBoundaryId: typeof state.taskBoundaryId === "string" ? state.taskBoundaryId : void 0,
|
|
18897
|
+
rootUserInput: typeof state.rootUserInput === "string" ? state.rootUserInput : void 0,
|
|
18398
18898
|
history: Array.isArray(state.history) ? state.history.slice(-MAX_WORKER_HISTORY).map((message) => toWorkerHistoryEntry(message)).filter((message) => !!message) : [],
|
|
18399
18899
|
plannerHistory: cloneUnknownArrayTail2(state.plannerHistory, MAX_WORKER_STEPS),
|
|
18400
18900
|
agentPrevSteps: cloneUnknownArrayTail2(state.agentPrevSteps, MAX_WORKER_STEPS * 2),
|
|
18401
18901
|
pendingAskUser: pendingQuestions.length ? {
|
|
18402
18902
|
questions: pendingQuestions,
|
|
18403
18903
|
source: state.pendingAskUser?.source === "planner" ? "planner" : "act",
|
|
18404
|
-
askedAt: Number(state.pendingAskUser?.askedAt) || Date.now()
|
|
18904
|
+
askedAt: Number(state.pendingAskUser?.askedAt) || Date.now(),
|
|
18905
|
+
boundaryId: typeof state.pendingAskUser?.boundaryId === "string" && state.pendingAskUser.boundaryId.trim() ? state.pendingAskUser.boundaryId.trim() : void 0,
|
|
18906
|
+
...state.pendingAskUser?.stepRef && Number.isFinite(Number(state.pendingAskUser.stepRef.stepIndex)) && Number(state.pendingAskUser.stepRef.stepIndex) >= 0 && Number.isFinite(Number(state.pendingAskUser.stepRef.functionIndex)) && Number(state.pendingAskUser.stepRef.functionIndex) >= 0 ? {
|
|
18907
|
+
stepRef: {
|
|
18908
|
+
stepIndex: Number(state.pendingAskUser.stepRef.stepIndex),
|
|
18909
|
+
functionIndex: Number(state.pendingAskUser.stepRef.functionIndex),
|
|
18910
|
+
...typeof state.pendingAskUser.stepRef.accTreeId === "string" && state.pendingAskUser.stepRef.accTreeId.trim() ? { accTreeId: state.pendingAskUser.stepRef.accTreeId.trim() } : {}
|
|
18911
|
+
}
|
|
18912
|
+
} : {}
|
|
18405
18913
|
} : void 0,
|
|
18406
18914
|
updatedAt: Number(state.updatedAt) || Date.now()
|
|
18407
18915
|
};
|
|
@@ -18411,6 +18919,7 @@ function sanitizePendingRun(input) {
|
|
|
18411
18919
|
return void 0;
|
|
18412
18920
|
const id = typeof input.id === "string" && input.id.trim() ? input.id.trim() : void 0;
|
|
18413
18921
|
const text = typeof input.text === "string" ? input.text.trim() : "";
|
|
18922
|
+
const taskBoundaryId = typeof input.taskBoundaryId === "string" && input.taskBoundaryId.trim() ? input.taskBoundaryId.trim() : void 0;
|
|
18414
18923
|
if (!id || !text)
|
|
18415
18924
|
return void 0;
|
|
18416
18925
|
return {
|
|
@@ -18419,6 +18928,7 @@ function sanitizePendingRun(input) {
|
|
|
18419
18928
|
startedAt: Number(input.startedAt) || Date.now(),
|
|
18420
18929
|
attempts: Math.max(0, Number(input.attempts) || 0),
|
|
18421
18930
|
autoResume: input.autoResume !== false,
|
|
18931
|
+
taskBoundaryId,
|
|
18422
18932
|
resumeRequired: input.resumeRequired === true,
|
|
18423
18933
|
resumeReason: input.resumeReason === "cross_host_navigation" || input.resumeReason === "agent_navigation" || input.resumeReason === "handoff" || input.resumeReason === "page_reload" ? input.resumeReason : void 0
|
|
18424
18934
|
};
|
|
@@ -18441,17 +18951,19 @@ function ensureUnloadHandler() {
|
|
|
18441
18951
|
unloadHandlerInstalled = true;
|
|
18442
18952
|
const onPageHide = () => {
|
|
18443
18953
|
if (runtimeState?.pendingRun?.autoResume) {
|
|
18954
|
+
const effectiveReason = runtimeState.pendingRun.resumeReason || (agentNavigationPending ? "agent_navigation" : "page_reload");
|
|
18444
18955
|
const markedPending = sanitizePendingRun({
|
|
18445
18956
|
...runtimeState.pendingRun,
|
|
18446
18957
|
resumeRequired: true,
|
|
18447
|
-
resumeReason:
|
|
18958
|
+
resumeReason: effectiveReason
|
|
18448
18959
|
});
|
|
18449
18960
|
runtimeState.pendingRun = markedPending;
|
|
18450
18961
|
if (markedPending) {
|
|
18451
18962
|
sessionCoordinator?.clearActiveRunRuntimeId(markedPending.id);
|
|
18452
18963
|
}
|
|
18453
18964
|
}
|
|
18454
|
-
|
|
18965
|
+
const pendingHandoff = getUnconsumedNavigationHandoff();
|
|
18966
|
+
sessionCoordinator?.broadcastClosing(toSharedNavigationHandoff(pendingHandoff));
|
|
18455
18967
|
if (runtimeState?.pendingRun) {
|
|
18456
18968
|
sessionCoordinator?.releaseWorkflowLock(runtimeState.pendingRun.id);
|
|
18457
18969
|
}
|
|
@@ -18463,8 +18975,16 @@ function ensureUnloadHandler() {
|
|
|
18463
18975
|
id: runtimeState.pendingRun.id,
|
|
18464
18976
|
text: runtimeState.pendingRun.text,
|
|
18465
18977
|
startedAt: runtimeState.pendingRun.startedAt,
|
|
18466
|
-
attempts: runtimeState.pendingRun.attempts
|
|
18978
|
+
attempts: runtimeState.pendingRun.attempts,
|
|
18979
|
+
taskBoundaryId: runtimeState.pendingRun.taskBoundaryId || currentTaskBoundaryId
|
|
18467
18980
|
},
|
|
18981
|
+
handoff: pendingHandoff ? {
|
|
18982
|
+
handoffId: pendingHandoff.handoffId,
|
|
18983
|
+
sourceLogicalTabId: pendingHandoff.sourceLogicalTabId,
|
|
18984
|
+
runId: pendingHandoff.runId,
|
|
18985
|
+
targetUrl: pendingHandoff.targetUrl,
|
|
18986
|
+
createdAt: pendingHandoff.createdAt
|
|
18987
|
+
} : void 0,
|
|
18468
18988
|
activeTask: runtimeState.activeTask ? { taskId: runtimeState.activeTask.taskId, status: runtimeState.activeTask.status } : void 0,
|
|
18469
18989
|
taskEpoch: runtimeState.taskEpoch,
|
|
18470
18990
|
timestamp: Date.now()
|
|
@@ -18732,7 +19252,20 @@ function setExecutionMode(mode, info) {
|
|
|
18732
19252
|
function setPendingRun(next) {
|
|
18733
19253
|
if (!runtimeState)
|
|
18734
19254
|
return;
|
|
18735
|
-
|
|
19255
|
+
if (next) {
|
|
19256
|
+
runtimeState.pendingRun = sanitizePendingRun({
|
|
19257
|
+
...next,
|
|
19258
|
+
taskBoundaryId: next.taskBoundaryId || currentTaskBoundaryId
|
|
19259
|
+
});
|
|
19260
|
+
} else {
|
|
19261
|
+
runtimeState.pendingRun = void 0;
|
|
19262
|
+
}
|
|
19263
|
+
persistRuntimeState();
|
|
19264
|
+
}
|
|
19265
|
+
function setLatestNavigationHandoff(next) {
|
|
19266
|
+
if (!runtimeState)
|
|
19267
|
+
return;
|
|
19268
|
+
runtimeState.lastNavigationHandoff = sanitizeNavigationHandoff(next);
|
|
18736
19269
|
persistRuntimeState();
|
|
18737
19270
|
}
|
|
18738
19271
|
function postRun(text, options) {
|
|
@@ -18762,12 +19295,15 @@ function postRun(text, options) {
|
|
|
18762
19295
|
appendUiMessage("user", trimmed, true);
|
|
18763
19296
|
}
|
|
18764
19297
|
const previousAttempts = runtimeState?.pendingRun?.id === runId ? runtimeState.pendingRun.attempts : 0;
|
|
19298
|
+
const boundaryForRun = runtimeState?.pendingRun?.id === runId ? runtimeState.pendingRun.taskBoundaryId || currentTaskBoundaryId : currentTaskBoundaryId;
|
|
19299
|
+
agentNavigationPending = false;
|
|
18765
19300
|
setPendingRun({
|
|
18766
19301
|
id: runId,
|
|
18767
19302
|
text: trimmed,
|
|
18768
19303
|
startedAt: Date.now(),
|
|
18769
19304
|
attempts: resume ? previousAttempts + 1 : 0,
|
|
18770
19305
|
autoResume: options?.autoResume !== false,
|
|
19306
|
+
taskBoundaryId: boundaryForRun,
|
|
18771
19307
|
resumeRequired: false,
|
|
18772
19308
|
resumeReason: void 0
|
|
18773
19309
|
});
|
|
@@ -18800,15 +19336,18 @@ function postRun(text, options) {
|
|
|
18800
19336
|
}, 5 * 6e4);
|
|
18801
19337
|
}
|
|
18802
19338
|
function dispatchUserPrompt(text, options) {
|
|
18803
|
-
const trimmed =
|
|
19339
|
+
const trimmed = buildAskUserDispatchText(text, options?.askUserAnswers);
|
|
18804
19340
|
if (!trimmed)
|
|
18805
19341
|
return;
|
|
18806
19342
|
maybeClearStalePendingRun();
|
|
18807
19343
|
const activeTaskStatus = runtimeState?.activeTask?.status;
|
|
18808
19344
|
const shouldStartFreshTask2 = !!options?.startNewTask || shouldStartFreshTask(activeTaskStatus);
|
|
18809
|
-
sessionCoordinator?.pruneTabs({
|
|
19345
|
+
sessionCoordinator?.pruneTabs(shouldStartFreshTask2 ? {
|
|
18810
19346
|
dropRuntimeDetached: true,
|
|
18811
|
-
|
|
19347
|
+
keepOnlyActiveLiveTab: true,
|
|
19348
|
+
keepRecentExternalPlaceholders: true
|
|
19349
|
+
} : {
|
|
19350
|
+
dropRuntimeDetached: true
|
|
18812
19351
|
});
|
|
18813
19352
|
if (shouldStartFreshTask2) {
|
|
18814
19353
|
const autoReason = options?.reason || (activeTaskStatus === "completed" ? "auto_after_task_complete" : "auto_after_task_end");
|
|
@@ -18914,12 +19453,24 @@ async function applyAsyncRuntimeStateHydration(key) {
|
|
|
18914
19453
|
const incomingUpdatedAt = Number(normalized.updatedAt) || 0;
|
|
18915
19454
|
if (incomingUpdatedAt <= localUpdatedAt + 200)
|
|
18916
19455
|
return;
|
|
19456
|
+
const localTaskEpoch = Math.max(1, Number(runtimeState.taskEpoch) || 1);
|
|
19457
|
+
const incomingTaskEpoch = Math.max(1, Number(normalized.taskEpoch) || 1);
|
|
19458
|
+
const incomingBoundaryId = resolveExistingTaskBoundaryIdFromState(normalized);
|
|
19459
|
+
if (!shouldAcceptIncomingWorkerBoundary({
|
|
19460
|
+
source: "indexeddb_checkpoint",
|
|
19461
|
+
incomingBoundaryId,
|
|
19462
|
+
taskEpochAdvanced: incomingTaskEpoch > localTaskEpoch,
|
|
19463
|
+
allowBootstrapAdoption: true
|
|
19464
|
+
})) {
|
|
19465
|
+
return;
|
|
19466
|
+
}
|
|
18917
19467
|
runtimeState = normalizePersistedState({
|
|
18918
19468
|
...runtimeState,
|
|
18919
19469
|
...normalized,
|
|
18920
19470
|
sessionId: runtimeState.sessionId,
|
|
18921
19471
|
runtimeId
|
|
18922
19472
|
}, runtimeState.sessionId, runtimeId);
|
|
19473
|
+
syncCurrentTaskBoundaryId({ rotateIfMissing: !currentTaskBoundaryId });
|
|
18923
19474
|
persistRuntimeState();
|
|
18924
19475
|
if (ui) {
|
|
18925
19476
|
ui.clearMessages();
|
|
@@ -18939,6 +19490,9 @@ async function applyAsyncRuntimeStateHydration(key) {
|
|
|
18939
19490
|
ui.close();
|
|
18940
19491
|
}
|
|
18941
19492
|
}
|
|
19493
|
+
if (workerReady && worker) {
|
|
19494
|
+
worker.postMessage({ type: "update_config", config: { taskBoundaryId: currentTaskBoundaryId } });
|
|
19495
|
+
}
|
|
18942
19496
|
if (workerReady && worker && runtimeState.workerState && currentMode === "controller") {
|
|
18943
19497
|
worker.postMessage({ type: "hydrate_state", state: runtimeState.workerState });
|
|
18944
19498
|
emit("context_restored", { source: "indexeddb_checkpoint", ts: Date.now() });
|
|
@@ -18959,6 +19513,9 @@ function applyCoordinatorState(state, source) {
|
|
|
18959
19513
|
runtimeState.timeline = [];
|
|
18960
19514
|
clearTaskUiState();
|
|
18961
19515
|
setPendingRun(void 0);
|
|
19516
|
+
runtimeState.workerState = void 0;
|
|
19517
|
+
currentTaskBoundaryId = createTaskBoundaryId();
|
|
19518
|
+
worker?.postMessage({ type: "update_config", config: { taskBoundaryId: currentTaskBoundaryId } });
|
|
18962
19519
|
hideTaskSuggestion();
|
|
18963
19520
|
}
|
|
18964
19521
|
const incomingMessages = sanitizeUiMessages(state.uiMessages);
|
|
@@ -19024,7 +19581,8 @@ function applyCoordinatorState(state, source) {
|
|
|
19024
19581
|
text: state.activeRun.text,
|
|
19025
19582
|
startedAt: state.activeRun.startedAt,
|
|
19026
19583
|
attempts: runtimeState.pendingRun?.attempts || 0,
|
|
19027
|
-
autoResume: true
|
|
19584
|
+
autoResume: true,
|
|
19585
|
+
resumeReason: runtimeState.pendingRun?.resumeReason
|
|
19028
19586
|
}));
|
|
19029
19587
|
} else {
|
|
19030
19588
|
const shouldClearPending = shouldClearPendingFromSharedState({
|
|
@@ -19051,9 +19609,16 @@ function applyCoordinatorState(state, source) {
|
|
|
19051
19609
|
const incomingWorker = sanitizeWorkerState(state.workerContext);
|
|
19052
19610
|
const localUpdatedAt = Number(runtimeState.workerState?.updatedAt) || 0;
|
|
19053
19611
|
const incomingUpdatedAt = Number(incomingWorker?.updatedAt) || 0;
|
|
19054
|
-
if (incomingWorker && incomingUpdatedAt > localUpdatedAt + 100
|
|
19612
|
+
if (incomingWorker && incomingUpdatedAt > localUpdatedAt + 100 && shouldAcceptIncomingWorkerBoundary({
|
|
19613
|
+
source: "shared_worker_context",
|
|
19614
|
+
incomingBoundaryId: incomingWorker.taskBoundaryId,
|
|
19615
|
+
taskEpochAdvanced,
|
|
19616
|
+
allowBootstrapAdoption: true
|
|
19617
|
+
})) {
|
|
19055
19618
|
runtimeState.workerState = incomingWorker;
|
|
19619
|
+
syncCurrentTaskBoundaryId();
|
|
19056
19620
|
if (workerReady && worker && currentMode === "controller") {
|
|
19621
|
+
worker.postMessage({ type: "update_config", config: { taskBoundaryId: currentTaskBoundaryId } });
|
|
19057
19622
|
worker.postMessage({ type: "hydrate_state", state: incomingWorker });
|
|
19058
19623
|
emit("context_restored", { source: "shared_session", ts: Date.now() });
|
|
19059
19624
|
}
|
|
@@ -19063,6 +19628,7 @@ function applyCoordinatorState(state, source) {
|
|
|
19063
19628
|
runtimeState.uiMessages = sanitizeUiMessages(runtimeState.uiMessages);
|
|
19064
19629
|
runtimeState.timeline = sanitizeTimelineEvents(runtimeState.timeline);
|
|
19065
19630
|
runtimeState.workerState = sanitizeWorkerState(runtimeState.workerState);
|
|
19631
|
+
syncCurrentTaskBoundaryId();
|
|
19066
19632
|
syncQuestionPromptFromWorkerState();
|
|
19067
19633
|
runtimeState.activeTask = sanitizeTask(runtimeState.activeTask, createDefaultTaskState("implicit"));
|
|
19068
19634
|
persistRuntimeState();
|
|
@@ -19081,6 +19647,7 @@ function cloneRuntimeStateForCheckpoint(state) {
|
|
|
19081
19647
|
executionMode: state.executionMode === "observer" || state.executionMode === "controller" ? state.executionMode : "controller",
|
|
19082
19648
|
workerState: sanitizeWorkerState(state.workerState),
|
|
19083
19649
|
pendingRun: sanitizePendingRun(state.pendingRun),
|
|
19650
|
+
lastNavigationHandoff: sanitizeNavigationHandoff(state.lastNavigationHandoff),
|
|
19084
19651
|
taskEpoch: Math.max(1, Number(state.taskEpoch) || 1),
|
|
19085
19652
|
activeTask: sanitizeTask(state.activeTask, fallbackTask),
|
|
19086
19653
|
lastRoutingDecision: state.lastRoutingDecision && (state.lastRoutingDecision.mode === "act" || state.lastRoutingDecision.mode === "planner") ? {
|
|
@@ -19135,7 +19702,10 @@ function applyCloudCheckpointPayload(payload) {
|
|
|
19135
19702
|
runtimeState.sessionId = remoteSessionId;
|
|
19136
19703
|
currentConfig = { ...currentConfig, sessionId: remoteSessionId };
|
|
19137
19704
|
setupSessionCoordinator(currentConfig);
|
|
19138
|
-
worker?.postMessage({
|
|
19705
|
+
worker?.postMessage({
|
|
19706
|
+
type: "update_config",
|
|
19707
|
+
config: { sessionId: remoteSessionId, taskBoundaryId: currentTaskBoundaryId }
|
|
19708
|
+
});
|
|
19139
19709
|
}
|
|
19140
19710
|
if (payload.sharedState && sessionCoordinator) {
|
|
19141
19711
|
const hydrated = sessionCoordinator.hydrateExternalState(payload.sharedState);
|
|
@@ -19157,12 +19727,24 @@ function applyCloudCheckpointPayload(payload) {
|
|
|
19157
19727
|
const localUpdatedAt = Number(runtimeState.updatedAt) || 0;
|
|
19158
19728
|
const incomingUpdatedAt = Number(incomingState.updatedAt) || 0;
|
|
19159
19729
|
if (incomingUpdatedAt > localUpdatedAt + 200) {
|
|
19730
|
+
const localTaskEpoch = Math.max(1, Number(runtimeState.taskEpoch) || 1);
|
|
19731
|
+
const incomingTaskEpoch = Math.max(1, Number(incomingState.taskEpoch) || 1);
|
|
19732
|
+
const incomingBoundaryId = resolveExistingTaskBoundaryIdFromState(incomingState);
|
|
19733
|
+
if (!shouldAcceptIncomingWorkerBoundary({
|
|
19734
|
+
source: "cloud_checkpoint",
|
|
19735
|
+
incomingBoundaryId,
|
|
19736
|
+
taskEpochAdvanced: incomingTaskEpoch > localTaskEpoch,
|
|
19737
|
+
allowBootstrapAdoption: true
|
|
19738
|
+
})) {
|
|
19739
|
+
return;
|
|
19740
|
+
}
|
|
19160
19741
|
runtimeState = normalizePersistedState({
|
|
19161
19742
|
...runtimeState,
|
|
19162
19743
|
...incomingState,
|
|
19163
19744
|
sessionId: remoteSessionId,
|
|
19164
19745
|
runtimeId
|
|
19165
19746
|
}, remoteSessionId, runtimeId);
|
|
19747
|
+
syncCurrentTaskBoundaryId();
|
|
19166
19748
|
persistRuntimeState();
|
|
19167
19749
|
if (runtimeState.uiStatus) {
|
|
19168
19750
|
ui?.setStatus(runtimeState.uiStatus);
|
|
@@ -19176,6 +19758,9 @@ function applyCloudCheckpointPayload(payload) {
|
|
|
19176
19758
|
else
|
|
19177
19759
|
ui?.close();
|
|
19178
19760
|
}
|
|
19761
|
+
if (workerReady) {
|
|
19762
|
+
worker?.postMessage({ type: "update_config", config: { taskBoundaryId: currentTaskBoundaryId } });
|
|
19763
|
+
}
|
|
19179
19764
|
if (workerReady && runtimeState.workerState) {
|
|
19180
19765
|
worker?.postMessage({ type: "hydrate_state", state: runtimeState.workerState });
|
|
19181
19766
|
emit("context_restored", { source: "cloud_checkpoint", ts: Date.now() });
|
|
@@ -19285,12 +19870,18 @@ function setupSessionCoordinator(cfg) {
|
|
|
19285
19870
|
const incomingWorker = sanitizeWorkerState(sharedWorkerContext);
|
|
19286
19871
|
const localUpdatedAt = Number(runtimeState?.workerState?.updatedAt) || 0;
|
|
19287
19872
|
const incomingUpdatedAt = Number(incomingWorker?.updatedAt) || 0;
|
|
19288
|
-
if (incomingWorker && incomingUpdatedAt > localUpdatedAt + 100
|
|
19873
|
+
if (incomingWorker && incomingUpdatedAt > localUpdatedAt + 100 && shouldAcceptIncomingWorkerBoundary({
|
|
19874
|
+
source: "controller_handoff",
|
|
19875
|
+
incomingBoundaryId: incomingWorker.taskBoundaryId,
|
|
19876
|
+
allowBootstrapAdoption: true
|
|
19877
|
+
})) {
|
|
19289
19878
|
if (runtimeState) {
|
|
19290
19879
|
runtimeState.workerState = incomingWorker;
|
|
19880
|
+
syncCurrentTaskBoundaryId();
|
|
19291
19881
|
persistRuntimeState();
|
|
19292
19882
|
}
|
|
19293
19883
|
if (workerReady && worker) {
|
|
19884
|
+
worker.postMessage({ type: "update_config", config: { taskBoundaryId: currentTaskBoundaryId } });
|
|
19294
19885
|
worker.postMessage({ type: "hydrate_state", state: incomingWorker });
|
|
19295
19886
|
emit("context_restored", { source: "controller_handoff", ts: Date.now() });
|
|
19296
19887
|
}
|
|
@@ -19313,7 +19904,15 @@ function setupSessionCoordinator(cfg) {
|
|
|
19313
19904
|
}
|
|
19314
19905
|
}
|
|
19315
19906
|
});
|
|
19316
|
-
|
|
19907
|
+
const startupHandoff = getUnconsumedNavigationHandoff();
|
|
19908
|
+
sessionCoordinator.start(toSharedNavigationHandoff(startupHandoff));
|
|
19909
|
+
if (runtimeState?.lastNavigationHandoff && startupHandoff) {
|
|
19910
|
+
runtimeState.lastNavigationHandoff = sanitizeNavigationHandoff({
|
|
19911
|
+
...runtimeState.lastNavigationHandoff,
|
|
19912
|
+
consumed: true
|
|
19913
|
+
});
|
|
19914
|
+
persistRuntimeState();
|
|
19915
|
+
}
|
|
19317
19916
|
sessionCoordinator.setRpcRequestHandler(async (request) => {
|
|
19318
19917
|
if (!bridge)
|
|
19319
19918
|
throw new Error("Bridge not available");
|
|
@@ -19460,10 +20059,18 @@ function handleWorkerMessage(msg) {
|
|
|
19460
20059
|
}
|
|
19461
20060
|
if (msg.type === "state_snapshot") {
|
|
19462
20061
|
if (runtimeState) {
|
|
19463
|
-
|
|
20062
|
+
const incomingWorkerState = sanitizeWorkerState({
|
|
19464
20063
|
...msg.state || {},
|
|
19465
20064
|
updatedAt: Date.now()
|
|
19466
20065
|
});
|
|
20066
|
+
if (!incomingWorkerState || !shouldAcceptIncomingWorkerBoundary({
|
|
20067
|
+
source: "worker_snapshot",
|
|
20068
|
+
incomingBoundaryId: incomingWorkerState.taskBoundaryId,
|
|
20069
|
+
allowBootstrapAdoption: true
|
|
20070
|
+
})) {
|
|
20071
|
+
return;
|
|
20072
|
+
}
|
|
20073
|
+
runtimeState.workerState = incomingWorkerState;
|
|
19467
20074
|
const activeRunId = typeof msg?.activeRun?.runId === "string" && msg.activeRun.runId ? msg.activeRun.runId : void 0;
|
|
19468
20075
|
const activeRunText = typeof msg?.activeRun?.text === "string" ? msg.activeRun.text : void 0;
|
|
19469
20076
|
const canAdoptActiveRun = shouldAdoptSnapshotActiveRun({
|
|
@@ -19516,6 +20123,7 @@ function handleWorkerMessage(msg) {
|
|
|
19516
20123
|
return;
|
|
19517
20124
|
}
|
|
19518
20125
|
const existing = runtimeState?.pendingRun;
|
|
20126
|
+
const messageTaskBoundaryId = typeof msg?.taskBoundaryId === "string" ? normalizeTaskBoundaryId(msg.taskBoundaryId) : void 0;
|
|
19519
20127
|
if (typeof msg.runId === "string" && msg.runId) {
|
|
19520
20128
|
removeIgnoredRunId(msg.runId);
|
|
19521
20129
|
}
|
|
@@ -19524,7 +20132,10 @@ function handleWorkerMessage(msg) {
|
|
|
19524
20132
|
text: msg.text,
|
|
19525
20133
|
startedAt: existing?.startedAt || Date.now(),
|
|
19526
20134
|
attempts: existing?.attempts || 0,
|
|
19527
|
-
autoResume: existing?.autoResume !== false
|
|
20135
|
+
autoResume: existing?.autoResume !== false,
|
|
20136
|
+
taskBoundaryId: messageTaskBoundaryId || existing?.taskBoundaryId || currentTaskBoundaryId,
|
|
20137
|
+
resumeReason: existing?.resumeReason,
|
|
20138
|
+
resumeRequired: existing?.resumeRequired
|
|
19528
20139
|
}));
|
|
19529
20140
|
sessionCoordinator?.setActiveRun({ runId: msg.runId, text: String(msg.text || "") });
|
|
19530
20141
|
ui?.setRunning(true);
|
|
@@ -19576,9 +20187,16 @@ function handleWorkerMessage(msg) {
|
|
|
19576
20187
|
if (!isTaskRunning()) {
|
|
19577
20188
|
return;
|
|
19578
20189
|
}
|
|
20190
|
+
const completionState = normalizeRunCompletionState(msg);
|
|
19579
20191
|
ui?.setQuestionPrompt(void 0);
|
|
19580
|
-
|
|
19581
|
-
|
|
20192
|
+
if (completionState.contextResetRecommended) {
|
|
20193
|
+
markTaskCompleted("worker_run_failed_terminal");
|
|
20194
|
+
sessionCoordinator?.resetTabsToCurrent(window.location.href, document.title || void 0);
|
|
20195
|
+
setUiStatus(`Task failed: ${String(msg.error)}. Start a new task to continue.`);
|
|
20196
|
+
} else {
|
|
20197
|
+
markTaskRunning("worker_run_failed");
|
|
20198
|
+
setUiStatus(`Task failed: ${String(msg.error)}`);
|
|
20199
|
+
}
|
|
19582
20200
|
if (completedRunId) {
|
|
19583
20201
|
latestAssistantByRunId.delete(completedRunId);
|
|
19584
20202
|
}
|
|
@@ -19595,20 +20213,39 @@ function handleWorkerMessage(msg) {
|
|
|
19595
20213
|
const completionState = normalizeRunCompletionState(msg);
|
|
19596
20214
|
const taskComplete = completionState.taskComplete;
|
|
19597
20215
|
const needsUserInput = completionState.needsUserInput;
|
|
19598
|
-
const
|
|
19599
|
-
|
|
20216
|
+
const terminalState = completionState.terminalState;
|
|
20217
|
+
const completionQuestions = completionState.questions || normalizeAskUserQuestions(msg.questions);
|
|
20218
|
+
const pendingStateQuestions = normalizeAskUserQuestions(runtimeState?.workerState?.pendingAskUser?.questions);
|
|
20219
|
+
const questions = completionQuestions.length ? completionQuestions : needsUserInput ? pendingStateQuestions : [];
|
|
20220
|
+
if (terminalState === "failed") {
|
|
19600
20221
|
ui?.setQuestionPrompt(void 0);
|
|
19601
|
-
|
|
19602
|
-
|
|
19603
|
-
|
|
19604
|
-
|
|
20222
|
+
if (completionState.contextResetRecommended) {
|
|
20223
|
+
markTaskCompleted("worker_run_failed_terminal");
|
|
20224
|
+
sessionCoordinator?.resetTabsToCurrent(window.location.href, document.title || void 0);
|
|
20225
|
+
setUiStatus("Task failed. Start a new task to continue.");
|
|
20226
|
+
} else {
|
|
20227
|
+
markTaskRunning("worker_run_failed");
|
|
20228
|
+
setUiStatus("Task failed.");
|
|
20229
|
+
}
|
|
20230
|
+
appendTimelineEvent({
|
|
20231
|
+
kind: "error",
|
|
20232
|
+
title: "Run failed",
|
|
20233
|
+
detail: typeof msg.error === "string" ? msg.error : "Run reported failure state.",
|
|
20234
|
+
status: "error"
|
|
19605
20235
|
});
|
|
20236
|
+
} else if (taskComplete || terminalState === "completed") {
|
|
20237
|
+
ui?.setQuestionPrompt(void 0);
|
|
20238
|
+
markTaskCompleted("worker_task_complete");
|
|
20239
|
+
sessionCoordinator?.resetTabsToCurrent(window.location.href, document.title || void 0);
|
|
19606
20240
|
setUiStatus("Task completed");
|
|
19607
20241
|
finalizeSuccessfulRunTimeline(typeof msg.runId === "string" ? msg.runId : void 0);
|
|
19608
20242
|
} else {
|
|
19609
|
-
|
|
20243
|
+
const nextReason = needsUserInput ? "worker_waiting_for_input" : terminalState === "in_progress" ? "worker_continuation" : "worker_task_active";
|
|
20244
|
+
markTaskRunning(nextReason);
|
|
19610
20245
|
if (needsUserInput && questions.length > 0) {
|
|
19611
20246
|
ui?.setQuestionPrompt({ questions });
|
|
20247
|
+
} else if (needsUserInput) {
|
|
20248
|
+
syncQuestionPromptFromWorkerState();
|
|
19612
20249
|
} else {
|
|
19613
20250
|
ui?.setQuestionPrompt(void 0);
|
|
19614
20251
|
}
|
|
@@ -19631,13 +20268,29 @@ function handleWorkerMessage(msg) {
|
|
|
19631
20268
|
loadAndMergeShortcuts(currentConfig);
|
|
19632
20269
|
}
|
|
19633
20270
|
const sharedWorkerContext = sessionCoordinator?.getWorkerContext();
|
|
19634
|
-
const
|
|
19635
|
-
const
|
|
20271
|
+
const sharedWorkerStateCandidate = sanitizeWorkerState(sharedWorkerContext);
|
|
20272
|
+
const sharedWorkerState = sharedWorkerStateCandidate && shouldAcceptIncomingWorkerBoundary({
|
|
20273
|
+
source: "ready_hydrate",
|
|
20274
|
+
incomingBoundaryId: sharedWorkerStateCandidate.taskBoundaryId,
|
|
20275
|
+
allowBootstrapAdoption: true
|
|
20276
|
+
}) ? sharedWorkerStateCandidate : void 0;
|
|
20277
|
+
const localWorkerStateCandidate = sanitizeWorkerState(runtimeState?.workerState);
|
|
20278
|
+
const localWorkerState = localWorkerStateCandidate && shouldAcceptIncomingWorkerBoundary({
|
|
20279
|
+
source: "ready_hydrate",
|
|
20280
|
+
incomingBoundaryId: localWorkerStateCandidate.taskBoundaryId,
|
|
20281
|
+
allowBootstrapAdoption: true
|
|
20282
|
+
}) ? localWorkerStateCandidate : void 0;
|
|
20283
|
+
const localUpdatedAt = Number(localWorkerState?.updatedAt) || 0;
|
|
19636
20284
|
const sharedUpdatedAt = Number(sharedWorkerState?.updatedAt) || 0;
|
|
19637
|
-
const stateToHydrate = sharedWorkerState && sharedUpdatedAt > localUpdatedAt + 100 ? sharedWorkerState :
|
|
19638
|
-
if (runtimeState
|
|
19639
|
-
runtimeState.workerState
|
|
19640
|
-
|
|
20285
|
+
const stateToHydrate = sharedWorkerState && sharedUpdatedAt > localUpdatedAt + 100 ? sharedWorkerState : localWorkerState;
|
|
20286
|
+
if (runtimeState) {
|
|
20287
|
+
if (stateToHydrate && stateToHydrate !== runtimeState.workerState) {
|
|
20288
|
+
runtimeState.workerState = stateToHydrate;
|
|
20289
|
+
persistRuntimeState();
|
|
20290
|
+
} else if (!stateToHydrate && runtimeState.workerState) {
|
|
20291
|
+
runtimeState.workerState = void 0;
|
|
20292
|
+
persistRuntimeState();
|
|
20293
|
+
}
|
|
19641
20294
|
}
|
|
19642
20295
|
if (stateToHydrate) {
|
|
19643
20296
|
worker?.postMessage({ type: "hydrate_state", state: stateToHydrate });
|
|
@@ -20008,26 +20661,33 @@ function createRuntime(cfg) {
|
|
|
20008
20661
|
status: "info"
|
|
20009
20662
|
});
|
|
20010
20663
|
},
|
|
20011
|
-
onBeforeAgentNavigation: (
|
|
20012
|
-
|
|
20664
|
+
onBeforeAgentNavigation: (intent) => {
|
|
20665
|
+
agentNavigationPending = true;
|
|
20666
|
+
if (!runtimeState)
|
|
20667
|
+
return;
|
|
20668
|
+
setLatestNavigationHandoff(toPersistedNavigationHandoff(intent));
|
|
20669
|
+
if (!runtimeState.pendingRun)
|
|
20013
20670
|
return;
|
|
20014
|
-
|
|
20015
|
-
const targetHost = new URL(_targetUrl, window.location.href).hostname;
|
|
20016
|
-
if (currentHost === targetHost) {
|
|
20671
|
+
if (!intent.isCrossHost) {
|
|
20017
20672
|
runtimeState.pendingRun = sanitizePendingRun({
|
|
20018
20673
|
...runtimeState.pendingRun,
|
|
20674
|
+
taskBoundaryId: runtimeState.pendingRun.taskBoundaryId || currentTaskBoundaryId,
|
|
20019
20675
|
resumeRequired: true,
|
|
20020
20676
|
resumeReason: "agent_navigation"
|
|
20021
20677
|
});
|
|
20022
20678
|
persistRuntimeState();
|
|
20023
20679
|
}
|
|
20024
20680
|
},
|
|
20025
|
-
onBeforeCrossHostNavigation: (
|
|
20681
|
+
onBeforeCrossHostNavigation: (intent) => {
|
|
20682
|
+
agentNavigationPending = true;
|
|
20026
20683
|
if (!runtimeState || !currentConfig)
|
|
20027
20684
|
return;
|
|
20685
|
+
setLatestNavigationHandoff(toPersistedNavigationHandoff(intent));
|
|
20686
|
+
const handoffForCookie = getUnconsumedNavigationHandoff();
|
|
20028
20687
|
if (runtimeState.pendingRun) {
|
|
20029
20688
|
runtimeState.pendingRun = sanitizePendingRun({
|
|
20030
20689
|
...runtimeState.pendingRun,
|
|
20690
|
+
taskBoundaryId: runtimeState.pendingRun.taskBoundaryId || currentTaskBoundaryId,
|
|
20031
20691
|
resumeRequired: true,
|
|
20032
20692
|
resumeReason: "cross_host_navigation"
|
|
20033
20693
|
});
|
|
@@ -20038,7 +20698,15 @@ function createRuntime(cfg) {
|
|
|
20038
20698
|
id: runtimeState.pendingRun.id,
|
|
20039
20699
|
text: runtimeState.pendingRun.text,
|
|
20040
20700
|
startedAt: runtimeState.pendingRun.startedAt,
|
|
20041
|
-
attempts: runtimeState.pendingRun.attempts
|
|
20701
|
+
attempts: runtimeState.pendingRun.attempts,
|
|
20702
|
+
taskBoundaryId: runtimeState.pendingRun.taskBoundaryId || currentTaskBoundaryId
|
|
20703
|
+
} : void 0,
|
|
20704
|
+
handoff: handoffForCookie ? {
|
|
20705
|
+
handoffId: handoffForCookie.handoffId,
|
|
20706
|
+
sourceLogicalTabId: handoffForCookie.sourceLogicalTabId,
|
|
20707
|
+
runId: handoffForCookie.runId,
|
|
20708
|
+
targetUrl: handoffForCookie.targetUrl,
|
|
20709
|
+
createdAt: handoffForCookie.createdAt
|
|
20042
20710
|
} : void 0,
|
|
20043
20711
|
activeTask: runtimeState.activeTask ? {
|
|
20044
20712
|
taskId: runtimeState.activeTask.taskId,
|
|
@@ -20137,7 +20805,7 @@ function createRuntime(cfg) {
|
|
|
20137
20805
|
title: document.title
|
|
20138
20806
|
};
|
|
20139
20807
|
},
|
|
20140
|
-
listSessionTabs: () => sessionCoordinator?.listTabs() || []
|
|
20808
|
+
listSessionTabs: () => sessionCoordinator?.listTabs({ scope: "context" }) || []
|
|
20141
20809
|
});
|
|
20142
20810
|
channel.port1.start?.();
|
|
20143
20811
|
const workerUrl = cfg.workerUrl ? cfg.workerUrl : new URL("./worker/worker.js", import.meta.url).toString();
|
|
@@ -20152,7 +20820,77 @@ function createRuntime(cfg) {
|
|
|
20152
20820
|
} catch (_e) {
|
|
20153
20821
|
}
|
|
20154
20822
|
worker = new Worker(effectiveWorkerUrl, { type: "module" });
|
|
20155
|
-
worker.postMessage({
|
|
20823
|
+
worker.postMessage({
|
|
20824
|
+
type: "init",
|
|
20825
|
+
config: {
|
|
20826
|
+
...cfg,
|
|
20827
|
+
taskBoundaryId: currentTaskBoundaryId
|
|
20828
|
+
},
|
|
20829
|
+
port: channel.port2
|
|
20830
|
+
}, [channel.port2]);
|
|
20831
|
+
const cancelCurrentFlow = (reason = "manual_cancel_task") => {
|
|
20832
|
+
if (!runtimeState)
|
|
20833
|
+
return;
|
|
20834
|
+
const pendingRun = runtimeState.pendingRun;
|
|
20835
|
+
if (pendingRun) {
|
|
20836
|
+
addIgnoredRunId(pendingRun.id);
|
|
20837
|
+
worker?.postMessage({ type: "cancel_run", runId: pendingRun.id });
|
|
20838
|
+
sessionCoordinator?.releaseWorkflowLock(pendingRun.id);
|
|
20839
|
+
sessionCoordinator?.setActiveRun(void 0);
|
|
20840
|
+
setPendingRun(void 0);
|
|
20841
|
+
runtimeState.workerState = void 0;
|
|
20842
|
+
sessionCoordinator?.setWorkerContext(void 0);
|
|
20843
|
+
currentTaskBoundaryId = createTaskBoundaryId();
|
|
20844
|
+
worker?.postMessage({ type: "update_config", config: { taskBoundaryId: currentTaskBoundaryId } });
|
|
20845
|
+
if (runSafetyTimer) {
|
|
20846
|
+
clearTimeout(runSafetyTimer);
|
|
20847
|
+
runSafetyTimer = null;
|
|
20848
|
+
}
|
|
20849
|
+
ui?.setRunning(false);
|
|
20850
|
+
ui?.setQuestionPrompt(void 0);
|
|
20851
|
+
setUiStatus("Task cancelled.");
|
|
20852
|
+
appendUiMessage("system", "Task cancelled.", true);
|
|
20853
|
+
appendTimelineEvent({
|
|
20854
|
+
kind: "info",
|
|
20855
|
+
title: "Run cancelled",
|
|
20856
|
+
status: "info"
|
|
20857
|
+
});
|
|
20858
|
+
persistRuntimeState();
|
|
20859
|
+
return;
|
|
20860
|
+
}
|
|
20861
|
+
const hasPendingQuestions = normalizeAskUserQuestions(runtimeState.workerState?.pendingAskUser?.questions).length > 0;
|
|
20862
|
+
const activeStatus = runtimeState.activeTask?.status;
|
|
20863
|
+
if (!hasPendingQuestions && activeStatus !== "running") {
|
|
20864
|
+
return;
|
|
20865
|
+
}
|
|
20866
|
+
currentTaskBoundaryId = createTaskBoundaryId();
|
|
20867
|
+
runtimeState.workerState = void 0;
|
|
20868
|
+
worker?.postMessage({ type: "update_config", config: { taskBoundaryId: currentTaskBoundaryId } });
|
|
20869
|
+
if (runSafetyTimer) {
|
|
20870
|
+
clearTimeout(runSafetyTimer);
|
|
20871
|
+
runSafetyTimer = null;
|
|
20872
|
+
}
|
|
20873
|
+
ui?.setRunning(false);
|
|
20874
|
+
ui?.setQuestionPrompt(void 0);
|
|
20875
|
+
hideTaskSuggestion();
|
|
20876
|
+
setPendingRun(void 0);
|
|
20877
|
+
const task = ensureActiveTask(reason);
|
|
20878
|
+
if (task) {
|
|
20879
|
+
task.status = "ended";
|
|
20880
|
+
task.endedAt = Date.now();
|
|
20881
|
+
task.boundaryReason = reason;
|
|
20882
|
+
}
|
|
20883
|
+
sessionCoordinator?.endTask(reason);
|
|
20884
|
+
sessionCoordinator?.setActiveRun(void 0);
|
|
20885
|
+
sessionCoordinator?.setWorkerContext(void 0);
|
|
20886
|
+
setUiStatus(reason === "question_prompt_cancel" ? "Input request cancelled." : "Task cancelled.");
|
|
20887
|
+
appendTimelineEvent({
|
|
20888
|
+
kind: "info",
|
|
20889
|
+
title: reason === "question_prompt_cancel" ? "Input request cancelled" : "Task cancelled",
|
|
20890
|
+
status: "info"
|
|
20891
|
+
});
|
|
20892
|
+
persistRuntimeState();
|
|
20893
|
+
};
|
|
20156
20894
|
ui = mountWidget({
|
|
20157
20895
|
shortcuts: getRenderableShortcuts(sanitizeShortcutList(cfg.ui?.shortcuts || [])),
|
|
20158
20896
|
greeting: resolveEffectiveGreetingConfig(cfg),
|
|
@@ -20182,26 +20920,10 @@ function createRuntime(cfg) {
|
|
|
20182
20920
|
}
|
|
20183
20921
|
},
|
|
20184
20922
|
onCancelRun: () => {
|
|
20185
|
-
|
|
20186
|
-
|
|
20187
|
-
|
|
20188
|
-
|
|
20189
|
-
sessionCoordinator?.setActiveRun(void 0);
|
|
20190
|
-
setPendingRun(void 0);
|
|
20191
|
-
if (runSafetyTimer) {
|
|
20192
|
-
clearTimeout(runSafetyTimer);
|
|
20193
|
-
runSafetyTimer = null;
|
|
20194
|
-
}
|
|
20195
|
-
ui?.setRunning(false);
|
|
20196
|
-
ui?.setQuestionPrompt(void 0);
|
|
20197
|
-
setUiStatus("Task cancelled.");
|
|
20198
|
-
appendUiMessage("system", "Task cancelled.", true);
|
|
20199
|
-
appendTimelineEvent({
|
|
20200
|
-
kind: "info",
|
|
20201
|
-
title: "Run cancelled",
|
|
20202
|
-
status: "info"
|
|
20203
|
-
});
|
|
20204
|
-
}
|
|
20923
|
+
cancelCurrentFlow("manual_cancel_task");
|
|
20924
|
+
},
|
|
20925
|
+
onCancelQuestionFlow: () => {
|
|
20926
|
+
cancelCurrentFlow("question_prompt_cancel");
|
|
20205
20927
|
},
|
|
20206
20928
|
onNewTask: () => {
|
|
20207
20929
|
newTask({ reason: "manual_new_task", clearUi: true });
|
|
@@ -20377,10 +21099,17 @@ function boot(cfg) {
|
|
|
20377
21099
|
seeded.pendingRun = sanitizePendingRun({
|
|
20378
21100
|
...crossDomainResume.pendingRun,
|
|
20379
21101
|
autoResume: true,
|
|
21102
|
+
taskBoundaryId: crossDomainResume.pendingRun.taskBoundaryId,
|
|
20380
21103
|
resumeRequired: true,
|
|
20381
21104
|
resumeReason: "cross_host_navigation"
|
|
20382
21105
|
});
|
|
20383
21106
|
}
|
|
21107
|
+
if (crossDomainResume.handoff) {
|
|
21108
|
+
seeded.lastNavigationHandoff = sanitizeNavigationHandoff({
|
|
21109
|
+
...crossDomainResume.handoff,
|
|
21110
|
+
createdAt: crossDomainResume.handoff.createdAt
|
|
21111
|
+
});
|
|
21112
|
+
}
|
|
20384
21113
|
if (crossDomainResume.activeTask) {
|
|
20385
21114
|
seeded.activeTask = {
|
|
20386
21115
|
...createDefaultTaskState("cross_domain_resume"),
|
|
@@ -20396,6 +21125,19 @@ function boot(cfg) {
|
|
|
20396
21125
|
if (desiredSessionId && runtimeState.sessionId !== desiredSessionId) {
|
|
20397
21126
|
runtimeState = createDefaultRuntimeState(desiredSessionId, runtimeId);
|
|
20398
21127
|
}
|
|
21128
|
+
currentTaskBoundaryId = resolveTaskBoundaryIdFromState(runtimeState);
|
|
21129
|
+
if (runtimeState.pendingRun && !runtimeState.pendingRun.taskBoundaryId) {
|
|
21130
|
+
runtimeState.pendingRun = sanitizePendingRun({
|
|
21131
|
+
...runtimeState.pendingRun,
|
|
21132
|
+
taskBoundaryId: currentTaskBoundaryId
|
|
21133
|
+
});
|
|
21134
|
+
}
|
|
21135
|
+
if (runtimeState.workerState && !runtimeState.workerState.taskBoundaryId) {
|
|
21136
|
+
runtimeState.workerState = sanitizeWorkerState({
|
|
21137
|
+
...runtimeState.workerState,
|
|
21138
|
+
taskBoundaryId: currentTaskBoundaryId
|
|
21139
|
+
});
|
|
21140
|
+
}
|
|
20399
21141
|
currentConfig = {
|
|
20400
21142
|
...cfg,
|
|
20401
21143
|
visitorId: resolvedVisitorId || cfg.visitorId,
|
|
@@ -20547,7 +21289,13 @@ function update(cfg) {
|
|
|
20547
21289
|
});
|
|
20548
21290
|
}
|
|
20549
21291
|
}
|
|
20550
|
-
worker.postMessage({
|
|
21292
|
+
worker.postMessage({
|
|
21293
|
+
type: "update_config",
|
|
21294
|
+
config: {
|
|
21295
|
+
...cfg,
|
|
21296
|
+
taskBoundaryId: currentTaskBoundaryId
|
|
21297
|
+
}
|
|
21298
|
+
});
|
|
20551
21299
|
applyEffectiveSiteConfig(currentConfig);
|
|
20552
21300
|
if (shouldReloadRemoteSiteConfig) {
|
|
20553
21301
|
loadAndMergeShortcuts(currentConfig);
|
|
@@ -20583,6 +21331,8 @@ function shutdown() {
|
|
|
20583
21331
|
currentConfig = null;
|
|
20584
21332
|
workerReady = false;
|
|
20585
21333
|
autoResumeAttempted = false;
|
|
21334
|
+
agentNavigationPending = false;
|
|
21335
|
+
currentTaskBoundaryId = "";
|
|
20586
21336
|
runtimeId = "";
|
|
20587
21337
|
resolvedVisitorId = void 0;
|
|
20588
21338
|
resolvedVisitor = void 0;
|
|
@@ -20657,6 +21407,7 @@ function newTask(options) {
|
|
|
20657
21407
|
ui?.setRunning(false);
|
|
20658
21408
|
ui?.setQuestionPrompt(void 0);
|
|
20659
21409
|
autoResumeAttempted = false;
|
|
21410
|
+
currentTaskBoundaryId = createTaskBoundaryId();
|
|
20660
21411
|
runtimeState.taskEpoch = taskEpoch;
|
|
20661
21412
|
runtimeState.activeTask = nextTask;
|
|
20662
21413
|
setPendingRun(void 0);
|
|
@@ -20679,7 +21430,7 @@ function newTask(options) {
|
|
|
20679
21430
|
sessionCoordinator?.setWorkerContext(void 0);
|
|
20680
21431
|
setUiStatus("New task started.");
|
|
20681
21432
|
persistRuntimeState();
|
|
20682
|
-
worker?.postMessage({ type: "start_new_task", taskId: nextTask.taskId });
|
|
21433
|
+
worker?.postMessage({ type: "start_new_task", taskId: nextTask.taskId, taskBoundaryId: currentTaskBoundaryId });
|
|
20683
21434
|
emit("task_started", {
|
|
20684
21435
|
taskId: nextTask.taskId,
|
|
20685
21436
|
reason,
|
|
@@ -20702,7 +21453,9 @@ function endTask(options) {
|
|
|
20702
21453
|
sessionCoordinator?.releaseWorkflowLock(runtimeState.pendingRun.id);
|
|
20703
21454
|
}
|
|
20704
21455
|
setPendingRun(void 0);
|
|
21456
|
+
currentTaskBoundaryId = createTaskBoundaryId();
|
|
20705
21457
|
runtimeState.workerState = void 0;
|
|
21458
|
+
worker?.postMessage({ type: "update_config", config: { taskBoundaryId: currentTaskBoundaryId } });
|
|
20706
21459
|
if (runSafetyTimer) {
|
|
20707
21460
|
clearTimeout(runSafetyTimer);
|
|
20708
21461
|
runSafetyTimer = null;
|