@quanta-intellect/vessel-browser 0.1.144 → 0.1.145

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/out/main/index.js CHANGED
@@ -1467,7 +1467,12 @@ function loadJsonFile({
1467
1467
  const decoded = decodeStoredData(raw, secure);
1468
1468
  return parse(JSON.parse(decoded));
1469
1469
  } catch (err) {
1470
- logger$A.warn(`Failed to load ${filePath2}, using fallback:`, err);
1470
+ const isMissingFile = err instanceof Error && "code" in err && err.code === "ENOENT";
1471
+ if (isMissingFile) {
1472
+ logger$A.info(`Persistence file not found; using fallback defaults: ${filePath2}`);
1473
+ } else {
1474
+ logger$A.warn(`Failed to load ${filePath2}, using fallback:`, err);
1475
+ }
1471
1476
  return fallback;
1472
1477
  }
1473
1478
  }
@@ -3867,7 +3872,14 @@ const AIChannels = {
3867
3872
  AGENT_CHECKPOINT_UPDATE_NOTE: "agent:checkpoint-update-note",
3868
3873
  AGENT_UNDO_LAST_ACTION: "agent:undo-last-action",
3869
3874
  AGENT_SESSION_CAPTURE: "agent:session-capture",
3870
- AGENT_SESSION_RESTORE: "agent:session-restore"
3875
+ AGENT_SESSION_RESTORE: "agent:session-restore",
3876
+ AGENT_TASK_START: "agent:task-start",
3877
+ AGENT_TASK_UPDATE: "agent:task-update",
3878
+ AGENT_TASK_NOTE: "agent:task-note",
3879
+ AGENT_TASK_BLOCKER: "agent:task-blocker",
3880
+ AGENT_TASK_RESOLVE: "agent:task-resolve",
3881
+ AGENT_TASK_ABANDON: "agent:task-abandon",
3882
+ AGENT_TASK_CLEAR: "agent:task-clear"
3871
3883
  };
3872
3884
  const AutofillChannels = {
3873
3885
  AUTOFILL_LIST: "autofill:list",
@@ -8683,6 +8695,106 @@ function recoverTextEncodedToolCalls(text, availableToolNames) {
8683
8695
  }
8684
8696
  return recovered;
8685
8697
  }
