@ai-agent-forge/agent-forge 0.88.4 → 0.88.6
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/CHANGELOG.md +30 -0
- package/bundled-plugins/agent-loop-policy/agent-forge.json +1 -1
- package/bundled-plugins/agent-loop-policy/plugin.json +1 -1
- package/bundled-plugins/alignment/agent-forge.json +19 -0
- package/bundled-plugins/alignment/dist/baseline.d.ts +12 -0
- package/bundled-plugins/alignment/dist/baseline.d.ts.map +1 -0
- package/bundled-plugins/alignment/dist/baseline.js +68 -0
- package/bundled-plugins/alignment/dist/baseline.js.map +1 -0
- package/bundled-plugins/alignment/dist/engine.d.ts +102 -0
- package/bundled-plugins/alignment/dist/engine.d.ts.map +1 -0
- package/bundled-plugins/alignment/dist/engine.js +654 -0
- package/bundled-plugins/alignment/dist/engine.js.map +1 -0
- package/bundled-plugins/alignment/dist/entry.d.ts +14 -0
- package/bundled-plugins/alignment/dist/entry.d.ts.map +1 -0
- package/bundled-plugins/alignment/dist/entry.js +23 -0
- package/bundled-plugins/alignment/dist/entry.js.map +1 -0
- package/bundled-plugins/alignment/dist/export.d.ts +15 -0
- package/bundled-plugins/alignment/dist/export.d.ts.map +1 -0
- package/bundled-plugins/alignment/dist/export.js +122 -0
- package/bundled-plugins/alignment/dist/export.js.map +1 -0
- package/bundled-plugins/alignment/dist/http-server.d.ts +33 -0
- package/bundled-plugins/alignment/dist/http-server.d.ts.map +1 -0
- package/bundled-plugins/alignment/dist/http-server.js +119 -0
- package/bundled-plugins/alignment/dist/http-server.js.map +1 -0
- package/bundled-plugins/alignment/dist/index.d.ts +24 -0
- package/bundled-plugins/alignment/dist/index.d.ts.map +1 -0
- package/bundled-plugins/alignment/dist/index.js +719 -0
- package/bundled-plugins/alignment/dist/index.js.map +1 -0
- package/bundled-plugins/alignment/dist/page.d.ts +15 -0
- package/bundled-plugins/alignment/dist/page.d.ts.map +1 -0
- package/bundled-plugins/alignment/dist/page.js +832 -0
- package/bundled-plugins/alignment/dist/page.js.map +1 -0
- package/bundled-plugins/alignment/dist/render.d.ts +40 -0
- package/bundled-plugins/alignment/dist/render.d.ts.map +1 -0
- package/bundled-plugins/alignment/dist/render.js +194 -0
- package/bundled-plugins/alignment/dist/render.js.map +1 -0
- package/bundled-plugins/alignment/dist/types.d.ts +217 -0
- package/bundled-plugins/alignment/dist/types.d.ts.map +1 -0
- package/bundled-plugins/alignment/dist/types.js +30 -0
- package/bundled-plugins/alignment/dist/types.js.map +1 -0
- package/bundled-plugins/alignment/plugin.json +12 -0
- package/bundled-plugins/browser-playwright/MANUAL.md +60 -0
- package/bundled-plugins/browser-playwright/agent-forge.json +25 -0
- package/bundled-plugins/browser-playwright/dist/capability.d.ts +25 -0
- package/bundled-plugins/browser-playwright/dist/capability.d.ts.map +1 -0
- package/bundled-plugins/browser-playwright/dist/capability.js +612 -0
- package/bundled-plugins/browser-playwright/dist/capability.js.map +1 -0
- package/bundled-plugins/browser-playwright/dist/entry.d.ts +13 -0
- package/bundled-plugins/browser-playwright/dist/entry.d.ts.map +1 -0
- package/bundled-plugins/browser-playwright/dist/entry.js +14 -0
- package/bundled-plugins/browser-playwright/dist/entry.js.map +1 -0
- package/bundled-plugins/browser-playwright/dist/index.d.ts +7 -0
- package/bundled-plugins/browser-playwright/dist/index.d.ts.map +1 -0
- package/bundled-plugins/browser-playwright/dist/index.js +5 -0
- package/bundled-plugins/browser-playwright/dist/index.js.map +1 -0
- package/bundled-plugins/browser-playwright/dist/operations.d.ts +69 -0
- package/bundled-plugins/browser-playwright/dist/operations.d.ts.map +1 -0
- package/bundled-plugins/browser-playwright/dist/operations.js +149 -0
- package/bundled-plugins/browser-playwright/dist/operations.js.map +1 -0
- package/bundled-plugins/browser-playwright/dist/playwright-driver.d.ts +275 -0
- package/bundled-plugins/browser-playwright/dist/playwright-driver.d.ts.map +1 -0
- package/bundled-plugins/browser-playwright/dist/playwright-driver.js +953 -0
- package/bundled-plugins/browser-playwright/dist/playwright-driver.js.map +1 -0
- package/bundled-plugins/browser-playwright/dist/setup.d.ts +88 -0
- package/bundled-plugins/browser-playwright/dist/setup.d.ts.map +1 -0
- package/bundled-plugins/browser-playwright/dist/setup.js +252 -0
- package/bundled-plugins/browser-playwright/dist/setup.js.map +1 -0
- package/bundled-plugins/browser-playwright/dist/types.d.ts +270 -0
- package/bundled-plugins/browser-playwright/dist/types.d.ts.map +1 -0
- package/bundled-plugins/browser-playwright/dist/types.js +2 -0
- package/bundled-plugins/browser-playwright/dist/types.js.map +1 -0
- package/bundled-plugins/browser-playwright/plugin.json +20 -0
- package/bundled-plugins/coding-tools/agent-forge.json +1 -1
- package/bundled-plugins/coding-tools/dist/bash.d.ts +2 -7
- package/bundled-plugins/coding-tools/dist/bash.d.ts.map +1 -1
- package/bundled-plugins/coding-tools/dist/bash.js +2 -34
- package/bundled-plugins/coding-tools/dist/bash.js.map +1 -1
- package/bundled-plugins/coding-tools/plugin.json +1 -1
- package/bundled-plugins/compaction-policy/agent-forge.json +1 -1
- package/bundled-plugins/compaction-policy/plugin.json +1 -1
- package/bundled-plugins/mcp-http/dist/mcp-http.d.ts.map +1 -1
- package/bundled-plugins/mcp-http/dist/mcp-http.js +84 -31
- package/bundled-plugins/mcp-http/dist/mcp-http.js.map +1 -1
- package/bundled-plugins/overflow-policy/agent-forge.json +1 -1
- package/bundled-plugins/overflow-policy/plugin.json +1 -1
- package/bundled-plugins/provider-failover/agent-forge.json +1 -1
- package/bundled-plugins/provider-failover/plugin.json +1 -1
- package/bundled-plugins/retry-policy/agent-forge.json +1 -1
- package/bundled-plugins/retry-policy/plugin.json +1 -1
- package/dist/bundle/.build-manifest.json +60 -58
- package/dist/bundle/chunks/{anthropic-messages-3FJHRAJL.js → anthropic-messages-NL4Y6WPB.js} +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-GCL47IDS.js → azure-openai-responses-CPXC42HO.js} +1 -1
- package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
- package/dist/bundle/chunks/chunk-5LRQFZFE.js +2 -0
- package/dist/bundle/chunks/{chunk-HTEVUY7F.js → chunk-7HSJPQKN.js} +1 -1
- package/dist/bundle/chunks/{chunk-AC2FIS4G.js → chunk-EDO7Q6XR.js} +1 -1
- package/dist/bundle/chunks/{chunk-755VNWIF.js → chunk-ISLHFRER.js} +6 -6
- package/dist/bundle/chunks/{chunk-HV64ASMT.js → chunk-K3S6GTL7.js} +1 -1
- package/dist/bundle/chunks/{chunk-HEL6TAWE.js → chunk-POLDAUYA.js} +37 -36
- package/dist/bundle/chunks/{chunk-V3ACW7VD.js → chunk-WJSKB3FC.js} +1 -1
- package/dist/bundle/chunks/{chunk-32YDZI4J.js → chunk-ZS5JEI76.js} +1 -1
- package/dist/bundle/chunks/{google-generative-ai-6BMXWA44.js → google-generative-ai-UMZ53EFA.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-6H7NLRTK.js → google-vertex-ZNR5NS6H.js} +1 -1
- package/dist/bundle/chunks/image-resize-worker.js +1 -1
- package/dist/bundle/chunks/{mistral-conversations-IXUHSFSJ.js → mistral-conversations-IT66WUNN.js} +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-YHUAEVCM.js → openai-codex-responses-FOVCVG6I.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-ULQCFC72.js → openai-completions-FLQ7CBOL.js} +1 -1
- package/dist/bundle/chunks/{openai-responses-NLLAJDPS.js → openai-responses-ABGYHS2T.js} +1 -1
- package/dist/bundle/chunks/{pi-messages-EJTI2EJ3.js → pi-messages-6K5W6LUN.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-TQWEGNNZ.js → virtual-modules-2QGILFV7.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/client.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/client/remote-session.d.ts.map +1 -1
- package/dist/client/remote-session.js +65 -6
- package/dist/client/remote-session.js.map +1 -1
- package/dist/core/agent-session-store.d.ts.map +1 -1
- package/dist/core/agent-session-store.js +20 -3
- package/dist/core/agent-session-store.js.map +1 -1
- package/dist/core/extensions/agent-composition.d.ts.map +1 -1
- package/dist/core/extensions/agent-composition.js +20 -1
- package/dist/core/extensions/agent-composition.js.map +1 -1
- package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -1
- package/dist/core/i18n/locales/zh-cn/core-errors.js +1 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -1
- package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -1
- package/dist/core/i18n/locales/zh-cn/interactive-mode.js +10 -3
- package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -1
- package/dist/core/keybindings.d.ts +35 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +34 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +62 -15
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +11 -3
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +2 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/capability-mount.d.ts.map +1 -1
- package/dist/core/tools/capability-mount.js +4 -21
- package/dist/core/tools/capability-mount.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +2 -2
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +2 -0
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +25 -0
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/changelog-pager.d.ts +53 -0
- package/dist/modes/interactive/components/changelog-pager.d.ts.map +1 -0
- package/dist/modes/interactive/components/changelog-pager.js +239 -0
- package/dist/modes/interactive/components/changelog-pager.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +6 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +12 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-run-group.d.ts +41 -11
- package/dist/modes/interactive/components/tool-run-group.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-run-group.js +126 -14
- package/dist/modes/interactive/components/tool-run-group.js.map +1 -1
- package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-commands.js +23 -13
- package/dist/modes/interactive/interactive-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-events.d.ts +14 -4
- package/dist/modes/interactive/interactive-events.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-events.js +94 -12
- package/dist/modes/interactive/interactive-events.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +6 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +21 -5
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/plugins/ecosystem/node-local-package-source.d.ts +2 -1
- package/dist/plugins/ecosystem/node-local-package-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-local-package-source.js +110 -4
- package/dist/plugins/ecosystem/node-local-package-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-host.js +106 -39
- package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-bootstrap.js +59 -2
- package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
- package/dist/suites/builtin-suites.d.ts.map +1 -1
- package/dist/suites/builtin-suites.js +2 -2
- package/dist/suites/builtin-suites.js.map +1 -1
- package/dist/utils/changelog.d.ts +27 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +110 -0
- package/dist/utils/changelog.js.map +1 -1
- package/docs/keybindings.md +14 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/extensions/with-deps/plugin.json +1 -1
- package/package.json +1 -1
- package/dist/bundle/chunks/chunk-A3JYRWB6.js +0 -2
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser capability factory: registers the seventeen browser tools on a
|
|
3
|
+
* `CapabilityAPI` and shapes every result as `PluginResultV1`.
|
|
4
|
+
*
|
|
5
|
+
* Tool surface: `browser_navigate`, `browser_snapshot`, `browser_locator_action`
|
|
6
|
+
* (click/dblclick/rightclick/fill/type/press/hover/select/check/uncheck/clear/
|
|
7
|
+
* upload/scroll), `browser_assert_postcondition`, `browser_collect_evidence`,
|
|
8
|
+
* the self-installing `browser_setup`, plus the prewritten operation tools
|
|
9
|
+
* `browser_evaluate` (escape hatch), `browser_console`, `browser_network`,
|
|
10
|
+
* `browser_performance`, `browser_wait`, `browser_drag`, `browser_mouse`,
|
|
11
|
+
* `browser_press_key`, `browser_tabs`, `browser_storage`, and
|
|
12
|
+
* `browser_viewport`. The readonly mode registers only the observation-only
|
|
13
|
+
* tools (`snapshot`, `assert_postcondition`, `collect_evidence`, `console`,
|
|
14
|
+
* `network`, `performance`, `wait`); everything that changes browser or disk
|
|
15
|
+
* state never registers there.
|
|
16
|
+
*
|
|
17
|
+
* All browser state lives behind the injected `BrowserRuntimeV1`; the factory
|
|
18
|
+
* itself has no Playwright knowledge. Error messages are sanitized like the
|
|
19
|
+
* pre-split capability: URLs collapse to origin + pathname (<=512) and the
|
|
20
|
+
* total message stays within 2048 chars.
|
|
21
|
+
*/
|
|
22
|
+
import { buildPluginResultV1, } from "@agent-forge/plugin-sdk";
|
|
23
|
+
import { Type } from "typebox";
|
|
24
|
+
import { boundedPreviewV1 } from "./setup.js";
|
|
25
|
+
function objectInput(first, second) {
|
|
26
|
+
const value = second === undefined ? first : second;
|
|
27
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
28
|
+
throw new Error("Plugin tool input must be an object");
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
function toolInvocation(first, second) {
|
|
33
|
+
return {
|
|
34
|
+
input: objectInput(first, second),
|
|
35
|
+
operationId: typeof first === "string" && first.trim() !== "" ? first : "profile-runtime-tool-call",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function signalFrom(value) {
|
|
39
|
+
return value instanceof AbortSignal ? value : undefined;
|
|
40
|
+
}
|
|
41
|
+
function nonEmptyString(value, label) {
|
|
42
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
43
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
function requiredInteger(value, label) {
|
|
47
|
+
if (typeof value !== "number" || !Number.isInteger(value))
|
|
48
|
+
throw new Error(`${label} must be an integer`);
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
/** URL-sanitized, 2048-char bounded error text (pre-split browser contract). */
|
|
52
|
+
function browserVisibleError(value) {
|
|
53
|
+
const raw = value instanceof Error && value.message.trim() !== "" ? value.message : "Browser operation failed";
|
|
54
|
+
const sanitized = raw.replace(/https?:\/\/[^\s"'<>]+/giu, (candidate) => {
|
|
55
|
+
try {
|
|
56
|
+
const parsed = new URL(candidate);
|
|
57
|
+
return `${parsed.origin}${parsed.pathname.slice(0, 512)}`;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return candidate.slice(0, 512);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return sanitized.length > 2048 ? `${sanitized.slice(0, 2047)}…` : sanitized;
|
|
64
|
+
}
|
|
65
|
+
function browserAbort(value) {
|
|
66
|
+
if (value instanceof Error && value.name === "AbortError")
|
|
67
|
+
return true;
|
|
68
|
+
return typeof value === "object" && value !== null && value.code === "ABORT_ERR";
|
|
69
|
+
}
|
|
70
|
+
const browserLocatorSchema = Type.Object({
|
|
71
|
+
kind: Type.Union([
|
|
72
|
+
Type.Literal("css"),
|
|
73
|
+
Type.Literal("id"),
|
|
74
|
+
Type.Literal("role"),
|
|
75
|
+
Type.Literal("text"),
|
|
76
|
+
Type.Literal("test-id"),
|
|
77
|
+
]),
|
|
78
|
+
value: Type.String({ minLength: 1 }),
|
|
79
|
+
name: Type.Optional(Type.String()),
|
|
80
|
+
});
|
|
81
|
+
const browserMouseActionSchema = Type.Union([
|
|
82
|
+
Type.Literal("move"),
|
|
83
|
+
Type.Literal("click"),
|
|
84
|
+
Type.Literal("dblclick"),
|
|
85
|
+
Type.Literal("rightclick"),
|
|
86
|
+
Type.Literal("wheel"),
|
|
87
|
+
]);
|
|
88
|
+
const browserMouseButtonSchema = Type.Union([Type.Literal("left"), Type.Literal("right"), Type.Literal("middle")]);
|
|
89
|
+
const browserTabsActionSchema = Type.Union([
|
|
90
|
+
Type.Literal("list"),
|
|
91
|
+
Type.Literal("new"),
|
|
92
|
+
Type.Literal("switch"),
|
|
93
|
+
Type.Literal("close"),
|
|
94
|
+
]);
|
|
95
|
+
const browserStorageActionSchema = Type.Union([
|
|
96
|
+
Type.Literal("get-cookies"),
|
|
97
|
+
Type.Literal("set-cookie"),
|
|
98
|
+
Type.Literal("clear-cookies"),
|
|
99
|
+
Type.Literal("get-local"),
|
|
100
|
+
Type.Literal("set-local"),
|
|
101
|
+
Type.Literal("clear-local"),
|
|
102
|
+
]);
|
|
103
|
+
const browserViewportActionSchema = Type.Union([Type.Literal("set"), Type.Literal("get")]);
|
|
104
|
+
const browserWaitUntilKindSchema = Type.Union([
|
|
105
|
+
Type.Literal("selector"),
|
|
106
|
+
Type.Literal("navigation"),
|
|
107
|
+
Type.Literal("networkidle"),
|
|
108
|
+
Type.Literal("time"),
|
|
109
|
+
]);
|
|
110
|
+
const browserConsoleLevelSchema = Type.String({
|
|
111
|
+
pattern: "^(error|warning|info|debug)(,(error|warning|info|debug))*$",
|
|
112
|
+
});
|
|
113
|
+
const browserPostconditionSchema = Type.Union([
|
|
114
|
+
Type.Object({
|
|
115
|
+
kind: Type.Literal("url"),
|
|
116
|
+
equals: Type.String({ minLength: 1 }),
|
|
117
|
+
contains: Type.Optional(Type.String({ minLength: 1 })),
|
|
118
|
+
}),
|
|
119
|
+
Type.Object({
|
|
120
|
+
kind: Type.Literal("url"),
|
|
121
|
+
equals: Type.Optional(Type.String({ minLength: 1 })),
|
|
122
|
+
contains: Type.String({ minLength: 1 }),
|
|
123
|
+
}),
|
|
124
|
+
Type.Object({
|
|
125
|
+
kind: Type.Literal("element"),
|
|
126
|
+
locator: browserLocatorSchema,
|
|
127
|
+
state: Type.Union([Type.Literal("visible"), Type.Literal("hidden"), Type.Literal("value")]),
|
|
128
|
+
value: Type.Optional(Type.String()),
|
|
129
|
+
}),
|
|
130
|
+
Type.Object({
|
|
131
|
+
kind: Type.Literal("text"),
|
|
132
|
+
locator: Type.Optional(browserLocatorSchema),
|
|
133
|
+
contains: Type.String({ minLength: 1 }),
|
|
134
|
+
}),
|
|
135
|
+
Type.Object({
|
|
136
|
+
kind: Type.Literal("console"),
|
|
137
|
+
contains: Type.String({ minLength: 1 }),
|
|
138
|
+
level: Type.Optional(Type.String()),
|
|
139
|
+
}),
|
|
140
|
+
Type.Object({
|
|
141
|
+
kind: Type.Literal("network"),
|
|
142
|
+
containsUrl: Type.String({ minLength: 1 }),
|
|
143
|
+
status: Type.Optional(Type.Integer({ minimum: 100, maximum: 599 })),
|
|
144
|
+
}),
|
|
145
|
+
]);
|
|
146
|
+
const browserPostconditionInputSchema = Type.Union([
|
|
147
|
+
browserPostconditionSchema,
|
|
148
|
+
Type.Array(browserPostconditionSchema, { minItems: 1, maxItems: 32 }),
|
|
149
|
+
]);
|
|
150
|
+
function setupResult(operationId, outcome) {
|
|
151
|
+
if (!outcome.ok) {
|
|
152
|
+
return buildPluginResultV1({
|
|
153
|
+
version: 1,
|
|
154
|
+
operationId,
|
|
155
|
+
status: "failed",
|
|
156
|
+
summary: "Playwright browser dependency setup failed",
|
|
157
|
+
artifacts: [],
|
|
158
|
+
evidence: [],
|
|
159
|
+
error: {
|
|
160
|
+
version: 1,
|
|
161
|
+
code: "browser_setup_failed",
|
|
162
|
+
message: boundedPreviewV1(outcome.message, 8192),
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return buildPluginResultV1({
|
|
167
|
+
version: 1,
|
|
168
|
+
operationId,
|
|
169
|
+
status: "succeeded",
|
|
170
|
+
summary: outcome.alreadyInstalled
|
|
171
|
+
? "Playwright browser dependencies are already installed"
|
|
172
|
+
: "Playwright browser dependencies installed",
|
|
173
|
+
artifacts: [],
|
|
174
|
+
evidence: [
|
|
175
|
+
{
|
|
176
|
+
version: 1,
|
|
177
|
+
evidenceId: `${operationId}-evidence-1`,
|
|
178
|
+
kind: "log",
|
|
179
|
+
operationId,
|
|
180
|
+
summary: outcome.log.trim() === "" ? "(no output)" : boundedPreviewV1(outcome.log, 4096),
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
verification: {
|
|
184
|
+
version: 1,
|
|
185
|
+
status: "passed",
|
|
186
|
+
checks: [outcome.alreadyInstalled ? "playwright-already-installed" : "playwright-install-completed"],
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
export function createBrowserCapabilityFactoryV1(runtime) {
|
|
191
|
+
return (api) => {
|
|
192
|
+
const readonlyMode = api.host.mode === "readonly";
|
|
193
|
+
let session;
|
|
194
|
+
const connect = () => {
|
|
195
|
+
if (session === undefined)
|
|
196
|
+
session = runtime.connect();
|
|
197
|
+
return session;
|
|
198
|
+
};
|
|
199
|
+
const withSession = async (operationId, action) => {
|
|
200
|
+
let active;
|
|
201
|
+
try {
|
|
202
|
+
active = await connect();
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
session = undefined;
|
|
206
|
+
return buildPluginResultV1({
|
|
207
|
+
version: 1,
|
|
208
|
+
operationId,
|
|
209
|
+
status: browserAbort(error) ? "cancelled" : "failed",
|
|
210
|
+
summary: "Browser session connection failed",
|
|
211
|
+
artifacts: [],
|
|
212
|
+
evidence: [],
|
|
213
|
+
error: {
|
|
214
|
+
version: 1,
|
|
215
|
+
code: browserAbort(error) ? "cancelled" : "browser_connection_failed",
|
|
216
|
+
message: browserAbort(error) ? "Browser operation was cancelled" : browserVisibleError(error),
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
return await action(active);
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
return buildPluginResultV1({
|
|
225
|
+
version: 1,
|
|
226
|
+
operationId,
|
|
227
|
+
status: browserAbort(error) ? "cancelled" : "failed",
|
|
228
|
+
summary: "Browser operation failed",
|
|
229
|
+
artifacts: [],
|
|
230
|
+
evidence: [],
|
|
231
|
+
error: {
|
|
232
|
+
version: 1,
|
|
233
|
+
code: browserAbort(error) ? "cancelled" : "browser_operation_failed",
|
|
234
|
+
message: browserAbort(error) ? "Browser operation was cancelled" : browserVisibleError(error),
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const operationOptions = (operationId, third) => ({
|
|
240
|
+
operationId,
|
|
241
|
+
...(signalFrom(third) === undefined ? {} : { signal: signalFrom(third) }),
|
|
242
|
+
});
|
|
243
|
+
const registrations = [];
|
|
244
|
+
if (!readonlyMode) {
|
|
245
|
+
registrations.push(api.registerTool({
|
|
246
|
+
name: "browser_navigate",
|
|
247
|
+
label: "Browser navigate",
|
|
248
|
+
description: "Navigate the active browser session and return structured verification evidence. Requires Playwright in <agentDir>/browser-deps; when missing, run browser_setup or follow the returned install commands",
|
|
249
|
+
parameters: Type.Object({
|
|
250
|
+
url: Type.String({ minLength: 1 }),
|
|
251
|
+
waitUntil: Type.Optional(Type.Union([
|
|
252
|
+
Type.Literal("commit"),
|
|
253
|
+
Type.Literal("domcontentloaded"),
|
|
254
|
+
Type.Literal("load"),
|
|
255
|
+
Type.Literal("networkidle"),
|
|
256
|
+
])),
|
|
257
|
+
}),
|
|
258
|
+
execute: async (first, second, third) => {
|
|
259
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
260
|
+
return withSession(operationId, (active) => active.navigate({
|
|
261
|
+
url: nonEmptyString(input.url, "url"),
|
|
262
|
+
...(input.waitUntil === undefined
|
|
263
|
+
? {}
|
|
264
|
+
: { waitUntil: input.waitUntil }),
|
|
265
|
+
}, operationOptions(operationId, third)));
|
|
266
|
+
},
|
|
267
|
+
}));
|
|
268
|
+
}
|
|
269
|
+
registrations.push(api.registerTool({
|
|
270
|
+
name: "browser_snapshot",
|
|
271
|
+
label: "Browser snapshot",
|
|
272
|
+
description: "Capture accessibility, DOM, or screenshot evidence from the active browser session (styles capture is not supported in this build)",
|
|
273
|
+
parameters: Type.Object({
|
|
274
|
+
includeDom: Type.Optional(Type.Boolean()),
|
|
275
|
+
includeA11y: Type.Optional(Type.Boolean()),
|
|
276
|
+
includeStyles: Type.Optional(Type.Boolean()),
|
|
277
|
+
includeScreenshot: Type.Optional(Type.Boolean()),
|
|
278
|
+
}),
|
|
279
|
+
execute: async (first, second, third) => {
|
|
280
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
281
|
+
return withSession(operationId, (active) => active.snapshot(input, operationOptions(operationId, third)));
|
|
282
|
+
},
|
|
283
|
+
}));
|
|
284
|
+
if (!readonlyMode) {
|
|
285
|
+
registrations.push(api.registerTool({
|
|
286
|
+
name: "browser_locator_action",
|
|
287
|
+
label: "Browser locator action",
|
|
288
|
+
description: "Perform a locator-based browser action (click/dblclick/rightclick/fill/type/press/hover/select/check/uncheck/clear/upload/scroll) and return post-action accessibility evidence",
|
|
289
|
+
parameters: Type.Object({
|
|
290
|
+
locator: browserLocatorSchema,
|
|
291
|
+
action: Type.Union([
|
|
292
|
+
Type.Literal("click"),
|
|
293
|
+
Type.Literal("dblclick"),
|
|
294
|
+
Type.Literal("rightclick"),
|
|
295
|
+
Type.Literal("fill"),
|
|
296
|
+
Type.Literal("type"),
|
|
297
|
+
Type.Literal("press"),
|
|
298
|
+
Type.Literal("hover"),
|
|
299
|
+
Type.Literal("select"),
|
|
300
|
+
Type.Literal("check"),
|
|
301
|
+
Type.Literal("uncheck"),
|
|
302
|
+
Type.Literal("clear"),
|
|
303
|
+
Type.Literal("upload"),
|
|
304
|
+
Type.Literal("scroll"),
|
|
305
|
+
]),
|
|
306
|
+
value: Type.Optional(Type.String({ maxLength: 4096 })),
|
|
307
|
+
key: Type.Optional(Type.String({ maxLength: 128 })),
|
|
308
|
+
delay: Type.Optional(Type.Integer({ minimum: 0, maximum: 60_000 })),
|
|
309
|
+
}),
|
|
310
|
+
execute: async (first, second, third) => {
|
|
311
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
312
|
+
return withSession(operationId, (active) => active.locatorAction(input, operationOptions(operationId, third)));
|
|
313
|
+
},
|
|
314
|
+
}));
|
|
315
|
+
}
|
|
316
|
+
registrations.push(api.registerTool({
|
|
317
|
+
name: "browser_assert_postcondition",
|
|
318
|
+
label: "Browser assertion",
|
|
319
|
+
description: "Assert a URL, element, text, console, or network postcondition (single condition or an array of 1..32, all ANDed) without changing the browser",
|
|
320
|
+
parameters: Type.Object({
|
|
321
|
+
condition: browserPostconditionInputSchema,
|
|
322
|
+
}),
|
|
323
|
+
execute: async (first, second, third) => {
|
|
324
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
325
|
+
return withSession(operationId, (active) => active.assertPostcondition(input.condition, operationOptions(operationId, third)));
|
|
326
|
+
},
|
|
327
|
+
}));
|
|
328
|
+
registrations.push(api.registerTool({
|
|
329
|
+
name: "browser_collect_evidence",
|
|
330
|
+
label: "Browser evidence",
|
|
331
|
+
description: "Collect console, network, or accessibility-snapshot evidence from the active browser session without changing it",
|
|
332
|
+
parameters: Type.Object({
|
|
333
|
+
kind: Type.Union([Type.Literal("console"), Type.Literal("network"), Type.Literal("snapshot")]),
|
|
334
|
+
}),
|
|
335
|
+
execute: async (first, second, third) => {
|
|
336
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
337
|
+
const kind = input.kind;
|
|
338
|
+
if (kind !== "console" && kind !== "network" && kind !== "snapshot") {
|
|
339
|
+
throw new Error("kind must be console, network, or snapshot");
|
|
340
|
+
}
|
|
341
|
+
return withSession(operationId, (active) => active.collectEvidence(kind, operationOptions(operationId, third)));
|
|
342
|
+
},
|
|
343
|
+
}));
|
|
344
|
+
registrations.push(api.registerTool({
|
|
345
|
+
name: "browser_console",
|
|
346
|
+
label: "Browser console",
|
|
347
|
+
description: "Read the bounded console ring buffer (page messages plus auto-accepted [dialog] traces) with optional level/contains filters, without changing the browser",
|
|
348
|
+
parameters: Type.Object({
|
|
349
|
+
level: Type.Optional(browserConsoleLevelSchema),
|
|
350
|
+
contains: Type.Optional(Type.String({ minLength: 1 })),
|
|
351
|
+
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 200 })),
|
|
352
|
+
}),
|
|
353
|
+
execute: async (first, second, third) => {
|
|
354
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
355
|
+
return withSession(operationId, (active) => active.consoleEntries({
|
|
356
|
+
...(typeof input.level === "string" ? { level: input.level } : {}),
|
|
357
|
+
...(typeof input.contains === "string" ? { contains: input.contains } : {}),
|
|
358
|
+
...(typeof input.limit === "number" ? { limit: input.limit } : {}),
|
|
359
|
+
}, operationOptions(operationId, third)));
|
|
360
|
+
},
|
|
361
|
+
}), api.registerTool({
|
|
362
|
+
name: "browser_network",
|
|
363
|
+
label: "Browser network",
|
|
364
|
+
description: "Read the bounded network ring buffer (method/url/status/duration/size when available) with optional containsUrl/status/method filters, without changing the browser",
|
|
365
|
+
parameters: Type.Object({
|
|
366
|
+
containsUrl: Type.Optional(Type.String({ minLength: 1 })),
|
|
367
|
+
status: Type.Optional(Type.Integer({ minimum: 100, maximum: 599 })),
|
|
368
|
+
method: Type.Optional(Type.String({ minLength: 1, maxLength: 16 })),
|
|
369
|
+
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 200 })),
|
|
370
|
+
}),
|
|
371
|
+
execute: async (first, second, third) => {
|
|
372
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
373
|
+
return withSession(operationId, (active) => active.networkEntries({
|
|
374
|
+
...(typeof input.containsUrl === "string" ? { containsUrl: input.containsUrl } : {}),
|
|
375
|
+
...(typeof input.status === "number" ? { status: input.status } : {}),
|
|
376
|
+
...(typeof input.method === "string" ? { method: input.method } : {}),
|
|
377
|
+
...(typeof input.limit === "number" ? { limit: input.limit } : {}),
|
|
378
|
+
}, operationOptions(operationId, third)));
|
|
379
|
+
},
|
|
380
|
+
}), api.registerTool({
|
|
381
|
+
name: "browser_performance",
|
|
382
|
+
label: "Browser performance",
|
|
383
|
+
description: "Read structured page performance metrics (Navigation Timing, paint, resource summary, DOM node count) without changing the browser",
|
|
384
|
+
parameters: Type.Object({}),
|
|
385
|
+
execute: async (first, second, third) => {
|
|
386
|
+
const { operationId } = toolInvocation(first, second);
|
|
387
|
+
return withSession(operationId, (active) => active.performance(operationOptions(operationId, third)));
|
|
388
|
+
},
|
|
389
|
+
}), api.registerTool({
|
|
390
|
+
name: "browser_wait",
|
|
391
|
+
label: "Browser wait",
|
|
392
|
+
description: "Wait until a selector is visible, navigation completes, the network goes idle, or a fixed time passes (max 30s) and report the actual wait duration",
|
|
393
|
+
parameters: Type.Object({
|
|
394
|
+
until: browserWaitUntilKindSchema,
|
|
395
|
+
locator: Type.Optional(browserLocatorSchema),
|
|
396
|
+
ms: Type.Optional(Type.Integer({ minimum: 0, maximum: 30_000 })),
|
|
397
|
+
}),
|
|
398
|
+
execute: async (first, second, third) => {
|
|
399
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
400
|
+
const until = input.until;
|
|
401
|
+
if (until !== "selector" && until !== "navigation" && until !== "networkidle" && until !== "time") {
|
|
402
|
+
throw new Error("until must be selector, navigation, networkidle, or time");
|
|
403
|
+
}
|
|
404
|
+
return withSession(operationId, (active) => active.wait({
|
|
405
|
+
until,
|
|
406
|
+
...(until === "selector" ? { locator: input.locator } : {}),
|
|
407
|
+
...(typeof input.ms === "number" ? { ms: input.ms } : {}),
|
|
408
|
+
}, operationOptions(operationId, third)));
|
|
409
|
+
},
|
|
410
|
+
}));
|
|
411
|
+
if (!readonlyMode) {
|
|
412
|
+
registrations.push(api.registerTool({
|
|
413
|
+
name: "browser_evaluate",
|
|
414
|
+
label: "Browser evaluate",
|
|
415
|
+
description: "Escape hatch: evaluate a JavaScript expression in the page context and return the JSON-serialized result (bounded 64KiB, 30s timeout; dialogs are auto-accepted). Keep it a plain expression; for multi-statement logic use an IIFE string like ((() => { ... return x; })()) — a bare () => ... arrow string is not invoked and yields undefined. Only use this when no built-in browser tool covers the operation",
|
|
416
|
+
parameters: Type.Object({
|
|
417
|
+
expression: Type.String({ minLength: 1, maxLength: 32_768 }),
|
|
418
|
+
arg: Type.Optional(Type.Unknown()),
|
|
419
|
+
}),
|
|
420
|
+
execute: async (first, second, third) => {
|
|
421
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
422
|
+
return withSession(operationId, (active) => active.evaluate({
|
|
423
|
+
expression: nonEmptyString(input.expression, "expression"),
|
|
424
|
+
...(input.arg === undefined ? {} : { arg: input.arg }),
|
|
425
|
+
}, operationOptions(operationId, third)));
|
|
426
|
+
},
|
|
427
|
+
}), api.registerTool({
|
|
428
|
+
name: "browser_drag",
|
|
429
|
+
label: "Browser drag",
|
|
430
|
+
description: "Drag from one element to another (hover source, press, hover target, stepped move to target center, release)",
|
|
431
|
+
parameters: Type.Object({
|
|
432
|
+
from: browserLocatorSchema,
|
|
433
|
+
to: browserLocatorSchema,
|
|
434
|
+
steps: Type.Optional(Type.Integer({ minimum: 1, maximum: 100 })),
|
|
435
|
+
}),
|
|
436
|
+
execute: async (first, second, third) => {
|
|
437
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
438
|
+
return withSession(operationId, (active) => active.drag({
|
|
439
|
+
from: input.from,
|
|
440
|
+
to: input.to,
|
|
441
|
+
...(typeof input.steps === "number" ? { steps: input.steps } : {}),
|
|
442
|
+
}, operationOptions(operationId, third)));
|
|
443
|
+
},
|
|
444
|
+
}), api.registerTool({
|
|
445
|
+
name: "browser_mouse",
|
|
446
|
+
label: "Browser mouse",
|
|
447
|
+
description: "Raw mouse actions at viewport coordinates without needing an element (move/click/dblclick/rightclick/wheel); wheel is the basic page-scroll primitive",
|
|
448
|
+
parameters: Type.Object({
|
|
449
|
+
action: browserMouseActionSchema,
|
|
450
|
+
x: Type.Integer({ minimum: 0 }),
|
|
451
|
+
y: Type.Integer({ minimum: 0 }),
|
|
452
|
+
deltaX: Type.Optional(Type.Integer({ minimum: -100_000, maximum: 100_000 })),
|
|
453
|
+
deltaY: Type.Optional(Type.Integer({ minimum: -100_000, maximum: 100_000 })),
|
|
454
|
+
button: Type.Optional(browserMouseButtonSchema),
|
|
455
|
+
}),
|
|
456
|
+
execute: async (first, second, third) => {
|
|
457
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
458
|
+
return withSession(operationId, (active) => active.mouse({
|
|
459
|
+
action: input.action,
|
|
460
|
+
x: requiredInteger(input.x, "x"),
|
|
461
|
+
y: requiredInteger(input.y, "y"),
|
|
462
|
+
...(typeof input.deltaX === "number" ? { deltaX: input.deltaX } : {}),
|
|
463
|
+
...(typeof input.deltaY === "number" ? { deltaY: input.deltaY } : {}),
|
|
464
|
+
...(input.button === undefined ? {} : { button: input.button }),
|
|
465
|
+
}, operationOptions(operationId, third)));
|
|
466
|
+
},
|
|
467
|
+
}), api.registerTool({
|
|
468
|
+
name: "browser_press_key",
|
|
469
|
+
label: "Browser press key",
|
|
470
|
+
description: "Press a page-level key combination by Playwright key name (e.g. Control+a, Enter, Meta+c) without needing an element",
|
|
471
|
+
parameters: Type.Object({
|
|
472
|
+
key: Type.String({ minLength: 1, maxLength: 128 }),
|
|
473
|
+
delay: Type.Optional(Type.Integer({ minimum: 0, maximum: 60_000 })),
|
|
474
|
+
}),
|
|
475
|
+
execute: async (first, second, third) => {
|
|
476
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
477
|
+
return withSession(operationId, (active) => active.pressKey({
|
|
478
|
+
key: nonEmptyString(input.key, "key"),
|
|
479
|
+
...(typeof input.delay === "number" ? { delay: input.delay } : {}),
|
|
480
|
+
}, operationOptions(operationId, third)));
|
|
481
|
+
},
|
|
482
|
+
}), api.registerTool({
|
|
483
|
+
name: "browser_tabs",
|
|
484
|
+
label: "Browser tabs",
|
|
485
|
+
description: "Manage browser tabs: list (title/url/index), new (optional url), switch by index, or close by index",
|
|
486
|
+
parameters: Type.Object({
|
|
487
|
+
action: browserTabsActionSchema,
|
|
488
|
+
index: Type.Optional(Type.Integer({ minimum: 0 })),
|
|
489
|
+
url: Type.Optional(Type.String({ minLength: 1, maxLength: 4096 })),
|
|
490
|
+
}),
|
|
491
|
+
execute: async (first, second, third) => {
|
|
492
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
493
|
+
return withSession(operationId, (active) => active.tabs({
|
|
494
|
+
action: input.action,
|
|
495
|
+
...(typeof input.index === "number" ? { index: input.index } : {}),
|
|
496
|
+
...(typeof input.url === "string" ? { url: input.url } : {}),
|
|
497
|
+
}, operationOptions(operationId, third)));
|
|
498
|
+
},
|
|
499
|
+
}), api.registerTool({
|
|
500
|
+
name: "browser_storage",
|
|
501
|
+
label: "Browser storage",
|
|
502
|
+
description: "Manage browser storage: cookies (get-cookies/set-cookie/clear-cookies via the context) and localStorage (get-local/set-local/clear-local via the page)",
|
|
503
|
+
parameters: Type.Object({
|
|
504
|
+
action: browserStorageActionSchema,
|
|
505
|
+
name: Type.Optional(Type.String({ minLength: 1, maxLength: 4096 })),
|
|
506
|
+
value: Type.Optional(Type.String({ maxLength: 4096 })),
|
|
507
|
+
domain: Type.Optional(Type.String({ minLength: 1, maxLength: 255 })),
|
|
508
|
+
path: Type.Optional(Type.String({ maxLength: 1024 })),
|
|
509
|
+
expires: Type.Optional(Type.Number()),
|
|
510
|
+
key: Type.Optional(Type.String({ minLength: 1, maxLength: 4096 })),
|
|
511
|
+
}),
|
|
512
|
+
execute: async (first, second, third) => {
|
|
513
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
514
|
+
return withSession(operationId, (active) => active.storage({
|
|
515
|
+
action: input.action,
|
|
516
|
+
...(typeof input.name === "string" ? { name: input.name } : {}),
|
|
517
|
+
...(typeof input.value === "string" ? { value: input.value } : {}),
|
|
518
|
+
...(typeof input.domain === "string" ? { domain: input.domain } : {}),
|
|
519
|
+
...(typeof input.path === "string" ? { path: input.path } : {}),
|
|
520
|
+
...(typeof input.expires === "number" ? { expires: input.expires } : {}),
|
|
521
|
+
...(typeof input.key === "string" ? { key: input.key } : {}),
|
|
522
|
+
}, operationOptions(operationId, third)));
|
|
523
|
+
},
|
|
524
|
+
}), api.registerTool({
|
|
525
|
+
name: "browser_viewport",
|
|
526
|
+
label: "Browser viewport",
|
|
527
|
+
description: "Set the viewport size (width/height clamped into 320..7680) or read the current one",
|
|
528
|
+
parameters: Type.Object({
|
|
529
|
+
action: browserViewportActionSchema,
|
|
530
|
+
width: Type.Optional(Type.Integer({ minimum: 0, maximum: 100_000 })),
|
|
531
|
+
height: Type.Optional(Type.Integer({ minimum: 0, maximum: 100_000 })),
|
|
532
|
+
}),
|
|
533
|
+
execute: async (first, second, third) => {
|
|
534
|
+
const { input, operationId } = toolInvocation(first, second);
|
|
535
|
+
return withSession(operationId, (active) => active.viewport({
|
|
536
|
+
action: input.action,
|
|
537
|
+
...(typeof input.width === "number" ? { width: input.width } : {}),
|
|
538
|
+
...(typeof input.height === "number" ? { height: input.height } : {}),
|
|
539
|
+
}, operationOptions(operationId, third)));
|
|
540
|
+
},
|
|
541
|
+
}));
|
|
542
|
+
}
|
|
543
|
+
if (!readonlyMode) {
|
|
544
|
+
registrations.push(api.registerTool({
|
|
545
|
+
name: "browser_setup",
|
|
546
|
+
label: "Browser setup",
|
|
547
|
+
description: "Install Playwright and the Chromium browser into <agentDir>/browser-deps (npm install playwright --prefix <dir>, then npx playwright install chromium). Reports alreadyInstalled when dependencies are present",
|
|
548
|
+
parameters: Type.Object({}),
|
|
549
|
+
execute: async (first, second, third) => {
|
|
550
|
+
const { operationId } = toolInvocation(first, second);
|
|
551
|
+
const signal = signalFrom(third);
|
|
552
|
+
if (signal?.aborted) {
|
|
553
|
+
return buildPluginResultV1({
|
|
554
|
+
version: 1,
|
|
555
|
+
operationId,
|
|
556
|
+
status: "cancelled",
|
|
557
|
+
summary: "Browser operation was cancelled",
|
|
558
|
+
artifacts: [],
|
|
559
|
+
evidence: [],
|
|
560
|
+
error: { version: 1, code: "cancelled", message: "Browser operation was cancelled" },
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
// Call through the runtime: extracting the method would drop
|
|
564
|
+
// `this`, and the production class reads `this.options` in setup().
|
|
565
|
+
if (runtime.setup === undefined) {
|
|
566
|
+
return buildPluginResultV1({
|
|
567
|
+
version: 1,
|
|
568
|
+
operationId,
|
|
569
|
+
status: "failed",
|
|
570
|
+
summary: "This browser runtime does not support self-installation",
|
|
571
|
+
artifacts: [],
|
|
572
|
+
evidence: [],
|
|
573
|
+
error: {
|
|
574
|
+
version: 1,
|
|
575
|
+
code: "browser_setup_unsupported",
|
|
576
|
+
message: "The injected browser runtime exposes no setup face. Install Playwright manually with npm install playwright --prefix <agentDir>/browser-deps and npx playwright install chromium.",
|
|
577
|
+
},
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
try {
|
|
581
|
+
return setupResult(operationId, await runtime.setup());
|
|
582
|
+
}
|
|
583
|
+
catch (error) {
|
|
584
|
+
return buildPluginResultV1({
|
|
585
|
+
version: 1,
|
|
586
|
+
operationId,
|
|
587
|
+
status: "failed",
|
|
588
|
+
summary: "Playwright browser dependency setup failed",
|
|
589
|
+
artifacts: [],
|
|
590
|
+
evidence: [],
|
|
591
|
+
error: {
|
|
592
|
+
version: 1,
|
|
593
|
+
code: "browser_setup_failed",
|
|
594
|
+
message: browserVisibleError(error),
|
|
595
|
+
},
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
},
|
|
599
|
+
}));
|
|
600
|
+
}
|
|
601
|
+
return {
|
|
602
|
+
dispose: () => {
|
|
603
|
+
if (session === undefined)
|
|
604
|
+
return;
|
|
605
|
+
// Both a failed connection and a failed close happen after this synchronous
|
|
606
|
+
// disposer returns. Consume either rejection so disposal cannot leak a promise.
|
|
607
|
+
void session.then((active) => active.close()).catch(() => undefined);
|
|
608
|
+
},
|
|
609
|
+
};
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
//# sourceMappingURL=capability.js.map
|