@weavetab/mcp 2.5.0-beta.1 → 2.5.0-beta.4

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.
Files changed (156) hide show
  1. package/AGENTS.md +2 -1
  2. package/ARCHITECTURE.md +6 -6
  3. package/LICENSE +1 -1
  4. package/README.md +164 -802
  5. package/SECURITY.md +33 -22
  6. package/TROUBLESHOOTING.md +3 -3
  7. package/dist/cdp/bridge.d.ts +10 -0
  8. package/dist/cdp/bridge.js +285 -78
  9. package/dist/cdp/connector.d.ts +7 -3
  10. package/dist/cdp/connector.js +196 -75
  11. package/dist/cdp/helpers.d.ts +4 -0
  12. package/dist/cdp/helpers.js +181 -0
  13. package/dist/cdp/lock.d.ts +9 -6
  14. package/dist/cdp/lock.js +72 -59
  15. package/dist/cdp/omni_broker.d.ts +2 -1
  16. package/dist/cdp/omni_broker.js +13 -7
  17. package/dist/cdp/profiles.d.ts +10 -0
  18. package/dist/cdp/profiles.js +65 -0
  19. package/dist/cdp/walker.d.ts +25 -1
  20. package/dist/cdp/walker.js +354 -7
  21. package/dist/cli/plugin.d.ts +0 -2
  22. package/dist/cli/plugin.js +51 -696
  23. package/dist/cli/updater.d.ts +1 -1
  24. package/dist/cli/updater.js +27 -7
  25. package/dist/config/loader.d.ts +33 -6
  26. package/dist/config/loader.js +174 -22
  27. package/dist/desktop/discovery.d.ts +44 -0
  28. package/dist/desktop/discovery.js +364 -0
  29. package/dist/index.js +140 -64
  30. package/dist/intelligence/marks.d.ts +36 -0
  31. package/dist/intelligence/marks.js +30 -0
  32. package/dist/intelligence/patternCompiler.d.ts +118 -0
  33. package/dist/intelligence/patternCompiler.js +259 -0
  34. package/dist/intelligence/sessionMemory.d.ts +2 -0
  35. package/dist/intelligence/sessionMemory.js +18 -8
  36. package/dist/overlay/ghost.js +2 -2
  37. package/dist/overlay/injector.js +3 -5
  38. package/dist/plugin/extension_bridge.d.ts +40 -0
  39. package/dist/plugin/extension_bridge.js +158 -0
  40. package/dist/plugin/interface.d.ts +151 -15
  41. package/dist/plugin/loader.d.ts +19 -1
  42. package/dist/plugin/loader.js +331 -63
  43. package/dist/plugin/pipeline.d.ts +75 -0
  44. package/dist/plugin/pipeline.js +183 -0
  45. package/dist/plugin/registry.js +12 -1
  46. package/dist/plugin/storage.d.ts +51 -0
  47. package/dist/plugin/storage.js +164 -0
  48. package/dist/security/secrets.d.ts +1 -0
  49. package/dist/security/secrets.js +13 -0
  50. package/dist/sensors/actionability.js +1 -2
  51. package/dist/sensors/guard.js +4 -10
  52. package/dist/sensors/mutations.js +12 -0
  53. package/dist/sensors/operation_monitor.js +1 -0
  54. package/dist/server.d.ts +1 -1
  55. package/dist/server.js +600 -236
  56. package/dist/state/agent.d.ts +1 -0
  57. package/dist/state/agent.js +3 -0
  58. package/dist/state/delta.d.ts +12 -4
  59. package/dist/state/delta.js +67 -14
  60. package/dist/state/session.d.ts +8 -2
  61. package/dist/state/session.js +60 -13
  62. package/dist/tools/browser_detect.d.ts +16 -2
  63. package/dist/tools/browser_detect.js +54 -6
  64. package/dist/tools/burst.d.ts +17 -7
  65. package/dist/tools/burst.js +240 -83
  66. package/dist/tools/checkpoint.d.ts +38 -0
  67. package/dist/tools/checkpoint.js +271 -0
  68. package/dist/tools/click.d.ts +1 -0
  69. package/dist/tools/click.js +97 -98
  70. package/dist/tools/clipboard.js +31 -24
  71. package/dist/tools/design_extract.js +1 -1
  72. package/dist/tools/eval.js +1 -1
  73. package/dist/tools/fill.d.ts +20 -1
  74. package/dist/tools/fill.js +199 -40
  75. package/dist/tools/find.d.ts +16 -0
  76. package/dist/tools/find.js +67 -44
  77. package/dist/tools/github/index.d.ts +19 -4
  78. package/dist/tools/github/index.js +40 -4
  79. package/dist/tools/highlight.d.ts +6 -2
  80. package/dist/tools/highlight.js +158 -72
  81. package/dist/tools/inspect.js +1 -1
  82. package/dist/tools/key.js +65 -56
  83. package/dist/tools/navigate.d.ts +1 -1
  84. package/dist/tools/navigate.js +57 -44
  85. package/dist/tools/pdf.js +21 -13
  86. package/dist/tools/pointer.d.ts +18 -3
  87. package/dist/tools/pointer.js +89 -1
  88. package/dist/tools/read.d.ts +28 -8
  89. package/dist/tools/read.js +230 -56
  90. package/dist/tools/scrape.js +67 -13
  91. package/dist/tools/screenshot.js +21 -16
  92. package/dist/tools/scroll.js +6 -11
  93. package/dist/tools/select.js +8 -2
  94. package/dist/tools/snapshot.js +3 -34
  95. package/dist/tools/tabs.d.ts +10 -10
  96. package/dist/tools/tabs.js +55 -39
  97. package/dist/tools/thought.d.ts +2 -0
  98. package/dist/tools/thought.js +13 -14
  99. package/dist/tools/type.d.ts +2 -0
  100. package/dist/tools/type.js +109 -60
  101. package/dist/tools/type_secret.js +42 -76
  102. package/dist/tools/upload.js +1 -1
  103. package/dist/tools/video_compiler.d.ts +1 -1
  104. package/dist/tools/video_compiler.js +11 -12
  105. package/dist/version.d.ts +5 -0
  106. package/dist/version.js +5 -0
  107. package/docs/DOCUMENTATION.md +82 -36
  108. package/docs/PLUGINS.md +82 -499
  109. package/docs/TOOLS.md +51 -99
  110. package/docs/architecture/blind-injection.md +83 -0
  111. package/docs/architecture/dual-injection.md +32 -0
  112. package/docs/architecture/overview.md +49 -0
  113. package/docs/architecture/security.md +35 -0
  114. package/docs/architecture/transport.md +37 -0
  115. package/docs/captcha-stealth/captcha-solver.md +75 -0
  116. package/docs/captcha-stealth/stealth-physics.md +60 -0
  117. package/docs/cli/cli-commands.md +44 -0
  118. package/docs/cli/cli-flags.md +20 -0
  119. package/docs/cli/cli-introduction.md +20 -0
  120. package/docs/cli/cli-scripting.md +32 -0
  121. package/docs/cli/g-ide/ide-antigravity.md +24 -0
  122. package/docs/cli/g-ide/ide-claude-code.md +24 -0
  123. package/docs/cli/g-ide/ide-claude-desktop.md +32 -0
  124. package/docs/cli/g-ide/ide-cursor.md +31 -0
  125. package/docs/cli/g-ide/ide-generic.md +34 -0
  126. package/docs/cli/g-ide/ide-opencode.md +24 -0
  127. package/docs/cli/g-ide/ide-vscode-copilot.md +24 -0
  128. package/docs/cli/g-ide/ide-windsurf.md +24 -0
  129. package/docs/configuration/config-locations.md +24 -0
  130. package/docs/configuration/configuration.md +73 -0
  131. package/docs/configuration/env-variables.md +19 -0
  132. package/docs/configuration/folders.md +55 -0
  133. package/docs/desktop-automation/electron-apps.md +217 -0
  134. package/docs/get-started/installation.md +47 -0
  135. package/docs/get-started/introduction.md +60 -0
  136. package/docs/get-started/quickstart.md +54 -0
  137. package/docs/get-started/setup-wizard.md +26 -0
  138. package/docs/intelligence/site-profiles.md +151 -0
  139. package/docs/skills-ecosystem/skills-overview.md +35 -0
  140. package/docs/skills-ecosystem/skills-recipes.md +36 -0
  141. package/docs/tools/tools.md +631 -0
  142. package/docs/troubleshooting/trouble-browser.md +27 -0
  143. package/docs/troubleshooting/trouble-config.md +20 -0
  144. package/docs/troubleshooting/trouble-loop.md +31 -0
  145. package/ext-dist/background.js +10 -62
  146. package/ext-dist/content.js +333 -921
  147. package/ext-dist/hud/hud.js +9 -9
  148. package/ext-dist/manifest.json +2 -6
  149. package/ext-dist/styles.css +6 -1
  150. package/mcp.json +108 -72
  151. package/package.json +14 -9
  152. package/server.json +3 -3
  153. package/docs/DEV_MODE.md +0 -68
  154. package/docs/dev_plugin.md +0 -310
  155. package/ext-dist/sidepanel/sidepanel.js +0 -25
  156. package/ext-dist/sidepanel.html +0 -547
