lsd-pi 1.3.2 → 1.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2 -1
- package/dist/lsd-settings-manager.d.ts +2 -0
- package/dist/lsd-settings-manager.js +5 -0
- package/dist/resource-loader.js +33 -3
- package/dist/resources/extensions/browser-tools/tools/codegen.js +5 -5
- package/dist/resources/extensions/browser-tools/tools/navigation.js +107 -178
- package/dist/resources/extensions/browser-tools/tools/network-mock.js +112 -167
- package/dist/resources/extensions/browser-tools/tools/pages.js +182 -234
- package/dist/resources/extensions/browser-tools/tools/refs.js +202 -461
- package/dist/resources/extensions/browser-tools/tools/session.js +176 -323
- package/dist/resources/extensions/browser-tools/tools/state-persistence.js +91 -154
- package/dist/resources/extensions/browser-tools/utils.js +1 -1
- package/dist/resources/extensions/cache-timer/index.js +3 -2
- package/dist/resources/extensions/slash-commands/extension-manifest.json +2 -2
- package/dist/resources/extensions/slash-commands/fast.js +73 -0
- package/dist/resources/extensions/slash-commands/index.js +2 -0
- package/dist/resources/extensions/slash-commands/plan.js +37 -12
- package/dist/resources/extensions/subagent/background-job-manager.js +13 -0
- package/dist/resources/extensions/subagent/in-process-runner.js +387 -0
- package/dist/resources/extensions/subagent/index.js +278 -626
- package/dist/resources/extensions/subagent/legacy-runner.js +503 -0
- package/dist/resources/extensions/voice/index.js +96 -36
- package/dist/resources/extensions/voice/push-to-talk.js +26 -0
- package/dist/welcome-screen.js +2 -2
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +19 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +16 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/src/agent.ts +32 -2
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts +34 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +32 -4
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +127 -16
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts +8 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.js +67 -0
- package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/openai-responses.js +21 -3
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +2 -0
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +5 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +143 -20
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +47 -4
- package/packages/pi-ai/src/providers/openai-responses.fast-mode.test.ts +73 -0
- package/packages/pi-ai/src/providers/openai-responses.ts +26 -3
- package/packages/pi-ai/src/providers/simple-options.ts +2 -0
- package/packages/pi-ai/src/types.ts +5 -0
- package/packages/pi-coding-agent/dist/core/keybindings.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.js +2 -0
- package/packages/pi-coding-agent/dist/core/keybindings.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +4 -2
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.js +35 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.js +35 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js +24 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
- package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +6 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tool-priority.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.js +18 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.test.js +27 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.js +21 -0
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +16 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js +34 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.d.ts +45 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.js +314 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.js +122 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +7 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +86 -28
- package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +23 -10
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +8 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +52 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +19 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +127 -14
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts +14 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js +93 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js +328 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +123 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +7 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +9 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +103 -23
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +41 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +4 -4
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/keybindings.ts +4 -1
- package/packages/pi-coding-agent/src/core/sdk.ts +4 -2
- package/packages/pi-coding-agent/src/core/settings-manager.collapse-tool-calls.test.ts +46 -0
- package/packages/pi-coding-agent/src/core/settings-manager.fast-mode.test.ts +46 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +36 -0
- package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +6 -1
- package/packages/pi-coding-agent/src/core/tool-priority.test.ts +30 -0
- package/packages/pi-coding-agent/src/core/tool-priority.ts +17 -0
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +20 -0
- package/packages/pi-coding-agent/src/core/tools/edit-diff.ts +26 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-summary-line.test.ts +41 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/btw-overlay.test.ts +172 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/btw-overlay.ts +402 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +105 -28
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +21 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +63 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1262 -1138
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-summary-line.ts +120 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.ts +396 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +530 -398
- package/packages/pi-coding-agent/src/modes/interactive/controllers/extension-ui-controller.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +7 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +4 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +109 -23
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +60 -1
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +4 -4
- package/packages/pi-tui/dist/components/editor.js +3 -3
- package/packages/pi-tui/dist/components/editor.js.map +1 -1
- package/packages/pi-tui/src/components/editor.ts +3 -3
- package/pkg/dist/modes/interactive/theme/themes.js +4 -4
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/tools/codegen.ts +5 -5
- package/src/resources/extensions/browser-tools/tools/navigation.ts +118 -196
- package/src/resources/extensions/browser-tools/tools/network-mock.ts +114 -205
- package/src/resources/extensions/browser-tools/tools/pages.ts +183 -237
- package/src/resources/extensions/browser-tools/tools/refs.ts +193 -507
- package/src/resources/extensions/browser-tools/tools/session.ts +182 -321
- package/src/resources/extensions/browser-tools/tools/state-persistence.ts +94 -172
- package/src/resources/extensions/browser-tools/utils.ts +1 -1
- package/src/resources/extensions/cache-timer/index.ts +3 -2
- package/src/resources/extensions/slash-commands/extension-manifest.json +2 -2
- package/src/resources/extensions/slash-commands/fast.ts +89 -0
- package/src/resources/extensions/slash-commands/index.ts +2 -0
- package/src/resources/extensions/slash-commands/plan.ts +42 -12
- package/src/resources/extensions/subagent/background-job-manager.ts +28 -0
- package/src/resources/extensions/subagent/in-process-runner.ts +534 -0
- package/src/resources/extensions/subagent/index.ts +489 -799
- package/src/resources/extensions/subagent/legacy-runner.ts +607 -0
- package/src/resources/extensions/voice/index.ts +308 -238
- package/src/resources/extensions/voice/push-to-talk.ts +42 -0
- package/src/resources/extensions/voice/tests/push-to-talk.test.ts +109 -0
|
@@ -16,360 +16,213 @@ export function registerSessionTools(pi, deps) {
|
|
|
16
16
|
async execute(_toolCallId, _params, _signal, _onUpdate, _ctx) {
|
|
17
17
|
try {
|
|
18
18
|
await deps.closeBrowser();
|
|
19
|
-
return {
|
|
20
|
-
content: [{ type: "text", text: "Browser closed." }],
|
|
21
|
-
details: {},
|
|
22
|
-
};
|
|
19
|
+
return { content: [{ type: "text", text: "Browser closed." }], details: {} };
|
|
23
20
|
}
|
|
24
21
|
catch (err) {
|
|
25
|
-
return {
|
|
26
|
-
content: [{ type: "text", text: `Close failed: ${err.message}` }],
|
|
27
|
-
details: { error: err.message },
|
|
28
|
-
isError: true,
|
|
29
|
-
};
|
|
22
|
+
return { content: [{ type: "text", text: `Close failed: ${err.message}` }], details: { error: err.message }, isError: true };
|
|
30
23
|
}
|
|
31
24
|
},
|
|
32
25
|
});
|
|
33
26
|
// -------------------------------------------------------------------------
|
|
34
|
-
//
|
|
27
|
+
// browser_trace — start, stop, export HAR
|
|
35
28
|
// -------------------------------------------------------------------------
|
|
36
29
|
pi.registerTool({
|
|
37
|
-
name: "
|
|
38
|
-
label: "Browser Trace
|
|
39
|
-
description: "
|
|
30
|
+
name: "browser_trace",
|
|
31
|
+
label: "Browser Trace",
|
|
32
|
+
description: "Manage Playwright tracing and HAR export: start/stop traces, export session HAR. " +
|
|
33
|
+
"Traces capture screenshots, snapshots, and sources for debugging.",
|
|
40
34
|
parameters: Type.Object({
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
action: Type.Union([
|
|
36
|
+
Type.Literal("start"),
|
|
37
|
+
Type.Literal("stop"),
|
|
38
|
+
Type.Literal("export_har"),
|
|
39
|
+
], { description: "'start' — begin trace, 'stop' — end trace and save, 'export_har' — export network HAR" }),
|
|
40
|
+
name: Type.Optional(Type.String({ description: "Name for the trace file or HAR export." })),
|
|
41
|
+
title: Type.Optional(Type.String({ description: "Trace title (start action only)." })),
|
|
43
42
|
}),
|
|
44
43
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
45
44
|
try {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (activeTrace) {
|
|
49
|
-
return {
|
|
50
|
-
content: [{ type: "text", text: `Trace already active: ${activeTrace.name}` }],
|
|
51
|
-
details: { error: "trace_already_active", activeTraceSession: activeTrace, ...deps.getSessionArtifactMetadata() },
|
|
52
|
-
isError: true,
|
|
53
|
-
};
|
|
45
|
+
if (params.action === "start") {
|
|
46
|
+
return await traceStart(params);
|
|
54
47
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
await browserContext.tracing.start({ screenshots: true, snapshots: true, sources: true, title: params.title ?? name });
|
|
58
|
-
setActiveTraceSession({ startedAt, name, title: params.title ?? name });
|
|
59
|
-
return {
|
|
60
|
-
content: [{ type: "text", text: `Trace started: ${name}\nSession dir: ${getSessionArtifactDir()}` }],
|
|
61
|
-
details: { activeTraceSession: getActiveTraceSession(), ...deps.getSessionArtifactMetadata() },
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
catch (err) {
|
|
65
|
-
return {
|
|
66
|
-
content: [{ type: "text", text: `Trace start failed: ${err.message}` }],
|
|
67
|
-
details: { error: err.message, ...deps.getSessionArtifactMetadata() },
|
|
68
|
-
isError: true,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
// -------------------------------------------------------------------------
|
|
74
|
-
// browser_trace_stop
|
|
75
|
-
// -------------------------------------------------------------------------
|
|
76
|
-
pi.registerTool({
|
|
77
|
-
name: "browser_trace_stop",
|
|
78
|
-
label: "Browser Trace Stop",
|
|
79
|
-
description: "Stop the active Playwright trace and write the trace zip to disk under the session artifact directory.",
|
|
80
|
-
parameters: Type.Object({
|
|
81
|
-
name: Type.Optional(Type.String({ description: "Optional artifact basename override for the trace zip." })),
|
|
82
|
-
}),
|
|
83
|
-
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
84
|
-
try {
|
|
85
|
-
const { context: browserContext } = await deps.ensureBrowser();
|
|
86
|
-
const activeTrace = getActiveTraceSession();
|
|
87
|
-
if (!activeTrace) {
|
|
88
|
-
return {
|
|
89
|
-
content: [{ type: "text", text: "No active trace session to stop." }],
|
|
90
|
-
details: { error: "trace_not_active", ...deps.getSessionArtifactMetadata() },
|
|
91
|
-
isError: true,
|
|
92
|
-
};
|
|
48
|
+
else if (params.action === "stop") {
|
|
49
|
+
return await traceStop(params);
|
|
93
50
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const tracePath = deps.buildSessionArtifactPath(`${traceName}.trace.zip`);
|
|
97
|
-
await browserContext.tracing.stop({ path: tracePath });
|
|
98
|
-
const fileStat = await stat(tracePath);
|
|
99
|
-
setActiveTraceSession(null);
|
|
100
|
-
return {
|
|
101
|
-
content: [{ type: "text", text: `Trace stopped: ${tracePath}` }],
|
|
102
|
-
details: {
|
|
103
|
-
path: tracePath,
|
|
104
|
-
bytes: fileStat.size,
|
|
105
|
-
elapsedMs: Date.now() - traceSession.startedAt,
|
|
106
|
-
traceName,
|
|
107
|
-
...deps.getSessionArtifactMetadata(),
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
catch (err) {
|
|
112
|
-
return {
|
|
113
|
-
content: [{ type: "text", text: `Trace stop failed: ${err.message}` }],
|
|
114
|
-
details: { error: err.message, ...deps.getSessionArtifactMetadata() },
|
|
115
|
-
isError: true,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
// -------------------------------------------------------------------------
|
|
121
|
-
// browser_export_har
|
|
122
|
-
// -------------------------------------------------------------------------
|
|
123
|
-
pi.registerTool({
|
|
124
|
-
name: "browser_export_har",
|
|
125
|
-
label: "Browser Export HAR",
|
|
126
|
-
description: "Export the truthfully recorded session HAR from disk to a stable artifact path and return compact metadata.",
|
|
127
|
-
parameters: Type.Object({
|
|
128
|
-
filename: Type.Optional(Type.String({ description: "Optional destination filename within the session artifact directory." })),
|
|
129
|
-
}),
|
|
130
|
-
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
131
|
-
try {
|
|
132
|
-
await deps.ensureBrowser();
|
|
133
|
-
const harState = getHarState();
|
|
134
|
-
if (!harState.enabled || !harState.configuredAtContextCreation || !harState.path) {
|
|
135
|
-
return {
|
|
136
|
-
content: [{ type: "text", text: "HAR export unavailable: HAR recording was not enabled at browser context creation." }],
|
|
137
|
-
details: { error: "har_not_enabled", ...deps.getSessionArtifactMetadata() },
|
|
138
|
-
isError: true,
|
|
139
|
-
};
|
|
51
|
+
else {
|
|
52
|
+
return await exportHar({ filename: params.name });
|
|
140
53
|
}
|
|
141
|
-
const sourcePath = harState.path;
|
|
142
|
-
const destinationName = (params.filename?.trim() || `export-${HAR_FILENAME}`).replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
143
|
-
const destinationPath = deps.buildSessionArtifactPath(destinationName);
|
|
144
|
-
const exportResult = sourcePath === destinationPath
|
|
145
|
-
? { path: sourcePath, bytes: (await stat(sourcePath)).size }
|
|
146
|
-
: await deps.copyArtifactFile(sourcePath, destinationPath);
|
|
147
|
-
setHarState({
|
|
148
|
-
...harState,
|
|
149
|
-
exportCount: harState.exportCount + 1,
|
|
150
|
-
lastExportedPath: exportResult.path,
|
|
151
|
-
lastExportedAt: Date.now(),
|
|
152
|
-
});
|
|
153
|
-
return {
|
|
154
|
-
content: [{ type: "text", text: `HAR exported: ${exportResult.path}` }],
|
|
155
|
-
details: { path: exportResult.path, bytes: exportResult.bytes, ...deps.getSessionArtifactMetadata() },
|
|
156
|
-
};
|
|
157
54
|
}
|
|
158
55
|
catch (err) {
|
|
159
|
-
return {
|
|
160
|
-
content: [{ type: "text", text: `HAR export failed: ${err.message}` }],
|
|
161
|
-
details: { error: err.message, ...deps.getSessionArtifactMetadata() },
|
|
162
|
-
isError: true,
|
|
163
|
-
};
|
|
56
|
+
return { content: [{ type: "text", text: `Trace '${params.action}' failed: ${err.message}` }], details: { error: err.message, ...deps.getSessionArtifactMetadata() }, isError: true };
|
|
164
57
|
}
|
|
165
58
|
},
|
|
166
59
|
});
|
|
167
60
|
// -------------------------------------------------------------------------
|
|
168
|
-
//
|
|
61
|
+
// browser_debug — timeline, session summary, debug bundle
|
|
169
62
|
// -------------------------------------------------------------------------
|
|
170
63
|
pi.registerTool({
|
|
171
|
-
name: "
|
|
172
|
-
label: "Browser
|
|
173
|
-
description: "
|
|
64
|
+
name: "browser_debug",
|
|
65
|
+
label: "Browser Debug",
|
|
66
|
+
description: "Browser session introspection: view action timeline, session summary, or write a full debug bundle to disk. " +
|
|
67
|
+
"Use for debugging failing tests or complex browser interactions.",
|
|
174
68
|
parameters: Type.Object({
|
|
175
|
-
|
|
176
|
-
|
|
69
|
+
action: Type.Union([
|
|
70
|
+
Type.Literal("timeline"),
|
|
71
|
+
Type.Literal("summary"),
|
|
72
|
+
Type.Literal("bundle"),
|
|
73
|
+
], { description: "'timeline' — action history, 'summary' — session overview, 'bundle' — write full debug bundle to disk" }),
|
|
74
|
+
writeToDisk: Type.Optional(Type.Boolean({ description: "Write timeline JSON to disk (timeline action)." })),
|
|
75
|
+
filename: Type.Optional(Type.String({ description: "Filename for timeline/bundle output." })),
|
|
76
|
+
selector: Type.Optional(Type.String({ description: "CSS selector scope for accessibility snapshot (bundle action)." })),
|
|
77
|
+
name: Type.Optional(Type.String({ description: "Bundle name suffix (bundle action)." })),
|
|
177
78
|
}),
|
|
178
79
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
179
80
|
try {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const filename = (params.filename?.trim() || "timeline.json").replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
189
|
-
artifact = await deps.writeArtifactFile(deps.buildSessionArtifactPath(filename), JSON.stringify(timeline, null, 2));
|
|
81
|
+
if (params.action === "timeline") {
|
|
82
|
+
return await timelineAction(params);
|
|
83
|
+
}
|
|
84
|
+
else if (params.action === "summary") {
|
|
85
|
+
return await summaryAction();
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
return await bundleAction(params);
|
|
190
89
|
}
|
|
191
|
-
return {
|
|
192
|
-
content: [{ type: "text", text: artifact ? `${timeline.summary}\nArtifact: ${artifact.path}` : timeline.summary }],
|
|
193
|
-
details: { ...timeline, artifact, ...deps.getSessionArtifactMetadata() },
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
catch (err) {
|
|
197
|
-
return {
|
|
198
|
-
content: [{ type: "text", text: `Timeline failed: ${err.message}` }],
|
|
199
|
-
details: { error: err.message, ...deps.getSessionArtifactMetadata() },
|
|
200
|
-
isError: true,
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
},
|
|
204
|
-
});
|
|
205
|
-
// -------------------------------------------------------------------------
|
|
206
|
-
// browser_session_summary
|
|
207
|
-
// -------------------------------------------------------------------------
|
|
208
|
-
pi.registerTool({
|
|
209
|
-
name: "browser_session_summary",
|
|
210
|
-
label: "Browser Session Summary",
|
|
211
|
-
description: "Return a compact structured summary of the current browser session, including pages, actions, waits/assertions, bounded-history caveats, and trace/HAR state.",
|
|
212
|
-
parameters: Type.Object({}),
|
|
213
|
-
async execute(_toolCallId, _params, _signal, _onUpdate, _ctx) {
|
|
214
|
-
try {
|
|
215
|
-
await deps.ensureBrowser();
|
|
216
|
-
const pages = await deps.getLivePagesSnapshot();
|
|
217
|
-
const actionTimeline = getActionTimeline();
|
|
218
|
-
const pageRegistry = getPageRegistry();
|
|
219
|
-
const consoleLogs = getConsoleLogs();
|
|
220
|
-
const networkLogs = getNetworkLogs();
|
|
221
|
-
const dialogLogs = getDialogLogs();
|
|
222
|
-
const baseSummary = summarizeBrowserSession({
|
|
223
|
-
timeline: actionTimeline,
|
|
224
|
-
totalActions: actionTimeline.nextId - 1,
|
|
225
|
-
pages,
|
|
226
|
-
activePageId: pageRegistry.activePageId,
|
|
227
|
-
activeFrame: getActiveFrameMetadata(),
|
|
228
|
-
consoleEntries: consoleLogs,
|
|
229
|
-
networkEntries: networkLogs,
|
|
230
|
-
dialogEntries: dialogLogs,
|
|
231
|
-
consoleLimit: 1000,
|
|
232
|
-
networkLimit: 1000,
|
|
233
|
-
dialogLimit: 1000,
|
|
234
|
-
sessionStartedAt: getSessionStartedAt(),
|
|
235
|
-
now: Date.now(),
|
|
236
|
-
});
|
|
237
|
-
const failureHypothesis = buildFailureHypothesis({
|
|
238
|
-
timeline: actionTimeline,
|
|
239
|
-
consoleEntries: consoleLogs,
|
|
240
|
-
networkEntries: networkLogs,
|
|
241
|
-
dialogEntries: dialogLogs,
|
|
242
|
-
});
|
|
243
|
-
const activeTrace = getActiveTraceSession();
|
|
244
|
-
const traceState = activeTrace
|
|
245
|
-
? { status: "active", ...activeTrace }
|
|
246
|
-
: { status: "inactive", lastTracePath: getSessionArtifactDir() ? deps.buildSessionArtifactPath("*.trace.zip") : null };
|
|
247
|
-
const harState = getHarState();
|
|
248
|
-
const harSummary = {
|
|
249
|
-
enabled: harState.enabled,
|
|
250
|
-
configuredAtContextCreation: harState.configuredAtContextCreation,
|
|
251
|
-
path: harState.path,
|
|
252
|
-
exportCount: harState.exportCount,
|
|
253
|
-
lastExportedPath: harState.lastExportedPath,
|
|
254
|
-
lastExportedAt: harState.lastExportedAt,
|
|
255
|
-
};
|
|
256
|
-
return {
|
|
257
|
-
content: [{ type: "text", text: `${baseSummary.summary}\nFailure hypothesis: ${failureHypothesis}` }],
|
|
258
|
-
details: {
|
|
259
|
-
...baseSummary,
|
|
260
|
-
failureHypothesis,
|
|
261
|
-
trace: traceState,
|
|
262
|
-
har: harSummary,
|
|
263
|
-
...deps.getSessionArtifactMetadata(),
|
|
264
|
-
},
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
catch (err) {
|
|
268
|
-
return {
|
|
269
|
-
content: [{ type: "text", text: `Session summary failed: ${err.message}` }],
|
|
270
|
-
details: { error: err.message, ...deps.getSessionArtifactMetadata() },
|
|
271
|
-
isError: true,
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
},
|
|
275
|
-
});
|
|
276
|
-
// -------------------------------------------------------------------------
|
|
277
|
-
// browser_debug_bundle
|
|
278
|
-
// -------------------------------------------------------------------------
|
|
279
|
-
pi.registerTool({
|
|
280
|
-
name: "browser_debug_bundle",
|
|
281
|
-
label: "Browser Debug Bundle",
|
|
282
|
-
description: "Write a timestamped debug bundle to disk with screenshot, logs, timeline, pages, session summary, and accessibility output, then return compact paths and counts.",
|
|
283
|
-
parameters: Type.Object({
|
|
284
|
-
selector: Type.Optional(Type.String({ description: "Optional CSS selector to scope the accessibility snapshot before fallback behavior applies." })),
|
|
285
|
-
name: Type.Optional(Type.String({ description: "Optional short bundle name suffix for the output directory." })),
|
|
286
|
-
}),
|
|
287
|
-
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
288
|
-
try {
|
|
289
|
-
const { page: p } = await deps.ensureBrowser();
|
|
290
|
-
const startedAt = Date.now();
|
|
291
|
-
const sessionDir = await deps.ensureSessionArtifactDir();
|
|
292
|
-
const bundleDir = path.join(ARTIFACT_ROOT, `${deps.formatArtifactTimestamp(startedAt)}-${deps.sanitizeArtifactName(params.name ?? "debug-bundle", "debug-bundle")}`);
|
|
293
|
-
await ensureDir(bundleDir);
|
|
294
|
-
const pages = await deps.getLivePagesSnapshot();
|
|
295
|
-
const actionTimeline = getActionTimeline();
|
|
296
|
-
const pageRegistry = getPageRegistry();
|
|
297
|
-
const consoleLogs = getConsoleLogs();
|
|
298
|
-
const networkLogs = getNetworkLogs();
|
|
299
|
-
const dialogLogs = getDialogLogs();
|
|
300
|
-
const timeline = formatTimelineEntries(actionTimeline.entries, {
|
|
301
|
-
limit: actionTimeline.limit,
|
|
302
|
-
totalActions: actionTimeline.nextId - 1,
|
|
303
|
-
});
|
|
304
|
-
const sessionSummary = summarizeBrowserSession({
|
|
305
|
-
timeline: actionTimeline,
|
|
306
|
-
totalActions: actionTimeline.nextId - 1,
|
|
307
|
-
pages,
|
|
308
|
-
activePageId: pageRegistry.activePageId,
|
|
309
|
-
activeFrame: getActiveFrameMetadata(),
|
|
310
|
-
consoleEntries: consoleLogs,
|
|
311
|
-
networkEntries: networkLogs,
|
|
312
|
-
dialogEntries: dialogLogs,
|
|
313
|
-
consoleLimit: 1000,
|
|
314
|
-
networkLimit: 1000,
|
|
315
|
-
dialogLimit: 1000,
|
|
316
|
-
sessionStartedAt: getSessionStartedAt(),
|
|
317
|
-
now: Date.now(),
|
|
318
|
-
});
|
|
319
|
-
const failureHypothesis = buildFailureHypothesis({
|
|
320
|
-
timeline: actionTimeline,
|
|
321
|
-
consoleEntries: consoleLogs,
|
|
322
|
-
networkEntries: networkLogs,
|
|
323
|
-
dialogEntries: dialogLogs,
|
|
324
|
-
});
|
|
325
|
-
const accessibility = await deps.captureAccessibilityMarkdown(params.selector);
|
|
326
|
-
const screenshotPath = path.join(bundleDir, "screenshot.jpg");
|
|
327
|
-
await p.screenshot({ path: screenshotPath, type: "jpeg", quality: 80, fullPage: false });
|
|
328
|
-
const screenshotStat = await stat(screenshotPath);
|
|
329
|
-
const artifacts = {
|
|
330
|
-
screenshot: { path: screenshotPath, bytes: screenshotStat.size },
|
|
331
|
-
console: await deps.writeArtifactFile(path.join(bundleDir, "console.json"), JSON.stringify(consoleLogs, null, 2)),
|
|
332
|
-
network: await deps.writeArtifactFile(path.join(bundleDir, "network.json"), JSON.stringify(networkLogs, null, 2)),
|
|
333
|
-
dialog: await deps.writeArtifactFile(path.join(bundleDir, "dialog.json"), JSON.stringify(dialogLogs, null, 2)),
|
|
334
|
-
timeline: await deps.writeArtifactFile(path.join(bundleDir, "timeline.json"), JSON.stringify(timeline, null, 2)),
|
|
335
|
-
summary: await deps.writeArtifactFile(path.join(bundleDir, "summary.json"), JSON.stringify({
|
|
336
|
-
...sessionSummary,
|
|
337
|
-
failureHypothesis,
|
|
338
|
-
trace: getActiveTraceSession(),
|
|
339
|
-
har: getHarState(),
|
|
340
|
-
sessionArtifactDir: sessionDir,
|
|
341
|
-
}, null, 2)),
|
|
342
|
-
pages: await deps.writeArtifactFile(path.join(bundleDir, "pages.json"), JSON.stringify(pages, null, 2)),
|
|
343
|
-
accessibility: await deps.writeArtifactFile(path.join(bundleDir, "accessibility.md"), accessibility.snapshot),
|
|
344
|
-
};
|
|
345
|
-
return {
|
|
346
|
-
content: [{ type: "text", text: `Debug bundle written: ${bundleDir}\n${sessionSummary.summary}\nFailure hypothesis: ${failureHypothesis}` }],
|
|
347
|
-
details: {
|
|
348
|
-
bundleDir,
|
|
349
|
-
artifacts,
|
|
350
|
-
accessibilityScope: accessibility.scope,
|
|
351
|
-
accessibilitySource: accessibility.source,
|
|
352
|
-
counts: {
|
|
353
|
-
console: consoleLogs.length,
|
|
354
|
-
network: networkLogs.length,
|
|
355
|
-
dialog: dialogLogs.length,
|
|
356
|
-
actions: timeline.retained,
|
|
357
|
-
pages: pages.length,
|
|
358
|
-
},
|
|
359
|
-
elapsedMs: Date.now() - startedAt,
|
|
360
|
-
summary: sessionSummary,
|
|
361
|
-
failureHypothesis,
|
|
362
|
-
...deps.getSessionArtifactMetadata(),
|
|
363
|
-
},
|
|
364
|
-
};
|
|
365
90
|
}
|
|
366
91
|
catch (err) {
|
|
367
|
-
return {
|
|
368
|
-
content: [{ type: "text", text: `Debug bundle failed: ${err.message}` }],
|
|
369
|
-
details: { error: err.message, ...deps.getSessionArtifactMetadata() },
|
|
370
|
-
isError: true,
|
|
371
|
-
};
|
|
92
|
+
return { content: [{ type: "text", text: `Debug '${params.action}' failed: ${err.message}` }], details: { error: err.message, ...deps.getSessionArtifactMetadata() }, isError: true };
|
|
372
93
|
}
|
|
373
94
|
},
|
|
374
95
|
});
|
|
96
|
+
// ── trace helpers ──
|
|
97
|
+
async function traceStart(params) {
|
|
98
|
+
const { context: browserContext } = await deps.ensureBrowser();
|
|
99
|
+
const activeTrace = getActiveTraceSession();
|
|
100
|
+
if (activeTrace) {
|
|
101
|
+
return { content: [{ type: "text", text: `Trace already active: ${activeTrace.name}` }], details: { error: "trace_already_active", ...deps.getSessionArtifactMetadata() }, isError: true };
|
|
102
|
+
}
|
|
103
|
+
const startedAt = Date.now();
|
|
104
|
+
const name = (params.name?.trim() || `trace-${deps.formatArtifactTimestamp(startedAt)}`).replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
105
|
+
await browserContext.tracing.start({ screenshots: true, snapshots: true, sources: true, title: params.title ?? name });
|
|
106
|
+
setActiveTraceSession({ startedAt, name, title: params.title ?? name });
|
|
107
|
+
return {
|
|
108
|
+
content: [{ type: "text", text: `Trace started: ${name}\nSession dir: ${getSessionArtifactDir()}` }],
|
|
109
|
+
details: { activeTraceSession: getActiveTraceSession(), ...deps.getSessionArtifactMetadata() },
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async function traceStop(params) {
|
|
113
|
+
const { context: browserContext } = await deps.ensureBrowser();
|
|
114
|
+
const activeTrace = getActiveTraceSession();
|
|
115
|
+
if (!activeTrace) {
|
|
116
|
+
return { content: [{ type: "text", text: "No active trace session." }], details: { error: "trace_not_active", ...deps.getSessionArtifactMetadata() }, isError: true };
|
|
117
|
+
}
|
|
118
|
+
const traceName = (params.name?.trim() || activeTrace.name).replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
119
|
+
const tracePath = deps.buildSessionArtifactPath(`${traceName}.trace.zip`);
|
|
120
|
+
await browserContext.tracing.stop({ path: tracePath });
|
|
121
|
+
const fileStat = await stat(tracePath);
|
|
122
|
+
setActiveTraceSession(null);
|
|
123
|
+
return {
|
|
124
|
+
content: [{ type: "text", text: `Trace stopped: ${tracePath}` }],
|
|
125
|
+
details: { path: tracePath, bytes: fileStat.size, elapsedMs: Date.now() - activeTrace.startedAt, traceName, ...deps.getSessionArtifactMetadata() },
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
async function exportHar(params) {
|
|
129
|
+
await deps.ensureBrowser();
|
|
130
|
+
const harState = getHarState();
|
|
131
|
+
if (!harState.enabled || !harState.configuredAtContextCreation || !harState.path) {
|
|
132
|
+
return { content: [{ type: "text", text: "HAR export unavailable: HAR recording was not enabled at context creation." }], details: { error: "har_not_enabled", ...deps.getSessionArtifactMetadata() }, isError: true };
|
|
133
|
+
}
|
|
134
|
+
const destinationName = (params.filename?.trim() || `export-${HAR_FILENAME}`).replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
135
|
+
const destinationPath = deps.buildSessionArtifactPath(destinationName);
|
|
136
|
+
const exportResult = harState.path === destinationPath
|
|
137
|
+
? { path: harState.path, bytes: (await stat(harState.path)).size }
|
|
138
|
+
: await deps.copyArtifactFile(harState.path, destinationPath);
|
|
139
|
+
setHarState({ ...harState, exportCount: harState.exportCount + 1, lastExportedPath: exportResult.path, lastExportedAt: Date.now() });
|
|
140
|
+
return {
|
|
141
|
+
content: [{ type: "text", text: `HAR exported: ${exportResult.path}` }],
|
|
142
|
+
details: { path: exportResult.path, bytes: exportResult.bytes, ...deps.getSessionArtifactMetadata() },
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// ── debug helpers ──
|
|
146
|
+
async function timelineAction(params) {
|
|
147
|
+
await deps.ensureBrowser();
|
|
148
|
+
const actionTimeline = getActionTimeline();
|
|
149
|
+
const timeline = formatTimelineEntries(actionTimeline.entries, { limit: actionTimeline.limit, totalActions: actionTimeline.nextId - 1 });
|
|
150
|
+
let artifact = null;
|
|
151
|
+
if (params.writeToDisk) {
|
|
152
|
+
const filename = (params.filename?.trim() || "timeline.json").replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
153
|
+
artifact = await deps.writeArtifactFile(deps.buildSessionArtifactPath(filename), JSON.stringify(timeline, null, 2));
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
content: [{ type: "text", text: artifact ? `${timeline.summary}\nArtifact: ${artifact.path}` : timeline.summary }],
|
|
157
|
+
details: { ...timeline, artifact, ...deps.getSessionArtifactMetadata() },
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
async function summaryAction() {
|
|
161
|
+
await deps.ensureBrowser();
|
|
162
|
+
const pages = await deps.getLivePagesSnapshot();
|
|
163
|
+
const actionTimeline = getActionTimeline();
|
|
164
|
+
const pageRegistry = getPageRegistry();
|
|
165
|
+
const consoleLogs = getConsoleLogs();
|
|
166
|
+
const networkLogs = getNetworkLogs();
|
|
167
|
+
const dialogLogs = getDialogLogs();
|
|
168
|
+
const baseSummary = summarizeBrowserSession({
|
|
169
|
+
timeline: actionTimeline, totalActions: actionTimeline.nextId - 1, pages,
|
|
170
|
+
activePageId: pageRegistry.activePageId, activeFrame: getActiveFrameMetadata(),
|
|
171
|
+
consoleEntries: consoleLogs, networkEntries: networkLogs, dialogEntries: dialogLogs,
|
|
172
|
+
consoleLimit: 1000, networkLimit: 1000, dialogLimit: 1000,
|
|
173
|
+
sessionStartedAt: getSessionStartedAt(), now: Date.now(),
|
|
174
|
+
});
|
|
175
|
+
const failureHypothesis = buildFailureHypothesis({ timeline: actionTimeline, consoleEntries: consoleLogs, networkEntries: networkLogs, dialogEntries: dialogLogs });
|
|
176
|
+
const activeTrace = getActiveTraceSession();
|
|
177
|
+
const traceState = activeTrace ? { status: "active", ...activeTrace } : { status: "inactive", lastTracePath: getSessionArtifactDir() ? deps.buildSessionArtifactPath("*.trace.zip") : null };
|
|
178
|
+
const harState = getHarState();
|
|
179
|
+
return {
|
|
180
|
+
content: [{ type: "text", text: `${baseSummary.summary}\nFailure hypothesis: ${failureHypothesis}` }],
|
|
181
|
+
details: { ...baseSummary, failureHypothesis, trace: traceState, har: { enabled: harState.enabled, exportCount: harState.exportCount }, ...deps.getSessionArtifactMetadata() },
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
async function bundleAction(params) {
|
|
185
|
+
const { page: p } = await deps.ensureBrowser();
|
|
186
|
+
const startedAt = Date.now();
|
|
187
|
+
const sessionDir = await deps.ensureSessionArtifactDir();
|
|
188
|
+
const bundleDir = path.join(ARTIFACT_ROOT, `${deps.formatArtifactTimestamp(startedAt)}-${deps.sanitizeArtifactName(params.name ?? "debug-bundle", "debug-bundle")}`);
|
|
189
|
+
await ensureDir(bundleDir);
|
|
190
|
+
const pages = await deps.getLivePagesSnapshot();
|
|
191
|
+
const actionTimeline = getActionTimeline();
|
|
192
|
+
const pageRegistry = getPageRegistry();
|
|
193
|
+
const consoleLogs = getConsoleLogs();
|
|
194
|
+
const networkLogs = getNetworkLogs();
|
|
195
|
+
const dialogLogs = getDialogLogs();
|
|
196
|
+
const timeline = formatTimelineEntries(actionTimeline.entries, { limit: actionTimeline.limit, totalActions: actionTimeline.nextId - 1 });
|
|
197
|
+
const sessionSummary = summarizeBrowserSession({
|
|
198
|
+
timeline: actionTimeline, totalActions: actionTimeline.nextId - 1, pages,
|
|
199
|
+
activePageId: pageRegistry.activePageId, activeFrame: getActiveFrameMetadata(),
|
|
200
|
+
consoleEntries: consoleLogs, networkEntries: networkLogs, dialogEntries: dialogLogs,
|
|
201
|
+
consoleLimit: 1000, networkLimit: 1000, dialogLimit: 1000,
|
|
202
|
+
sessionStartedAt: getSessionStartedAt(), now: Date.now(),
|
|
203
|
+
});
|
|
204
|
+
const failureHypothesis = buildFailureHypothesis({ timeline: actionTimeline, consoleEntries: consoleLogs, networkEntries: networkLogs, dialogEntries: dialogLogs });
|
|
205
|
+
const accessibility = await deps.captureAccessibilityMarkdown(params.selector);
|
|
206
|
+
const screenshotPath = path.join(bundleDir, "screenshot.jpg");
|
|
207
|
+
await p.screenshot({ path: screenshotPath, type: "jpeg", quality: 80, fullPage: false });
|
|
208
|
+
const screenshotStat = await stat(screenshotPath);
|
|
209
|
+
const artifacts = {
|
|
210
|
+
screenshot: { path: screenshotPath, bytes: screenshotStat.size },
|
|
211
|
+
console: await deps.writeArtifactFile(path.join(bundleDir, "console.json"), JSON.stringify(consoleLogs, null, 2)),
|
|
212
|
+
network: await deps.writeArtifactFile(path.join(bundleDir, "network.json"), JSON.stringify(networkLogs, null, 2)),
|
|
213
|
+
dialog: await deps.writeArtifactFile(path.join(bundleDir, "dialog.json"), JSON.stringify(dialogLogs, null, 2)),
|
|
214
|
+
timeline: await deps.writeArtifactFile(path.join(bundleDir, "timeline.json"), JSON.stringify(timeline, null, 2)),
|
|
215
|
+
summary: await deps.writeArtifactFile(path.join(bundleDir, "summary.json"), JSON.stringify({ ...sessionSummary, failureHypothesis, trace: getActiveTraceSession(), sessionArtifactDir: sessionDir }, null, 2)),
|
|
216
|
+
pages: await deps.writeArtifactFile(path.join(bundleDir, "pages.json"), JSON.stringify(pages, null, 2)),
|
|
217
|
+
accessibility: await deps.writeArtifactFile(path.join(bundleDir, "accessibility.md"), accessibility.snapshot),
|
|
218
|
+
};
|
|
219
|
+
return {
|
|
220
|
+
content: [{ type: "text", text: `Debug bundle written: ${bundleDir}\n${sessionSummary.summary}\nFailure hypothesis: ${failureHypothesis}` }],
|
|
221
|
+
details: {
|
|
222
|
+
bundleDir, artifacts, accessibilityScope: accessibility.scope, accessibilitySource: accessibility.source,
|
|
223
|
+
counts: { console: consoleLogs.length, network: networkLogs.length, dialog: dialogLogs.length, actions: timeline.retained, pages: pages.length },
|
|
224
|
+
elapsedMs: Date.now() - startedAt, summary: sessionSummary, failureHypothesis, ...deps.getSessionArtifactMetadata(),
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
375
228
|
}
|