8698
+ function findInlineToolMarkerBodies(text) {
8699
+ const bodies = [];
8700
+ const lowerText = text.toLowerCase();
8701
+ let searchIndex = 0;
8702
+ while (searchIndex < text.length) {
8703
+ const start = lowerText.indexOf("<<tool", searchIndex);
8704
+ if (start === -1) break;
8705
+ let quote = null;
8706
+ let escaped = false;
8707
+ let end = -1;
8708
+ for (let index = start + 2; index < text.length - 1; index += 1) {
8709
+ const char = text[index];
8710
+ if (quote) {
8711
+ if (escaped) {
8712
+ escaped = false;
8713
+ } else if (char === "\\") {
8714
+ escaped = true;
8715
+ } else if (char === quote) {
8716
+ quote = null;
8717
+ }
8718
+ continue;
8719
+ }
8720
+ if (char === '"' || char === "'") {
8721
+ quote = char;
8722
+ continue;
8723
+ }
8724
+ if (char === ">" && text[index + 1] === ">") {
8725
+ end = index;
8726
+ break;
8727
+ }
8728
+ }
8729
+ if (end === -1) {
8730
+ searchIndex = start + 2;
8731
+ continue;
8732
+ }
8733
+ bodies.push(text.slice(start + 2, end));
8734
+ searchIndex = end + 2;
8735
+ }
8736
+ return bodies;
8737
+ }
8738
+ function recoverInlineToolMarkerToolCalls(text, availableToolNames) {
8739
+ const recovered = [];
8740
+ for (const markerBody of findInlineToolMarkerBodies(text)) {
8741
+ const match = markerBody.trim().match(/^tool[:=]([a-z_][a-z0-9_]*)(?:[:=]([\s\S]*))?$/i);
8742
+ if (!match) continue;
8743
+ const rawName = match[1] ?? "";
8744
+ const rawArgs = (match[2] ?? "").trim();
8745
+ const resolvedName = resolveToolCallName(
8746
+ rawName,
8747
+ {},
8748
+ availableToolNames
8749
+ );
8750
+ if (!availableToolNames.has(resolvedName)) continue;
8751
+ let parsedArgs = null;
8752
+ if (rawArgs.startsWith("{")) {
8753
+ const repaired = parseToolArgsWithRepair(resolvedName, rawArgs);
8754
+ if (repaired) {
8755
+ parsedArgs = repaired.args;
8756
+ }
8757
+ }
8758
+ if (!parsedArgs) {
8759
+ const kvArgs = {};
8760
+ const kvPattern = /([a-z_][a-z0-9_]*)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^,\s]*))/gi;
8761
+ let kvMatch;
8762
+ while ((kvMatch = kvPattern.exec(rawArgs)) !== null) {
8763
+ const key2 = kvMatch[1];
8764
+ const value = kvMatch[2] ?? kvMatch[3] ?? kvMatch[4] ?? "";
8765
+ kvArgs[key2] = value;
8766
+ }
8767
+ if (Object.keys(kvArgs).length > 0) {
8768
+ parsedArgs = kvArgs;
8769
+ }
8770
+ }
8771
+ if (!parsedArgs && rawArgs) {
8772
+ const repaired = parseToolArgsWithRepair(resolvedName, rawArgs);
8773
+ if (repaired) {
8774
+ parsedArgs = repaired.args;
8775
+ }
8776
+ }
8777
+ if (!parsedArgs) {
8778
+ parsedArgs = {};
8779
+ }
8780
+ recovered.push({
8781
+ id: `recovered_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
8782
+ name: resolvedName,
8783
+ argsJson: JSON.stringify(parsedArgs)
8784
+ });
8785
+ }
8786
+ return recovered;
8787
+ }
8788
+ function recoverAssistantTextToolCalls(text, availableToolNames) {
8789
+ const textEncodedCalls = recoverTextEncodedToolCalls(text, availableToolNames);
8790
+ if (textEncodedCalls.length > 0) return textEncodedCalls;
8791
+ const inlineMarkerCalls = recoverInlineToolMarkerToolCalls(
8792
+ text,
8793
+ availableToolNames
8794
+ );
8795
+ if (inlineMarkerCalls.length > 0) return inlineMarkerCalls;
8796
+ return recoverNarratedActionToolCalls(text, availableToolNames);
8797
+ }
8686
8798
  function recoverNarratedActionToolCalls(text, availableToolNames) {
8687
8799
  const trimmed = text.trim();
8688
8800
  if (!trimmed) return [];
@@ -9398,22 +9510,13 @@ class OpenAICompatProvider {
9398
9510
  tc.name = resolveToolCallName(tc.name, parsedArgs, availableToolNames);
9399
9511
  }
9400
9512
  if (toolCalls.length === 0) {
9401
- const recoveredToolCalls = recoverTextEncodedToolCalls(
9513
+ const recoveredToolCalls = recoverAssistantTextToolCalls(
9402
9514
  textAccum,
9403
9515
  availableToolNames
9404
9516
  );
9405
9517
  if (recoveredToolCalls.length > 0) {
9406
9518
  toolCalls = recoveredToolCalls;
9407
9519
  if (textAccum.trim()) onChunk("<<erase_prev>>");
9408
- } else {
9409
- const narratedToolCalls = recoverNarratedActionToolCalls(
9410
- textAccum,
9411
- availableToolNames
9412
- );
9413
- if (narratedToolCalls.length > 0) {
9414
- toolCalls = narratedToolCalls;
9415
- if (textAccum.trim()) onChunk("<<erase_prev>>");
9416
- }
9417
9520
  }
9418
9521
  }
9419
9522
  logAgentLoopDebug({
@@ -10587,11 +10690,10 @@ class CodexProvider {
10587
10690
  (item) => item.type === "function_call"
10588
10691
  );
10589
10692
  if (functionCalls.length === 0) {
10590
- const recoveredTextCalls = recoverTextEncodedToolCalls(
10693
+ const recoveredCalls = recoverAssistantTextToolCalls(
10591
10694
  result.text,
10592
10695
  availableToolNames
10593
10696
  );
10594
- const recoveredCalls = recoveredTextCalls.length > 0 ? recoveredTextCalls : recoverNarratedActionToolCalls(result.text, availableToolNames);
10595
10697
  if (recoveredCalls.length > 0) {
10596
10698
  if (result.text.trim()) onChunk("<<erase_prev>>");
10597
10699
  functionCalls = recoveredCalls.map((toolCall) => ({
@@ -23312,7 +23414,10 @@ Recent checkpoints:
23312
23414
  ${input.recentCheckpoints || "- none"}
23313
23415
 
23314
23416
  Task tracker:
23315
- ${input.taskTrackerContext || "- none"}`;
23417
+ ${input.taskTrackerContext || "- none"}
23418
+
23419
+ Task memory:
23420
+ ${input.taskMemoryContext || "- none"}`;
23316
23421
  }
23317
23422
  function buildAgentSystemPrompt(input) {
23318
23423
  const instructionBlocks = input.profile === "compact" ? [
@@ -23693,6 +23798,7 @@ async function handleAIQuery(query, provider, activeWebContents, onChunk, onEnd,
23693
23798
  const runtimeState = runtime2.getState();
23694
23799
  const recentCheckpoints = runtimeState.checkpoints.slice(-3).map((item) => `- ${item.name} (${item.id})`).join("\n");
23695
23800
  const taskTrackerContext = runtime2.getTaskTrackerContext();
23801
+ const taskMemoryContext = runtime2.getTaskMemoryContext();
23696
23802
  const activeTabTitle = pageContent.title || "(untitled)";
23697
23803
  const activeTabUrl = pageContent.url || activeWebContents.getURL();
23698
23804
  const allTabs = tabManager.getAllStates();
@@ -23711,7 +23817,8 @@ All open tabs: ${allTabs.map((t) => `${t.id === activeTabId ? "→ " : ""}${t.ti
23711
23817
  approvalMode: runtimeState.supervisor.approvalMode,
23712
23818
  pendingApprovals: runtimeState.supervisor.pendingApprovals.length,
23713
23819
  recentCheckpoints: recentCheckpoints || "- none",
23714
- taskTrackerContext: taskTrackerContext || "- none"
23820
+ taskTrackerContext: taskTrackerContext || "- none",
23821
+ taskMemoryContext: taskMemoryContext || "- none"
23715
23822
  });
23716
23823
  const actionCtx = {
23717
23824
  tabManager,
@@ -24311,6 +24418,17 @@ function setMcpHealth(update) {
24311
24418
  }
24312
24419
  const ApprovalModeSchema = zod.z.enum(["auto", "confirm-dangerous", "manual"]);
24313
24420
  const CheckpointIdSchema = zod.z.string().min(1);
24421
+ const TaskTextSchema = zod.z.string().trim().min(1).max(2e4);
24422
+ const OptionalTaskTextSchema = zod.z.string().trim().max(2e4).optional();
24423
+ const OptionalNullableTaskTextSchema = zod.z.string().trim().max(2e4).nullable().optional();
24424
+ const TaskFactsSchema = zod.z.record(
24425
+ zod.z.string().trim().min(1).max(200),
24426
+ zod.z.string().max(2e4)
24427
+ );
24428
+ const TaskMemoryPatchSchema = zod.z.object({
24429
+ nextStep: OptionalNullableTaskTextSchema,
24430
+ facts: TaskFactsSchema.optional()
24431
+ });
24314
24432
  function registerAgentRuntimeHandlers(runtime2, chromeView, sidebarView, sendToRendererViews) {
24315
24433
  let runtimeUpdateTimer = null;
24316
24434
  let pendingRuntimeState = null;
@@ -24403,6 +24521,45 @@ function registerAgentRuntimeHandlers(runtime2, chromeView, sidebarView, sendToR
24403
24521
  return runtime2.restoreSession(snapshot2);
24404
24522
  }
24405
24523
  );
24524
+ electron.ipcMain.handle(Channels.AGENT_TASK_START, (event, goal) => {
24525
+ assertTrustedIpcSender(event);
24526
+ return runtime2.startTaskMemory(parseIpc(TaskTextSchema, goal, "goal"));
24527
+ });
24528
+ electron.ipcMain.handle(
24529
+ Channels.AGENT_TASK_UPDATE,
24530
+ (event, patch) => {
24531
+ assertTrustedIpcSender(event);
24532
+ return runtime2.updateTaskMemory(
24533
+ parseIpc(TaskMemoryPatchSchema, patch ?? {}, "patch")
24534
+ );
24535
+ }
24536
+ );
24537
+ electron.ipcMain.handle(Channels.AGENT_TASK_NOTE, (event, text) => {
24538
+ assertTrustedIpcSender(event);
24539
+ return runtime2.addTaskNote(parseIpc(TaskTextSchema, text, "text"));
24540
+ });
24541
+ electron.ipcMain.handle(Channels.AGENT_TASK_BLOCKER, (event, blocker) => {
24542
+ assertTrustedIpcSender(event);
24543
+ const validated = blocker == null ? null : parseIpc(OptionalNullableTaskTextSchema, blocker, "blocker");
24544
+ return runtime2.setTaskBlocker(validated ?? null);
24545
+ });
24546
+ electron.ipcMain.handle(Channels.AGENT_TASK_RESOLVE, (event, summary) => {
24547
+ assertTrustedIpcSender(event);
24548
+ return runtime2.resolveTaskMemory(
24549
+ summary == null ? void 0 : parseIpc(OptionalTaskTextSchema, summary, "summary")
24550
+ );
24551
+ });
24552
+ electron.ipcMain.handle(Channels.AGENT_TASK_ABANDON, (event, reason) => {
24553
+ assertTrustedIpcSender(event);
24554
+ return runtime2.abandonTaskMemory(
24555
+ reason == null ? void 0 : parseIpc(OptionalTaskTextSchema, reason, "reason")
24556
+ );
24557
+ });
24558
+ electron.ipcMain.handle(Channels.AGENT_TASK_CLEAR, (event) => {
24559
+ assertTrustedIpcSender(event);
24560
+ runtime2.clearTaskMemory();
24561
+ return null;
24562
+ });
24406
24563
  }
24407
24564
  function asTextResponse$1(text) {
24408
24565
  return { content: [{ type: "text", text }] };
@@ -28129,6 +28286,137 @@ ${flow.steps.map((s, i) => ` ${i === 0 ? "→" : " "} ${s.label}`).join("\n")}`
28129
28286
  }
28130
28287
  );
28131
28288
  }
28289
+ function registerTaskMemoryTools(server, _tabManager, runtime2) {
28290
+ server.registerTool(
28291
+ "task_start",
28292
+ {
28293
+ title: "Start Task",
28294
+ description: "Start tracking a task. Creates a task memory record with a goal that persists across actions and browser navigation. Use this at the beginning of a multi-step task so the human supervisor can see what you are working on.",
28295
+ inputSchema: {
28296
+ goal: zod.z.string().describe("What this task aims to accomplish"),
28297
+ nextStep: zod.z.string().optional().describe("The first step you plan to take"),
28298
+ facts: zod.z.record(zod.z.string()).optional().describe("Key-value facts relevant to this task (e.g. { username: alice })")
28299
+ }
28300
+ },
28301
+ async ({ goal, nextStep, facts }) => {
28302
+ const task = runtime2.startTaskMemory(goal, {
28303
+ nextStep: nextStep ?? null,
28304
+ facts: facts ?? {}
28305
+ });
28306
+ return asTextResponse(
28307
+ `Task started: ${task.goal}
28308
+ Status: ${task.status}${task.nextStep ? `
28309
+ Next step: ${task.nextStep}` : ""}`
28310
+ );
28311
+ }
28312
+ );
28313
+ server.registerTool(
28314
+ "task_update",
28315
+ {
28316
+ title: "Update Task",
28317
+ description: "Update the current task's next step or facts. Facts are merged with existing facts. Use this to record progress and keep the human supervisor informed.",
28318
+ inputSchema: {
28319
+ nextStep: zod.z.string().optional().describe("The next step you plan to take"),
28320
+ facts: zod.z.record(zod.z.string()).optional().describe("Key-value facts to merge into the task (existing keys are overwritten)")
28321
+ }
28322
+ },
28323
+ async ({ nextStep, facts }) => {
28324
+ const updated = runtime2.updateTaskMemory({
28325
+ nextStep,
28326
+ facts
28327
+ });
28328
+ if (!updated) return asTextResponse("No active task to update. Start one with task_start first.");
28329
+ return asTextResponse(
28330
+ `Task updated: ${updated.goal}
28331
+ Status: ${updated.status}${updated.nextStep ? `
28332
+ Next step: ${updated.nextStep}` : ""}${Object.keys(updated.facts).length > 0 ? `
28333
+ Facts: ${Object.entries(updated.facts).map(([k, v]) => `${k}=${v}`).join(", ")}` : ""}`
28334
+ );
28335
+ }
28336
+ );
28337
+ server.registerTool(
28338
+ "task_note",
28339
+ {
28340
+ title: "Add Task Note",
28341
+ description: "Add a note to the current task. Use this to record observations, intermediate results, or context for the human supervisor.",
28342
+ inputSchema: {
28343
+ text: zod.z.string().describe("The note text to add")
28344
+ }
28345
+ },
28346
+ async ({ text }) => {
28347
+ const updated = runtime2.addTaskNote(text);
28348
+ if (!updated) return asTextResponse("No active task to add a note to. Start one with task_start first.");
28349
+ return asTextResponse(`Note added to task: ${updated.goal}`);
28350
+ }
28351
+ );
28352
+ server.registerTool(
28353
+ "task_blocker",
28354
+ {
28355
+ title: "Set or Clear Task Blocker",
28356
+ description: "Mark the task as blocked with a reason, or clear a blocker to resume. Use this when you are stuck and need human input to continue.",
28357
+ inputSchema: {
28358
+ blocker: zod.z.string().optional().describe("Description of what is blocking progress. Omit or empty string to clear a blocker.")
28359
+ }
28360
+ },
28361
+ async ({ blocker }) => {
28362
+ const updated = runtime2.setTaskBlocker(blocker?.trim() || null);
28363
+ if (!updated) return asTextResponse("No active task. Start one with task_start first.");
28364
+ if (updated.blocker) {
28365
+ return asTextResponse(`Task blocked: ${updated.blocker}
28366
+ Status: ${updated.status}`);
28367
+ }
28368
+ return asTextResponse(`Blocker cleared. Task: ${updated.goal}
28369
+ Status: ${updated.status}`);
28370
+ }
28371
+ );
28372
+ server.registerTool(
28373
+ "task_resolve",
28374
+ {
28375
+ title: "Resolve Task",
28376
+ description: "Mark the current task as completed. Optionally add a summary note. Use this when the task goal has been achieved.",
28377
+ inputSchema: {
28378
+ summary: zod.z.string().optional().describe("Brief summary of the completed task")
28379
+ }
28380
+ },
28381
+ async ({ summary }) => {
28382
+ const resolved = runtime2.resolveTaskMemory(summary);
28383
+ if (!resolved) return asTextResponse("No active task to resolve. Start one with task_start first.");
28384
+ return asTextResponse(
28385
+ `Task completed: ${resolved.goal}${resolved.notes.length > 0 ? `
28386
+ Notes: ${resolved.notes.length} note(s)` : ""}`
28387
+ );
28388
+ }
28389
+ );
28390
+ server.registerTool(
28391
+ "task_abandon",
28392
+ {
28393
+ title: "Abandon Task",
28394
+ description: "Mark the current task as abandoned. Use this when the task cannot be completed or is no longer relevant.",
28395
+ inputSchema: {
28396
+ reason: zod.z.string().optional().describe("Reason for abandoning the task")
28397
+ }
28398
+ },
28399
+ async ({ reason }) => {
28400
+ const abandoned = runtime2.abandonTaskMemory(reason);
28401
+ if (!abandoned) return asTextResponse("No active task to abandon. Start one with task_start first.");
28402
+ return asTextResponse(
28403
+ `Task abandoned: ${abandoned.goal}${reason ? ` (${reason})` : ""}`
28404
+ );
28405
+ }
28406
+ );
28407
+ server.registerTool(
28408
+ "task_status",
28409
+ {
28410
+ title: "Task Status",
28411
+ description: "Check the current task memory status including goal, progress, notes, and blocker."
28412
+ },
28413
+ async () => {
28414
+ const ctx = runtime2.getTaskMemoryContext();
28415
+ if (!ctx) return asTextResponse("No active task. Start one with task_start.");
28416
+ return asTextResponse(ctx);
28417
+ }
28418
+ );
28419
+ }
28132
28420
  function registerMacroTools(server, tabManager, runtime2) {
28133
28421
  server.registerTool(
28134
28422
  "fill_form",
@@ -29429,6 +29717,7 @@ function registerTools(server, tabManager, runtime2) {
29429
29717
  registerSessionTools(server, tabManager, runtime2);
29430
29718
  registerMemoryTools(server, tabManager, runtime2);
29431
29719
  registerFlowTools(server, tabManager, runtime2);
29720
+ registerTaskMemoryTools(server, tabManager, runtime2);
29432
29721
  registerMacroTools(server, tabManager, runtime2);
29433
29722
  registerVaultTools(server, tabManager);
29434
29723
  registerMetricsTools(server, tabManager, runtime2);
@@ -32672,6 +32961,121 @@ function formatTaskTracker(state2) {
32672
32961
  ${lines.join("\n")}
32673
32962
  ---`;
32674
32963
  }
32964
+ function createTaskMemory(goal, options = {}) {
32965
+ const now = (/* @__PURE__ */ new Date()).toISOString();
32966
+ return {
32967
+ id: crypto$1.randomUUID(),
32968
+ goal: goal.trim(),
32969
+ status: "active",
32970
+ blocker: null,
32971
+ notes: [],
32972
+ nextStep: options.nextStep?.trim() || null,
32973
+ facts: { ...options.facts ?? {} },
32974
+ startedAt: now,
32975
+ updatedAt: now,
32976
+ completedAt: null
32977
+ };
32978
+ }
32979
+ function updateTaskMemory(task, patch) {
32980
+ const updated = {
32981
+ ...task,
32982
+ nextStep: patch.nextStep !== void 0 ? patch.nextStep : task.nextStep,
32983
+ facts: {
32984
+ ...task.facts,
32985
+ ...patch.facts ?? {}
32986
+ },
32987
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
32988
+ };
32989
+ return updated;
32990
+ }
32991
+ function addTaskNote(task, text) {
32992
+ const note = {
32993
+ id: crypto$1.randomUUID(),
32994
+ text: text.trim(),
32995
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
32996
+ };
32997
+ const notes = [...task.notes, note].slice(-50);
32998
+ return {
32999
+ ...task,
33000
+ notes,
33001
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
33002
+ };
33003
+ }
33004
+ function setTaskBlocker(task, blocker) {
33005
+ const status = blocker ? "blocked" : task.status === "blocked" ? "active" : task.status;
33006
+ return {
33007
+ ...task,
33008
+ status,
33009
+ blocker,
33010
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
33011
+ };
33012
+ }
33013
+ function resolveTaskMemory(task, summary) {
33014
+ const now = (/* @__PURE__ */ new Date()).toISOString();
33015
+ let notes = task.notes;
33016
+ if (summary?.trim()) {
33017
+ const note = {
33018
+ id: crypto$1.randomUUID(),
33019
+ text: summary.trim(),
33020
+ createdAt: now
33021
+ };
33022
+ notes = [...task.notes, note].slice(-50);
33023
+ }
33024
+ return {
33025
+ ...task,
33026
+ status: "completed",
33027
+ blocker: null,
33028
+ notes,
33029
+ completedAt: now,
33030
+ updatedAt: now
33031
+ };
33032
+ }
33033
+ function abandonTaskMemory(task, reason) {
33034
+ const now = (/* @__PURE__ */ new Date()).toISOString();
33035
+ let notes = task.notes;
33036
+ if (reason?.trim()) {
33037
+ const note = {
33038
+ id: crypto$1.randomUUID(),
33039
+ text: `Abandoned: ${reason.trim()}`,
33040
+ createdAt: now
33041
+ };
33042
+ notes = [...task.notes, note].slice(-50);
33043
+ }
33044
+ return {
33045
+ ...task,
33046
+ status: "abandoned",
33047
+ blocker: null,
33048
+ notes,
33049
+ completedAt: now,
33050
+ updatedAt: now
33051
+ };
33052
+ }
33053
+ function formatTaskMemory(task) {
33054
+ if (!task) return "";
33055
+ const lines = [
33056
+ "--- Task Memory ---",
33057
+ `Goal: ${task.goal}`,
33058
+ `Status: ${task.status}${task.blocker ? ` (blocked: ${task.blocker})` : ""}`
33059
+ ];
33060
+ if (task.nextStep) {
33061
+ lines.push(`Next step: ${task.nextStep}`);
33062
+ }
33063
+ if (Object.keys(task.facts).length > 0) {
33064
+ lines.push("Facts:");
33065
+ for (const [key2, value] of Object.entries(task.facts)) {
33066
+ lines.push(` ${key2}: ${value}`);
33067
+ }
33068
+ }
33069
+ if (task.notes.length > 0) {
33070
+ lines.push("Notes:");
33071
+ for (const note of task.notes.slice(-10)) {
33072
+ const time = note.createdAt.slice(11, 16);
33073
+ lines.push(` [${time}] ${note.text}`);
33074
+ }
33075
+ }
33076
+ lines.push("---");
33077
+ return lines.join("\n");
33078
+ }
32675
33079
  const MAX_TRANSCRIPT_TEXT_LENGTH = 8e3;
32676
33080
  const PERSIST_DEBOUNCE_MS = 500;
32677
33081
  const INTERRUPTED_ACTION_STATUSES = /* @__PURE__ */ new Set([
@@ -32701,6 +33105,7 @@ function getRuntimeStatePath() {
32701
33105
  }
32702
33106
  function sanitizePersistence(persisted) {
32703
33107
  const recoveredAt = (/* @__PURE__ */ new Date()).toISOString();
33108
+ const persistedTaskMemory = persisted?.taskMemory?.completedAt ? null : persisted?.taskMemory ?? null;
32704
33109
  const actions = Array.isArray(persisted?.actions) ? persisted.actions.slice(-120).map(
32705
33110
  (action) => INTERRUPTED_ACTION_STATUSES.has(action.status) ? {
32706
33111
  ...action,
@@ -32722,7 +33127,8 @@ function sanitizePersistence(persisted) {
32722
33127
  transcript: [],
32723
33128
  mcpStatus: "stopped",
32724
33129
  flowState: null,
32725
- taskTracker: null
33130
+ taskTracker: null,
33131
+ taskMemory: persistedTaskMemory
32726
33132
  };
32727
33133
  }
32728
33134
  class AgentRuntime {
@@ -32809,7 +33215,8 @@ class AgentRuntime {
32809
33215
  name: name?.trim() || `Checkpoint ${this.state.checkpoints.length + 1}`,
32810
33216
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
32811
33217
  note: note?.trim() || void 0,
32812
- snapshot: snapshot2
33218
+ snapshot: snapshot2,
33219
+ taskMemory: this.state.taskMemory ? clone(this.state.taskMemory) : null
32813
33220
  };
32814
33221
  this.state.checkpoints = [...this.state.checkpoints, checkpoint].slice(
32815
33222
  -20
@@ -32822,6 +33229,7 @@ class AgentRuntime {
32822
33229
  const checkpoint = this.state.checkpoints.find((item) => item.id === checkpointId) || null;
32823
33230
  if (!checkpoint) return null;
32824
33231
  this.tabManager.restoreSession(checkpoint.snapshot);
33232
+ this.state.taskMemory = checkpoint.taskMemory ? clone(checkpoint.taskMemory) : null;
32825
33233
  this.captureSession(`Restored ${checkpoint.name}`);
32826
33234
  return clone(checkpoint);
32827
33235
  }
@@ -32938,6 +33346,54 @@ class AgentRuntime {
32938
33346
  getTaskTrackerContext() {
32939
33347
  return formatTaskTracker(this.state.taskTracker);
32940
33348
  }
33349
+ // --- Task Memory ---
33350
+ startTaskMemory(goal, options) {
33351
+ this.state.taskMemory = createTaskMemory(goal, options);
33352
+ this.emit();
33353
+ return clone(this.state.taskMemory);
33354
+ }
33355
+ updateTaskMemory(patch) {
33356
+ if (!this.state.taskMemory || this.state.taskMemory.completedAt) return null;
33357
+ this.state.taskMemory = updateTaskMemory(this.state.taskMemory, patch);
33358
+ this.emit();
33359
+ return clone(this.state.taskMemory);
33360
+ }
33361
+ addTaskNote(text) {
33362
+ if (!this.state.taskMemory || this.state.taskMemory.completedAt) return null;
33363
+ this.state.taskMemory = addTaskNote(this.state.taskMemory, text);
33364
+ this.emit();
33365
+ return clone(this.state.taskMemory);
33366
+ }
33367
+ setTaskBlocker(blocker) {
33368
+ if (!this.state.taskMemory || this.state.taskMemory.completedAt) return null;
33369
+ this.state.taskMemory = setTaskBlocker(
33370
+ this.state.taskMemory,
33371
+ blocker
33372
+ );
33373
+ this.emit();
33374
+ return clone(this.state.taskMemory);
33375
+ }
33376
+ resolveTaskMemory(summary) {
33377
+ if (!this.state.taskMemory || this.state.taskMemory.completedAt) return null;
33378
+ const resolved = resolveTaskMemory(this.state.taskMemory, summary);
33379
+ this.state.taskMemory = null;
33380
+ this.emit();
33381
+ return clone(resolved);
33382
+ }
33383
+ abandonTaskMemory(reason) {
33384
+ if (!this.state.taskMemory || this.state.taskMemory.completedAt) return null;
33385
+ const abandoned = abandonTaskMemory(this.state.taskMemory, reason);
33386
+ this.state.taskMemory = null;
33387
+ this.emit();
33388
+ return clone(abandoned);
33389
+ }
33390
+ clearTaskMemory() {
33391
+ this.state.taskMemory = null;
33392
+ this.emit();
33393
+ }
33394
+ getTaskMemoryContext() {
33395
+ return formatTaskMemory(this.state.taskMemory);
33396
+ }
32941
33397
  // --- Speedee Flow State ---
32942
33398
  startFlow(goal, steps, startUrl) {
32943
33399
  const flow = {
@@ -33163,7 +33619,8 @@ ${progress}
33163
33619
  lastError: this.state.supervisor.lastError
33164
33620
  },
33165
33621
  actions: this.state.actions.slice(-120),
33166
- checkpoints: this.state.checkpoints.slice(-20)
33622
+ checkpoints: this.state.checkpoints.slice(-20),
33623
+ taskMemory: this.state.taskMemory
33167
33624
  };
33168
33625
  return fs$1.promises.mkdir(path.dirname(getRuntimeStatePath()), { recursive: true }).then(
33169
33626
  () => fs$1.promises.writeFile(
@@ -20,7 +20,14 @@ const AIChannels = {
20
20
  AGENT_CHECKPOINT_UPDATE_NOTE: "agent:checkpoint-update-note",
21
21
  AGENT_UNDO_LAST_ACTION: "agent:undo-last-action",
22
22
  AGENT_SESSION_CAPTURE: "agent:session-capture",
23
- AGENT_SESSION_RESTORE: "agent:session-restore"
23
+ AGENT_SESSION_RESTORE: "agent:session-restore",
24
+ AGENT_TASK_START: "agent:task-start",
25
+ AGENT_TASK_UPDATE: "agent:task-update",
26
+ AGENT_TASK_NOTE: "agent:task-note",
27
+ AGENT_TASK_BLOCKER: "agent:task-blocker",
28
+ AGENT_TASK_RESOLVE: "agent:task-resolve",
29
+ AGENT_TASK_ABANDON: "agent:task-abandon",
30
+ AGENT_TASK_CLEAR: "agent:task-clear"
24
31
  };
25
32
  const AutofillChannels = {
26
33
  AUTOFILL_LIST: "autofill:list",
@@ -374,7 +381,14 @@ const api = {
374
381
  updateCheckpointNote: (checkpointId, note) => electron.ipcRenderer.invoke(Channels.AGENT_CHECKPOINT_UPDATE_NOTE, checkpointId, note),
375
382
  undoLastAction: () => electron.ipcRenderer.invoke(Channels.AGENT_UNDO_LAST_ACTION),
376
383
  captureSession: (note) => electron.ipcRenderer.invoke(Channels.AGENT_SESSION_CAPTURE, note),
377
- restoreSession: (snapshot) => electron.ipcRenderer.invoke(Channels.AGENT_SESSION_RESTORE, snapshot)
384
+ restoreSession: (snapshot) => electron.ipcRenderer.invoke(Channels.AGENT_SESSION_RESTORE, snapshot),
385
+ startTaskMemory: (goal) => electron.ipcRenderer.invoke(Channels.AGENT_TASK_START, goal),
386
+ updateTaskMemory: (patch) => electron.ipcRenderer.invoke(Channels.AGENT_TASK_UPDATE, patch),
387
+ addTaskNote: (text) => electron.ipcRenderer.invoke(Channels.AGENT_TASK_NOTE, text),
388
+ setTaskBlocker: (blocker) => electron.ipcRenderer.invoke(Channels.AGENT_TASK_BLOCKER, blocker),
389
+ resolveTaskMemory: (summary) => electron.ipcRenderer.invoke(Channels.AGENT_TASK_RESOLVE, summary),
390
+ abandonTaskMemory: (reason) => electron.ipcRenderer.invoke(Channels.AGENT_TASK_ABANDON, reason),
391
+ clearTaskMemory: () => electron.ipcRenderer.invoke(Channels.AGENT_TASK_CLEAR)
378
392
  },
379
393
  research: {
380
394
  getState: () => electron.ipcRenderer.invoke(Channels.RESEARCH_STATE_GET),
@@ -1147,6 +1147,112 @@
1147
1147
  white-space: nowrap;
1148
1148
  }
1149
1149
 
1150
+ /* ═══════════════════════════════════════
1151
+ Task Memory overlay — in-flow progress
1152
+ ═══════════════════════════════════════ */
1153
+
1154
+ .task-memory-status {
1155
+ font-size: 10px;
1156
+ font-weight: 600;
1157
+ text-transform: uppercase;
1158
+ letter-spacing: 0.5px;
1159
+ padding: 2px 6px;
1160
+ border-radius: 3px;
1161
+ flex-shrink: 0;
1162
+ }
1163
+
1164
+ .task-memory-status-active {
1165
+ color: var(--accent-primary);
1166
+ background: color-mix(in srgb, var(--accent-primary) 12%, transparent);
1167
+ }
1168
+
1169
+ .task-memory-status-completed {
1170
+ color: var(--accent-secondary, #8aad6b);
1171
+ background: color-mix(in srgb, var(--accent-secondary, #8aad6b) 12%, transparent);
1172
+ }
1173
+
1174
+ .task-memory-status-abandoned {
1175
+ color: var(--text-muted);
1176
+ background: color-mix(in srgb, var(--text-muted) 8%, transparent);
1177
+ }
1178
+
1179
+ .task-memory-status-blocked {
1180
+ color: var(--status-error);
1181
+ background: color-mix(in srgb, var(--status-error) 12%, transparent);
1182
+ }
1183
+
1184
+ .task-memory-blocker {
1185
+ margin-top: 6px;
1186
+ font-size: 11px;
1187
+ color: var(--status-error);
1188
+ line-height: 1.4;
1189
+ }
1190
+
1191
+ .task-memory-next-step {
1192
+ margin-top: 4px;
1193
+ font-size: 11px;
1194
+ color: var(--text-secondary);
1195
+ line-height: 1.4;
1196
+ }
1197
+
1198
+ .task-memory-facts {
1199
+ margin-top: 6px;
1200
+ display: flex;
1201
+ flex-direction: column;
1202
+ gap: 2px;
1203
+ }
1204
+
1205
+ .task-memory-fact {
1206
+ display: flex;
1207
+ gap: 6px;
1208
+ font-size: 11px;
1209
+ line-height: 1.4;
1210
+ }
1211
+
1212
+ .task-memory-fact-key {
1213
+ color: var(--text-muted);
1214
+ flex-shrink: 0;
1215
+ }
1216
+
1217
+ .task-memory-fact-key::after {
1218
+ content: ":";
1219
+ }
1220
+
1221
+ .task-memory-fact-value {
1222
+ color: var(--text-secondary);
1223
+ overflow: hidden;
1224
+ text-overflow: ellipsis;
1225
+ white-space: nowrap;
1226
+ }
1227
+
1228
+ .task-memory-notes {
1229
+ margin-top: 6px;
1230
+ display: flex;
1231
+ flex-direction: column;
1232
+ gap: 3px;
1233
+ }
1234
+
1235
+ .task-memory-note {
1236
+ display: flex;
1237
+ gap: 6px;
1238
+ font-size: 11px;
1239
+ line-height: 1.4;
1240
+ }
1241
+
1242
+ .task-memory-note-time {
1243
+ color: var(--text-muted);
1244
+ flex-shrink: 0;
1245
+ font-family: var(--font-mono);
1246
+ font-size: 10px;
1247
+ }
1248
+
1249
+ .task-memory-note-text {
1250
+ color: var(--text-secondary);
1251
+ overflow: hidden;
1252
+ text-overflow: ellipsis;
1253
+ white-space: nowrap;
1254
+ }
1255
+
1150
1256
  /* ═══════════════════════════════════════
1151
1257
  Agent transcript dock — floating panel
1152
1258
  ═══════════════════════════════════════ */
@@ -7011,6 +7117,11 @@
7011
7117
  background-repeat: no-repeat;
7012
7118
  background-position: right 10px center;
7013
7119
  }
7120
+ .settings-select option,
7121
+ .settings-select optgroup {
7122
+ color: var(--text-primary);
7123
+ background-color: var(--bg-elevated);
7124
+ }
7014
7125
  .settings-textarea {
7015
7126
  width: 100%;
7016
7127
  padding: 8px 10px;
@@ -2497,6 +2497,7 @@ const DEFAULT_RUNTIME_STATE = {
2497
2497
  mcpStatus: "stopped",
2498
2498
  flowState: null,
2499
2499
  taskTracker: null,
2500
+ taskMemory: null,
2500
2501
  canUndo: false,
2501
2502
  undoInfo: null
2502
2503
  };
@@ -2538,7 +2539,14 @@ function useRuntime() {
2538
2539
  updateCheckpointNote: (checkpointId, note) => window.vessel.ai.updateCheckpointNote(checkpointId, note),
2539
2540
  undoLastAction: () => window.vessel.ai.undoLastAction(),
2540
2541
  captureSession: (note) => window.vessel.ai.captureSession(note),
2541
- restoreSession: () => window.vessel.ai.restoreSession()
2542
+ restoreSession: () => window.vessel.ai.restoreSession(),
2543
+ startTaskMemory: (goal) => window.vessel.ai.startTaskMemory(goal),
2544
+ updateTaskMemory: (patch) => window.vessel.ai.updateTaskMemory(patch),
2545
+ addTaskNote: (text2) => window.vessel.ai.addTaskNote(text2),
2546
+ setTaskBlocker: (blocker) => window.vessel.ai.setTaskBlocker(blocker),
2547
+ resolveTaskMemory: (summary) => window.vessel.ai.resolveTaskMemory(summary),
2548
+ abandonTaskMemory: (reason) => window.vessel.ai.abandonTaskMemory(reason),
2549
+ clearTaskMemory: () => window.vessel.ai.clearTaskMemory()
2542
2550
  };
2543
2551
  }
2544
2552
  const AGENT_ACTIVITY_WINDOW_MS = 6e3;
@@ -2573,7 +2581,7 @@ function getAgentActiveTabIds(state, currentTime = Date.now()) {
2573
2581
  }
2574
2582
  return activeTabIds;
2575
2583
  }
2576
- var _tmpl$$r = /* @__PURE__ */ template(`<img class=tab-favicon alt>`), _tmpl$2$q = /* @__PURE__ */ template(`<span class=tab-favicon-fallback>`), _tmpl$3$m = /* @__PURE__ */ template(`<div class=tab-bar><div class=tab-list></div><div class=tab-actions><button class=tab-new data-tooltip="New window"data-tooltip-pos=left></button><button class=tab-new data-tooltip="Add active tab to group"data-tooltip-pos=left></button><button class=tab-new data-tooltip="New tab"data-tooltip-pos=left></button><button class="tab-new tab-new-private"data-tooltip="Private window"data-tooltip-pos=left><svg width=12 height=12 viewBox="0 0 16 16"fill=currentColor><path d="M8 1a7 7 0 100 14A7 7 0 008 1zm0 1.5a5.5 5.5 0 110 11 5.5 5.5 0 010-11z">`), _tmpl$4$l = /* @__PURE__ */ template(`<button><span class=tab-group-dot></span><span class=tab-group-name></span><span class=tab-group-count>`), _tmpl$5$h = /* @__PURE__ */ template(`<button class="tab-audio tab-audio-pinned">`), _tmpl$6$f = /* @__PURE__ */ template(`<div role=tab>`), _tmpl$7$d = /* @__PURE__ */ template(`<span class=tab-title>`), _tmpl$8$a = /* @__PURE__ */ template(`<button class=tab-audio>`), _tmpl$9$9 = /* @__PURE__ */ template(`<button class=tab-close>×`), _tmpl$0$7 = /* @__PURE__ */ template(`<span class=tab-agent-indicator aria-hidden=true title="Agent active on this tab">`), _tmpl$1$7 = /* @__PURE__ */ template(`<span class=tab-loading>`);
2584
+ var _tmpl$$r = /* @__PURE__ */ template(`<img class=tab-favicon alt>`), _tmpl$2$q = /* @__PURE__ */ template(`<span class=tab-favicon-fallback>`), _tmpl$3$m = /* @__PURE__ */ template(`<div class=tab-bar><div class=tab-list></div><div class=tab-actions><button class=tab-new data-tooltip="New window"data-tooltip-pos=left></button><button class=tab-new data-tooltip="Add active tab to group"data-tooltip-pos=left></button><button class=tab-new data-tooltip="New tab"data-tooltip-pos=left></button><button class="tab-new tab-new-private"data-tooltip="Private window"data-tooltip-pos=left><svg width=12 height=12 viewBox="0 0 16 16"fill=currentColor><path d="M8 1a7 7 0 100 14A7 7 0 008 1zm0 1.5a5.5 5.5 0 110 11 5.5 5.5 0 010-11z">`), _tmpl$4$l = /* @__PURE__ */ template(`<button><span class=tab-group-dot></span><span class=tab-group-name></span><span class=tab-group-count>`), _tmpl$5$h = /* @__PURE__ */ template(`<button class="tab-audio tab-audio-pinned">`), _tmpl$6$g = /* @__PURE__ */ template(`<div role=tab>`), _tmpl$7$e = /* @__PURE__ */ template(`<span class=tab-title>`), _tmpl$8$b = /* @__PURE__ */ template(`<button class=tab-audio>`), _tmpl$9$a = /* @__PURE__ */ template(`<button class=tab-close>×`), _tmpl$0$8 = /* @__PURE__ */ template(`<span class=tab-agent-indicator aria-hidden=true title="Agent active on this tab">`), _tmpl$1$8 = /* @__PURE__ */ template(`<span class=tab-loading>`);
2577
2585
  const TAB_CLOSE_MS = 200;
2578
2586
  function stringToHue(str) {
2579
2587
  let hash = 0;
@@ -2710,7 +2718,7 @@ const TabBar = () => {
2710
2718
  return memo(() => entry.type === "tab")() && (() => {
2711
2719
  const tab = entry.tab;
2712
2720
  return (() => {
2713
- var _el$12 = _tmpl$6$f();
2721
+ var _el$12 = _tmpl$6$g();
2714
2722
  _el$12.$$contextmenu = (e) => {
2715
2723
  e.preventDefault();
2716
2724
  window.vessel.tabs.showContextMenu(tab.id);
@@ -2761,8 +2769,8 @@ const TabBar = () => {
2761
2769
  }), null);
2762
2770
  insert(_el$12, (() => {
2763
2771
  var _c$ = memo(() => !!!tab.isPinned);
2764
- return () => _c$() && [memo(() => memo(() => !!modelActiveTabIds().has(tab.id))() && _tmpl$0$7()), (() => {
2765
- var _el$14 = _tmpl$7$d();
2772
+ return () => _c$() && [memo(() => memo(() => !!modelActiveTabIds().has(tab.id))() && _tmpl$0$8()), (() => {
2773
+ var _el$14 = _tmpl$7$e();
2766
2774
  insert(_el$14, () => tab.title || "New Tab");
2767
2775
  return _el$14;
2768
2776
  })(), createComponent(Show, {
@@ -2770,7 +2778,7 @@ const TabBar = () => {
2770
2778
  return tab.isAudible || tab.isMuted;
2771
2779
  },
2772
2780
  get children() {
2773
- var _el$15 = _tmpl$8$a();
2781
+ var _el$15 = _tmpl$8$b();
2774
2782
  _el$15.$$click = (e) => {
2775
2783
  e.stopPropagation();
2776
2784
  void toggleMute(tab.id);
@@ -2793,8 +2801,8 @@ const TabBar = () => {
2793
2801
  createRenderEffect(() => setAttribute(_el$15, "title", tab.isMuted ? "Unmute tab" : "Mute tab"));
2794
2802
  return _el$15;
2795
2803
  }
2796
- }), memo(() => memo(() => !!tab.isLoading)() && _tmpl$1$7()), (() => {
2797
- var _el$16 = _tmpl$9$9();
2804
+ }), memo(() => memo(() => !!tab.isLoading)() && _tmpl$1$8()), (() => {
2805
+ var _el$16 = _tmpl$9$a();
2798
2806
  _el$16.$$click = (e) => {
2799
2807
  e.stopPropagation();
2800
2808
  handleClose(tab.id);
@@ -3330,7 +3338,7 @@ const SEARCH_ENGINE_PRESETS = {
3330
3338
  ecosia: { label: "Ecosia", url: "https://www.ecosia.org/search?q=" },
3331
3339
  kagi: { label: "Kagi", url: "https://kagi.com/search?q=" }
3332
3340
  };
3333
- var _tmpl$$p = /* @__PURE__ */ template(`<div class=private-badge title="Private Browsing - history and cookies are not saved"><svg width=12 height=12 viewBox="0 0 16 16"fill=currentColor><path d="M8 1a7 7 0 100 14A7 7 0 008 1zm0 1.5a5.5 5.5 0 110 11 5.5 5.5 0 010-11zM5.5 7a1.5 1.5 0 103 0 1.5 1.5 0 00-3 0zm3.5 3.5c0-1-1.5-2-2.5-2s-2.5 1-2.5 2"></path></svg><span>Private`), _tmpl$2$o = /* @__PURE__ */ template(`<svg width=14 height=14 viewBox="0 0 14 14"fill=currentColor><path d="M7 1a4 4 0 00-4 4v2H1.5a.5.5 0 00-.5.5v5a.5.5 0 00.5.5h11a.5.5 0 00.5-.5v-5a.5.5 0 00-.5-.5H11V5a4 4 0 00-4-4zm0 1a3 3 0 013 3v2H4V5a3 3 0 013-3z">`), _tmpl$3$k = /* @__PURE__ */ template(`<svg width=14 height=14 viewBox="0 0 14 14"fill=currentColor><path d="M7 1a4 4 0 00-4 4v2H1.5a.5.5 0 00-.5.5v5a.5.5 0 00.5.5h11a.5.5 0 00.5-.5v-5a.5.5 0 00-.5-.5H11V5a4 4 0 00-4-4zm0 1a3 3 0 013 3v2H4V5a3 3 0 013-3z"></path><line x1=2 y1=12 x2=12 y2=2 stroke=currentColor stroke-width=1.5>`), _tmpl$4$j = /* @__PURE__ */ template(`<div class=security-indicator-wrapper><button>`), _tmpl$5$f = /* @__PURE__ */ template(`<div id=address-autocomplete class=autocomplete-dropdown role=listbox>`), _tmpl$6$e = /* @__PURE__ */ template(`<button class=page-diff-trigger title="Open the What Changed timeline"><span class=page-diff-trigger-dot aria-hidden=true></span><span class=page-diff-trigger-text>What Changed?`), _tmpl$7$c = /* @__PURE__ */ template(`<span class=page-diff-burst-meta>Updated <!> times over `), _tmpl$8$9 = /* @__PURE__ */ template(`<div class=page-diff-burst-history><div class=page-diff-burst-history-label>Recent detections`), _tmpl$9$8 = /* @__PURE__ */ template(`<div class=page-diff-popup><div class=page-diff-popup-header><div class=page-diff-popup-header-copy><span>Compared with your last visit</span><span class=page-diff-burst-meta>Previous snapshot from </span></div><div style=display:flex;gap:8px;align-items:center><button class=nav-btn title="Open the full What Changed timeline"style="height:24px;min-width:auto;padding:0 8px">Timeline</button><button class=page-diff-popup-close>&times;`), _tmpl$0$6 = /* @__PURE__ */ template(`<svg><path d="M3 3 L11 3 L11 9 Q7 13 3 9 Z"fill=none stroke=currentColor stroke-width=1.2 stroke-linejoin=round></svg>`, false, true, false), _tmpl$1$6 = /* @__PURE__ */ template(`<svg><line x1=2 y1=12 x2=12 y2=2 stroke=currentColor stroke-width=1.4 stroke-linecap=round></svg>`, false, true, false), _tmpl$10$6 = /* @__PURE__ */ template(`<button class=nav-btn data-tooltip="Reader Mode"><svg width=14 height=14 viewBox="0 0 14 14"><rect x=2 y=1 width=10 height=12 rx=1 fill=none stroke=currentColor stroke-width=1.2></rect><line x1=4 y1=4 x2=10 y2=4 stroke=currentColor stroke-width=1></line><line x1=4 y1=6.5 x2=10 y2=6.5 stroke=currentColor stroke-width=1></line><line x1=4 y1=9 x2=8 y2=9 stroke=currentColor stroke-width=1>`), _tmpl$11$6 = /* @__PURE__ */ template(`<button class=nav-btn data-tooltip="Dev Tools"><svg width=14 height=14 viewBox="0 0 14 14"><polyline points="3,5 1,7 3,9"fill=none stroke=currentColor stroke-width=1.2 stroke-linecap=round stroke-linejoin=round></polyline><polyline points="11,5 13,7 11,9"fill=none stroke=currentColor stroke-width=1.2 stroke-linecap=round stroke-linejoin=round></polyline><line x1=8.5 y1=2 x2=5.5 y2=12 stroke=currentColor stroke-width=1.2 stroke-linecap=round>`), _tmpl$12$6 = /* @__PURE__ */ template(`<span class=nav-btn-badge>`), _tmpl$13$5 = /* @__PURE__ */ template(`<button class="nav-btn nav-btn-sidebar"><svg width=14 height=14 viewBox="0 0 14 14"><rect x=1 y=1 width=12 height=12 rx=1.5 fill=none stroke=currentColor stroke-width=1.2></rect><line x1=9 y1=1 x2=9 y2=13 stroke=currentColor stroke-width=1.2>`), _tmpl$14$5 = /* @__PURE__ */ template(`<button class=nav-btn data-tooltip="Clear Data">`), _tmpl$15$5 = /* @__PURE__ */ template(`<button class=nav-btn data-tooltip=Settings><svg width=14 height=14 viewBox="0 0 14 14"><circle cx=7 cy=7 r=2 fill=none stroke=currentColor stroke-width=1.2></circle><path d="M7 1v2M7 11v2M1 7h2M11 7h2M2.8 2.8l1.4 1.4M9.8 9.8l1.4 1.4M11.2 2.8l-1.4 1.4M4.2 9.8l-1.4 1.4"stroke=currentColor stroke-width=1 stroke-linecap=round>`), _tmpl$16$4 = /* @__PURE__ */ template(`<div class=address-bar><div class=nav-controls><button class=nav-btn data-tooltip=Back><svg width=14 height=14 viewBox="0 0 14 14"><path d="M9 2L4 7l5 5"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round></path></svg></button><button class=nav-btn data-tooltip=Forward><svg width=14 height=14 viewBox="0 0 14 14"><path d="M5 2l5 5-5 5"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round></path></svg></button><button class=nav-btn data-tooltip=Reload><svg width=14 height=14 viewBox="0 0 14 14"><path d="M2.5 7a4.5 4.5 0 1 1 1 3"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round></path><path d="M2 4v3.5h3.5"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round></path></svg></button></div><div class=url-shell><form class=url-form><input class=url-input type=text placeholder="Search or enter URL"autocomplete=off aria-autocomplete=list aria-controls=address-autocomplete></form></div><div class=toolbar-actions><button class=nav-btn><svg width=14 height=14 viewBox="0 0 14 14">`), _tmpl$17$4 = /* @__PURE__ */ template(`<svg width=14 height=14 viewBox="0 0 14 14"fill=currentColor><path d="M7 1a4 4 0 00-4 4v2H1.5a.5.5 0 00-.5.5v5a.5.5 0 00.5.5h11a.5.5 0 00.5-.5v-5a.5.5 0 00-.5-.5H11V5a4 4 0 00-4-4zm0 1a3 3 0 013 3v2H4V5a3 3 0 013-3z"></path><circle cx=7 cy=8 r=0.8 fill=white>`), _tmpl$18$4 = /* @__PURE__ */ template(`<div role=option><span class=autocomplete-icon></span><span class=autocomplete-text><span class=autocomplete-title></span><span class=autocomplete-url>`), _tmpl$19$4 = /* @__PURE__ */ template(`<div class=page-diff-burst-row><span class=page-diff-burst-time></span><span class=page-diff-burst-summary>`), _tmpl$20$4 = /* @__PURE__ */ template(`<span class=page-diff-burst-summary-section>`), _tmpl$21$4 = /* @__PURE__ */ template(`<span class=page-diff-burst-summary-part><span>`), _tmpl$22$4 = /* @__PURE__ */ template(`<div class=page-diff-snippet><span class=page-diff-snippet-label>Before</span><span class=page-diff-snippet-text>`), _tmpl$23$4 = /* @__PURE__ */ template(`<div class=page-diff-snippet><span class=page-diff-snippet-label>After</span><span class=page-diff-snippet-text>`), _tmpl$24$4 = /* @__PURE__ */ template(`<div class=page-diff-snippets>`), _tmpl$25$3 = /* @__PURE__ */ template(`<div class=page-diff-list-group><span class=page-diff-list-label>Added</span><ul class=page-diff-list>`), _tmpl$26$3 = /* @__PURE__ */ template(`<div class=page-diff-list-group><span class=page-diff-list-label>Removed</span><ul class=page-diff-list>`), _tmpl$27$3 = /* @__PURE__ */ template(`<div><div class=page-diff-item-header><div class=page-diff-badges><span class=page-diff-kind></span><span class=page-diff-section></span></div><span class=page-diff-summary>`), _tmpl$28$3 = /* @__PURE__ */ template(`<li>`);
3341
+ var _tmpl$$p = /* @__PURE__ */ template(`<div class=private-badge title="Private Browsing - history and cookies are not saved"><svg width=12 height=12 viewBox="0 0 16 16"fill=currentColor><path d="M8 1a7 7 0 100 14A7 7 0 008 1zm0 1.5a5.5 5.5 0 110 11 5.5 5.5 0 010-11zM5.5 7a1.5 1.5 0 103 0 1.5 1.5 0 00-3 0zm3.5 3.5c0-1-1.5-2-2.5-2s-2.5 1-2.5 2"></path></svg><span>Private`), _tmpl$2$o = /* @__PURE__ */ template(`<svg width=14 height=14 viewBox="0 0 14 14"fill=currentColor><path d="M7 1a4 4 0 00-4 4v2H1.5a.5.5 0 00-.5.5v5a.5.5 0 00.5.5h11a.5.5 0 00.5-.5v-5a.5.5 0 00-.5-.5H11V5a4 4 0 00-4-4zm0 1a3 3 0 013 3v2H4V5a3 3 0 013-3z">`), _tmpl$3$k = /* @__PURE__ */ template(`<svg width=14 height=14 viewBox="0 0 14 14"fill=currentColor><path d="M7 1a4 4 0 00-4 4v2H1.5a.5.5 0 00-.5.5v5a.5.5 0 00.5.5h11a.5.5 0 00.5-.5v-5a.5.5 0 00-.5-.5H11V5a4 4 0 00-4-4zm0 1a3 3 0 013 3v2H4V5a3 3 0 013-3z"></path><line x1=2 y1=12 x2=12 y2=2 stroke=currentColor stroke-width=1.5>`), _tmpl$4$j = /* @__PURE__ */ template(`<div class=security-indicator-wrapper><button>`), _tmpl$5$f = /* @__PURE__ */ template(`<div id=address-autocomplete class=autocomplete-dropdown role=listbox>`), _tmpl$6$f = /* @__PURE__ */ template(`<button class=page-diff-trigger title="Open the What Changed timeline"><span class=page-diff-trigger-dot aria-hidden=true></span><span class=page-diff-trigger-text>What Changed?`), _tmpl$7$d = /* @__PURE__ */ template(`<span class=page-diff-burst-meta>Updated <!> times over `), _tmpl$8$a = /* @__PURE__ */ template(`<div class=page-diff-burst-history><div class=page-diff-burst-history-label>Recent detections`), _tmpl$9$9 = /* @__PURE__ */ template(`<div class=page-diff-popup><div class=page-diff-popup-header><div class=page-diff-popup-header-copy><span>Compared with your last visit</span><span class=page-diff-burst-meta>Previous snapshot from </span></div><div style=display:flex;gap:8px;align-items:center><button class=nav-btn title="Open the full What Changed timeline"style="height:24px;min-width:auto;padding:0 8px">Timeline</button><button class=page-diff-popup-close>&times;`), _tmpl$0$7 = /* @__PURE__ */ template(`<svg><path d="M3 3 L11 3 L11 9 Q7 13 3 9 Z"fill=none stroke=currentColor stroke-width=1.2 stroke-linejoin=round></svg>`, false, true, false), _tmpl$1$7 = /* @__PURE__ */ template(`<svg><line x1=2 y1=12 x2=12 y2=2 stroke=currentColor stroke-width=1.4 stroke-linecap=round></svg>`, false, true, false), _tmpl$10$7 = /* @__PURE__ */ template(`<button class=nav-btn data-tooltip="Reader Mode"><svg width=14 height=14 viewBox="0 0 14 14"><rect x=2 y=1 width=10 height=12 rx=1 fill=none stroke=currentColor stroke-width=1.2></rect><line x1=4 y1=4 x2=10 y2=4 stroke=currentColor stroke-width=1></line><line x1=4 y1=6.5 x2=10 y2=6.5 stroke=currentColor stroke-width=1></line><line x1=4 y1=9 x2=8 y2=9 stroke=currentColor stroke-width=1>`), _tmpl$11$6 = /* @__PURE__ */ template(`<button class=nav-btn data-tooltip="Dev Tools"><svg width=14 height=14 viewBox="0 0 14 14"><polyline points="3,5 1,7 3,9"fill=none stroke=currentColor stroke-width=1.2 stroke-linecap=round stroke-linejoin=round></polyline><polyline points="11,5 13,7 11,9"fill=none stroke=currentColor stroke-width=1.2 stroke-linecap=round stroke-linejoin=round></polyline><line x1=8.5 y1=2 x2=5.5 y2=12 stroke=currentColor stroke-width=1.2 stroke-linecap=round>`), _tmpl$12$6 = /* @__PURE__ */ template(`<span class=nav-btn-badge>`), _tmpl$13$5 = /* @__PURE__ */ template(`<button class="nav-btn nav-btn-sidebar"><svg width=14 height=14 viewBox="0 0 14 14"><rect x=1 y=1 width=12 height=12 rx=1.5 fill=none stroke=currentColor stroke-width=1.2></rect><line x1=9 y1=1 x2=9 y2=13 stroke=currentColor stroke-width=1.2>`), _tmpl$14$5 = /* @__PURE__ */ template(`<button class=nav-btn data-tooltip="Clear Data">`), _tmpl$15$5 = /* @__PURE__ */ template(`<button class=nav-btn data-tooltip=Settings><svg width=14 height=14 viewBox="0 0 14 14"><circle cx=7 cy=7 r=2 fill=none stroke=currentColor stroke-width=1.2></circle><path d="M7 1v2M7 11v2M1 7h2M11 7h2M2.8 2.8l1.4 1.4M9.8 9.8l1.4 1.4M11.2 2.8l-1.4 1.4M4.2 9.8l-1.4 1.4"stroke=currentColor stroke-width=1 stroke-linecap=round>`), _tmpl$16$4 = /* @__PURE__ */ template(`<div class=address-bar><div class=nav-controls><button class=nav-btn data-tooltip=Back><svg width=14 height=14 viewBox="0 0 14 14"><path d="M9 2L4 7l5 5"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round></path></svg></button><button class=nav-btn data-tooltip=Forward><svg width=14 height=14 viewBox="0 0 14 14"><path d="M5 2l5 5-5 5"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round></path></svg></button><button class=nav-btn data-tooltip=Reload><svg width=14 height=14 viewBox="0 0 14 14"><path d="M2.5 7a4.5 4.5 0 1 1 1 3"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round></path><path d="M2 4v3.5h3.5"fill=none stroke=currentColor stroke-width=1.5 stroke-linecap=round stroke-linejoin=round></path></svg></button></div><div class=url-shell><form class=url-form><input class=url-input type=text placeholder="Search or enter URL"autocomplete=off aria-autocomplete=list aria-controls=address-autocomplete></form></div><div class=toolbar-actions><button class=nav-btn><svg width=14 height=14 viewBox="0 0 14 14">`), _tmpl$17$4 = /* @__PURE__ */ template(`<svg width=14 height=14 viewBox="0 0 14 14"fill=currentColor><path d="M7 1a4 4 0 00-4 4v2H1.5a.5.5 0 00-.5.5v5a.5.5 0 00.5.5h11a.5.5 0 00.5-.5v-5a.5.5 0 00-.5-.5H11V5a4 4 0 00-4-4zm0 1a3 3 0 013 3v2H4V5a3 3 0 013-3z"></path><circle cx=7 cy=8 r=0.8 fill=white>`), _tmpl$18$4 = /* @__PURE__ */ template(`<div role=option><span class=autocomplete-icon></span><span class=autocomplete-text><span class=autocomplete-title></span><span class=autocomplete-url>`), _tmpl$19$4 = /* @__PURE__ */ template(`<div class=page-diff-burst-row><span class=page-diff-burst-time></span><span class=page-diff-burst-summary>`), _tmpl$20$4 = /* @__PURE__ */ template(`<span class=page-diff-burst-summary-section>`), _tmpl$21$4 = /* @__PURE__ */ template(`<span class=page-diff-burst-summary-part><span>`), _tmpl$22$4 = /* @__PURE__ */ template(`<div class=page-diff-snippet><span class=page-diff-snippet-label>Before</span><span class=page-diff-snippet-text>`), _tmpl$23$4 = /* @__PURE__ */ template(`<div class=page-diff-snippet><span class=page-diff-snippet-label>After</span><span class=page-diff-snippet-text>`), _tmpl$24$4 = /* @__PURE__ */ template(`<div class=page-diff-snippets>`), _tmpl$25$3 = /* @__PURE__ */ template(`<div class=page-diff-list-group><span class=page-diff-list-label>Added</span><ul class=page-diff-list>`), _tmpl$26$3 = /* @__PURE__ */ template(`<div class=page-diff-list-group><span class=page-diff-list-label>Removed</span><ul class=page-diff-list>`), _tmpl$27$3 = /* @__PURE__ */ template(`<div><div class=page-diff-item-header><div class=page-diff-badges><span class=page-diff-kind></span><span class=page-diff-section></span></div><span class=page-diff-summary>`), _tmpl$28$3 = /* @__PURE__ */ template(`<li>`);
3334
3342
  const AddressBar = (props) => {
3335
3343
  const {
3336
3344
  activeTab,
@@ -3764,7 +3772,7 @@ const AddressBar = (props) => {
3764
3772
  return pageDiff();
3765
3773
  },
3766
3774
  get children() {
3767
- var _el$15 = _tmpl$6$e();
3775
+ var _el$15 = _tmpl$6$f();
3768
3776
  _el$15.$$click = () => void openDiffTimeline();
3769
3777
  return _el$15;
3770
3778
  }
@@ -3774,7 +3782,7 @@ const AddressBar = (props) => {
3774
3782
  return memo(() => !!pageDiff())() && diffExpanded();
3775
3783
  },
3776
3784
  get children() {
3777
- var _el$16 = _tmpl$9$8(), _el$17 = _el$16.firstChild, _el$18 = _el$17.firstChild, _el$19 = _el$18.firstChild, _el$20 = _el$19.nextSibling;
3785
+ var _el$16 = _tmpl$9$9(), _el$17 = _el$16.firstChild, _el$18 = _el$17.firstChild, _el$19 = _el$18.firstChild, _el$20 = _el$19.nextSibling;
3778
3786
  _el$20.firstChild;
3779
3787
  var _el$27 = _el$18.nextSibling, _el$28 = _el$27.firstChild, _el$29 = _el$28.nextSibling;
3780
3788
  insert(_el$20, () => formatRelativeTime(pageDiff().oldSnapshot.capturedAt), null);
@@ -3783,7 +3791,7 @@ const AddressBar = (props) => {
3783
3791
  return memo(() => !!((pageDiff().burstCount || 0) > 1 && pageDiff().firstDetectedAt))() && pageDiff().lastDetectedAt;
3784
3792
  },
3785
3793
  get children() {
3786
- var _el$22 = _tmpl$7$c(), _el$23 = _el$22.firstChild, _el$26 = _el$23.nextSibling;
3794
+ var _el$22 = _tmpl$7$d(), _el$23 = _el$22.firstChild, _el$26 = _el$23.nextSibling;
3787
3795
  _el$26.nextSibling;
3788
3796
  insert(_el$22, () => pageDiff().burstCount, _el$26);
3789
3797
  insert(_el$22, () => formatElapsedTime(pageDiff().firstDetectedAt, pageDiff().lastDetectedAt), null);
@@ -3797,7 +3805,7 @@ const AddressBar = (props) => {
3797
3805
  return memo(() => !!pageDiff().recentBursts?.length)() && (pageDiff().recentBursts?.length || 0) > 1;
3798
3806
  },
3799
3807
  get children() {
3800
- var _el$30 = _tmpl$8$9();
3808
+ var _el$30 = _tmpl$8$a();
3801
3809
  _el$30.firstChild;
3802
3810
  insert(_el$30, createComponent(For, {
3803
3811
  get each() {
@@ -3929,7 +3937,7 @@ const AddressBar = (props) => {
3929
3937
  return activeTab()?.adBlockingEnabled;
3930
3938
  },
3931
3939
  get children() {
3932
- return _tmpl$0$6();
3940
+ return _tmpl$0$7();
3933
3941
  }
3934
3942
  }), null);
3935
3943
  insert(_el$34, createComponent(Show, {
@@ -3937,13 +3945,13 @@ const AddressBar = (props) => {
3937
3945
  return !activeTab()?.adBlockingEnabled;
3938
3946
  },
3939
3947
  get children() {
3940
- return [_tmpl$0$6(), _tmpl$1$6()];
3948
+ return [_tmpl$0$7(), _tmpl$1$7()];
3941
3949
  }
3942
3950
  }), null);
3943
3951
  insert(_el$32, createComponent(Show, {
3944
3952
  when: !isPrivateWindow,
3945
3953
  get children() {
3946
- var _el$38 = _tmpl$10$6();
3954
+ var _el$38 = _tmpl$10$7();
3947
3955
  _el$38.$$click = () => window.vessel.content.toggleReader();
3948
3956
  createRenderEffect(() => _el$38.classList.toggle("active", !!activeTab()?.isReaderMode));
3949
3957
  return _el$38;
@@ -4159,7 +4167,7 @@ const HighlightNotifications = (props) => {
4159
4167
  });
4160
4168
  };
4161
4169
  delegateEvents(["click"]);
4162
- var _tmpl$$m = /* @__PURE__ */ template(`<div class=download-toast-stack aria-live=polite>`), _tmpl$2$m = /* @__PURE__ */ template(`<span class=download-toast-done>&#10003;`), _tmpl$3$j = /* @__PURE__ */ template(`<span class=download-toast-failed>!`), _tmpl$4$i = /* @__PURE__ */ template(`<div class=download-toast-bar-track><div class=download-toast-bar-fill>`), _tmpl$5$e = /* @__PURE__ */ template(`<div class=download-toast-size>`), _tmpl$6$d = /* @__PURE__ */ template(`<div class="download-toast-size download-toast-size-done"> downloaded`), _tmpl$7$b = /* @__PURE__ */ template(`<div class=download-toast role=status><div class=download-toast-header><span class=download-toast-filename>`);
4170
+ var _tmpl$$m = /* @__PURE__ */ template(`<div class=download-toast-stack aria-live=polite>`), _tmpl$2$m = /* @__PURE__ */ template(`<span class=download-toast-done>&#10003;`), _tmpl$3$j = /* @__PURE__ */ template(`<span class=download-toast-failed>!`), _tmpl$4$i = /* @__PURE__ */ template(`<div class=download-toast-bar-track><div class=download-toast-bar-fill>`), _tmpl$5$e = /* @__PURE__ */ template(`<div class=download-toast-size>`), _tmpl$6$e = /* @__PURE__ */ template(`<div class="download-toast-size download-toast-size-done"> downloaded`), _tmpl$7$c = /* @__PURE__ */ template(`<div class=download-toast role=status><div class=download-toast-header><span class=download-toast-filename>`);
4163
4171
  const TOAST_DONE_DURATION_MS = 4200;
4164
4172
  const TOAST_EXIT_MS = 300;
4165
4173
  function formatBytes$1(bytes) {
@@ -4256,7 +4264,7 @@ const DownloadToast = () => {
4256
4264
  return downloads();
4257
4265
  },
4258
4266
  children: (dl) => (() => {
4259
- var _el$2 = _tmpl$7$b(), _el$3 = _el$2.firstChild, _el$4 = _el$3.firstChild;
4267
+ var _el$2 = _tmpl$7$c(), _el$3 = _el$2.firstChild, _el$4 = _el$3.firstChild;
4260
4268
  insert(_el$4, () => dl.filename);
4261
4269
  insert(_el$3, createComponent(Show, {
4262
4270
  get when() {
@@ -4303,7 +4311,7 @@ const DownloadToast = () => {
4303
4311
  return dl.state === "completed";
4304
4312
  },
4305
4313
  get children() {
4306
- var _el$0 = _tmpl$6$d(), _el$1 = _el$0.firstChild;
4314
+ var _el$0 = _tmpl$6$e(), _el$1 = _el$0.firstChild;
4307
4315
  insert(_el$0, () => formatBytes$1(dl.receivedBytes), _el$1);
4308
4316
  return _el$0;
4309
4317
  }
@@ -4492,13 +4500,26 @@ const FindBar = () => {
4492
4500
  });
4493
4501
  };
4494
4502
  delegateEvents(["input", "click"]);
4495
- var _tmpl$$j = /* @__PURE__ */ template(`<div class=flow-progress>`), _tmpl$2$j = /* @__PURE__ */ template(`<div class=flow-progress-hint>Last: `), _tmpl$3$h = /* @__PURE__ */ template(`<div class=flow-progress-hint>Next: `), _tmpl$4$g = /* @__PURE__ */ template(`<div class=flow-progress-section><div class=flow-progress-header><span class=flow-progress-goal></span><span class=flow-progress-pct>%</span></div><div class=flow-progress-bar-track><div class=flow-progress-bar-fill></div></div><div class=flow-steps>`), _tmpl$5$d = /* @__PURE__ */ template(`<div><span class=flow-step-dot></span><span class=flow-step-label>`);
4503
+ var _tmpl$$j = /* @__PURE__ */ template(`<div class=flow-progress>`), _tmpl$2$j = /* @__PURE__ */ template(`<div class=task-memory-blocker>Blocked: `), _tmpl$3$h = /* @__PURE__ */ template(`<div class=task-memory-next-step>Next: `), _tmpl$4$g = /* @__PURE__ */ template(`<div class=task-memory-facts>`), _tmpl$5$d = /* @__PURE__ */ template(`<div class=task-memory-notes>`), _tmpl$6$d = /* @__PURE__ */ template(`<div class=flow-progress-section><div class=flow-progress-header><span class=flow-progress-goal> </span><span>`), _tmpl$7$b = /* @__PURE__ */ template(`<div class=task-memory-fact><span class=task-memory-fact-key></span><span class=task-memory-fact-value>`), _tmpl$8$9 = /* @__PURE__ */ template(`<div class=task-memory-note><span class=task-memory-note-time></span><span class=task-memory-note-text>`), _tmpl$9$8 = /* @__PURE__ */ template(`<div class=flow-progress-hint>Last: `), _tmpl$0$6 = /* @__PURE__ */ template(`<div class=flow-progress-hint>Next: `), _tmpl$1$6 = /* @__PURE__ */ template(`<div class=flow-progress-section><div class=flow-progress-header><span class=flow-progress-goal></span><span class=flow-progress-pct>%</span></div><div class=flow-progress-bar-track><div class=flow-progress-bar-fill></div></div><div class=flow-steps>`), _tmpl$10$6 = /* @__PURE__ */ template(`<div><span class=flow-step-dot></span><span class=flow-step-label>`);
4504
+ const statusLabel = {
4505
+ active: "Active",
4506
+ completed: "Completed",
4507
+ abandoned: "Abandoned",
4508
+ blocked: "Blocked"
4509
+ };
4510
+ const statusIcon = {
4511
+ active: "▶",
4512
+ completed: "✓",
4513
+ abandoned: "✗",
4514
+ blocked: "⏸"
4515
+ };
4496
4516
  const FlowProgress = () => {
4497
4517
  const {
4498
4518
  runtimeState: runtimeState2
4499
4519
  } = useRuntime();
4500
4520
  const flow = createMemo(() => runtimeState2().flowState);
4501
4521
  const tracker = createMemo(() => runtimeState2().taskTracker);
4522
+ const taskMemory = createMemo(() => runtimeState2().taskMemory);
4502
4523
  const stepStatusClass = (status) => {
4503
4524
  switch (status) {
4504
4525
  case "done":
@@ -4520,53 +4541,136 @@ const FlowProgress = () => {
4520
4541
  };
4521
4542
  return createComponent(Show, {
4522
4543
  get when() {
4523
- return flow() || tracker();
4544
+ return flow() || tracker() || taskMemory();
4524
4545
  },
4525
4546
  get children() {
4526
4547
  var _el$ = _tmpl$$j();
4548
+ insert(_el$, createComponent(Show, {
4549
+ get when() {
4550
+ return taskMemory();
4551
+ },
4552
+ children: (tm) => (() => {
4553
+ var _el$2 = _tmpl$6$d(), _el$3 = _el$2.firstChild, _el$4 = _el$3.firstChild, _el$5 = _el$4.firstChild, _el$6 = _el$4.nextSibling;
4554
+ insert(_el$4, () => statusIcon[tm().status], _el$5);
4555
+ insert(_el$4, () => tm().goal, null);
4556
+ insert(_el$6, () => statusLabel[tm().status]);
4557
+ insert(_el$2, createComponent(Show, {
4558
+ get when() {
4559
+ return tm().blocker;
4560
+ },
4561
+ get children() {
4562
+ var _el$7 = _tmpl$2$j();
4563
+ _el$7.firstChild;
4564
+ insert(_el$7, () => tm().blocker, null);
4565
+ return _el$7;
4566
+ }
4567
+ }), null);
4568
+ insert(_el$2, createComponent(Show, {
4569
+ get when() {
4570
+ return tm().nextStep;
4571
+ },
4572
+ get children() {
4573
+ var _el$9 = _tmpl$3$h();
4574
+ _el$9.firstChild;
4575
+ insert(_el$9, () => tm().nextStep, null);
4576
+ return _el$9;
4577
+ }
4578
+ }), null);
4579
+ insert(_el$2, createComponent(Show, {
4580
+ get when() {
4581
+ return Object.keys(tm().facts).length > 0;
4582
+ },
4583
+ get children() {
4584
+ var _el$1 = _tmpl$4$g();
4585
+ insert(_el$1, createComponent(For, {
4586
+ get each() {
4587
+ return Object.entries(tm().facts);
4588
+ },
4589
+ children: ([key, value]) => (() => {
4590
+ var _el$11 = _tmpl$7$b(), _el$12 = _el$11.firstChild, _el$13 = _el$12.nextSibling;
4591
+ insert(_el$12, key);
4592
+ insert(_el$13, value);
4593
+ return _el$11;
4594
+ })()
4595
+ }));
4596
+ return _el$1;
4597
+ }
4598
+ }), null);
4599
+ insert(_el$2, createComponent(Show, {
4600
+ get when() {
4601
+ return tm().notes.length > 0;
4602
+ },
4603
+ get children() {
4604
+ var _el$10 = _tmpl$5$d();
4605
+ insert(_el$10, createComponent(For, {
4606
+ get each() {
4607
+ return tm().notes.slice(-3);
4608
+ },
4609
+ children: (note) => (() => {
4610
+ var _el$14 = _tmpl$8$9(), _el$15 = _el$14.firstChild, _el$16 = _el$15.nextSibling;
4611
+ insert(_el$15, () => note.createdAt.slice(11, 16));
4612
+ insert(_el$16, () => note.text);
4613
+ return _el$14;
4614
+ })()
4615
+ }));
4616
+ return _el$10;
4617
+ }
4618
+ }), null);
4619
+ createRenderEffect((_p$) => {
4620
+ var _v$ = tracker() || flow() ? "12px" : "0", _v$2 = `task-memory-status task-memory-status-${tm().status}`;
4621
+ _v$ !== _p$.e && setStyleProperty(_el$2, "margin-bottom", _p$.e = _v$);
4622
+ _v$2 !== _p$.t && className(_el$6, _p$.t = _v$2);
4623
+ return _p$;
4624
+ }, {
4625
+ e: void 0,
4626
+ t: void 0
4627
+ });
4628
+ return _el$2;
4629
+ })()
4630
+ }), null);
4527
4631
  insert(_el$, createComponent(Show, {
4528
4632
  get when() {
4529
4633
  return tracker();
4530
4634
  },
4531
4635
  children: (t) => (() => {
4532
- var _el$2 = _tmpl$4$g(), _el$3 = _el$2.firstChild, _el$4 = _el$3.firstChild, _el$5 = _el$4.nextSibling, _el$6 = _el$5.firstChild, _el$7 = _el$3.nextSibling, _el$8 = _el$7.firstChild, _el$9 = _el$7.nextSibling;
4533
- insert(_el$4, () => t().goal);
4534
- insert(_el$5, () => progressPercent(t().steps), _el$6);
4535
- insert(_el$9, createComponent(For, {
4636
+ var _el$17 = _tmpl$1$6(), _el$18 = _el$17.firstChild, _el$19 = _el$18.firstChild, _el$20 = _el$19.nextSibling, _el$21 = _el$20.firstChild, _el$22 = _el$18.nextSibling, _el$23 = _el$22.firstChild, _el$24 = _el$22.nextSibling;
4637
+ insert(_el$19, () => t().goal);
4638
+ insert(_el$20, () => progressPercent(t().steps), _el$21);
4639
+ insert(_el$24, createComponent(For, {
4536
4640
  get each() {
4537
4641
  return t().steps;
4538
4642
  },
4539
4643
  children: (step) => (() => {
4540
- var _el$12 = _tmpl$5$d(), _el$13 = _el$12.firstChild, _el$14 = _el$13.nextSibling;
4541
- insert(_el$14, () => step.label);
4542
- createRenderEffect(() => className(_el$12, `flow-step ${stepStatusClass(step.status)}`));
4543
- return _el$12;
4644
+ var _el$29 = _tmpl$10$6(), _el$30 = _el$29.firstChild, _el$31 = _el$30.nextSibling;
4645
+ insert(_el$31, () => step.label);
4646
+ createRenderEffect(() => className(_el$29, `flow-step ${stepStatusClass(step.status)}`));
4647
+ return _el$29;
4544
4648
  })()
4545
4649
  }));
4546
- insert(_el$2, createComponent(Show, {
4650
+ insert(_el$17, createComponent(Show, {
4547
4651
  get when() {
4548
4652
  return t().lastAction;
4549
4653
  },
4550
4654
  get children() {
4551
- var _el$0 = _tmpl$2$j();
4552
- _el$0.firstChild;
4553
- insert(_el$0, () => t().lastAction, null);
4554
- return _el$0;
4655
+ var _el$25 = _tmpl$9$8();
4656
+ _el$25.firstChild;
4657
+ insert(_el$25, () => t().lastAction, null);
4658
+ return _el$25;
4555
4659
  }
4556
4660
  }), null);
4557
- insert(_el$2, createComponent(Show, {
4661
+ insert(_el$17, createComponent(Show, {
4558
4662
  get when() {
4559
4663
  return memo(() => !!t().nextHint)() && !t().steps.every((s) => s.status === "done");
4560
4664
  },
4561
4665
  get children() {
4562
- var _el$10 = _tmpl$3$h();
4563
- _el$10.firstChild;
4564
- insert(_el$10, () => t().nextHint, null);
4565
- return _el$10;
4666
+ var _el$27 = _tmpl$0$6();
4667
+ _el$27.firstChild;
4668
+ insert(_el$27, () => t().nextHint, null);
4669
+ return _el$27;
4566
4670
  }
4567
4671
  }), null);
4568
- createRenderEffect((_$p) => setStyleProperty(_el$8, "width", `${progressPercent(t().steps)}%`));
4569
- return _el$2;
4672
+ createRenderEffect((_$p) => setStyleProperty(_el$23, "width", `${progressPercent(t().steps)}%`));
4673
+ return _el$17;
4570
4674
  })()
4571
4675
  }), null);
4572
4676
  insert(_el$, createComponent(Show, {
@@ -4574,22 +4678,22 @@ const FlowProgress = () => {
4574
4678
  return memo(() => !!flow())() && !tracker();
4575
4679
  },
4576
4680
  children: (f) => (() => {
4577
- var _el$15 = _tmpl$4$g(), _el$16 = _el$15.firstChild, _el$17 = _el$16.firstChild, _el$18 = _el$17.nextSibling, _el$19 = _el$18.firstChild, _el$20 = _el$16.nextSibling, _el$21 = _el$20.firstChild, _el$22 = _el$20.nextSibling;
4578
- insert(_el$17, () => f().goal);
4579
- insert(_el$18, () => progressPercent(f().steps), _el$19);
4580
- insert(_el$22, createComponent(For, {
4681
+ var _el$32 = _tmpl$1$6(), _el$33 = _el$32.firstChild, _el$34 = _el$33.firstChild, _el$35 = _el$34.nextSibling, _el$36 = _el$35.firstChild, _el$37 = _el$33.nextSibling, _el$38 = _el$37.firstChild, _el$39 = _el$37.nextSibling;
4682
+ insert(_el$34, () => f().goal);
4683
+ insert(_el$35, () => progressPercent(f().steps), _el$36);
4684
+ insert(_el$39, createComponent(For, {
4581
4685
  get each() {
4582
4686
  return f().steps;
4583
4687
  },
4584
4688
  children: (step) => (() => {
4585
- var _el$23 = _tmpl$5$d(), _el$24 = _el$23.firstChild, _el$25 = _el$24.nextSibling;
4586
- insert(_el$25, () => step.label);
4587
- createRenderEffect(() => className(_el$23, `flow-step ${stepStatusClass(step.status)}`));
4588
- return _el$23;
4689
+ var _el$40 = _tmpl$10$6(), _el$41 = _el$40.firstChild, _el$42 = _el$41.nextSibling;
4690
+ insert(_el$42, () => step.label);
4691
+ createRenderEffect(() => className(_el$40, `flow-step ${stepStatusClass(step.status)}`));
4692
+ return _el$40;
4589
4693
  })()
4590
4694
  }));
4591
- createRenderEffect((_$p) => setStyleProperty(_el$21, "width", `${progressPercent(f().steps)}%`));
4592
- return _el$15;
4695
+ createRenderEffect((_$p) => setStyleProperty(_el$38, "width", `${progressPercent(f().steps)}%`));
4696
+ return _el$32;
4593
4697
  })()
4594
4698
  }), null);
4595
4699
  return _el$;
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; base-uri 'none'; object-src 'none'; frame-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; font-src 'self' data:; form-action 'self';" />
7
7
  <title>Vessel</title>
8
- <script type="module" crossorigin src="./assets/index-BW4Oa1R1.js"></script>
9
- <link rel="stylesheet" crossorigin href="./assets/index-B4pY2BdC.css">
8
+ <script type="module" crossorigin src="./assets/index-DPKkNFWo.js"></script>
9
+ <link rel="stylesheet" crossorigin href="./assets/index-BJctp4s0.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quanta-intellect/vessel-browser",
3
3
  "mcpName": "io.github.unmodeled-tyler/vessel-browser",
4
- "version": "0.1.144",
4
+ "version": "0.1.145",
5
5
  "description": "AI-native web browser runtime for autonomous agents with human supervision",
6
6
  "main": "./out/main/index.js",
7
7
  "bin": {