@@ -28,70 +28,88 @@ import { buildActionMap } from "../cdp/walker.js";
28
28
  import { sessionRegistry } from "../state/session.js";
29
29
  import { getConfigAgentId, getConfigBrowserType } from "../config/loader.js";
30
30
  import { sendToExtension } from "../cdp/helpers.js";
31
- import { resetLoopCounter } from "../intelligence/trail.js";
32
- /**
33
- * Expand a macro step into primitive BurstSteps.
34
- */
31
+ import { resetLoopCounter, getTrail } from "../intelligence/trail.js";
32
+ function extractTarget(params) {
33
+ const target = {};
34
+ if (!params || typeof params !== "object")
35
+ return target;
36
+ if (params.ref !== undefined)
37
+ target.ref = params.ref;
38
+ if (params.id !== undefined)
39
+ target.id = params.id;
40
+ if (params.target !== undefined) {
41
+ if (typeof params.target === "string" && params.target.startsWith("w:"))
42
+ target.ref = params.target;
43
+ else
44
+ target.selector = params.target;
45
+ }
46
+ if (params.selector !== undefined)
47
+ target.selector = params.selector;
48
+ if (params.label !== undefined)
49
+ target.label = params.label;
50
+ if (params.x !== undefined)
51
+ target.x = params.x;
52
+ if (params.y !== undefined)
53
+ target.y = params.y;
54
+ return target;
55
+ }
35
56
  function expandMacro(step) {
57
+ const args = step.args || {};
36
58
  if (step.tool === "type_and_send") {
37
- const { x, y, text, id, label, pressEnter = true } = step.args;
38
- if (!id && !label && x === undefined && y === undefined) {
39
- throw new Error("type_and_send macro failed: no target specified (requires id, label, or x/y)");
40
- }
59
+ const { text, pressEnter = true } = args;
60
+ const target = extractTarget(args);
41
61
  if (text === undefined) {
42
- throw new Error("type_and_send macro failed: text argument is required");
62
+ throw new Error("type_and_send failed: text is required");
43
63
  }
44
- const typeArgs = { text, noRetry: true };
45
- if (x !== undefined)
46
- typeArgs.x = x;
47
- if (y !== undefined)
48
- typeArgs.y = y;
49
- if (id)
50
- typeArgs.id = id;
51
- if (label)
52
- typeArgs.label = label;
64
+ const typeArgs = { ...target, text, noRetry: true };
53
65
  const steps = [{ tool: "browser_type", args: typeArgs }];
54
66
  if (pressEnter)
55
67
  steps.push({ tool: "browser_key", args: { key: "Enter" } });
56
68
  return steps;
57
69
  }
58
70
  if (step.tool === "navigate_and_read") {
59
- const { url } = step.args;
71
+ const { url } = args;
60
72
  return [
61
73
  { tool: "browser_go", args: { url } },
62
74
  { tool: "browser_map", args: {} },
63
75
  ];
64
76
  }
65
77
  if (step.tool === "click_and_wait") {
66
- const { id, label, wait_for, wait_value, x, y } = step.args;
67
- const clickArgs = {};
68
- if (id)
69
- clickArgs.id = id;
70
- if (label)
71
- clickArgs.label = label;
72
- if (x !== undefined)
73
- clickArgs.x = x;
74
- if (y !== undefined)
75
- clickArgs.y = y;
76
- clickArgs.waitForNetwork = true;
77
- clickArgs.waitAfter = 500;
78
- return [
79
- { tool: "browser_click", args: clickArgs },
80
- ];
78
+ const { wait_for, wait_value, wait_after, waitAfter } = args;
79
+ const target = extractTarget(args);
80
+ const clickArgs = {
81
+ ...target,
82
+ waitForNetwork: true,
83
+ waitAfter: wait_after ?? waitAfter ?? 500,
84
+ };
85
+ const steps = [{ tool: "browser_click", args: clickArgs }];
86
+ if (wait_for) {
87
+ steps.push({ tool: "browser_wait", args: { wait_for, value: wait_value } });
88
+ }
89
+ return steps;
81
90
  }
82
91
  if (step.tool === "scroll_and_read") {
83
- const { direction, distance } = step.args;
92
+ const { direction, distance } = args;
84
93
  return [
85
94
  { tool: "browser_scroll", args: { direction, distance } },
86
95
  { tool: "browser_map", args: {} },
87
96
  ];
88
97
  }
89
98
  if (step.tool === "fill_form") {
90
- const { fields, submit } = step.args;
99
+ const { fields, submit } = args;
91
100
  const steps = [];
92
- if (fields && typeof fields === "object") {
93
- for (const [id, value] of Object.entries(fields)) {
94
- steps.push({ tool: "browser_fill", args: { id, value } });
101
+ if (Array.isArray(fields)) {
102
+ for (const f of fields) {
103
+ if (f && typeof f === "object") {
104
+ const target = extractTarget(f);
105
+ steps.push({ tool: "browser_fill", args: { ...target, value: f.value } });
106
+ }
107
+ }
108
+ }
109
+ else if (fields && typeof fields === "object") {
110
+ for (const [key, value] of Object.entries(fields)) {
111
+ const target = key.startsWith("w:") ? { ref: key } : { id: key };
112
+ steps.push({ tool: "browser_fill", args: { ...target, value } });
95
113
  }
96
114
  }
97
115
  if (submit) {
@@ -100,18 +118,13 @@ function expandMacro(step) {
100
118
  return steps;
101
119
  }
102
120
  if (step.tool === "drag_and_drop") {
103
- const { id, end_id, x, y, end_x, end_y, label } = step.args;
104
- const pointerArgs = { action: "drag_and_drop" };
105
- if (id)
106
- pointerArgs.ref = id;
121
+ const { end_id, end_ref, end_x, end_y } = args;
122
+ const target = extractTarget(args);
123
+ const pointerArgs = { action: "drag_and_drop", ...target };
124
+ if (end_ref)
125
+ pointerArgs.end_ref = end_ref;
107
126
  if (end_id)
108
- pointerArgs.end_ref = end_id;
109
- if (label)
110
- pointerArgs.label = label;
111
- if (x !== undefined)
112
- pointerArgs.x = x;
113
- if (y !== undefined)
114
- pointerArgs.y = y;
127
+ pointerArgs.end_id = end_id;
115
128
  if (end_x !== undefined)
116
129
  pointerArgs.end_x = end_x;
117
130
  if (end_y !== undefined)
@@ -119,53 +132,163 @@ function expandMacro(step) {
119
132
  return [{ tool: "browser_pointer", args: pointerArgs }];
120
133
  }
121
134
  if (step.tool === "hover_and_read") {
122
- const { id, label, x, y, holdMs = 300 } = step.args;
123
- const pointerArgs = { action: "hover", holdMs };
124
- if (id)
125
- pointerArgs.ref = id;
126
- if (label)
127
- pointerArgs.label = label;
128
- if (x !== undefined)
129
- pointerArgs.x = x;
130
- if (y !== undefined)
131
- pointerArgs.y = y;
135
+ const { holdMs = 300 } = args;
136
+ const target = extractTarget(args);
132
137
  return [
133
- { tool: "browser_pointer", args: pointerArgs },
138
+ { tool: "browser_pointer", args: { action: "hover", holdMs, ...target } },
134
139
  { tool: "browser_map", args: {} },
135
140
  ];
136
141
  }
137
142
  return [];
138
143
  }
144
+ function normalizeRawSteps(raw) {
145
+ const norm = [];
146
+ for (const item of raw) {
147
+ if (!item || typeof item !== "object")
148
+ continue;
149
+ const entry = item;
150
+ const tool = (entry.tool || entry.action);
151
+ if (!tool)
152
+ continue;
153
+ let stepArgs = {};
154
+ if (entry.args && typeof entry.args === "object" && !Array.isArray(entry.args)) {
155
+ stepArgs = { ...entry.args };
156
+ }
157
+ for (const [k, v] of Object.entries(entry)) {
158
+ if (k === "tool" || k === "args")
159
+ continue;
160
+ if (stepArgs[k] === undefined)
161
+ stepArgs[k] = v;
162
+ }
163
+ norm.push({ tool, args: stepArgs });
164
+ }
165
+ return norm;
166
+ }
167
+ function extractArgs(step) {
168
+ const s = step;
169
+ const knownKeys = [
170
+ 'arguments', 'args', 'mcp_arguments', 'input',
171
+ 'params', 'parameters', 'tool_args', 'toolInput',
172
+ 'data', 'payload', 'options',
173
+ ];
174
+ for (const key of knownKeys) {
175
+ const val = s[key];
176
+ if (val !== null && val !== undefined && typeof val === 'object' && !Array.isArray(val)) {
177
+ return val;
178
+ }
179
+ }
180
+ const metaKeys = new Set([
181
+ 'tool', 'result', 'timestamp', 'type', 'id',
182
+ 'status', 'error', 'duration', 'startTime', 'endTime',
183
+ 'session', 'tabId', 'targetId',
184
+ ]);
185
+ for (const key of Object.keys(s)) {
186
+ if (metaKeys.has(key))
187
+ continue;
188
+ const val = s[key];
189
+ if (val !== null && val !== undefined && typeof val === 'object' && !Array.isArray(val)) {
190
+ return val;
191
+ }
192
+ }
193
+ return {};
194
+ }
195
+ const BURST_TOOLS = new Set([
196
+ "browser_click", "browser_type", "browser_navigate", "browser_go",
197
+ "browser_key", "browser_scroll", "browser_wait", "browser_select",
198
+ "browser_pointer", "browser_eval", "browser_console", "browser_find",
199
+ "browser_fill", "browser_type_secret", "browser_inspect",
200
+ "browser_screenshot", "browser_storage", "browser_cookies",
201
+ "browser_highlight", "browser_scrape",
202
+ "browser_canvas", "browser_performance", "browser_snapshot",
203
+ "browser_pdf", "browser_dialog", "browser_upload", "browser_automation",
204
+ "browser_viewport", "browser_clipboard", "browser_detect",
205
+ "browser_recording",
206
+ "type_and_send", "navigate_and_read", "click_and_wait",
207
+ "scroll_and_read", "fill_form", "drag_and_drop", "hover_and_read",
208
+ ]);
209
+ export function compileTraceToMacro(steps) {
210
+ const macro = [];
211
+ let lastKey = "";
212
+ steps.forEach((step, idx) => {
213
+ if (step.result && !step.result.success)
214
+ return;
215
+ if (step.tool === "browser_map") {
216
+ if (idx === steps.length - 1) {
217
+ macro.push({ tool: "browser_map", args: step.input || {} });
218
+ }
219
+ return;
220
+ }
221
+ if (BURST_TOOLS.has(step.tool)) {
222
+ const args = extractArgs(step);
223
+ const key = `${step.tool}:${JSON.stringify(args)}`;
224
+ if (key !== lastKey) {
225
+ macro.push({ tool: step.tool, args });
226
+ lastKey = key;
227
+ }
228
+ }
229
+ });
230
+ return macro;
231
+ }
139
232
  export async function browserBurst(session, args, config) {
140
- if (!args.steps || args.steps.length === 0) {
141
- return { success: true, steps_completed: 0, results: [], aborted: false };
233
+ let rawSteps = args.steps || args.actions;
234
+ let compiledSteps;
235
+ if (args.compile_from_history) {
236
+ const trail = getTrail();
237
+ const limit = args.history_limit ?? 20;
238
+ const slice = limit > 0 ? trail.slice(-limit) : trail;
239
+ compiledSteps = compileTraceToMacro(slice);
240
+ if (args.dry_run) {
241
+ return {
242
+ success: true,
243
+ steps_completed: 0,
244
+ results: [],
245
+ aborted: false,
246
+ compiled_steps: compiledSteps,
247
+ message: `compiled ${compiledSteps.length} macro steps from history`,
248
+ };
249
+ }
250
+ if (!rawSteps || rawSteps.length === 0) {
251
+ rawSteps = compiledSteps;
252
+ }
253
+ }
254
+ const normalized = normalizeRawSteps(rawSteps || []);
255
+ if (normalized.length === 0) {
256
+ return {
257
+ success: true,
258
+ steps_completed: 0,
259
+ results: [],
260
+ aborted: false,
261
+ compiled_steps: compiledSteps,
262
+ message: args.compile_from_history ? "no actionable steps found in history" : "no steps provided",
263
+ };
142
264
  }
143
- // Expand macro steps into primitive steps first
144
265
  const steps = [];
145
266
  const MACRO_TOOLS = new Set(["type_and_send", "navigate_and_read", "click_and_wait", "scroll_and_read", "fill_form", "drag_and_drop", "hover_and_read"]);
146
- for (const step of args.steps) {
267
+ for (const step of normalized) {
147
268
  if (MACRO_TOOLS.has(step.tool)) {
148
269
  steps.push(...expandMacro(step));
149
270
  }
150
271
  else {
151
272
  steps.push({
152
273
  tool: step.tool,
153
- args: JSON.parse(JSON.stringify(step.args || {}))
274
+ args: JSON.parse(JSON.stringify(step.args || {})),
154
275
  });
155
276
  }
156
277
  }
157
- const { batch } = args;
158
- // Inject fast: true if batch mode is on, unless explicitly set to false
278
+ const { batch, stop_on_error } = args;
279
+ const stopOnError = stop_on_error !== false;
159
280
  if (batch) {
160
281
  for (const step of steps) {
161
- if (step.args.fast === undefined) {
282
+ if (step.args.fast === undefined)
162
283
  step.args.fast = true;
163
- }
164
284
  }
165
285
  }
166
286
  const results = [];
167
287
  let stepsCompleted = 0;
168
- await sendToExtension(session, { type: 'Weavetab_STATE', hud: { action: `running ${steps.length} steps ${batch ? 'in batch' : 'in sequence'}...` } });
288
+ await sendToExtension(session, {
289
+ type: 'Weavetab_STATE',
290
+ hud: { action: `running ${steps.length} steps ${batch ? 'in batch' : 'in sequence'}...` },
291
+ });
169
292
  resetLoopCounter("burst");
170
293
  for (let i = 0; i < steps.length; i++) {
171
294
  const step = steps[i];
@@ -180,7 +303,8 @@ export async function browserBurst(session, args, config) {
180
303
  result = await weaveType(session, step.args, config);
181
304
  break;
182
305
  case "browser_go":
183
- result = await weaveNavigate(session, step.args.url, config);
306
+ case "browser_navigate":
307
+ result = await weaveNavigate(session, step.args.url, config, undefined, false, false, args.app);
184
308
  break;
185
309
  case "browser_key":
186
310
  result = await weaveKey(session, step.args, config);
@@ -192,7 +316,7 @@ export async function browserBurst(session, args, config) {
192
316
  result = await browserWait(session, step.args, config);
193
317
  break;
194
318
  case "browser_map": {
195
- const mapTargetId = sessionRegistry.getActive(getConfigAgentId(config))?.targetId || "default";
319
+ const mapTargetId = sessionRegistry.getActive(getConfigAgentId(config), args.app)?.targetId || "default";
196
320
  result = await browserMap(session, step.args, mapTargetId, config);
197
321
  break;
198
322
  }
@@ -207,7 +331,7 @@ export async function browserBurst(session, args, config) {
207
331
  break;
208
332
  case "browser_console": {
209
333
  let targetId = "default";
210
- const active = sessionRegistry.getActive(getConfigAgentId(config));
334
+ const active = sessionRegistry.getActive(getConfigAgentId(config), args.app);
211
335
  if (active)
212
336
  targetId = active.targetId;
213
337
  result = await browserConsole(session, step.args, config, targetId);
@@ -219,9 +343,6 @@ export async function browserBurst(session, args, config) {
219
343
  case "browser_fill":
220
344
  result = await browserFill(session, step.args, config);
221
345
  break;
222
- case "browser_navigate":
223
- result = await weaveNavigate(session, step.args.url, config);
224
- break;
225
346
  case "browser_type_secret":
226
347
  result = await weaveTypeSecret(session, step.args, config);
227
348
  break;
@@ -307,38 +428,74 @@ export async function browserBurst(session, args, config) {
307
428
  results.push({ step: i + 1, tool: step.tool, success: false, error: stepError });
308
429
  stepsCompleted++;
309
430
  logAction("browser_burst", `step_${i + 1}`, `error: ${stepError}`);
431
+ if (stopOnError) {
432
+ await sendToExtension(session, { type: 'Weavetab_STATE', hud: { action: '' } });
433
+ return {
434
+ success: false,
435
+ steps_completed: stepsCompleted,
436
+ results,
437
+ aborted: true,
438
+ abort_reason: `halted on step ${i + 1} (${step.tool}): ${stepError}`,
439
+ compiled_steps: compiledSteps,
440
+ };
441
+ }
310
442
  continue;
311
443
  }
312
444
  const resultObj = result && typeof result === "object" ? result : {};
313
445
  const isError = resultObj.success === false;
446
+ const errDetail = resultObj.message || resultObj.stuck_hint || undefined;
314
447
  results.push({
315
448
  step: i + 1,
316
449
  tool: step.tool,
317
450
  success: !isError,
318
451
  result: isError ? undefined : result,
319
- error: isError ? resultObj.message || resultObj.stuck_hint || undefined : undefined,
452
+ error: isError ? errDetail : undefined,
320
453
  });
321
454
  stepsCompleted++;
455
+ if (isError && stopOnError) {
456
+ logAction("browser_burst", `step_${i + 1}`, `halted on error: ${errDetail}`);
457
+ await sendToExtension(session, { type: 'Weavetab_STATE', hud: { action: '' } });
458
+ return {
459
+ success: false,
460
+ steps_completed: stepsCompleted,
461
+ results,
462
+ aborted: true,
463
+ abort_reason: `halted on step ${i + 1} (${step.tool}): ${errDetail ?? "action failed"}`,
464
+ compiled_steps: compiledSteps,
465
+ };
466
+ }
322
467
  }
323
468
  catch (err) {
324
- logAction("browser_burst", `step_${i + 1}`, `exception: ${err?.message ?? err}`);
325
- results.push({ step: i + 1, tool: step.tool, success: false, error: `Exception: ${err?.message ?? String(err)}` });
469
+ const errMsg = err?.message ?? String(err);
470
+ logAction("browser_burst", `step_${i + 1}`, `exception: ${errMsg}`);
471
+ results.push({ step: i + 1, tool: step.tool, success: false, error: `Exception: ${errMsg}` });
326
472
  stepsCompleted++;
473
+ if (stopOnError) {
474
+ await sendToExtension(session, { type: 'Weavetab_STATE', hud: { action: '' } });
475
+ return {
476
+ success: false,
477
+ steps_completed: stepsCompleted,
478
+ results,
479
+ aborted: true,
480
+ abort_reason: `exception on step ${i + 1} (${step.tool}): ${errMsg}`,
481
+ compiled_steps: compiledSteps,
482
+ };
483
+ }
327
484
  }
328
485
  logAction("browser_burst", `step_${i + 1}/${steps.length}`, step.tool);
329
486
  }
330
- // If batch was used, update cache once at the end
331
487
  if (batch) {
332
488
  const targetId = sessionRegistry.getActive(getConfigAgentId(config))?.targetId || "default";
333
489
  const map = await buildActionMap(session, { lite: true }, targetId);
334
490
  cacheActionMap(targetId, map);
335
491
  }
336
492
  await sendToExtension(session, { type: 'Weavetab_STATE', hud: { action: '' } });
337
- const anySuccess = results.some(r => r.success);
493
+ const allPassed = results.length > 0 && results.every(r => r.success);
338
494
  return {
339
- success: anySuccess,
495
+ success: allPassed,
340
496
  steps_completed: stepsCompleted,
341
497
  results,
342
498
  aborted: false,
499
+ compiled_steps: compiledSteps,
343
500
  };
344
501
  }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Weavetab — tools/checkpoint.ts
3
+ * browser_checkpoint: Session time-travel and rollback.
4
+ *
5
+ * Captures and restores named checkpoints of browser state:
6
+ * - Cookies (HttpOnly and Secure via CDP Network)
7
+ * - LocalStorage & SessionStorage
8
+ * - URL, page title, and viewport scroll position
9
+ * - Optional lightweight DOM snapshot
10
+ *
11
+ * Saves tokens and time when trial-and-error automation branches fail.
12
+ *
13
+ * Weavetab by fy2ne
14
+ */
15
+ import CDP from "chrome-remote-interface";
16
+ import type { Config } from "../config/loader.js";
17
+ export interface CheckpointData {
18
+ name: string;
19
+ url: string;
20
+ title: string;
21
+ timestamp: string;
22
+ cookies: any[];
23
+ localStorage: Record<string, string>;
24
+ sessionStorage: Record<string, string>;
25
+ scroll?: {
26
+ x: number;
27
+ y: number;
28
+ };
29
+ domSnapshot?: string;
30
+ }
31
+ export interface CheckpointArgs {
32
+ action: "save" | "restore" | "list" | "delete";
33
+ name?: string;
34
+ includeDom?: boolean;
35
+ }
36
+ export declare function getCheckpointsForTarget(targetId: string): Map<string, CheckpointData>;
37
+ export declare function clearAllCheckpoints(): void;
38
+ export declare function browserCheckpoint(session: CDP.Client, args: CheckpointArgs, config: Config): Promise<any>;