@akshayram1/omnibrowser-agent 0.2.32 → 0.3.0

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/.env ADDED
@@ -0,0 +1 @@
1
+ HF_TOKEN=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
package/README.github.md CHANGED
@@ -165,6 +165,43 @@ See [docs/EMBEDDING.md](docs/EMBEDDING.md) for the full WebLLM bridge wiring gui
165
165
 
166
166
  Model availability can vary by WebLLM release/build; if one fails to load, use a smaller fallback like `Llama-3.2-1B-Instruct-q4f16_1-MLC`.
167
167
 
168
+ ### Bring Your Own Model (Colab + MLC)
169
+
170
+ Use the notebook workflow to fine-tune and quantize a planner model for OmniBrowser:
171
+
172
+ - [Notebook assets](notebook/README.md)
173
+ - [Google Colab notebook](notebook/custom_quantized_llm_colab.ipynb)
174
+ - [Starter dataset JSONL](notebook/data/omnibrowser_planner_train.jsonl)
175
+
176
+ The workflow:
177
+
178
+ 1. Generate/expand a dataset in OmniBrowser prompt format (`notebook/scripts/generate_dataset.mjs`).
179
+ 2. Validate selector + action correctness (`notebook/scripts/validate_dataset.mjs`).
180
+ 3. QLoRA fine-tune `Qwen/Qwen2.5-1.5B-Instruct` in Colab.
181
+ 4. Merge and quantize with `mlc_llm convert_weight --quantization q4f16_1`.
182
+ 5. Upload to Hugging Face and load in WebLLM via custom `appConfig`.
183
+
184
+ ```ts
185
+ import * as webllm from "@mlc-ai/web-llm";
186
+ import { createWebLLMBridge } from "@akshayram1/omnibrowser-agent";
187
+
188
+ const appConfig: webllm.AppConfig = {
189
+ model_list: [
190
+ {
191
+ model: "https://huggingface.co/your-account/omnibrowser-planner-q4f16_1-MLC",
192
+ model_id: "omnibrowser-planner-q4f16_1",
193
+ model_lib:
194
+ webllm.modelLibURLPrefix +
195
+ webllm.modelVersion +
196
+ "/Qwen2.5-1.5B-Instruct-q4f16_1-ctx4k_cs1k-webgpu.wasm",
197
+ },
198
+ ],
199
+ };
200
+
201
+ const engine = await webllm.CreateMLCEngine("omnibrowser-planner-q4f16_1", { appConfig });
202
+ window.__browserAgentWebLLM = createWebLLMBridge(engine);
203
+ ```
204
+
168
205
  ---
169
206
 
170
207
  ## Agent modes
package/demo1.gif ADDED
Binary file
@@ -52,7 +52,7 @@ async function tick(tabId) {
52
52
  session.isRunning = false;
53
53
  return;
54
54
  }
55
- setTimeout(() => tick(tabId), 600);
55
+ setTimeout(() => tick(tabId), 500);
56
56
  }
57
57
  chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
58
58
  if (message.type === "START_AGENT") {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/background/index.ts"],
4
- "sourcesContent": ["import type { AgentMode, AgentSession, PlannerConfig } from \"../shared/contracts\";\n\nconst sessions = new Map<number, AgentSession>();\n\nfunction normalizePlannerConfig(rawPlanner: unknown): PlannerConfig {\n if (typeof rawPlanner === \"string\" && (rawPlanner === \"heuristic\" || rawPlanner === \"webllm\")) {\n return { kind: rawPlanner };\n }\n\n if (typeof rawPlanner === \"object\" && rawPlanner !== null) {\n const record = rawPlanner as Record<string, unknown>;\n const kind = record.kind;\n if (kind === \"heuristic\" || kind === \"webllm\") {\n return {\n kind,\n modelId: typeof record.modelId === \"string\" && record.modelId.trim() ? record.modelId : undefined,\n systemPrompt: typeof record.systemPrompt === \"string\" && record.systemPrompt.trim() ? record.systemPrompt : undefined\n };\n }\n }\n\n return { kind: \"heuristic\" };\n}\n\nfunction makeSession(tabId: number, goal: string, mode: AgentMode, planner: PlannerConfig): AgentSession {\n return {\n id: crypto.randomUUID(),\n tabId: tabId,\n goal,\n mode,\n planner,\n history: [],\n isRunning: true\n };\n}\n\nasync function tick(tabId: number) {\n const session = sessions.get(tabId);\n if (!session || !session.isRunning) {\n return;\n }\n\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"AGENT_TICK\",\n session\n });\n\n session.history.push(result.message);\n if (result.reflection?.memory !== undefined) {\n session.memory = result.reflection.memory;\n }\n session.lastError = result.status === \"error\" ? result.message : undefined;\n\n if (result.status === \"needs_approval\") {\n session.pendingAction = result.action;\n session.isRunning = false;\n return;\n }\n\n session.pendingAction = undefined;\n\n if ([\"done\", \"blocked\", \"error\"].includes(result.status)) {\n session.isRunning = false;\n return;\n }\n\n setTimeout(() => tick(tabId), 600);\n}\n\nchrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {\n if (message.type === \"START_AGENT\") {\n const session = makeSession(message.tabId, message.goal, message.mode, normalizePlannerConfig(message.planner));\n sessions.set(message.tabId, session);\n tick(message.tabId).catch((error) => {\n const failed = sessions.get(message.tabId);\n if (failed) {\n failed.history.push(`Error: ${String(error)}`);\n failed.isRunning = false;\n }\n });\n sendResponse({ ok: true });\n return true;\n }\n\n if (message.type === \"APPROVE_ACTION\") {\n const session = sessions.get(message.tabId);\n if (!session) {\n sendResponse({ ok: false, error: \"No active session\" });\n return true;\n }\n\n session.isRunning = true;\n tick(message.tabId).catch((error) => {\n session.history.push(`Error: ${String(error)}`);\n session.isRunning = false;\n });\n sendResponse({ ok: true });\n return true;\n }\n\n if (message.type === \"STOP_AGENT\") {\n const session = sessions.get(message.tabId);\n if (session) {\n session.isRunning = false;\n }\n chrome.tabs.sendMessage(message.tabId, { type: \"AGENT_STOP\" }).catch(() => undefined);\n sendResponse({ ok: true });\n return true;\n }\n\n if (message.type === \"GET_STATUS\") {\n const lines = Array.from(sessions.values()).map(\n (session) =>\n `${session.isRunning ? \"RUNNING\" : \"IDLE\"} ${session.tabId}: ${session.goal.slice(0, 45)}${session.goal.length > 45 ? \"...\" : \"\"}`\n );\n\n sendResponse({ status: lines.length > 0 ? lines.join(\"\\n\") : \"Idle\" });\n return true;\n }\n\n return false;\n});\n"],
4
+ "sourcesContent": ["import type { AgentMode, AgentSession, PlannerConfig } from \"../shared/contracts\";\n\nconst sessions = new Map<number, AgentSession>();\n\nfunction normalizePlannerConfig(rawPlanner: unknown): PlannerConfig {\n if (typeof rawPlanner === \"string\" && (rawPlanner === \"heuristic\" || rawPlanner === \"webllm\")) {\n return { kind: rawPlanner };\n }\n\n if (typeof rawPlanner === \"object\" && rawPlanner !== null) {\n const record = rawPlanner as Record<string, unknown>;\n const kind = record.kind;\n if (kind === \"heuristic\" || kind === \"webllm\") {\n return {\n kind,\n modelId: typeof record.modelId === \"string\" && record.modelId.trim() ? record.modelId : undefined,\n systemPrompt: typeof record.systemPrompt === \"string\" && record.systemPrompt.trim() ? record.systemPrompt : undefined\n };\n }\n }\n\n return { kind: \"heuristic\" };\n}\n\nfunction makeSession(tabId: number, goal: string, mode: AgentMode, planner: PlannerConfig): AgentSession {\n return {\n id: crypto.randomUUID(),\n tabId: tabId,\n goal,\n mode,\n planner,\n history: [],\n isRunning: true\n };\n}\n\nasync function tick(tabId: number) {\n const session = sessions.get(tabId);\n if (!session || !session.isRunning) {\n return;\n }\n\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"AGENT_TICK\",\n session\n });\n\n session.history.push(result.message);\n if (result.reflection?.memory !== undefined) {\n session.memory = result.reflection.memory;\n }\n session.lastError = result.status === \"error\" ? result.message : undefined;\n\n if (result.status === \"needs_approval\") {\n session.pendingAction = result.action;\n session.isRunning = false;\n return;\n }\n\n session.pendingAction = undefined;\n\n if ([\"done\", \"blocked\", \"error\"].includes(result.status)) {\n session.isRunning = false;\n return;\n }\n\n setTimeout(() => tick(tabId), 500);\n}\n\nchrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {\n if (message.type === \"START_AGENT\") {\n const session = makeSession(message.tabId, message.goal, message.mode, normalizePlannerConfig(message.planner));\n sessions.set(message.tabId, session);\n tick(message.tabId).catch((error) => {\n const failed = sessions.get(message.tabId);\n if (failed) {\n failed.history.push(`Error: ${String(error)}`);\n failed.isRunning = false;\n }\n });\n sendResponse({ ok: true });\n return true;\n }\n\n if (message.type === \"APPROVE_ACTION\") {\n const session = sessions.get(message.tabId);\n if (!session) {\n sendResponse({ ok: false, error: \"No active session\" });\n return true;\n }\n\n session.isRunning = true;\n tick(message.tabId).catch((error) => {\n session.history.push(`Error: ${String(error)}`);\n session.isRunning = false;\n });\n sendResponse({ ok: true });\n return true;\n }\n\n if (message.type === \"STOP_AGENT\") {\n const session = sessions.get(message.tabId);\n if (session) {\n session.isRunning = false;\n }\n chrome.tabs.sendMessage(message.tabId, { type: \"AGENT_STOP\" }).catch(() => undefined);\n sendResponse({ ok: true });\n return true;\n }\n\n if (message.type === \"GET_STATUS\") {\n const lines = Array.from(sessions.values()).map(\n (session) =>\n `${session.isRunning ? \"RUNNING\" : \"IDLE\"} ${session.tabId}: ${session.goal.slice(0, 45)}${session.goal.length > 45 ? \"...\" : \"\"}`\n );\n\n sendResponse({ status: lines.length > 0 ? lines.join(\"\\n\") : \"Idle\" });\n return true;\n }\n\n return false;\n});\n"],
5
5
  "mappings": ";AAEA,IAAM,WAAW,oBAAI,IAA0B;AAE/C,SAAS,uBAAuB,YAAoC;AAClE,MAAI,OAAO,eAAe,aAAa,eAAe,eAAe,eAAe,WAAW;AAC7F,WAAO,EAAE,MAAM,WAAW;AAAA,EAC5B;AAEA,MAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,UAAM,SAAS;AACf,UAAM,OAAO,OAAO;AACpB,QAAI,SAAS,eAAe,SAAS,UAAU;AAC7C,aAAO;AAAA,QACL;AAAA,QACA,SAAS,OAAO,OAAO,YAAY,YAAY,OAAO,QAAQ,KAAK,IAAI,OAAO,UAAU;AAAA,QACxF,cAAc,OAAO,OAAO,iBAAiB,YAAY,OAAO,aAAa,KAAK,IAAI,OAAO,eAAe;AAAA,MAC9G;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,YAAY;AAC7B;AAEA,SAAS,YAAY,OAAe,MAAc,MAAiB,SAAsC;AACvG,SAAO;AAAA,IACL,IAAI,OAAO,WAAW;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,CAAC;AAAA,IACV,WAAW;AAAA,EACb;AACF;AAEA,eAAe,KAAK,OAAe;AACjC,QAAM,UAAU,SAAS,IAAI,KAAK;AAClC,MAAI,CAAC,WAAW,CAAC,QAAQ,WAAW;AAClC;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,IAClD,MAAM;AAAA,IACN;AAAA,EACF,CAAC;AAED,UAAQ,QAAQ,KAAK,OAAO,OAAO;AACnC,MAAI,OAAO,YAAY,WAAW,QAAW;AAC3C,YAAQ,SAAS,OAAO,WAAW;AAAA,EACrC;AACA,UAAQ,YAAY,OAAO,WAAW,UAAU,OAAO,UAAU;AAEjE,MAAI,OAAO,WAAW,kBAAkB;AACtC,YAAQ,gBAAgB,OAAO;AAC/B,YAAQ,YAAY;AACpB;AAAA,EACF;AAEA,UAAQ,gBAAgB;AAExB,MAAI,CAAC,QAAQ,WAAW,OAAO,EAAE,SAAS,OAAO,MAAM,GAAG;AACxD,YAAQ,YAAY;AACpB;AAAA,EACF;AAEA,aAAW,MAAM,KAAK,KAAK,GAAG,GAAG;AACnC;AAEA,OAAO,QAAQ,UAAU,YAAY,CAAC,SAAS,SAAS,iBAAiB;AACvE,MAAI,QAAQ,SAAS,eAAe;AAClC,UAAM,UAAU,YAAY,QAAQ,OAAO,QAAQ,MAAM,QAAQ,MAAM,uBAAuB,QAAQ,OAAO,CAAC;AAC9G,aAAS,IAAI,QAAQ,OAAO,OAAO;AACnC,SAAK,QAAQ,KAAK,EAAE,MAAM,CAAC,UAAU;AACnC,YAAM,SAAS,SAAS,IAAI,QAAQ,KAAK;AACzC,UAAI,QAAQ;AACV,eAAO,QAAQ,KAAK,UAAU,OAAO,KAAK,CAAC,EAAE;AAC7C,eAAO,YAAY;AAAA,MACrB;AAAA,IACF,CAAC;AACD,iBAAa,EAAE,IAAI,KAAK,CAAC;AACzB,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,SAAS,kBAAkB;AACrC,UAAM,UAAU,SAAS,IAAI,QAAQ,KAAK;AAC1C,QAAI,CAAC,SAAS;AACZ,mBAAa,EAAE,IAAI,OAAO,OAAO,oBAAoB,CAAC;AACtD,aAAO;AAAA,IACT;AAEA,YAAQ,YAAY;AACpB,SAAK,QAAQ,KAAK,EAAE,MAAM,CAAC,UAAU;AACnC,cAAQ,QAAQ,KAAK,UAAU,OAAO,KAAK,CAAC,EAAE;AAC9C,cAAQ,YAAY;AAAA,IACtB,CAAC;AACD,iBAAa,EAAE,IAAI,KAAK,CAAC;AACzB,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,SAAS,cAAc;AACjC,UAAM,UAAU,SAAS,IAAI,QAAQ,KAAK;AAC1C,QAAI,SAAS;AACX,cAAQ,YAAY;AAAA,IACtB;AACA,WAAO,KAAK,YAAY,QAAQ,OAAO,EAAE,MAAM,aAAa,CAAC,EAAE,MAAM,MAAM,MAAS;AACpF,iBAAa,EAAE,IAAI,KAAK,CAAC;AACzB,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,SAAS,cAAc;AACjC,UAAM,QAAQ,MAAM,KAAK,SAAS,OAAO,CAAC,EAAE;AAAA,MAC1C,CAAC,YACC,GAAG,QAAQ,YAAY,YAAY,MAAM,IAAI,QAAQ,KAAK,KAAK,QAAQ,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,QAAQ,KAAK,SAAS,KAAK,QAAQ,EAAE;AAAA,IACpI;AAEA,iBAAa,EAAE,QAAQ,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,CAAC;AACrE,WAAO;AAAA,EACT;AAEA,SAAO;AACT,CAAC;",
6
6
  "names": []
7
7
  }
package/dist/content.js CHANGED
@@ -11,6 +11,7 @@ var __export = (target, all) => {
11
11
  // src/shared/parse-action.ts
12
12
  var parse_action_exports = {};
13
13
  __export(parse_action_exports, {
14
+ PARSE_FAILURE_PATTERN: () => PARSE_FAILURE_PATTERN,
14
15
  parseAction: () => parseAction,
15
16
  parsePlannerResult: () => parsePlannerResult
16
17
  });
@@ -66,6 +67,28 @@ function parseAction(raw) {
66
67
  if (typeof obj.type !== "string" || !VALID_TYPES.has(obj.type)) {
67
68
  return { type: "done", reason: `Unknown or missing action type: ${String(obj.type)}` };
68
69
  }
70
+ const t = obj.type;
71
+ if ((t === "click" || t === "type" || t === "extract" || t === "focus") && typeof obj.selector !== "string") {
72
+ return { type: "done", reason: `Missing required field 'selector' for action type: ${t}` };
73
+ }
74
+ if (t === "extract" && typeof obj.label !== "string") {
75
+ return { type: "done", reason: `Missing required field 'label' for action type: extract` };
76
+ }
77
+ if (t === "type" && typeof obj.text !== "string") {
78
+ return { type: "done", reason: `Missing required field 'text' for action type: type` };
79
+ }
80
+ if (t === "navigate" && typeof obj.url !== "string") {
81
+ return { type: "done", reason: `Missing required field 'url' for action type: navigate` };
82
+ }
83
+ if (t === "scroll" && typeof obj.deltaY !== "number") {
84
+ return { type: "done", reason: `Missing required field 'deltaY' for action type: scroll` };
85
+ }
86
+ if (t === "wait" && typeof obj.ms !== "number") {
87
+ return { type: "done", reason: `Missing required field 'ms' for action type: wait` };
88
+ }
89
+ if (t === "done" && typeof obj.reason !== "string") {
90
+ return { type: "done", reason: `Missing required field 'reason' for action type: done` };
91
+ }
69
92
  return obj;
70
93
  }
71
94
  function parsePlannerResult(raw) {
@@ -96,10 +119,11 @@ function parsePlannerResult(raw) {
96
119
  }
97
120
  return { action: parseAction(jsonStr) };
98
121
  }
99
- var VALID_TYPES;
122
+ var PARSE_FAILURE_PATTERN, VALID_TYPES;
100
123
  var init_parse_action = __esm({
101
124
  "src/shared/parse-action.ts"() {
102
125
  "use strict";
126
+ PARSE_FAILURE_PATTERN = /(No JSON|JSON parse error|Parsed value is not an object|Unknown or missing action type|Missing required field)/;
103
127
  VALID_TYPES = /* @__PURE__ */ new Set([
104
128
  "click",
105
129
  "type",
@@ -118,9 +142,16 @@ var RISKY_KEYWORDS = /\b(delete|remove|pay|purchase|submit|confirm|checkout|tran
118
142
  function elementTextRisky(text) {
119
143
  return text != null && RISKY_KEYWORDS.test(text);
120
144
  }
121
- function assessRisk(action) {
145
+ function candidateText(selector, candidates) {
146
+ const match = candidates?.find((c) => c.selector === selector);
147
+ return match ? [match.label, match.text, match.placeholder].filter(Boolean).join(" ") || void 0 : void 0;
148
+ }
149
+ function assessRisk(action, candidates) {
122
150
  switch (action.type) {
123
151
  case "navigate": {
152
+ if (action.url.startsWith("#") || action.url.startsWith("/") || action.url.startsWith("./") || action.url.startsWith("../")) {
153
+ return "safe";
154
+ }
124
155
  try {
125
156
  const next = new URL(action.url);
126
157
  if (!["http:", "https:"].includes(next.protocol)) {
@@ -131,10 +162,14 @@ function assessRisk(action) {
131
162
  }
132
163
  return "safe";
133
164
  }
134
- case "click":
135
- return elementTextRisky(action.label) ? "review" : "safe";
136
- case "type":
137
- return elementTextRisky(action.label) ? "review" : "safe";
165
+ case "click": {
166
+ const text = action.label ?? candidateText(action.selector, candidates) ?? action.selector;
167
+ return elementTextRisky(text) ? "review" : "safe";
168
+ }
169
+ case "type": {
170
+ const text = action.label ?? candidateText(action.selector, candidates) ?? action.selector;
171
+ return elementTextRisky(text) ? "review" : "safe";
172
+ }
138
173
  case "focus":
139
174
  case "scroll":
140
175
  case "wait":
@@ -185,6 +220,9 @@ async function executeAction(action) {
185
220
  }
186
221
  case "type": {
187
222
  const input = mustFind(action.selector);
223
+ if (input.value === action.text) {
224
+ return `Already contains correct value in ${action.selector}`;
225
+ }
188
226
  input.focus();
189
227
  if (action.clearFirst) {
190
228
  input.value = "";
@@ -288,8 +326,8 @@ function cssPath(element) {
288
326
  return parts.join(" > ");
289
327
  }
290
328
  function isVisible(el) {
291
- if (el.offsetParent === null && el.tagName !== "BODY") return false;
292
329
  const style = window.getComputedStyle(el);
330
+ if (el.offsetParent === null && el.tagName !== "BODY" && style.position !== "fixed") return false;
293
331
  if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
294
332
  const rect = el.getBoundingClientRect();
295
333
  return rect.width > 0 || rect.height > 0;
@@ -298,6 +336,14 @@ function isInViewport(el) {
298
336
  const rect = el.getBoundingClientRect();
299
337
  return rect.bottom > 0 && rect.top < window.innerHeight && rect.right > 0 && rect.left < window.innerWidth;
300
338
  }
339
+ function isActiveElement(el) {
340
+ if (el.classList.contains("active")) return true;
341
+ if (el.getAttribute("aria-selected") === "true") return true;
342
+ const ariaCurrent = el.getAttribute("aria-current");
343
+ if (ariaCurrent && ariaCurrent !== "false") return true;
344
+ if (el.getAttribute("aria-pressed") === "true") return true;
345
+ return false;
346
+ }
301
347
  function getAssociatedLabel(el) {
302
348
  if (el.id) {
303
349
  const label = document.querySelector(`label[for="${CSS.escape(el.id)}"]`);
@@ -319,7 +365,7 @@ function getAssociatedLabel(el) {
319
365
  function collectSnapshot() {
320
366
  const allNodes = Array.from(
321
367
  document.querySelectorAll(CANDIDATE_SELECTOR)
322
- ).filter(isVisible);
368
+ ).filter(isVisible).filter((el) => !el.closest("[data-agent-exclude]"));
323
369
  const inView = allNodes.filter(isInViewport);
324
370
  const offScreen = allNodes.filter((el) => !isInViewport(el));
325
371
  const nodes = [...inView, ...offScreen].slice(0, MAX_CANDIDATES);
@@ -331,7 +377,8 @@ function collectSnapshot() {
331
377
  role: node.getAttribute("role") ?? node.tagName.toLowerCase(),
332
378
  text: (node.innerText || node.getAttribute("name") || "").trim().slice(0, 120),
333
379
  placeholder: placeholder || void 0,
334
- label: associatedLabel || void 0
380
+ label: associatedLabel || void 0,
381
+ active: isActiveElement(node) || void 0
335
382
  };
336
383
  });
337
384
  const textPreview = document.body.innerText.replace(/\s+/g, " ").trim().slice(0, 1500);
@@ -410,14 +457,15 @@ function toPlannerResult(raw) {
410
457
  return { action: raw };
411
458
  }
412
459
  async function parsePlannerText(raw) {
413
- const parser = await Promise.resolve().then(() => (init_parse_action(), parse_action_exports));
414
- return parser.parsePlannerResult(raw);
460
+ const { parsePlannerResult: parsePlannerResult2, PARSE_FAILURE_PATTERN: PARSE_FAILURE_PATTERN2 } = await Promise.resolve().then(() => (init_parse_action(), parse_action_exports));
461
+ const result = parsePlannerResult2(raw);
462
+ const parseFailed = result.action.type === "done" && PARSE_FAILURE_PATTERN2.test(result.action.reason);
463
+ return { result, parseFailed };
415
464
  }
416
465
  async function normalizeBridgeResponse(raw) {
417
466
  if (typeof raw === "string") {
418
- const parsed = await parsePlannerText(raw);
419
- const parseFailed = parsed.action.type === "done" && /(No JSON|JSON parse error|Parsed value is not an object|Unknown or missing action type)/.test(parsed.action.reason);
420
- return { result: parsed, parseFailed, rawText: raw };
467
+ const { result, parseFailed } = await parsePlannerText(raw);
468
+ return { result, parseFailed, rawText: raw };
421
469
  }
422
470
  return { result: toPlannerResult(raw), parseFailed: false };
423
471
  }
@@ -468,7 +516,7 @@ async function runTick(session) {
468
516
  });
469
517
  const { action } = plannerResult;
470
518
  const reflection = plannerResult.evaluation !== void 0 || plannerResult.memory !== void 0 || plannerResult.nextGoal !== void 0 ? { evaluation: plannerResult.evaluation, memory: plannerResult.memory, nextGoal: plannerResult.nextGoal } : void 0;
471
- const risk = assessRisk(action);
519
+ const risk = assessRisk(action, snapshot.candidates);
472
520
  if (risk === "blocked") {
473
521
  return { status: "blocked", action, message: `Blocked action: ${JSON.stringify(action)}`, reflection };
474
522
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/shared/parse-action.ts", "../src/shared/safety.ts", "../src/core/executor.ts", "../src/core/observer.ts", "../src/core/planner.ts", "../src/content/index.ts"],
4
- "sourcesContent": ["import type { AgentAction, PlannerResult } from \"./contracts\";\n\nconst VALID_TYPES = new Set([\n \"click\", \"type\", \"navigate\", \"extract\", \"scroll\", \"focus\", \"wait\", \"done\",\n]);\n\n/**\n * Extract the first complete JSON object from text using bracket counting.\n * More robust than regex: handles prose before/after JSON, and repairs\n * truncated output (e.g. when the model hits a token limit mid-JSON).\n */\nfunction extractFirstJsonObject(text: string): string | null {\n const start = text.indexOf(\"{\");\n if (start === -1) return null;\n\n let depth = 0;\n let inString = false;\n let escaped = false;\n\n for (let i = start; i < text.length; i++) {\n const ch = text[i];\n if (escaped) { escaped = false; continue; }\n if (ch === \"\\\\\" && inString) { escaped = true; continue; }\n if (ch === '\"') { inString = !inString; continue; }\n if (inString) continue;\n if (ch === \"{\") depth++;\n else if (ch === \"}\") {\n depth--;\n if (depth === 0) return text.slice(start, i + 1);\n }\n }\n\n // Truncated JSON (hit token limit mid-output) \u2014 close remaining open braces.\n if (depth > 0) {\n return text.slice(start) + \"}\".repeat(depth);\n }\n\n return null;\n}\n\n/**\n * Parse an AgentAction from raw LLM output.\n *\n * Handles bare JSON, markdown fences, and JSON embedded in prose.\n * Returns a \"done\" action if parsing fails, so the caller always gets a valid AgentAction.\n */\nexport function parseAction(raw: string): AgentAction {\n const fenceMatch = raw.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n const candidate = fenceMatch ? fenceMatch[1].trim() : raw.trim();\n\n const jsonStr = extractFirstJsonObject(candidate);\n if (!jsonStr) {\n return { type: \"done\", reason: `No JSON object found in: ${raw.slice(0, 120)}` };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonStr);\n } catch {\n return { type: \"done\", reason: `JSON parse error for: ${jsonStr.slice(0, 120)}` };\n }\n\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return { type: \"done\", reason: \"Parsed value is not an object\" };\n }\n\n const obj = parsed as Record<string, unknown>;\n if (typeof obj.type !== \"string\" || !VALID_TYPES.has(obj.type)) {\n return { type: \"done\", reason: `Unknown or missing action type: ${String(obj.type)}` };\n }\n\n return obj as unknown as AgentAction;\n}\n\n/**\n * Parse a full PlannerResult from raw LLM output.\n *\n * Accepts the reflection+action format:\n * { \"evaluation\": \"...\", \"memory\": \"...\", \"nextGoal\": \"...\", \"action\": { ... } }\n * Also supports legacy `next_goal` key for backward compatibility.\n *\n * Also accepts a bare AgentAction for backward compatibility with simple bridges.\n */\nexport function parsePlannerResult(raw: string): PlannerResult {\n const fenceMatch = raw.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n const candidate = fenceMatch ? fenceMatch[1].trim() : raw.trim();\n\n const jsonStr = extractFirstJsonObject(candidate);\n if (!jsonStr) {\n return { action: { type: \"done\", reason: `No JSON found in: ${raw.slice(0, 120)}` } };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonStr);\n } catch {\n return { action: { type: \"done\", reason: `JSON parse error: ${jsonStr.slice(0, 120)}` } };\n }\n\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return { action: { type: \"done\", reason: \"Parsed value is not an object\" } };\n }\n\n const obj = parsed as Record<string, unknown>;\n\n // Full reflection format: { evaluation, memory, nextGoal, action }\n if (typeof obj.action === \"object\" && obj.action !== null) {\n const action = parseAction(JSON.stringify(obj.action));\n return {\n action,\n evaluation: typeof obj.evaluation === \"string\" ? obj.evaluation : undefined,\n memory: typeof obj.memory === \"string\" ? obj.memory : undefined,\n nextGoal:\n typeof obj.nextGoal === \"string\"\n ? obj.nextGoal\n : typeof obj.next_goal === \"string\"\n ? obj.next_goal\n : undefined,\n };\n }\n\n // Fallback: bare AgentAction (no reflection fields)\n return { action: parseAction(jsonStr) };\n}\n", "import type { AgentAction, RiskLevel } from \"./contracts\";\n\nconst RISKY_KEYWORDS = /\\b(delete|remove|pay|purchase|submit|confirm|checkout|transfer|withdraw|send)\\b/i;\n\nfunction elementTextRisky(text?: string): boolean {\n return text != null && RISKY_KEYWORDS.test(text);\n}\n\nexport function assessRisk(action: AgentAction): RiskLevel {\n switch (action.type) {\n case \"navigate\": {\n try {\n const next = new URL(action.url);\n if (![\"http:\", \"https:\"].includes(next.protocol)) {\n return \"blocked\";\n }\n } catch {\n return \"blocked\";\n }\n return \"safe\";\n }\n case \"click\":\n return elementTextRisky(action.label) ? \"review\" : \"safe\";\n case \"type\":\n return elementTextRisky(action.label) ? \"review\" : \"safe\";\n case \"focus\":\n case \"scroll\":\n case \"wait\":\n return \"safe\";\n case \"extract\":\n return \"review\";\n case \"done\":\n return \"safe\";\n default:\n return \"review\";\n }\n}\n", "import type { AgentAction } from \"../shared/contracts\";\n\nfunction mustFind(selector: string): HTMLElement {\n const node = document.querySelector(selector);\n if (node instanceof HTMLElement) {\n return node;\n }\n\n // Fallback: if selector looks like a bare nth-of-type or is invalid,\n // try to find the element by tag and common attributes extracted from the selector\n const tagMatch = selector.match(/^(\\w+)/);\n if (tagMatch) {\n const tag = tagMatch[1];\n // Try matching by name, placeholder, or aria-label attributes in the selector\n const attrMatch = selector.match(/\\[(\\w[\\w-]*)=[\"']?([^\\]\"']+)[\"']?\\]/);\n if (attrMatch) {\n const fallback = document.querySelector(`${tag}[${attrMatch[1]}=\"${attrMatch[2]}\"]`);\n if (fallback instanceof HTMLElement) return fallback;\n }\n // Last resort: if only one element of that tag exists, use it\n const allOfTag = document.querySelectorAll(tag);\n if (allOfTag.length === 1 && allOfTag[0] instanceof HTMLElement) {\n return allOfTag[0];\n }\n }\n\n throw new Error(`Selector not found: ${selector}`);\n}\n\nfunction dispatchInputEvents(el: HTMLInputElement | HTMLTextAreaElement): void {\n el.dispatchEvent(new InputEvent(\"input\", { bubbles: true, cancelable: true }));\n el.dispatchEvent(new Event(\"change\", { bubbles: true }));\n}\n\nexport async function executeAction(action: AgentAction): Promise<string> {\n switch (action.type) {\n case \"click\": {\n const el = mustFind(action.selector);\n if ((el as HTMLButtonElement).disabled) {\n throw new Error(`Element is disabled: ${action.selector}`);\n }\n el.click();\n return `Clicked ${action.selector}`;\n }\n case \"type\": {\n const input = mustFind(action.selector) as HTMLInputElement | HTMLTextAreaElement;\n input.focus();\n if (action.clearFirst) {\n input.value = \"\";\n dispatchInputEvents(input);\n }\n input.value = `${input.value}${action.text}`;\n dispatchInputEvents(input);\n if (input.value.indexOf(action.text) === -1) {\n throw new Error(`Type verification failed: value did not update for ${action.selector}`);\n }\n return `Typed into ${action.selector}`;\n }\n case \"navigate\": {\n window.location.href = action.url;\n return `Navigated to ${action.url}`;\n }\n case \"extract\": {\n const value = mustFind(action.selector).innerText.trim();\n if (!value) {\n throw new Error(`Extract returned empty text from ${action.selector}`);\n }\n return `${action.label}: ${value}`;\n }\n case \"scroll\": {\n const target = action.selector ? mustFind(action.selector) : document.documentElement;\n target.scrollBy({ top: action.deltaY, behavior: \"smooth\" });\n return `Scrolled ${action.deltaY > 0 ? \"down\" : \"up\"} ${Math.abs(action.deltaY)}px`;\n }\n case \"focus\": {\n mustFind(action.selector).focus();\n return `Focused ${action.selector}`;\n }\n case \"wait\": {\n await new Promise((resolve) => setTimeout(resolve, action.ms));\n return `Waited ${action.ms}ms`;\n }\n case \"done\": {\n return action.reason;\n }\n default:\n return \"No-op\";\n }\n}\n", "import type { CandidateElement, PageSnapshot } from \"../shared/contracts\";\n\nconst CANDIDATE_SELECTOR =\n \"a,button,input,textarea,select,[role='button'],[role='link'],[contenteditable='true']\";\n\nconst MAX_CANDIDATES = 60;\n\nfunction cssPath(element: Element): string {\n if (!(element instanceof HTMLElement)) {\n return element.tagName.toLowerCase();\n }\n\n if (element.id) {\n return `#${CSS.escape(element.id)}`;\n }\n\n // For form elements, prefer attribute-based selectors that are more stable\n const tag = element.tagName.toLowerCase();\n if (tag === \"input\" || tag === \"textarea\" || tag === \"select\") {\n const name = element.getAttribute(\"name\");\n if (name && document.querySelectorAll(`${tag}[name=${CSS.escape(name)}]`).length === 1) {\n return `${tag}[name=${CSS.escape(name)}]`;\n }\n const type = (element as HTMLInputElement).type;\n const placeholder = element.getAttribute(\"placeholder\");\n if (placeholder && document.querySelectorAll(`${tag}[placeholder=${CSS.escape(placeholder)}]`).length === 1) {\n return `${tag}[placeholder=${CSS.escape(placeholder)}]`;\n }\n const ariaLabel = element.getAttribute(\"aria-label\");\n if (ariaLabel && document.querySelectorAll(`${tag}[aria-label=${CSS.escape(ariaLabel)}]`).length === 1) {\n return `${tag}[aria-label=${CSS.escape(ariaLabel)}]`;\n }\n // Combine name + type for uniqueness\n if (name && type) {\n const combo = `${tag}[name=${CSS.escape(name)}][type=${CSS.escape(type)}]`;\n if (document.querySelectorAll(combo).length === 1) {\n return combo;\n }\n }\n }\n\n // For buttons/links, prefer text-based or aria selectors\n if (tag === \"button\" || tag === \"a\") {\n const ariaLabel = element.getAttribute(\"aria-label\");\n if (ariaLabel && document.querySelectorAll(`${tag}[aria-label=${CSS.escape(ariaLabel)}]`).length === 1) {\n return `${tag}[aria-label=${CSS.escape(ariaLabel)}]`;\n }\n }\n\n const parts: string[] = [];\n let current: HTMLElement | null = element;\n while (current && parts.length < 4) {\n let part = current.tagName.toLowerCase();\n if (current.classList.length > 0) {\n part += `.${Array.from(current.classList).slice(0, 2).map(CSS.escape).join(\".\")}`;\n }\n const parent: HTMLElement | null = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter((s: Element) => s.tagName === current!.tagName);\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n part += `:nth-of-type(${index})`;\n }\n }\n parts.unshift(part);\n current = parent;\n }\n return parts.join(\" > \");\n}\n\nfunction isVisible(el: HTMLElement): boolean {\n if (el.offsetParent === null && el.tagName !== \"BODY\") return false;\n const style = window.getComputedStyle(el);\n if (style.display === \"none\" || style.visibility === \"hidden\" || style.opacity === \"0\") return false;\n // Zero-dimension elements are functionally hidden\n const rect = el.getBoundingClientRect();\n return rect.width > 0 || rect.height > 0;\n}\n\nfunction isInViewport(el: HTMLElement): boolean {\n const rect = el.getBoundingClientRect();\n return (\n rect.bottom > 0 &&\n rect.top < window.innerHeight &&\n rect.right > 0 &&\n rect.left < window.innerWidth\n );\n}\n\n/** Resolve the visible label text via for/id, aria-labelledby, aria-label, or wrapping <label>. */\nfunction getAssociatedLabel(el: HTMLElement): string {\n if (el.id) {\n const label = document.querySelector<HTMLLabelElement>(`label[for=\"${CSS.escape(el.id)}\"]`);\n if (label) return label.innerText.trim();\n }\n\n const labelledBy = el.getAttribute(\"aria-labelledby\");\n if (labelledBy) {\n const labelEl = document.getElementById(labelledBy);\n if (labelEl) return labelEl.innerText.trim();\n }\n\n const ariaLabel = el.getAttribute(\"aria-label\");\n if (ariaLabel) return ariaLabel.trim();\n\n const parentLabel = el.closest(\"label\");\n if (parentLabel) {\n return Array.from(parentLabel.childNodes)\n .filter((n) => n.nodeType === Node.TEXT_NODE)\n .map((n) => n.textContent?.trim() ?? \"\")\n .filter(Boolean)\n .join(\" \");\n }\n\n return \"\";\n}\n\nexport function collectSnapshot(): PageSnapshot {\n const allNodes = Array.from(\n document.querySelectorAll<HTMLElement>(CANDIDATE_SELECTOR)\n ).filter(isVisible);\n\n // In-viewport elements first so the model sees the most relevant candidates first\n const inView = allNodes.filter(isInViewport);\n const offScreen = allNodes.filter((el) => !isInViewport(el));\n const nodes = [...inView, ...offScreen].slice(0, MAX_CANDIDATES);\n\n const candidates: CandidateElement[] = nodes.map((node) => {\n const placeholder =\n (node as HTMLInputElement).placeholder?.trim() || node.getAttribute(\"placeholder\")?.trim();\n const associatedLabel = getAssociatedLabel(node);\n return {\n selector: cssPath(node),\n role: node.getAttribute(\"role\") ?? node.tagName.toLowerCase(),\n text: (node.innerText || node.getAttribute(\"name\") || \"\").trim().slice(0, 120),\n placeholder: placeholder || undefined,\n label: associatedLabel || undefined,\n };\n });\n\n const textPreview = document.body.innerText.replace(/\\s+/g, \" \").trim().slice(0, 1500);\n\n return {\n url: window.location.href,\n title: document.title,\n textPreview,\n candidates,\n };\n}\n", "import type { AgentAction, CandidateElement, PlannerConfig, PlannerInput, PlannerResult } from \"../shared/contracts\";\n\ntype WebLLMBridge = {\n // Bridge may return PlannerResult (new), AgentAction (legacy), or raw LLM text.\n plan(input: PlannerInput, modelId?: string): Promise<PlannerResult | AgentAction | string>;\n // Optional retry hook that keeps chat history and asks for corrected JSON.\n retryInvalidJson?(input: PlannerInput, badOutput: string, modelId?: string): Promise<PlannerResult | AgentAction | string>;\n};\n\nconst URL_PATTERN = /(?:go to|navigate to|open)\\s+(https?:\\/\\/\\S+)/i;\nconst SEARCH_PATTERN = /search(?:\\s+for)?\\s+(.+)/i;\nconst FILL_PATTERN = /(?:fill|type|enter)\\s+\"?([^\"]+)\"?\\s+(?:in(?:to)?|for|on)\\s+(.+)/i;\nconst CLICK_PATTERN = /click(?:\\s+(?:on|the))?\\s+(.+)/i;\n\nfunction findByText(candidates: CandidateElement[], text: string): CandidateElement | undefined {\n const lower = text.toLowerCase();\n return candidates.find(\n (c) =>\n c.text.toLowerCase().includes(lower) ||\n (c.placeholder?.toLowerCase().includes(lower) ?? false) ||\n (c.label?.toLowerCase().includes(lower) ?? false)\n );\n}\n\nfunction findInput(candidates: CandidateElement[]): CandidateElement | undefined {\n return candidates.find(\n (c) => c.role === \"input\" || c.role === \"textarea\" || c.selector.includes(\"input\") || c.selector.includes(\"textarea\")\n );\n}\n\nfunction findButton(candidates: CandidateElement[]): CandidateElement | undefined {\n return candidates.find(\n (c) => c.role === \"button\" || c.role === \"a\" || c.selector.includes(\"button\") || c.selector.includes(\"a\")\n );\n}\n\nfunction heuristicPlan(input: PlannerInput): AgentAction {\n const { goal, snapshot, history } = input;\n\n const navMatch = goal.match(URL_PATTERN);\n if (navMatch) {\n return { type: \"navigate\", url: navMatch[1] };\n }\n\n const fillMatch = goal.match(FILL_PATTERN);\n if (fillMatch) {\n const [, text, fieldHint] = fillMatch;\n const target = findByText(snapshot.candidates, fieldHint) ?? findInput(snapshot.candidates);\n if (target) {\n return { type: \"type\", selector: target.selector, text, clearFirst: true, label: target.label || target.text || target.placeholder };\n }\n }\n\n const searchMatch = goal.match(SEARCH_PATTERN);\n if (searchMatch) {\n const input = findInput(snapshot.candidates);\n if (input) {\n return { type: \"type\", selector: input.selector, text: searchMatch[1].trim(), clearFirst: true, label: input.label || input.text || input.placeholder };\n }\n }\n\n const clickMatch = goal.match(CLICK_PATTERN);\n if (clickMatch) {\n const target = findByText(snapshot.candidates, clickMatch[1].trim());\n if (target) {\n return { type: \"click\", selector: target.selector, label: target.text };\n }\n }\n\n const firstInput = findInput(snapshot.candidates);\n const firstButton = findButton(snapshot.candidates);\n\n if (firstInput && !history.some((h) => h.startsWith(\"Typed\"))) {\n const searchTerm = goal.replace(/.*(?:search|find|look up)\\s+/i, \"\").trim();\n return { type: \"type\", selector: firstInput.selector, text: searchTerm, clearFirst: true, label: firstInput.label || firstInput.text || firstInput.placeholder };\n }\n\n if (firstButton && !history.some((h) => h.startsWith(\"Clicked\"))) {\n return { type: \"click\", selector: firstButton.selector, label: firstButton.text };\n }\n\n return { type: \"done\", reason: \"No further heuristic actions available\" };\n}\n\n/** Normalize whatever a bridge returns into a PlannerResult. */\nfunction toPlannerResult(raw: PlannerResult | AgentAction): PlannerResult {\n // New format: has an `action` key that is an object\n if (\"action\" in raw && typeof (raw as PlannerResult).action === \"object\") {\n return raw as PlannerResult;\n }\n // Legacy format: bare AgentAction\n return { action: raw as AgentAction };\n}\n\nasync function parsePlannerText(raw: string): Promise<PlannerResult> {\n const parser = await import(\"../shared/parse-action\");\n return parser.parsePlannerResult(raw);\n}\n\nasync function normalizeBridgeResponse(\n raw: PlannerResult | AgentAction | string\n): Promise<{ result: PlannerResult; parseFailed: boolean; rawText?: string }> {\n if (typeof raw === \"string\") {\n const parsed = await parsePlannerText(raw);\n const parseFailed = parsed.action.type === \"done\" &&\n /(No JSON|JSON parse error|Parsed value is not an object|Unknown or missing action type)/.test(parsed.action.reason);\n return { result: parsed, parseFailed, rawText: raw };\n }\n\n return { result: toPlannerResult(raw), parseFailed: false };\n}\n\nexport async function planNextAction(config: PlannerConfig, input: PlannerInput): Promise<PlannerResult> {\n if (config.kind === \"heuristic\") {\n return { action: heuristicPlan(input) };\n }\n\n const bridge = (window as Window & { __browserAgentWebLLM?: WebLLMBridge }).__browserAgentWebLLM;\n if (!bridge) {\n return {\n action: {\n type: \"done\",\n reason: \"WebLLM bridge is not configured. Use heuristic mode or wire a WebLLM bridge implementation.\"\n }\n };\n }\n\n const plannerInput = { ...input, systemPrompt: config.systemPrompt };\n const firstAttempt = await normalizeBridgeResponse(await bridge.plan(plannerInput, config.modelId));\n\n if (!firstAttempt.parseFailed) {\n return firstAttempt.result;\n }\n\n if (bridge.retryInvalidJson && firstAttempt.rawText) {\n const retryAttempt = await normalizeBridgeResponse(\n await bridge.retryInvalidJson(plannerInput, firstAttempt.rawText, config.modelId)\n );\n\n if (!retryAttempt.parseFailed) {\n return retryAttempt.result;\n }\n }\n\n return {\n action: {\n type: \"done\",\n reason: \"WebLLM output could not be parsed after retry.\"\n }\n };\n}\n", "import type { AgentSession, ContentCommand, ContentResult } from \"../shared/contracts\";\nimport { assessRisk } from \"../shared/safety\";\nimport { executeAction } from \"../core/executor\";\nimport { collectSnapshot } from \"../core/observer\";\nimport { planNextAction } from \"../core/planner\";\n\nlet stopped = false;\n\nasync function runTick(session: AgentSession): Promise<ContentResult> {\n const snapshot = collectSnapshot();\n const plannerResult = await planNextAction(session.planner, {\n goal: session.goal,\n snapshot,\n history: session.history,\n lastError: session.lastError,\n memory: session.memory\n });\n\n const { action } = plannerResult;\n const reflection = plannerResult.evaluation !== undefined || plannerResult.memory !== undefined || plannerResult.nextGoal !== undefined\n ? { evaluation: plannerResult.evaluation, memory: plannerResult.memory, nextGoal: plannerResult.nextGoal }\n : undefined;\n\n const risk = assessRisk(action);\n if (risk === \"blocked\") {\n return { status: \"blocked\", action, message: `Blocked action: ${JSON.stringify(action)}`, reflection };\n }\n\n if (session.mode === \"human-approved\" && risk === \"review\") {\n return { status: \"needs_approval\", action, message: `Approval needed for ${action.type}`, reflection };\n }\n\n if (action.type === \"done\") {\n return { status: \"done\", action, message: action.reason, reflection };\n }\n\n try {\n const message = await executeAction(action);\n return { status: \"executed\", action, message, reflection };\n } catch (error) {\n return { status: \"error\", action, message: String(error), reflection };\n }\n}\n\nasync function executePendingAction(session: AgentSession): Promise<ContentResult> {\n if (!session.pendingAction) {\n return { status: \"error\", message: \"No pending action to approve\" };\n }\n\n const message = await executeAction(session.pendingAction);\n return { status: \"executed\", action: session.pendingAction, message };\n}\n\nchrome.runtime.onMessage.addListener((command: ContentCommand, _sender, sendResponse) => {\n if (command.type === \"AGENT_STOP\") {\n stopped = true;\n sendResponse({ status: \"done\", message: \"Stopped by user\" } satisfies ContentResult);\n return true;\n }\n\n if (command.type !== \"AGENT_TICK\") {\n return false;\n }\n\n const session = command.session;\n const exec = session.pendingAction ? executePendingAction(session) : runTick(session);\n\n exec\n .then((result) => {\n if (stopped) {\n sendResponse({ status: \"done\", message: \"Stopped\" } satisfies ContentResult);\n return;\n }\n sendResponse(result);\n })\n .catch((error) => {\n sendResponse({ status: \"error\", message: String(error) } satisfies ContentResult);\n });\n\n return true;\n});\n"],
5
- "mappings": "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",
6
- "names": ["input"]
4
+ "sourcesContent": ["import type { AgentAction, PlannerResult } from \"./contracts\";\n\nexport const PARSE_FAILURE_PATTERN = /(No JSON|JSON parse error|Parsed value is not an object|Unknown or missing action type|Missing required field)/;\n\nconst VALID_TYPES = new Set([\n \"click\", \"type\", \"navigate\", \"extract\", \"scroll\", \"focus\", \"wait\", \"done\",\n]);\n\n/**\n * Extract the first complete JSON object from text using bracket counting.\n * More robust than regex: handles prose before/after JSON, and repairs\n * truncated output (e.g. when the model hits a token limit mid-JSON).\n */\nfunction extractFirstJsonObject(text: string): string | null {\n const start = text.indexOf(\"{\");\n if (start === -1) return null;\n\n let depth = 0;\n let inString = false;\n let escaped = false;\n\n for (let i = start; i < text.length; i++) {\n const ch = text[i];\n if (escaped) { escaped = false; continue; }\n if (ch === \"\\\\\" && inString) { escaped = true; continue; }\n if (ch === '\"') { inString = !inString; continue; }\n if (inString) continue;\n if (ch === \"{\") depth++;\n else if (ch === \"}\") {\n depth--;\n if (depth === 0) return text.slice(start, i + 1);\n }\n }\n\n // Truncated JSON (hit token limit mid-output) \u2014 close remaining open braces.\n if (depth > 0) {\n return text.slice(start) + \"}\".repeat(depth);\n }\n\n return null;\n}\n\n/**\n * Parse an AgentAction from raw LLM output.\n *\n * Handles bare JSON, markdown fences, and JSON embedded in prose.\n * Returns a \"done\" action if parsing fails, so the caller always gets a valid AgentAction.\n */\nexport function parseAction(raw: string): AgentAction {\n const fenceMatch = raw.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n const candidate = fenceMatch ? fenceMatch[1].trim() : raw.trim();\n\n const jsonStr = extractFirstJsonObject(candidate);\n if (!jsonStr) {\n return { type: \"done\", reason: `No JSON object found in: ${raw.slice(0, 120)}` };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonStr);\n } catch {\n return { type: \"done\", reason: `JSON parse error for: ${jsonStr.slice(0, 120)}` };\n }\n\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return { type: \"done\", reason: \"Parsed value is not an object\" };\n }\n\n const obj = parsed as Record<string, unknown>;\n if (typeof obj.type !== \"string\" || !VALID_TYPES.has(obj.type)) {\n return { type: \"done\", reason: `Unknown or missing action type: ${String(obj.type)}` };\n }\n\n const t = obj.type;\n if ((t === \"click\" || t === \"type\" || t === \"extract\" || t === \"focus\") && typeof obj.selector !== \"string\") {\n return { type: \"done\", reason: `Missing required field 'selector' for action type: ${t}` };\n }\n if (t === \"extract\" && typeof obj.label !== \"string\") {\n return { type: \"done\", reason: `Missing required field 'label' for action type: extract` };\n }\n if (t === \"type\" && typeof obj.text !== \"string\") {\n return { type: \"done\", reason: `Missing required field 'text' for action type: type` };\n }\n if (t === \"navigate\" && typeof obj.url !== \"string\") {\n return { type: \"done\", reason: `Missing required field 'url' for action type: navigate` };\n }\n if (t === \"scroll\" && typeof obj.deltaY !== \"number\") {\n return { type: \"done\", reason: `Missing required field 'deltaY' for action type: scroll` };\n }\n if (t === \"wait\" && typeof obj.ms !== \"number\") {\n return { type: \"done\", reason: `Missing required field 'ms' for action type: wait` };\n }\n if (t === \"done\" && typeof obj.reason !== \"string\") {\n return { type: \"done\", reason: `Missing required field 'reason' for action type: done` };\n }\n\n return obj as unknown as AgentAction;\n}\n\n/**\n * Parse a full PlannerResult from raw LLM output.\n *\n * Accepts the reflection+action format:\n * { \"evaluation\": \"...\", \"memory\": \"...\", \"nextGoal\": \"...\", \"action\": { ... } }\n * Also supports legacy `next_goal` key for backward compatibility.\n *\n * Also accepts a bare AgentAction for backward compatibility with simple bridges.\n */\nexport function parsePlannerResult(raw: string): PlannerResult {\n const fenceMatch = raw.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n const candidate = fenceMatch ? fenceMatch[1].trim() : raw.trim();\n\n const jsonStr = extractFirstJsonObject(candidate);\n if (!jsonStr) {\n return { action: { type: \"done\", reason: `No JSON found in: ${raw.slice(0, 120)}` } };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonStr);\n } catch {\n return { action: { type: \"done\", reason: `JSON parse error: ${jsonStr.slice(0, 120)}` } };\n }\n\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return { action: { type: \"done\", reason: \"Parsed value is not an object\" } };\n }\n\n const obj = parsed as Record<string, unknown>;\n\n // Full reflection format: { evaluation, memory, nextGoal, action }\n if (typeof obj.action === \"object\" && obj.action !== null) {\n const action = parseAction(JSON.stringify(obj.action));\n return {\n action,\n evaluation: typeof obj.evaluation === \"string\" ? obj.evaluation : undefined,\n memory: typeof obj.memory === \"string\" ? obj.memory : undefined,\n nextGoal:\n typeof obj.nextGoal === \"string\"\n ? obj.nextGoal\n : typeof obj.next_goal === \"string\"\n ? obj.next_goal\n : undefined,\n };\n }\n\n // Fallback: bare AgentAction (no reflection fields)\n return { action: parseAction(jsonStr) };\n}\n", "import type { AgentAction, CandidateElement, RiskLevel } from \"./contracts\";\n\nconst RISKY_KEYWORDS = /\\b(delete|remove|pay|purchase|submit|confirm|checkout|transfer|withdraw|send)\\b/i;\n\nfunction elementTextRisky(text?: string): boolean {\n return text != null && RISKY_KEYWORDS.test(text);\n}\n\nfunction candidateText(selector: string, candidates?: CandidateElement[]): string | undefined {\n const match = candidates?.find((c) => c.selector === selector);\n return match ? ([match.label, match.text, match.placeholder].filter(Boolean).join(\" \") || undefined) : undefined;\n}\n\nexport function assessRisk(action: AgentAction, candidates?: CandidateElement[]): RiskLevel {\n switch (action.type) {\n case \"navigate\": {\n // Fragment-only (#anchor) and relative paths are safe on-page navigations.\n if (action.url.startsWith(\"#\") || action.url.startsWith(\"/\") || action.url.startsWith(\"./\") || action.url.startsWith(\"../\")) {\n return \"safe\";\n }\n try {\n const next = new URL(action.url);\n if (![\"http:\", \"https:\"].includes(next.protocol)) {\n return \"blocked\";\n }\n } catch {\n // Unparseable URL that is not a known relative form \u2014 block it.\n return \"blocked\";\n }\n return \"safe\";\n }\n case \"click\": {\n const text = action.label ?? candidateText(action.selector, candidates) ?? action.selector;\n return elementTextRisky(text) ? \"review\" : \"safe\";\n }\n case \"type\": {\n const text = action.label ?? candidateText(action.selector, candidates) ?? action.selector;\n return elementTextRisky(text) ? \"review\" : \"safe\";\n }\n case \"focus\":\n case \"scroll\":\n case \"wait\":\n return \"safe\";\n case \"extract\":\n return \"review\";\n case \"done\":\n return \"safe\";\n default:\n return \"review\";\n }\n}\n", "import type { AgentAction } from \"../shared/contracts\";\n\nfunction mustFind(selector: string): HTMLElement {\n const node = document.querySelector(selector);\n if (node instanceof HTMLElement) {\n return node;\n }\n\n // Fallback: if selector looks like a bare nth-of-type or is invalid,\n // try to find the element by tag and common attributes extracted from the selector\n const tagMatch = selector.match(/^(\\w+)/);\n if (tagMatch) {\n const tag = tagMatch[1];\n // Try matching by name, placeholder, or aria-label attributes in the selector\n const attrMatch = selector.match(/\\[(\\w[\\w-]*)=[\"']?([^\\]\"']+)[\"']?\\]/);\n if (attrMatch) {\n const fallback = document.querySelector(`${tag}[${attrMatch[1]}=\"${attrMatch[2]}\"]`);\n if (fallback instanceof HTMLElement) return fallback;\n }\n // Last resort: if only one element of that tag exists, use it\n const allOfTag = document.querySelectorAll(tag);\n if (allOfTag.length === 1 && allOfTag[0] instanceof HTMLElement) {\n return allOfTag[0];\n }\n }\n\n throw new Error(`Selector not found: ${selector}`);\n}\n\nfunction dispatchInputEvents(el: HTMLInputElement | HTMLTextAreaElement): void {\n el.dispatchEvent(new InputEvent(\"input\", { bubbles: true, cancelable: true }));\n el.dispatchEvent(new Event(\"change\", { bubbles: true }));\n}\n\nexport async function executeAction(action: AgentAction): Promise<string> {\n switch (action.type) {\n case \"click\": {\n const el = mustFind(action.selector);\n if ((el as HTMLButtonElement).disabled) {\n throw new Error(`Element is disabled: ${action.selector}`);\n }\n el.click();\n return `Clicked ${action.selector}`;\n }\n case \"type\": {\n const input = mustFind(action.selector) as HTMLInputElement | HTMLTextAreaElement;\n if (input.value === action.text) {\n return `Already contains correct value in ${action.selector}`;\n }\n input.focus();\n if (action.clearFirst) {\n input.value = \"\";\n dispatchInputEvents(input);\n }\n input.value = `${input.value}${action.text}`;\n dispatchInputEvents(input);\n if (input.value.indexOf(action.text) === -1) {\n throw new Error(`Type verification failed: value did not update for ${action.selector}`);\n }\n return `Typed into ${action.selector}`;\n }\n case \"navigate\": {\n window.location.href = action.url;\n return `Navigated to ${action.url}`;\n }\n case \"extract\": {\n const value = mustFind(action.selector).innerText.trim();\n if (!value) {\n throw new Error(`Extract returned empty text from ${action.selector}`);\n }\n return `${action.label}: ${value}`;\n }\n case \"scroll\": {\n const target = action.selector ? mustFind(action.selector) : document.documentElement;\n target.scrollBy({ top: action.deltaY, behavior: \"smooth\" });\n return `Scrolled ${action.deltaY > 0 ? \"down\" : \"up\"} ${Math.abs(action.deltaY)}px`;\n }\n case \"focus\": {\n mustFind(action.selector).focus();\n return `Focused ${action.selector}`;\n }\n case \"wait\": {\n await new Promise((resolve) => setTimeout(resolve, action.ms));\n return `Waited ${action.ms}ms`;\n }\n case \"done\": {\n return action.reason;\n }\n default:\n return \"No-op\";\n }\n}\n", "import type { CandidateElement, PageSnapshot } from \"../shared/contracts\";\n\nconst CANDIDATE_SELECTOR =\n \"a,button,input,textarea,select,[role='button'],[role='link'],[contenteditable='true']\";\n\nconst MAX_CANDIDATES = 60;\n\nfunction cssPath(element: Element): string {\n if (!(element instanceof HTMLElement)) {\n return element.tagName.toLowerCase();\n }\n\n if (element.id) {\n return `#${CSS.escape(element.id)}`;\n }\n\n // For form elements, prefer attribute-based selectors that are more stable\n const tag = element.tagName.toLowerCase();\n if (tag === \"input\" || tag === \"textarea\" || tag === \"select\") {\n const name = element.getAttribute(\"name\");\n if (name && document.querySelectorAll(`${tag}[name=${CSS.escape(name)}]`).length === 1) {\n return `${tag}[name=${CSS.escape(name)}]`;\n }\n const type = (element as HTMLInputElement).type;\n const placeholder = element.getAttribute(\"placeholder\");\n if (placeholder && document.querySelectorAll(`${tag}[placeholder=${CSS.escape(placeholder)}]`).length === 1) {\n return `${tag}[placeholder=${CSS.escape(placeholder)}]`;\n }\n const ariaLabel = element.getAttribute(\"aria-label\");\n if (ariaLabel && document.querySelectorAll(`${tag}[aria-label=${CSS.escape(ariaLabel)}]`).length === 1) {\n return `${tag}[aria-label=${CSS.escape(ariaLabel)}]`;\n }\n // Combine name + type for uniqueness\n if (name && type) {\n const combo = `${tag}[name=${CSS.escape(name)}][type=${CSS.escape(type)}]`;\n if (document.querySelectorAll(combo).length === 1) {\n return combo;\n }\n }\n }\n\n // For buttons/links, prefer text-based or aria selectors\n if (tag === \"button\" || tag === \"a\") {\n const ariaLabel = element.getAttribute(\"aria-label\");\n if (ariaLabel && document.querySelectorAll(`${tag}[aria-label=${CSS.escape(ariaLabel)}]`).length === 1) {\n return `${tag}[aria-label=${CSS.escape(ariaLabel)}]`;\n }\n }\n\n const parts: string[] = [];\n let current: HTMLElement | null = element;\n while (current && parts.length < 4) {\n let part = current.tagName.toLowerCase();\n if (current.classList.length > 0) {\n part += `.${Array.from(current.classList).slice(0, 2).map(CSS.escape).join(\".\")}`;\n }\n const parent: HTMLElement | null = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter((s: Element) => s.tagName === current!.tagName);\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n part += `:nth-of-type(${index})`;\n }\n }\n parts.unshift(part);\n current = parent;\n }\n return parts.join(\" > \");\n}\n\nfunction isVisible(el: HTMLElement): boolean {\n const style = window.getComputedStyle(el);\n if (el.offsetParent === null && el.tagName !== \"BODY\" && style.position !== \"fixed\") return false;\n if (style.display === \"none\" || style.visibility === \"hidden\" || style.opacity === \"0\") return false;\n // Zero-dimension elements are functionally hidden\n const rect = el.getBoundingClientRect();\n return rect.width > 0 || rect.height > 0;\n}\n\nfunction isInViewport(el: HTMLElement): boolean {\n const rect = el.getBoundingClientRect();\n return (\n rect.bottom > 0 &&\n rect.top < window.innerHeight &&\n rect.right > 0 &&\n rect.left < window.innerWidth\n );\n}\n\nfunction isActiveElement(el: HTMLElement): boolean {\n if (el.classList.contains(\"active\")) return true;\n if (el.getAttribute(\"aria-selected\") === \"true\") return true;\n const ariaCurrent = el.getAttribute(\"aria-current\");\n if (ariaCurrent && ariaCurrent !== \"false\") return true;\n if (el.getAttribute(\"aria-pressed\") === \"true\") return true;\n return false;\n}\n\n/** Resolve the visible label text via for/id, aria-labelledby, aria-label, or wrapping <label>. */\nfunction getAssociatedLabel(el: HTMLElement): string {\n if (el.id) {\n const label = document.querySelector<HTMLLabelElement>(`label[for=\"${CSS.escape(el.id)}\"]`);\n if (label) return label.innerText.trim();\n }\n\n const labelledBy = el.getAttribute(\"aria-labelledby\");\n if (labelledBy) {\n const labelEl = document.getElementById(labelledBy);\n if (labelEl) return labelEl.innerText.trim();\n }\n\n const ariaLabel = el.getAttribute(\"aria-label\");\n if (ariaLabel) return ariaLabel.trim();\n\n const parentLabel = el.closest(\"label\");\n if (parentLabel) {\n return Array.from(parentLabel.childNodes)\n .filter((n) => n.nodeType === Node.TEXT_NODE)\n .map((n) => n.textContent?.trim() ?? \"\")\n .filter(Boolean)\n .join(\" \");\n }\n\n return \"\";\n}\n\nexport function collectSnapshot(): PageSnapshot {\n const allNodes = Array.from(\n document.querySelectorAll<HTMLElement>(CANDIDATE_SELECTOR)\n ).filter(isVisible).filter((el) => !el.closest(\"[data-agent-exclude]\"));\n\n // In-viewport elements first so the model sees the most relevant candidates first\n const inView = allNodes.filter(isInViewport);\n const offScreen = allNodes.filter((el) => !isInViewport(el));\n const nodes = [...inView, ...offScreen].slice(0, MAX_CANDIDATES);\n\n const candidates: CandidateElement[] = nodes.map((node) => {\n const placeholder =\n (node as HTMLInputElement).placeholder?.trim() || node.getAttribute(\"placeholder\")?.trim();\n const associatedLabel = getAssociatedLabel(node);\n return {\n selector: cssPath(node),\n role: node.getAttribute(\"role\") ?? node.tagName.toLowerCase(),\n text: (node.innerText || node.getAttribute(\"name\") || \"\").trim().slice(0, 120),\n placeholder: placeholder || undefined,\n label: associatedLabel || undefined,\n active: isActiveElement(node) || undefined,\n };\n });\n\n const textPreview = document.body.innerText.replace(/\\s+/g, \" \").trim().slice(0, 1500);\n\n return {\n url: window.location.href,\n title: document.title,\n textPreview,\n candidates,\n };\n}\n", "import type { AgentAction, CandidateElement, PlannerConfig, PlannerInput, PlannerResult } from \"../shared/contracts\";\n\ntype WebLLMBridge = {\n // Bridge may return PlannerResult (new), AgentAction (legacy), or raw LLM text.\n plan(input: PlannerInput, modelId?: string): Promise<PlannerResult | AgentAction | string>;\n // Optional retry hook that keeps chat history and asks for corrected JSON.\n retryInvalidJson?(input: PlannerInput, badOutput: string, modelId?: string): Promise<PlannerResult | AgentAction | string>;\n};\n\nconst URL_PATTERN = /(?:go to|navigate to|open)\\s+(https?:\\/\\/\\S+)/i;\nconst SEARCH_PATTERN = /search(?:\\s+for)?\\s+(.+)/i;\nconst FILL_PATTERN = /(?:fill|type|enter)\\s+\"?([^\"]+)\"?\\s+(?:in(?:to)?|for|on)\\s+(.+)/i;\nconst CLICK_PATTERN = /click(?:\\s+(?:on|the))?\\s+(.+)/i;\n\nfunction findByText(candidates: CandidateElement[], text: string): CandidateElement | undefined {\n const lower = text.toLowerCase();\n return candidates.find(\n (c) =>\n c.text.toLowerCase().includes(lower) ||\n (c.placeholder?.toLowerCase().includes(lower) ?? false) ||\n (c.label?.toLowerCase().includes(lower) ?? false)\n );\n}\n\nfunction findInput(candidates: CandidateElement[]): CandidateElement | undefined {\n return candidates.find(\n (c) => c.role === \"input\" || c.role === \"textarea\" || c.selector.includes(\"input\") || c.selector.includes(\"textarea\")\n );\n}\n\nfunction findButton(candidates: CandidateElement[]): CandidateElement | undefined {\n return candidates.find(\n (c) => c.role === \"button\" || c.role === \"a\" || c.selector.includes(\"button\") || c.selector.includes(\"a\")\n );\n}\n\nfunction heuristicPlan(input: PlannerInput): AgentAction {\n const { goal, snapshot, history } = input;\n\n const navMatch = goal.match(URL_PATTERN);\n if (navMatch) {\n return { type: \"navigate\", url: navMatch[1] };\n }\n\n const fillMatch = goal.match(FILL_PATTERN);\n if (fillMatch) {\n const [, text, fieldHint] = fillMatch;\n const target = findByText(snapshot.candidates, fieldHint) ?? findInput(snapshot.candidates);\n if (target) {\n return { type: \"type\", selector: target.selector, text, clearFirst: true, label: target.label || target.text || target.placeholder };\n }\n }\n\n const searchMatch = goal.match(SEARCH_PATTERN);\n if (searchMatch) {\n const input = findInput(snapshot.candidates);\n if (input) {\n return { type: \"type\", selector: input.selector, text: searchMatch[1].trim(), clearFirst: true, label: input.label || input.text || input.placeholder };\n }\n }\n\n const clickMatch = goal.match(CLICK_PATTERN);\n if (clickMatch) {\n const target = findByText(snapshot.candidates, clickMatch[1].trim());\n if (target) {\n return { type: \"click\", selector: target.selector, label: target.text };\n }\n }\n\n const firstInput = findInput(snapshot.candidates);\n const firstButton = findButton(snapshot.candidates);\n\n if (firstInput && !history.some((h) => h.startsWith(\"Typed\"))) {\n const searchTerm = goal.replace(/.*(?:search|find|look up)\\s+/i, \"\").trim();\n return { type: \"type\", selector: firstInput.selector, text: searchTerm, clearFirst: true, label: firstInput.label || firstInput.text || firstInput.placeholder };\n }\n\n if (firstButton && !history.some((h) => h.startsWith(\"Clicked\"))) {\n return { type: \"click\", selector: firstButton.selector, label: firstButton.text };\n }\n\n return { type: \"done\", reason: \"No further heuristic actions available\" };\n}\n\n/** Normalize whatever a bridge returns into a PlannerResult. */\nfunction toPlannerResult(raw: PlannerResult | AgentAction): PlannerResult {\n // New format: has an `action` key that is an object\n if (\"action\" in raw && typeof (raw as PlannerResult).action === \"object\") {\n return raw as PlannerResult;\n }\n // Legacy format: bare AgentAction\n return { action: raw as AgentAction };\n}\n\nasync function parsePlannerText(raw: string): Promise<{ result: PlannerResult; parseFailed: boolean }> {\n const { parsePlannerResult, PARSE_FAILURE_PATTERN } = await import(\"../shared/parse-action\");\n const result = parsePlannerResult(raw);\n const parseFailed = result.action.type === \"done\" && PARSE_FAILURE_PATTERN.test(result.action.reason);\n return { result, parseFailed };\n}\n\n\nasync function normalizeBridgeResponse(\n raw: PlannerResult | AgentAction | string\n): Promise<{ result: PlannerResult; parseFailed: boolean; rawText?: string }> {\n if (typeof raw === \"string\") {\n const { result, parseFailed } = await parsePlannerText(raw);\n return { result, parseFailed, rawText: raw };\n }\n\n return { result: toPlannerResult(raw), parseFailed: false };\n}\n\nexport async function planNextAction(config: PlannerConfig, input: PlannerInput): Promise<PlannerResult> {\n if (config.kind === \"heuristic\") {\n return { action: heuristicPlan(input) };\n }\n\n const bridge = (window as Window & { __browserAgentWebLLM?: WebLLMBridge }).__browserAgentWebLLM;\n if (!bridge) {\n return {\n action: {\n type: \"done\",\n reason: \"WebLLM bridge is not configured. Use heuristic mode or wire a WebLLM bridge implementation.\"\n }\n };\n }\n\n const plannerInput = { ...input, systemPrompt: config.systemPrompt };\n const firstAttempt = await normalizeBridgeResponse(await bridge.plan(plannerInput, config.modelId));\n\n if (!firstAttempt.parseFailed) {\n return firstAttempt.result;\n }\n\n if (bridge.retryInvalidJson && firstAttempt.rawText) {\n const retryAttempt = await normalizeBridgeResponse(\n await bridge.retryInvalidJson(plannerInput, firstAttempt.rawText, config.modelId)\n );\n\n if (!retryAttempt.parseFailed) {\n return retryAttempt.result;\n }\n }\n\n return {\n action: {\n type: \"done\",\n reason: \"WebLLM output could not be parsed after retry.\"\n }\n };\n}\n", "import type { AgentSession, ContentCommand, ContentResult } from \"../shared/contracts\";\nimport { assessRisk } from \"../shared/safety\";\nimport { executeAction } from \"../core/executor\";\nimport { collectSnapshot } from \"../core/observer\";\nimport { planNextAction } from \"../core/planner\";\n\nlet stopped = false;\n\nasync function runTick(session: AgentSession): Promise<ContentResult> {\n const snapshot = collectSnapshot();\n const plannerResult = await planNextAction(session.planner, {\n goal: session.goal,\n snapshot,\n history: session.history,\n lastError: session.lastError,\n memory: session.memory\n });\n\n const { action } = plannerResult;\n const reflection = plannerResult.evaluation !== undefined || plannerResult.memory !== undefined || plannerResult.nextGoal !== undefined\n ? { evaluation: plannerResult.evaluation, memory: plannerResult.memory, nextGoal: plannerResult.nextGoal }\n : undefined;\n\n const risk = assessRisk(action, snapshot.candidates);\n if (risk === \"blocked\") {\n return { status: \"blocked\", action, message: `Blocked action: ${JSON.stringify(action)}`, reflection };\n }\n\n if (session.mode === \"human-approved\" && risk === \"review\") {\n return { status: \"needs_approval\", action, message: `Approval needed for ${action.type}`, reflection };\n }\n\n if (action.type === \"done\") {\n return { status: \"done\", action, message: action.reason, reflection };\n }\n\n try {\n const message = await executeAction(action);\n return { status: \"executed\", action, message, reflection };\n } catch (error) {\n return { status: \"error\", action, message: String(error), reflection };\n }\n}\n\nasync function executePendingAction(session: AgentSession): Promise<ContentResult> {\n if (!session.pendingAction) {\n return { status: \"error\", message: \"No pending action to approve\" };\n }\n\n const message = await executeAction(session.pendingAction);\n return { status: \"executed\", action: session.pendingAction, message };\n}\n\nchrome.runtime.onMessage.addListener((command: ContentCommand, _sender, sendResponse) => {\n if (command.type === \"AGENT_STOP\") {\n stopped = true;\n sendResponse({ status: \"done\", message: \"Stopped by user\" } satisfies ContentResult);\n return true;\n }\n\n if (command.type !== \"AGENT_TICK\") {\n return false;\n }\n\n const session = command.session;\n const exec = session.pendingAction ? executePendingAction(session) : runTick(session);\n\n exec\n .then((result) => {\n if (stopped) {\n sendResponse({ status: \"done\", message: \"Stopped\" } satisfies ContentResult);\n return;\n }\n sendResponse(result);\n })\n .catch((error) => {\n sendResponse({ status: \"error\", message: String(error) } satisfies ContentResult);\n });\n\n return true;\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["input", "parsePlannerResult", "PARSE_FAILURE_PATTERN"]
7
7
  }