@ai-agent-forge/agent-forge 0.88.5 → 0.88.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/CHANGELOG.md +36 -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 +857 -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/dist/read.d.ts +2 -0
- package/bundled-plugins/coding-tools/dist/read.d.ts.map +1 -1
- package/bundled-plugins/coding-tools/dist/read.js +11 -0
- package/bundled-plugins/coding-tools/dist/read.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-L2SXIPI5.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 +85 -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 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Self-installation of Playwright into `<agentDir>/browser-deps` (the\n * `browser_setup` tool's engine).\n *\n * Playwright is deliberately not a dependency of this package: it is the only\n * optional heavy dependency in the product's browser channel, and it is\n * resolved at runtime through `createRequire(<browser-deps>/package.json)`.\n * This module owns the install sequence (`npm install playwright --prefix`\n * then `npx playwright install chromium`), the already-installed probe\n * (module resolvable plus the Chromium executable present), the environment\n * whitelist passed to the spawned installers, bounded progress/preview\n * shaping, and the structured guidance message returned when the module is\n * missing.\n */\nimport { spawnSync as nodeSpawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join } from \"node:path\";\nimport type { BrowserSetupOutcomeV1 } from \"./types.ts\";\n\nexport const BROWSER_SETUP_TIMEOUT_MS_V1 = 600_000;\nexport const BROWSER_DEPS_DIR_NAME_V1 = \"browser-deps\";\nexport const BROWSER_BROWSERS_DIR_NAME_V1 = \"browsers\";\nexport const BROWSER_MAX_PROGRESS_CHARS_V1 = 8192;\nexport const BROWSER_MAX_FAILURE_MESSAGE_CHARS_V1 = 8192;\nexport const BROWSER_MAX_STDERR_TAIL_CHARS_V1 = 4096;\nexport const BROWSER_MAX_STDOUT_TAIL_CHARS_V1 = 2048;\n\nexport type BrowserSpawnResultV1 = {\n\treadonly error?: Error;\n\treadonly status: number | null;\n\treadonly stdout: string;\n\treadonly stderr: string;\n};\n\nexport type BrowserSpawnSyncV1 = (\n\tcommand: string,\n\targs: readonly string[],\n\toptions: {\n\t\treadonly cwd: string;\n\t\treadonly env: NodeJS.ProcessEnv;\n\t\treadonly encoding: \"utf8\";\n\t\treadonly timeout: number;\n\t\treadonly windowsHide: boolean;\n\t\treadonly shell: boolean;\n\t},\n) => BrowserSpawnResultV1;\n\nexport interface BrowserSetupOptionsV1 {\n\t/** Host agent directory; `<agentDir>/browser-deps` is the install target. */\n\treadonly agentDir?: string;\n\t/** Direct override of the install target; wins over `agentDir`. */\n\treadonly browserDepsDir?: string;\n\treadonly timeoutMs?: number;\n\t/** Deterministic seam for tests and brokered hosts. */\n\treadonly spawnSync?: BrowserSpawnSyncV1;\n\t/** Deterministic seam for the \"already installed\" probe. */\n\treadonly resolvePlaywright?: (browserDepsDir: string) => string | undefined;\n\t/** Deterministic seam for the Chromium executable probe. */\n\treadonly resolveChromiumExecutable?: (browserDepsDir: string) => string | undefined;\n\t/** Deterministic seam for the executable existence check (tests inject a fake). */\n\treadonly executableExists?: (path: string) => boolean;\n\t/** Deterministic seam for directory creation (tests inject a no-op). */\n\treadonly ensureDir?: (dir: string) => void;\n}\n\nexport function browserDepsDirFor(agentDir: string): string {\n\treturn join(agentDir, BROWSER_DEPS_DIR_NAME_V1);\n}\n\n/**\n * Resolves the `playwright` module against `<browser-deps>` without touching\n * this package's own dependency graph. Returns the resolved entry path, or\n * undefined when the module is absent. Never throws.\n */\nexport function resolvePlaywrightModule(browserDepsDir: string): string | undefined {\n\tif (browserDepsDir === \"\") return undefined;\n\ttry {\n\t\treturn createRequire(join(browserDepsDir, \"package.json\")).resolve(\"playwright\") as string;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Minimal shape of the installed playwright module used by the browser probe. */\ninterface PlaywrightChromiumProbeV1 {\n\tchromium: {\n\t\texecutablePath(): string;\n\t};\n}\n\n/**\n * Resolves the Chromium executable path through the installed playwright\n * module itself, so the probe targets the exact binary `chromium.launch()`\n * will use. Returns undefined when the module cannot be loaded; the reported\n * path may not exist on disk (the caller checks existence). Never throws.\n */\nexport function resolveChromiumExecutable(browserDepsDir: string): string | undefined {\n\tif (browserDepsDir === \"\") return undefined;\n\ttry {\n\t\t// playwright-core computes its registry directory once at module load\n\t\t// from PLAYWRIGHT_BROWSERS_PATH; when the user has not set it, pin it\n\t\t// before the require to the same isolated directory the install flow\n\t\t// populates and connect() falls back to. An explicit user value wins\n\t\t// (same precedence as connect()'s ??=), so probe and launch agree.\n\t\tconst previous = process.env.PLAYWRIGHT_BROWSERS_PATH;\n\t\tif (previous === undefined) {\n\t\t\tprocess.env.PLAYWRIGHT_BROWSERS_PATH = join(browserDepsDir, BROWSER_BROWSERS_DIR_NAME_V1);\n\t\t}\n\t\ttry {\n\t\t\tconst require = createRequire(join(browserDepsDir, \"package.json\"));\n\t\t\tconst playwright = require(\"playwright\") as PlaywrightChromiumProbeV1;\n\t\t\treturn playwright.chromium.executablePath();\n\t\t} finally {\n\t\t\tif (previous === undefined) delete process.env.PLAYWRIGHT_BROWSERS_PATH;\n\t\t}\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Structured guidance returned when Playwright is missing. The message lists\n * the two exact install commands and points at the `browser_setup` tool; the\n * capability layer passes it through verbatim (it stays under the 2048-char\n * browser error budget).\n */\nexport function installGuidanceMessage(browserDepsDir?: string): string {\n\tconst target =\n\t\tbrowserDepsDir === undefined || browserDepsDir === \"\"\n\t\t\t? join(\"<agentDir>\", BROWSER_DEPS_DIR_NAME_V1)\n\t\t\t: browserDepsDir;\n\treturn [\n\t\t\"Playwright is required by the browser tools but is not installed.\",\n\t\t\"Install it with:\",\n\t\t` npm install playwright --prefix ${target}`,\n\t\t// With an explicit PLAYWRIGHT_BROWSERS_PATH in the environment the bare\n\t\t// command already installs where the driver looks; pinning the prefix\n\t\t// here would override the user's directory (connect honors it via ??=).\n\t\tprocess.env.PLAYWRIGHT_BROWSERS_PATH === undefined\n\t\t\t? ` PLAYWRIGHT_BROWSERS_PATH=${join(target, BROWSER_BROWSERS_DIR_NAME_V1)} npx playwright install chromium`\n\t\t\t: \" npx playwright install chromium\",\n\t\t\"Or call the browser_setup tool to install these dependencies automatically.\",\n\t].join(\"\\n\");\n}\n\nconst BROWSER_SETUP_ENV_KEYS_V1: readonly string[] = [\"PATH\", \"HOME\", \"APPDATA\", \"USER\", \"LOGNAME\", \"TMPDIR\"];\n\n/**\n * Environment for the spawned installers (and, via PLAYWRIGHT_BROWSERS_PATH,\n * for the driver's own browser launches): the whitelist from the macOS AX\n * adapter plus PLAYWRIGHT_BROWSERS_PATH — an explicit user value wins so\n * install and launch resolve browsers from the same directory, otherwise the\n * given default browsers dir is pinned (matches connect()'s ??=). Everything\n * else is dropped.\n */\nexport function browserSetupEnvironmentV1(browsersDir: string): NodeJS.ProcessEnv {\n\tconst env: NodeJS.ProcessEnv = {};\n\tfor (const key of BROWSER_SETUP_ENV_KEYS_V1) {\n\t\tconst value = process.env[key];\n\t\tif (value !== undefined) env[key] = value;\n\t}\n\tenv.PLAYWRIGHT_BROWSERS_PATH = process.env.PLAYWRIGHT_BROWSERS_PATH ?? browsersDir;\n\treturn env;\n}\n\n/** Head/tail bounded preview (75% head, rest tail) mirroring process-exec's shaping. */\nexport function boundedPreviewV1(text: string, maximumChars: number): string {\n\tif (text.length <= maximumChars) return text;\n\tconst head = Math.ceil((maximumChars * 3) / 4);\n\tconst tail = Math.max(0, maximumChars - head - 40);\n\tconst omitted = text.length - head - tail;\n\treturn `${text.slice(0, head)}\\n... [${omitted} chars omitted] ...\\n${tail > 0 ? text.slice(text.length - tail) : \"\"}`;\n}\n\n/** Tail-only bounded preview, keeping the original ending intact. */\nexport function boundedTailV1(text: string, maximumChars: number): string {\n\tif (text.length <= maximumChars) return text;\n\treturn `... [${text.length - maximumChars} chars omitted] ...\\n${text.slice(text.length - maximumChars)}`;\n}\n\nconst isWin32 = process.platform === \"win32\";\nconst npmCommand = (): string => (isWin32 ? \"npm.cmd\" : \"npm\");\nconst npxCommand = (): string => (isWin32 ? \"npx.cmd\" : \"npx\");\n\nconst defaultSpawn: BrowserSpawnSyncV1 = (command, args, options) => {\n\tconst outcome = nodeSpawnSync(command, [...args], { ...options });\n\treturn {\n\t\terror: outcome.error,\n\t\tstatus: outcome.status,\n\t\tstdout: typeof outcome.stdout === \"string\" ? outcome.stdout : \"\",\n\t\tstderr: typeof outcome.stderr === \"string\" ? outcome.stderr : \"\",\n\t};\n};\n\nconst describeExit = (outcome: BrowserSpawnResultV1): string => {\n\tif (outcome.status === 0) return \"0\";\n\tif (outcome.status !== null) return String(outcome.status);\n\treturn outcome.error?.message ?? \"no exit status\";\n};\n\nconst spawnSucceeded = (outcome: BrowserSpawnResultV1): boolean => outcome.error === undefined && outcome.status === 0;\n\nconst failureMessage = (label: string, outcome: BrowserSpawnResultV1, depsDir: string): string => {\n\tconst parts = [`${label} failed (exit ${describeExit(outcome)})`];\n\tconst stderr = boundedTailV1(outcome.stderr, BROWSER_MAX_STDERR_TAIL_CHARS_V1);\n\tif (stderr.trim() !== \"\") parts.push(`stderr tail:\\n${stderr}`);\n\tconst stdout = boundedTailV1(outcome.stdout, BROWSER_MAX_STDOUT_TAIL_CHARS_V1);\n\tif (stdout.trim() !== \"\") parts.push(`stdout tail:\\n${stdout}`);\n\tparts.push(installGuidanceMessage(depsDir));\n\treturn boundedPreviewV1(parts.join(\"\\n\"), BROWSER_MAX_FAILURE_MESSAGE_CHARS_V1);\n};\n\n/**\n * Installs Playwright into the browser-deps directory:\n * 1. already resolvable with the Chromium executable present -> succeed with\n * `alreadyInstalled: true` (no spawn); a module without its browser binary\n * does not short-circuit;\n * 2. otherwise `npm install playwright --prefix <depsDir>`, then\n * `npx playwright install chromium` (cwd = depsDir, whitelisted env plus\n * PLAYWRIGHT_BROWSERS_PATH — explicit user value wins, else\n * <depsDir>/browsers — bounded timeout);\n * 3. post-install verification (module resolvable plus the Chromium\n * executable present, the same probe as step 1) so a silent install\n * failure is reported.\n */\nexport async function setupBrowserDepsPlaywrightV1(\n\toptions: BrowserSetupOptionsV1 = {},\n): Promise<BrowserSetupOutcomeV1> {\n\tconst depsDir =\n\t\toptions.browserDepsDir ?? (options.agentDir === undefined ? undefined : browserDepsDirFor(options.agentDir));\n\tif (depsDir === undefined || depsDir === \"\") {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage: `${installGuidanceMessage()}\\nThe running host did not declare an agentDir, so browser_setup cannot install anything.`,\n\t\t};\n\t}\n\tconst resolve = options.resolvePlaywright ?? resolvePlaywrightModule;\n\tconst resolveChromium = options.resolveChromiumExecutable ?? resolveChromiumExecutable;\n\tconst executableExists = options.executableExists ?? existsSync;\n\tconst spawn = options.spawnSync ?? defaultSpawn;\n\tconst ensureDir = options.ensureDir ?? ((dir: string) => mkdirSync(dir, { recursive: true }));\n\tconst timeoutMs = options.timeoutMs ?? BROWSER_SETUP_TIMEOUT_MS_V1;\n\tconst resolved = resolve(depsDir);\n\t// Already-installed requires BOTH the module and the browser binary:\n\t// a past run that installed the package but failed the chromium download\n\t// must re-run the install instead of reporting success the driver cannot\n\t// honor (launch would fail with \"Executable doesn't exist\").\n\tconst chromiumExecutable = resolved === undefined ? undefined : resolveChromium(depsDir);\n\tif (resolved !== undefined && chromiumExecutable !== undefined && executableExists(chromiumExecutable)) {\n\t\treturn { ok: true, alreadyInstalled: true, log: `playwright resolvable at ${resolved}` };\n\t}\n\tconst log: string[] = [`target: ${depsDir}`];\n\tensureDir(depsDir);\n\tconst env = browserSetupEnvironmentV1(join(depsDir, BROWSER_BROWSERS_DIR_NAME_V1));\n\tconst spawnOptions = {\n\t\tcwd: depsDir,\n\t\tenv,\n\t\tencoding: \"utf8\",\n\t\ttimeout: timeoutMs,\n\t\twindowsHide: true,\n\t\t// Node >= 18.20 refuses to spawn .cmd shims directly (EINVAL), so win32\n\t\t// runs through cmd.exe, which joins argv with spaces and never quotes;\n\t\t// --prefix carries an arbitrary user path (homedir may contain spaces),\n\t\t// so quote it explicitly on win32 (node-package-install-host precedent).\n\t\tshell: isWin32,\n\t} as const;\n\tconst install = spawn(\n\t\tnpmCommand(),\n\t\t[\"install\", \"playwright\", \"--prefix\", isWin32 ? `\"${depsDir}\"` : depsDir],\n\t\tspawnOptions,\n\t);\n\tif (!spawnSucceeded(install)) {\n\t\treturn { ok: false, message: failureMessage(\"npm install playwright --prefix\", install, depsDir) };\n\t}\n\tlog.push(`npm install playwright --prefix: exit ${describeExit(install)}`);\n\tconst browsers = spawn(npxCommand(), [\"playwright\", \"install\", \"chromium\"], spawnOptions);\n\tif (!spawnSucceeded(browsers)) {\n\t\treturn { ok: false, message: failureMessage(\"npx playwright install chromium\", browsers, depsDir) };\n\t}\n\tlog.push(`npx playwright install chromium: exit ${describeExit(browsers)}`);\n\tconst verified = resolve(depsDir);\n\tif (verified === undefined) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage: boundedPreviewV1(\n\t\t\t\t`${installGuidanceMessage(depsDir)}\\nInstallation commands reported success but playwright is still not resolvable from ${depsDir}.`,\n\t\t\t\tBROWSER_MAX_FAILURE_MESSAGE_CHARS_V1,\n\t\t\t),\n\t\t};\n\t}\n\tlog.push(`verification: playwright resolvable at ${verified}`);\n\t// The install commands can exit 0 while the chromium download silently\n\t// failed (e.g. a blocked download host), so verify the exact binary\n\t// chromium.launch() will use — the same probe the already-installed\n\t// check above runs.\n\tconst verifiedExecutable = resolveChromium(depsDir);\n\tif (verifiedExecutable === undefined || !executableExists(verifiedExecutable)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage: boundedPreviewV1(\n\t\t\t\t`${installGuidanceMessage(depsDir)}\\nInstallation commands reported success but the Chromium executable is still missing${\n\t\t\t\t\tverifiedExecutable === undefined ? \".\" : ` (expected at ${verifiedExecutable}).`\n\t\t\t\t}`,\n\t\t\t\tBROWSER_MAX_FAILURE_MESSAGE_CHARS_V1,\n\t\t\t),\n\t\t};\n\t}\n\tlog.push(`verification: chromium executable at ${verifiedExecutable}`);\n\treturn {\n\t\tok: true,\n\t\talreadyInstalled: false,\n\t\tlog: boundedPreviewV1(log.join(\"\\n\"), BROWSER_MAX_PROGRESS_CHARS_V1),\n\t};\n}\n"]}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser capability contracts for the built-in Playwright plugin.
|
|
3
|
+
*
|
|
4
|
+
* The plugin is the product's single browser channel. Playwright itself is
|
|
5
|
+
* never bundled: the driver resolves it from `<agentDir>/browser-deps` at
|
|
6
|
+
* connect time and `browser_setup` installs it on first use. Everything here
|
|
7
|
+
* is host-independent; hosts and tests inject a `BrowserRuntimeV1` whose
|
|
8
|
+
* `connect()` yields a driver, so the capability layer never imports
|
|
9
|
+
* Playwright types.
|
|
10
|
+
*/
|
|
11
|
+
import type { PluginResultV1 } from "@agent-forge/plugin-sdk";
|
|
12
|
+
export type BrowserLocatorKindV1 = "css" | "id" | "role" | "text" | "test-id";
|
|
13
|
+
export interface BrowserLocatorV1 {
|
|
14
|
+
readonly kind: BrowserLocatorKindV1;
|
|
15
|
+
readonly value: string;
|
|
16
|
+
/** Accessible name refinement for `kind: "role"`. */
|
|
17
|
+
readonly name?: string;
|
|
18
|
+
}
|
|
19
|
+
export type BrowserWaitUntilV1 = "commit" | "domcontentloaded" | "load" | "networkidle";
|
|
20
|
+
export interface BrowserNavigateInputV1 {
|
|
21
|
+
readonly url: string;
|
|
22
|
+
readonly waitUntil?: BrowserWaitUntilV1;
|
|
23
|
+
}
|
|
24
|
+
export interface BrowserSnapshotInputV1 {
|
|
25
|
+
readonly includeDom?: boolean;
|
|
26
|
+
readonly includeA11y?: boolean;
|
|
27
|
+
readonly includeStyles?: boolean;
|
|
28
|
+
readonly includeScreenshot?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export type BrowserLocatorActionKindV1 = "click" | "dblclick" | "rightclick" | "fill" | "type" | "press" | "hover" | "select" | "check" | "uncheck" | "clear" | "upload" | "scroll";
|
|
31
|
+
export interface BrowserLocatorActionInputV1 {
|
|
32
|
+
readonly locator: BrowserLocatorV1;
|
|
33
|
+
readonly action: BrowserLocatorActionKindV1;
|
|
34
|
+
/**
|
|
35
|
+
* Value for `fill`, `type`, and `select`; for `upload` a single absolute
|
|
36
|
+
* file path or a JSON array of paths; for `scroll` a `<direction>:<pixels>`
|
|
37
|
+
* directive (`down:500`, `up:200`, `left:100`, `right:100`).
|
|
38
|
+
*/
|
|
39
|
+
readonly value?: string;
|
|
40
|
+
/** Key sequence for `press`. */
|
|
41
|
+
readonly key?: string;
|
|
42
|
+
/** Inter-key delay in milliseconds for `type`. */
|
|
43
|
+
readonly delay?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface BrowserEvaluateInputV1 {
|
|
46
|
+
/**
|
|
47
|
+
* JavaScript expression evaluated via `page.evaluate`. Keep it a plain
|
|
48
|
+
* expression (`document.title`, `1 + 1`); for multi-statement logic use an
|
|
49
|
+
* IIFE string (`(() => { ... return x; })()`) — a bare `() => ...` string is
|
|
50
|
+
* not invoked by Playwright and serializes to `undefined`.
|
|
51
|
+
*/
|
|
52
|
+
readonly expression: string;
|
|
53
|
+
/** JSON-serializable argument passed through to the page context. */
|
|
54
|
+
readonly arg?: unknown;
|
|
55
|
+
}
|
|
56
|
+
export interface BrowserConsoleReadInputV1 {
|
|
57
|
+
/** Comma-combined level filter: error/warning/info/debug (`info` also matches `log`). */
|
|
58
|
+
readonly level?: string;
|
|
59
|
+
/** Substring filter on the message text. */
|
|
60
|
+
readonly contains?: string;
|
|
61
|
+
/** Most-recent count to return; defaults to 50. */
|
|
62
|
+
readonly limit?: number;
|
|
63
|
+
}
|
|
64
|
+
export interface BrowserConsoleEntryV1 {
|
|
65
|
+
readonly type: string;
|
|
66
|
+
readonly text: string;
|
|
67
|
+
readonly location?: {
|
|
68
|
+
readonly url: string;
|
|
69
|
+
readonly lineNumber: number;
|
|
70
|
+
readonly columnNumber: number;
|
|
71
|
+
};
|
|
72
|
+
readonly timestamp: number;
|
|
73
|
+
}
|
|
74
|
+
export interface BrowserNetworkReadInputV1 {
|
|
75
|
+
readonly containsUrl?: string;
|
|
76
|
+
readonly status?: number;
|
|
77
|
+
readonly method?: string;
|
|
78
|
+
/** Most-recent count to return; defaults to 50. */
|
|
79
|
+
readonly limit?: number;
|
|
80
|
+
}
|
|
81
|
+
export interface BrowserNetworkEntryV1 {
|
|
82
|
+
readonly method: string;
|
|
83
|
+
readonly url: string;
|
|
84
|
+
readonly status: number;
|
|
85
|
+
readonly timestamp: number;
|
|
86
|
+
/** Wall-clock duration in milliseconds when the request timing is available. */
|
|
87
|
+
readonly durationMs?: number;
|
|
88
|
+
/** Response `content-length` in bytes when the header is present. */
|
|
89
|
+
readonly sizeBytes?: number;
|
|
90
|
+
}
|
|
91
|
+
/** Raw in-page performance collection; the driver shapes it into {@link BrowserPerformancePayloadV1}. */
|
|
92
|
+
export interface BrowserPerformanceRawV1 {
|
|
93
|
+
readonly navigation: {
|
|
94
|
+
readonly ttfbMs: number;
|
|
95
|
+
readonly domContentLoadedMs: number;
|
|
96
|
+
readonly loadMs: number;
|
|
97
|
+
} | null;
|
|
98
|
+
readonly paints: readonly {
|
|
99
|
+
readonly name: string;
|
|
100
|
+
readonly startTimeMs: number;
|
|
101
|
+
}[];
|
|
102
|
+
readonly resources: readonly {
|
|
103
|
+
readonly url: string;
|
|
104
|
+
readonly durationMs: number;
|
|
105
|
+
readonly transferBytes: number;
|
|
106
|
+
}[];
|
|
107
|
+
readonly domNodes: number;
|
|
108
|
+
}
|
|
109
|
+
export interface BrowserPerformancePayloadV1 {
|
|
110
|
+
readonly navigation?: {
|
|
111
|
+
readonly ttfbMs: number;
|
|
112
|
+
readonly domContentLoadedMs: number;
|
|
113
|
+
readonly loadMs: number;
|
|
114
|
+
};
|
|
115
|
+
readonly paint: {
|
|
116
|
+
readonly firstPaintMs?: number;
|
|
117
|
+
readonly firstContentfulPaintMs?: number;
|
|
118
|
+
};
|
|
119
|
+
readonly resources: {
|
|
120
|
+
readonly count: number;
|
|
121
|
+
readonly totalTransferBytes: number;
|
|
122
|
+
readonly slowest: readonly {
|
|
123
|
+
readonly url: string;
|
|
124
|
+
readonly durationMs: number;
|
|
125
|
+
}[];
|
|
126
|
+
};
|
|
127
|
+
readonly domNodes: number;
|
|
128
|
+
}
|
|
129
|
+
export type BrowserWaitUntilKindV1 = "selector" | "navigation" | "networkidle" | "time";
|
|
130
|
+
export interface BrowserWaitInputV1 {
|
|
131
|
+
readonly until: BrowserWaitUntilKindV1;
|
|
132
|
+
/** Locator for `until: "selector"` (waits for the element to be visible). */
|
|
133
|
+
readonly locator?: BrowserLocatorV1;
|
|
134
|
+
/** Milliseconds; required for `until: "time"`, optional timeout for the others. Clamped to 30000. */
|
|
135
|
+
readonly ms?: number;
|
|
136
|
+
}
|
|
137
|
+
export interface BrowserDragInputV1 {
|
|
138
|
+
readonly from: BrowserLocatorV1;
|
|
139
|
+
readonly to: BrowserLocatorV1;
|
|
140
|
+
/** Number of intermediate mouse moves over the target; defaults to 8. */
|
|
141
|
+
readonly steps?: number;
|
|
142
|
+
}
|
|
143
|
+
export type BrowserMouseActionKindV1 = "move" | "click" | "dblclick" | "rightclick" | "wheel";
|
|
144
|
+
export type BrowserMouseButtonV1 = "left" | "right" | "middle";
|
|
145
|
+
export interface BrowserMouseInputV1 {
|
|
146
|
+
readonly action: BrowserMouseActionKindV1;
|
|
147
|
+
/** Non-negative integer viewport x coordinate. */
|
|
148
|
+
readonly x: number;
|
|
149
|
+
/** Non-negative integer viewport y coordinate. */
|
|
150
|
+
readonly y: number;
|
|
151
|
+
/** Horizontal wheel delta in pixels (`wheel`). */
|
|
152
|
+
readonly deltaX?: number;
|
|
153
|
+
/** Vertical wheel delta in pixels (`wheel`). */
|
|
154
|
+
readonly deltaY?: number;
|
|
155
|
+
readonly button?: BrowserMouseButtonV1;
|
|
156
|
+
}
|
|
157
|
+
export interface BrowserPressKeyInputV1 {
|
|
158
|
+
/** Playwright key name, e.g. `Control+a`, `Enter`, `Meta+c`. */
|
|
159
|
+
readonly key: string;
|
|
160
|
+
/** Delay between keydown and keyup in milliseconds. */
|
|
161
|
+
readonly delay?: number;
|
|
162
|
+
}
|
|
163
|
+
export type BrowserTabsActionKindV1 = "list" | "new" | "switch" | "close";
|
|
164
|
+
export interface BrowserTabsInputV1 {
|
|
165
|
+
readonly action: BrowserTabsActionKindV1;
|
|
166
|
+
/** Tab index for `switch` and `close`. */
|
|
167
|
+
readonly index?: number;
|
|
168
|
+
/** URL for `new`; defaults to `about:blank`. */
|
|
169
|
+
readonly url?: string;
|
|
170
|
+
}
|
|
171
|
+
export type BrowserStorageActionKindV1 = "get-cookies" | "set-cookie" | "clear-cookies" | "get-local" | "set-local" | "clear-local";
|
|
172
|
+
export interface BrowserStorageInputV1 {
|
|
173
|
+
readonly action: BrowserStorageActionKindV1;
|
|
174
|
+
/** Cookie name for `set-cookie`. */
|
|
175
|
+
readonly name?: string;
|
|
176
|
+
/** Cookie value for `set-cookie`; localStorage value for `set-local`. */
|
|
177
|
+
readonly value?: string;
|
|
178
|
+
/** Cookie domain for `set-cookie` (Playwright requires domain or url). */
|
|
179
|
+
readonly domain?: string;
|
|
180
|
+
readonly path?: string;
|
|
181
|
+
/** Cookie expiry as Unix seconds; omit for a session cookie. */
|
|
182
|
+
readonly expires?: number;
|
|
183
|
+
/** localStorage key for `get-local` and `set-local`. */
|
|
184
|
+
readonly key?: string;
|
|
185
|
+
}
|
|
186
|
+
export type BrowserViewportActionKindV1 = "set" | "get";
|
|
187
|
+
export interface BrowserViewportInputV1 {
|
|
188
|
+
readonly action: BrowserViewportActionKindV1;
|
|
189
|
+
/** Requested width; clamped into 320..7680. */
|
|
190
|
+
readonly width?: number;
|
|
191
|
+
/** Requested height; clamped into 320..7680. */
|
|
192
|
+
readonly height?: number;
|
|
193
|
+
}
|
|
194
|
+
export type BrowserElementStateV1 = "visible" | "hidden" | "value";
|
|
195
|
+
export type BrowserPostconditionV1 = {
|
|
196
|
+
readonly kind: "url";
|
|
197
|
+
readonly equals?: string;
|
|
198
|
+
readonly contains?: string;
|
|
199
|
+
} | {
|
|
200
|
+
readonly kind: "element";
|
|
201
|
+
readonly locator: BrowserLocatorV1;
|
|
202
|
+
readonly state: BrowserElementStateV1;
|
|
203
|
+
readonly value?: string;
|
|
204
|
+
} | {
|
|
205
|
+
readonly kind: "text";
|
|
206
|
+
readonly locator?: BrowserLocatorV1;
|
|
207
|
+
readonly contains: string;
|
|
208
|
+
} | {
|
|
209
|
+
readonly kind: "console";
|
|
210
|
+
readonly contains: string;
|
|
211
|
+
readonly level?: string;
|
|
212
|
+
} | {
|
|
213
|
+
readonly kind: "network";
|
|
214
|
+
readonly containsUrl: string;
|
|
215
|
+
readonly status?: number;
|
|
216
|
+
};
|
|
217
|
+
/** `browser_collect_evidence` kinds; console/network come from bounded page ring buffers. */
|
|
218
|
+
export type BrowserEvidenceKindV1 = "console" | "network" | "snapshot";
|
|
219
|
+
export interface BrowserOperationOptionsV1 {
|
|
220
|
+
readonly operationId?: string;
|
|
221
|
+
readonly signal?: AbortSignal;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Driver contract behind `BrowserRuntimeV1`. Every operation returns a
|
|
225
|
+
* validated `PluginResultV1`; failures are structured results, not throws
|
|
226
|
+
* (module/install problems surface as thrown errors at `connect` time and are
|
|
227
|
+
* sanitized by the capability layer). Structured payloads (console/network
|
|
228
|
+
* entries, performance metrics, evaluate results, storage and tab state) are
|
|
229
|
+
* carried as bounded JSON text in evidence summaries.
|
|
230
|
+
*/
|
|
231
|
+
export interface BrowserDriverV1 {
|
|
232
|
+
navigate(input: BrowserNavigateInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
233
|
+
snapshot(input?: BrowserSnapshotInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
234
|
+
locatorAction(input: BrowserLocatorActionInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
235
|
+
assertPostcondition(input: BrowserPostconditionV1 | readonly BrowserPostconditionV1[], options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
236
|
+
collectEvidence(kind: BrowserEvidenceKindV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
237
|
+
/** Escape hatch: runs a JS expression in the page context; use only when no built-in tool covers the operation. */
|
|
238
|
+
evaluate(input: BrowserEvaluateInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
239
|
+
consoleEntries(input: BrowserConsoleReadInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
240
|
+
networkEntries(input: BrowserNetworkReadInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
241
|
+
/** Navigation Timing, paint, resource summary, and DOM node count; read-only. */
|
|
242
|
+
performance(options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
243
|
+
wait(input: BrowserWaitInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
244
|
+
drag(input: BrowserDragInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
245
|
+
mouse(input: BrowserMouseInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
246
|
+
pressKey(input: BrowserPressKeyInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
247
|
+
tabs(input: BrowserTabsInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
248
|
+
storage(input: BrowserStorageInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
249
|
+
viewport(input: BrowserViewportInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;
|
|
250
|
+
/** Idempotent, best-effort teardown; never throws. */
|
|
251
|
+
close(): void;
|
|
252
|
+
}
|
|
253
|
+
export type BrowserSetupOutcomeV1 = {
|
|
254
|
+
readonly ok: true;
|
|
255
|
+
readonly alreadyInstalled: boolean;
|
|
256
|
+
readonly log: string;
|
|
257
|
+
} | {
|
|
258
|
+
readonly ok: false;
|
|
259
|
+
readonly message: string;
|
|
260
|
+
};
|
|
261
|
+
/**
|
|
262
|
+
* Injection face for the capability factory. Tests bind a fake runtime over a
|
|
263
|
+
* mock driver; the production entry binds `PlaywrightBrowserRuntimeV1`, whose
|
|
264
|
+
* optional `setup()` self-installs Playwright into `<agentDir>/browser-deps`.
|
|
265
|
+
*/
|
|
266
|
+
export interface BrowserRuntimeV1 {
|
|
267
|
+
connect(): Promise<BrowserDriverV1>;
|
|
268
|
+
setup?(): Promise<BrowserSetupOutcomeV1>;
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE9D,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qDAAqD;IACrD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,kBAAkB,GAAG,MAAM,GAAG,aAAa,CAAC;AAExF,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,kBAAkB,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,MAAM,MAAM,0BAA0B,GACnC,OAAO,GACP,UAAU,GACV,YAAY,GACZ,MAAM,GACN,MAAM,GACN,OAAO,GACP,OAAO,GACP,QAAQ,GACR,OAAO,GACP,SAAS,GACT,OAAO,GACP,QAAQ,GACR,QAAQ,CAAC;AAEZ,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gCAAgC;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,qEAAqE;IACrE,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,yBAAyB;IACzC,yFAAyF;IACzF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IACzG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,gFAAgF;IAChF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,qEAAqE;IACrE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,yGAAyG;AACzG,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,UAAU,EAAE;QACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;QACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACxB,GAAG,IAAI,CAAC;IACT,QAAQ,CAAC,MAAM,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACpF,QAAQ,CAAC,SAAS,EAAE,SAAS;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAChH,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7F,QAAQ,CAAC,SAAS,EAAE;QACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;QACpC,QAAQ,CAAC,OAAO,EAAE,SAAS;YAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KACnF,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,YAAY,GAAG,aAAa,GAAG,MAAM,CAAC;AAExF,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC;IACvC,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IACpC,qGAAqG;IACrG,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,EAAE,EAAE,gBAAgB,CAAC;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,YAAY,GAAG,OAAO,CAAC;AAC9F,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE/D,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;IAC1C,kDAAkD;IAClD,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,oBAAoB,CAAC;CACvC;AAED,MAAM,WAAW,sBAAsB;IACtC,gEAAgE;IAChE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1E,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,0BAA0B,GACnC,aAAa,GACb,YAAY,GACZ,eAAe,GACf,WAAW,GACX,WAAW,GACX,aAAa,CAAC;AAEjB,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;IAC5C,oCAAoC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,2BAA2B,GAAG,KAAK,GAAG,KAAK,CAAC;AAExD,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;IAC7C,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEnE,MAAM,MAAM,sBAAsB,GAC/B;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9E;IACA,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACvB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACzF;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChF;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExF,6FAA6F;AAC7F,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAEvE,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,KAAK,EAAE,sBAAsB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACtG,QAAQ,CAAC,KAAK,CAAC,EAAE,sBAAsB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACvG,aAAa,CAAC,KAAK,EAAE,2BAA2B,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAChH,mBAAmB,CAClB,KAAK,EAAE,sBAAsB,GAAG,SAAS,sBAAsB,EAAE,EACjE,OAAO,CAAC,EAAE,yBAAyB,GACjC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3B,eAAe,CAAC,IAAI,EAAE,qBAAqB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3G,mHAAmH;IACnH,QAAQ,CAAC,KAAK,EAAE,sBAAsB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACtG,cAAc,CAAC,KAAK,EAAE,yBAAyB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/G,cAAc,CAAC,KAAK,EAAE,yBAAyB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/G,iFAAiF;IACjF,WAAW,CAAC,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1E,IAAI,CAAC,KAAK,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9F,IAAI,CAAC,KAAK,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9F,KAAK,CAAC,KAAK,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAChG,QAAQ,CAAC,KAAK,EAAE,sBAAsB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACtG,IAAI,CAAC,KAAK,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9F,OAAO,CAAC,KAAK,EAAE,qBAAqB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACpG,QAAQ,CAAC,KAAK,EAAE,sBAAsB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACtG,sDAAsD;IACtD,KAAK,IAAI,IAAI,CAAC;CACd;AAED,MAAM,MAAM,qBAAqB,GAC9B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/E;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAChC,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IACpC,KAAK,CAAC,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;CACzC","sourcesContent":["/**\n * Browser capability contracts for the built-in Playwright plugin.\n *\n * The plugin is the product's single browser channel. Playwright itself is\n * never bundled: the driver resolves it from `<agentDir>/browser-deps` at\n * connect time and `browser_setup` installs it on first use. Everything here\n * is host-independent; hosts and tests inject a `BrowserRuntimeV1` whose\n * `connect()` yields a driver, so the capability layer never imports\n * Playwright types.\n */\nimport type { PluginResultV1 } from \"@agent-forge/plugin-sdk\";\n\nexport type BrowserLocatorKindV1 = \"css\" | \"id\" | \"role\" | \"text\" | \"test-id\";\n\nexport interface BrowserLocatorV1 {\n\treadonly kind: BrowserLocatorKindV1;\n\treadonly value: string;\n\t/** Accessible name refinement for `kind: \"role\"`. */\n\treadonly name?: string;\n}\n\nexport type BrowserWaitUntilV1 = \"commit\" | \"domcontentloaded\" | \"load\" | \"networkidle\";\n\nexport interface BrowserNavigateInputV1 {\n\treadonly url: string;\n\treadonly waitUntil?: BrowserWaitUntilV1;\n}\n\nexport interface BrowserSnapshotInputV1 {\n\treadonly includeDom?: boolean;\n\treadonly includeA11y?: boolean;\n\treadonly includeStyles?: boolean;\n\treadonly includeScreenshot?: boolean;\n}\n\nexport type BrowserLocatorActionKindV1 =\n\t| \"click\"\n\t| \"dblclick\"\n\t| \"rightclick\"\n\t| \"fill\"\n\t| \"type\"\n\t| \"press\"\n\t| \"hover\"\n\t| \"select\"\n\t| \"check\"\n\t| \"uncheck\"\n\t| \"clear\"\n\t| \"upload\"\n\t| \"scroll\";\n\nexport interface BrowserLocatorActionInputV1 {\n\treadonly locator: BrowserLocatorV1;\n\treadonly action: BrowserLocatorActionKindV1;\n\t/**\n\t * Value for `fill`, `type`, and `select`; for `upload` a single absolute\n\t * file path or a JSON array of paths; for `scroll` a `<direction>:<pixels>`\n\t * directive (`down:500`, `up:200`, `left:100`, `right:100`).\n\t */\n\treadonly value?: string;\n\t/** Key sequence for `press`. */\n\treadonly key?: string;\n\t/** Inter-key delay in milliseconds for `type`. */\n\treadonly delay?: number;\n}\n\nexport interface BrowserEvaluateInputV1 {\n\t/**\n\t * JavaScript expression evaluated via `page.evaluate`. Keep it a plain\n\t * expression (`document.title`, `1 + 1`); for multi-statement logic use an\n\t * IIFE string (`(() => { ... return x; })()`) — a bare `() => ...` string is\n\t * not invoked by Playwright and serializes to `undefined`.\n\t */\n\treadonly expression: string;\n\t/** JSON-serializable argument passed through to the page context. */\n\treadonly arg?: unknown;\n}\n\nexport interface BrowserConsoleReadInputV1 {\n\t/** Comma-combined level filter: error/warning/info/debug (`info` also matches `log`). */\n\treadonly level?: string;\n\t/** Substring filter on the message text. */\n\treadonly contains?: string;\n\t/** Most-recent count to return; defaults to 50. */\n\treadonly limit?: number;\n}\n\nexport interface BrowserConsoleEntryV1 {\n\treadonly type: string;\n\treadonly text: string;\n\treadonly location?: { readonly url: string; readonly lineNumber: number; readonly columnNumber: number };\n\treadonly timestamp: number;\n}\n\nexport interface BrowserNetworkReadInputV1 {\n\treadonly containsUrl?: string;\n\treadonly status?: number;\n\treadonly method?: string;\n\t/** Most-recent count to return; defaults to 50. */\n\treadonly limit?: number;\n}\n\nexport interface BrowserNetworkEntryV1 {\n\treadonly method: string;\n\treadonly url: string;\n\treadonly status: number;\n\treadonly timestamp: number;\n\t/** Wall-clock duration in milliseconds when the request timing is available. */\n\treadonly durationMs?: number;\n\t/** Response `content-length` in bytes when the header is present. */\n\treadonly sizeBytes?: number;\n}\n\n/** Raw in-page performance collection; the driver shapes it into {@link BrowserPerformancePayloadV1}. */\nexport interface BrowserPerformanceRawV1 {\n\treadonly navigation: {\n\t\treadonly ttfbMs: number;\n\t\treadonly domContentLoadedMs: number;\n\t\treadonly loadMs: number;\n\t} | null;\n\treadonly paints: readonly { readonly name: string; readonly startTimeMs: number }[];\n\treadonly resources: readonly { readonly url: string; readonly durationMs: number; readonly transferBytes: number }[];\n\treadonly domNodes: number;\n}\n\nexport interface BrowserPerformancePayloadV1 {\n\treadonly navigation?: { readonly ttfbMs: number; readonly domContentLoadedMs: number; readonly loadMs: number };\n\treadonly paint: { readonly firstPaintMs?: number; readonly firstContentfulPaintMs?: number };\n\treadonly resources: {\n\t\treadonly count: number;\n\t\treadonly totalTransferBytes: number;\n\t\treadonly slowest: readonly { readonly url: string; readonly durationMs: number }[];\n\t};\n\treadonly domNodes: number;\n}\n\nexport type BrowserWaitUntilKindV1 = \"selector\" | \"navigation\" | \"networkidle\" | \"time\";\n\nexport interface BrowserWaitInputV1 {\n\treadonly until: BrowserWaitUntilKindV1;\n\t/** Locator for `until: \"selector\"` (waits for the element to be visible). */\n\treadonly locator?: BrowserLocatorV1;\n\t/** Milliseconds; required for `until: \"time\"`, optional timeout for the others. Clamped to 30000. */\n\treadonly ms?: number;\n}\n\nexport interface BrowserDragInputV1 {\n\treadonly from: BrowserLocatorV1;\n\treadonly to: BrowserLocatorV1;\n\t/** Number of intermediate mouse moves over the target; defaults to 8. */\n\treadonly steps?: number;\n}\n\nexport type BrowserMouseActionKindV1 = \"move\" | \"click\" | \"dblclick\" | \"rightclick\" | \"wheel\";\nexport type BrowserMouseButtonV1 = \"left\" | \"right\" | \"middle\";\n\nexport interface BrowserMouseInputV1 {\n\treadonly action: BrowserMouseActionKindV1;\n\t/** Non-negative integer viewport x coordinate. */\n\treadonly x: number;\n\t/** Non-negative integer viewport y coordinate. */\n\treadonly y: number;\n\t/** Horizontal wheel delta in pixels (`wheel`). */\n\treadonly deltaX?: number;\n\t/** Vertical wheel delta in pixels (`wheel`). */\n\treadonly deltaY?: number;\n\treadonly button?: BrowserMouseButtonV1;\n}\n\nexport interface BrowserPressKeyInputV1 {\n\t/** Playwright key name, e.g. `Control+a`, `Enter`, `Meta+c`. */\n\treadonly key: string;\n\t/** Delay between keydown and keyup in milliseconds. */\n\treadonly delay?: number;\n}\n\nexport type BrowserTabsActionKindV1 = \"list\" | \"new\" | \"switch\" | \"close\";\n\nexport interface BrowserTabsInputV1 {\n\treadonly action: BrowserTabsActionKindV1;\n\t/** Tab index for `switch` and `close`. */\n\treadonly index?: number;\n\t/** URL for `new`; defaults to `about:blank`. */\n\treadonly url?: string;\n}\n\nexport type BrowserStorageActionKindV1 =\n\t| \"get-cookies\"\n\t| \"set-cookie\"\n\t| \"clear-cookies\"\n\t| \"get-local\"\n\t| \"set-local\"\n\t| \"clear-local\";\n\nexport interface BrowserStorageInputV1 {\n\treadonly action: BrowserStorageActionKindV1;\n\t/** Cookie name for `set-cookie`. */\n\treadonly name?: string;\n\t/** Cookie value for `set-cookie`; localStorage value for `set-local`. */\n\treadonly value?: string;\n\t/** Cookie domain for `set-cookie` (Playwright requires domain or url). */\n\treadonly domain?: string;\n\treadonly path?: string;\n\t/** Cookie expiry as Unix seconds; omit for a session cookie. */\n\treadonly expires?: number;\n\t/** localStorage key for `get-local` and `set-local`. */\n\treadonly key?: string;\n}\n\nexport type BrowserViewportActionKindV1 = \"set\" | \"get\";\n\nexport interface BrowserViewportInputV1 {\n\treadonly action: BrowserViewportActionKindV1;\n\t/** Requested width; clamped into 320..7680. */\n\treadonly width?: number;\n\t/** Requested height; clamped into 320..7680. */\n\treadonly height?: number;\n}\n\nexport type BrowserElementStateV1 = \"visible\" | \"hidden\" | \"value\";\n\nexport type BrowserPostconditionV1 =\n\t| { readonly kind: \"url\"; readonly equals?: string; readonly contains?: string }\n\t| {\n\t\t\treadonly kind: \"element\";\n\t\t\treadonly locator: BrowserLocatorV1;\n\t\t\treadonly state: BrowserElementStateV1;\n\t\t\treadonly value?: string;\n\t }\n\t| { readonly kind: \"text\"; readonly locator?: BrowserLocatorV1; readonly contains: string }\n\t| { readonly kind: \"console\"; readonly contains: string; readonly level?: string }\n\t| { readonly kind: \"network\"; readonly containsUrl: string; readonly status?: number };\n\n/** `browser_collect_evidence` kinds; console/network come from bounded page ring buffers. */\nexport type BrowserEvidenceKindV1 = \"console\" | \"network\" | \"snapshot\";\n\nexport interface BrowserOperationOptionsV1 {\n\treadonly operationId?: string;\n\treadonly signal?: AbortSignal;\n}\n\n/**\n * Driver contract behind `BrowserRuntimeV1`. Every operation returns a\n * validated `PluginResultV1`; failures are structured results, not throws\n * (module/install problems surface as thrown errors at `connect` time and are\n * sanitized by the capability layer). Structured payloads (console/network\n * entries, performance metrics, evaluate results, storage and tab state) are\n * carried as bounded JSON text in evidence summaries.\n */\nexport interface BrowserDriverV1 {\n\tnavigate(input: BrowserNavigateInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tsnapshot(input?: BrowserSnapshotInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tlocatorAction(input: BrowserLocatorActionInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tassertPostcondition(\n\t\tinput: BrowserPostconditionV1 | readonly BrowserPostconditionV1[],\n\t\toptions?: BrowserOperationOptionsV1,\n\t): Promise<PluginResultV1>;\n\tcollectEvidence(kind: BrowserEvidenceKindV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\t/** Escape hatch: runs a JS expression in the page context; use only when no built-in tool covers the operation. */\n\tevaluate(input: BrowserEvaluateInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tconsoleEntries(input: BrowserConsoleReadInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tnetworkEntries(input: BrowserNetworkReadInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\t/** Navigation Timing, paint, resource summary, and DOM node count; read-only. */\n\tperformance(options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\twait(input: BrowserWaitInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tdrag(input: BrowserDragInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tmouse(input: BrowserMouseInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tpressKey(input: BrowserPressKeyInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\ttabs(input: BrowserTabsInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tstorage(input: BrowserStorageInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tviewport(input: BrowserViewportInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\t/** Idempotent, best-effort teardown; never throws. */\n\tclose(): void;\n}\n\nexport type BrowserSetupOutcomeV1 =\n\t| { readonly ok: true; readonly alreadyInstalled: boolean; readonly log: string }\n\t| { readonly ok: false; readonly message: string };\n\n/**\n * Injection face for the capability factory. Tests bind a fake runtime over a\n * mock driver; the production entry binds `PlaywrightBrowserRuntimeV1`, whose\n * optional `setup()` self-installs Playwright into `<agentDir>/browser-deps`.\n */\nexport interface BrowserRuntimeV1 {\n\tconnect(): Promise<BrowserDriverV1>;\n\tsetup?(): Promise<BrowserSetupOutcomeV1>;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Browser capability contracts for the built-in Playwright plugin.\n *\n * The plugin is the product's single browser channel. Playwright itself is\n * never bundled: the driver resolves it from `<agentDir>/browser-deps` at\n * connect time and `browser_setup` installs it on first use. Everything here\n * is host-independent; hosts and tests inject a `BrowserRuntimeV1` whose\n * `connect()` yields a driver, so the capability layer never imports\n * Playwright types.\n */\nimport type { PluginResultV1 } from \"@agent-forge/plugin-sdk\";\n\nexport type BrowserLocatorKindV1 = \"css\" | \"id\" | \"role\" | \"text\" | \"test-id\";\n\nexport interface BrowserLocatorV1 {\n\treadonly kind: BrowserLocatorKindV1;\n\treadonly value: string;\n\t/** Accessible name refinement for `kind: \"role\"`. */\n\treadonly name?: string;\n}\n\nexport type BrowserWaitUntilV1 = \"commit\" | \"domcontentloaded\" | \"load\" | \"networkidle\";\n\nexport interface BrowserNavigateInputV1 {\n\treadonly url: string;\n\treadonly waitUntil?: BrowserWaitUntilV1;\n}\n\nexport interface BrowserSnapshotInputV1 {\n\treadonly includeDom?: boolean;\n\treadonly includeA11y?: boolean;\n\treadonly includeStyles?: boolean;\n\treadonly includeScreenshot?: boolean;\n}\n\nexport type BrowserLocatorActionKindV1 =\n\t| \"click\"\n\t| \"dblclick\"\n\t| \"rightclick\"\n\t| \"fill\"\n\t| \"type\"\n\t| \"press\"\n\t| \"hover\"\n\t| \"select\"\n\t| \"check\"\n\t| \"uncheck\"\n\t| \"clear\"\n\t| \"upload\"\n\t| \"scroll\";\n\nexport interface BrowserLocatorActionInputV1 {\n\treadonly locator: BrowserLocatorV1;\n\treadonly action: BrowserLocatorActionKindV1;\n\t/**\n\t * Value for `fill`, `type`, and `select`; for `upload` a single absolute\n\t * file path or a JSON array of paths; for `scroll` a `<direction>:<pixels>`\n\t * directive (`down:500`, `up:200`, `left:100`, `right:100`).\n\t */\n\treadonly value?: string;\n\t/** Key sequence for `press`. */\n\treadonly key?: string;\n\t/** Inter-key delay in milliseconds for `type`. */\n\treadonly delay?: number;\n}\n\nexport interface BrowserEvaluateInputV1 {\n\t/**\n\t * JavaScript expression evaluated via `page.evaluate`. Keep it a plain\n\t * expression (`document.title`, `1 + 1`); for multi-statement logic use an\n\t * IIFE string (`(() => { ... return x; })()`) — a bare `() => ...` string is\n\t * not invoked by Playwright and serializes to `undefined`.\n\t */\n\treadonly expression: string;\n\t/** JSON-serializable argument passed through to the page context. */\n\treadonly arg?: unknown;\n}\n\nexport interface BrowserConsoleReadInputV1 {\n\t/** Comma-combined level filter: error/warning/info/debug (`info` also matches `log`). */\n\treadonly level?: string;\n\t/** Substring filter on the message text. */\n\treadonly contains?: string;\n\t/** Most-recent count to return; defaults to 50. */\n\treadonly limit?: number;\n}\n\nexport interface BrowserConsoleEntryV1 {\n\treadonly type: string;\n\treadonly text: string;\n\treadonly location?: { readonly url: string; readonly lineNumber: number; readonly columnNumber: number };\n\treadonly timestamp: number;\n}\n\nexport interface BrowserNetworkReadInputV1 {\n\treadonly containsUrl?: string;\n\treadonly status?: number;\n\treadonly method?: string;\n\t/** Most-recent count to return; defaults to 50. */\n\treadonly limit?: number;\n}\n\nexport interface BrowserNetworkEntryV1 {\n\treadonly method: string;\n\treadonly url: string;\n\treadonly status: number;\n\treadonly timestamp: number;\n\t/** Wall-clock duration in milliseconds when the request timing is available. */\n\treadonly durationMs?: number;\n\t/** Response `content-length` in bytes when the header is present. */\n\treadonly sizeBytes?: number;\n}\n\n/** Raw in-page performance collection; the driver shapes it into {@link BrowserPerformancePayloadV1}. */\nexport interface BrowserPerformanceRawV1 {\n\treadonly navigation: {\n\t\treadonly ttfbMs: number;\n\t\treadonly domContentLoadedMs: number;\n\t\treadonly loadMs: number;\n\t} | null;\n\treadonly paints: readonly { readonly name: string; readonly startTimeMs: number }[];\n\treadonly resources: readonly { readonly url: string; readonly durationMs: number; readonly transferBytes: number }[];\n\treadonly domNodes: number;\n}\n\nexport interface BrowserPerformancePayloadV1 {\n\treadonly navigation?: { readonly ttfbMs: number; readonly domContentLoadedMs: number; readonly loadMs: number };\n\treadonly paint: { readonly firstPaintMs?: number; readonly firstContentfulPaintMs?: number };\n\treadonly resources: {\n\t\treadonly count: number;\n\t\treadonly totalTransferBytes: number;\n\t\treadonly slowest: readonly { readonly url: string; readonly durationMs: number }[];\n\t};\n\treadonly domNodes: number;\n}\n\nexport type BrowserWaitUntilKindV1 = \"selector\" | \"navigation\" | \"networkidle\" | \"time\";\n\nexport interface BrowserWaitInputV1 {\n\treadonly until: BrowserWaitUntilKindV1;\n\t/** Locator for `until: \"selector\"` (waits for the element to be visible). */\n\treadonly locator?: BrowserLocatorV1;\n\t/** Milliseconds; required for `until: \"time\"`, optional timeout for the others. Clamped to 30000. */\n\treadonly ms?: number;\n}\n\nexport interface BrowserDragInputV1 {\n\treadonly from: BrowserLocatorV1;\n\treadonly to: BrowserLocatorV1;\n\t/** Number of intermediate mouse moves over the target; defaults to 8. */\n\treadonly steps?: number;\n}\n\nexport type BrowserMouseActionKindV1 = \"move\" | \"click\" | \"dblclick\" | \"rightclick\" | \"wheel\";\nexport type BrowserMouseButtonV1 = \"left\" | \"right\" | \"middle\";\n\nexport interface BrowserMouseInputV1 {\n\treadonly action: BrowserMouseActionKindV1;\n\t/** Non-negative integer viewport x coordinate. */\n\treadonly x: number;\n\t/** Non-negative integer viewport y coordinate. */\n\treadonly y: number;\n\t/** Horizontal wheel delta in pixels (`wheel`). */\n\treadonly deltaX?: number;\n\t/** Vertical wheel delta in pixels (`wheel`). */\n\treadonly deltaY?: number;\n\treadonly button?: BrowserMouseButtonV1;\n}\n\nexport interface BrowserPressKeyInputV1 {\n\t/** Playwright key name, e.g. `Control+a`, `Enter`, `Meta+c`. */\n\treadonly key: string;\n\t/** Delay between keydown and keyup in milliseconds. */\n\treadonly delay?: number;\n}\n\nexport type BrowserTabsActionKindV1 = \"list\" | \"new\" | \"switch\" | \"close\";\n\nexport interface BrowserTabsInputV1 {\n\treadonly action: BrowserTabsActionKindV1;\n\t/** Tab index for `switch` and `close`. */\n\treadonly index?: number;\n\t/** URL for `new`; defaults to `about:blank`. */\n\treadonly url?: string;\n}\n\nexport type BrowserStorageActionKindV1 =\n\t| \"get-cookies\"\n\t| \"set-cookie\"\n\t| \"clear-cookies\"\n\t| \"get-local\"\n\t| \"set-local\"\n\t| \"clear-local\";\n\nexport interface BrowserStorageInputV1 {\n\treadonly action: BrowserStorageActionKindV1;\n\t/** Cookie name for `set-cookie`. */\n\treadonly name?: string;\n\t/** Cookie value for `set-cookie`; localStorage value for `set-local`. */\n\treadonly value?: string;\n\t/** Cookie domain for `set-cookie` (Playwright requires domain or url). */\n\treadonly domain?: string;\n\treadonly path?: string;\n\t/** Cookie expiry as Unix seconds; omit for a session cookie. */\n\treadonly expires?: number;\n\t/** localStorage key for `get-local` and `set-local`. */\n\treadonly key?: string;\n}\n\nexport type BrowserViewportActionKindV1 = \"set\" | \"get\";\n\nexport interface BrowserViewportInputV1 {\n\treadonly action: BrowserViewportActionKindV1;\n\t/** Requested width; clamped into 320..7680. */\n\treadonly width?: number;\n\t/** Requested height; clamped into 320..7680. */\n\treadonly height?: number;\n}\n\nexport type BrowserElementStateV1 = \"visible\" | \"hidden\" | \"value\";\n\nexport type BrowserPostconditionV1 =\n\t| { readonly kind: \"url\"; readonly equals?: string; readonly contains?: string }\n\t| {\n\t\t\treadonly kind: \"element\";\n\t\t\treadonly locator: BrowserLocatorV1;\n\t\t\treadonly state: BrowserElementStateV1;\n\t\t\treadonly value?: string;\n\t }\n\t| { readonly kind: \"text\"; readonly locator?: BrowserLocatorV1; readonly contains: string }\n\t| { readonly kind: \"console\"; readonly contains: string; readonly level?: string }\n\t| { readonly kind: \"network\"; readonly containsUrl: string; readonly status?: number };\n\n/** `browser_collect_evidence` kinds; console/network come from bounded page ring buffers. */\nexport type BrowserEvidenceKindV1 = \"console\" | \"network\" | \"snapshot\";\n\nexport interface BrowserOperationOptionsV1 {\n\treadonly operationId?: string;\n\treadonly signal?: AbortSignal;\n}\n\n/**\n * Driver contract behind `BrowserRuntimeV1`. Every operation returns a\n * validated `PluginResultV1`; failures are structured results, not throws\n * (module/install problems surface as thrown errors at `connect` time and are\n * sanitized by the capability layer). Structured payloads (console/network\n * entries, performance metrics, evaluate results, storage and tab state) are\n * carried as bounded JSON text in evidence summaries.\n */\nexport interface BrowserDriverV1 {\n\tnavigate(input: BrowserNavigateInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tsnapshot(input?: BrowserSnapshotInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tlocatorAction(input: BrowserLocatorActionInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tassertPostcondition(\n\t\tinput: BrowserPostconditionV1 | readonly BrowserPostconditionV1[],\n\t\toptions?: BrowserOperationOptionsV1,\n\t): Promise<PluginResultV1>;\n\tcollectEvidence(kind: BrowserEvidenceKindV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\t/** Escape hatch: runs a JS expression in the page context; use only when no built-in tool covers the operation. */\n\tevaluate(input: BrowserEvaluateInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tconsoleEntries(input: BrowserConsoleReadInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tnetworkEntries(input: BrowserNetworkReadInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\t/** Navigation Timing, paint, resource summary, and DOM node count; read-only. */\n\tperformance(options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\twait(input: BrowserWaitInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tdrag(input: BrowserDragInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tmouse(input: BrowserMouseInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tpressKey(input: BrowserPressKeyInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\ttabs(input: BrowserTabsInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tstorage(input: BrowserStorageInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\tviewport(input: BrowserViewportInputV1, options?: BrowserOperationOptionsV1): Promise<PluginResultV1>;\n\t/** Idempotent, best-effort teardown; never throws. */\n\tclose(): void;\n}\n\nexport type BrowserSetupOutcomeV1 =\n\t| { readonly ok: true; readonly alreadyInstalled: boolean; readonly log: string }\n\t| { readonly ok: false; readonly message: string };\n\n/**\n * Injection face for the capability factory. Tests bind a fake runtime over a\n * mock driver; the production entry binds `PlaywrightBrowserRuntimeV1`, whose\n * optional `setup()` self-installs Playwright into `<agentDir>/browser-deps`.\n */\nexport interface BrowserRuntimeV1 {\n\tconnect(): Promise<BrowserDriverV1>;\n\tsetup?(): Promise<BrowserSetupOutcomeV1>;\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "agent-forge.plugin.browser-playwright",
|
|
3
|
+
"version": "0.88.7",
|
|
4
|
+
"apiVersion": "1-draft",
|
|
5
|
+
"entry": "./dist/entry.js",
|
|
6
|
+
"hostVersion": ">=0.84.4",
|
|
7
|
+
"description": "浏览器调试/测试/抓取:Playwright 17 工具(导航/DOM 与 a11y 快照/点击填写/拖拽/滚动/截图/console/网络/性能/存储/多标签),首次使用先 browser_setup 自装 Playwright",
|
|
8
|
+
"activation": "on-demand",
|
|
9
|
+
"manual": "./MANUAL.md",
|
|
10
|
+
"requiredCapabilities": [
|
|
11
|
+
"tools"
|
|
12
|
+
],
|
|
13
|
+
"provides": [
|
|
14
|
+
{
|
|
15
|
+
"id": "browser",
|
|
16
|
+
"version": 1,
|
|
17
|
+
"kind": "contribution"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -29,11 +29,6 @@ export interface BashToolOptions {
|
|
|
29
29
|
/** Hook to adjust command, cwd, or env before execution */
|
|
30
30
|
spawnHook?: BashSpawnHook;
|
|
31
31
|
}
|
|
32
|
-
export type BashRenderState = {
|
|
33
|
-
startedAt: number | undefined;
|
|
34
|
-
endedAt: number | undefined;
|
|
35
|
-
interval: NodeJS.Timeout | undefined;
|
|
36
|
-
};
|
|
37
32
|
export interface ShellToolConfig {
|
|
38
33
|
name: string;
|
|
39
34
|
label: string;
|
|
@@ -43,7 +38,7 @@ export interface ShellToolConfig {
|
|
|
43
38
|
promptGuidelines?: readonly string[];
|
|
44
39
|
tempFilePrefix: string;
|
|
45
40
|
}
|
|
46
|
-
export declare function createShellToolDefinition(cwd: string, config: ShellToolConfig, options?: BashToolOptions): ToolDefinition<typeof bashSchema, BashToolDetails | undefined
|
|
47
|
-
export declare function createBashToolDefinition(cwd: string, options?: BashToolOptions): ToolDefinition<typeof bashSchema, BashToolDetails | undefined
|
|
41
|
+
export declare function createShellToolDefinition(cwd: string, config: ShellToolConfig, options?: BashToolOptions): ToolDefinition<typeof bashSchema, BashToolDetails | undefined>;
|
|
42
|
+
export declare function createBashToolDefinition(cwd: string, options?: BashToolOptions): ToolDefinition<typeof bashSchema, BashToolDetails | undefined>;
|
|
48
43
|
export declare function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema>;
|
|
49
44
|
//# sourceMappingURL=bash.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../src/bash.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,yBAAyB,EACzB,0BAA0B,EAC1B,MAAM,mCAAmC,CAAC;AAO3C,OAAO,KAAK,EAAE,cAAc,EAA+C,MAAM,mCAAmC,CAAC;AACrH,OAAO,EAAoD,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGrH,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,KAAK,SAAS,EAAsB,MAAM,YAAY,CAAC;AAIhE,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,yBAAyB,EACzB,0BAA0B,GAC1B,CAAC;AAEF,QAAA,MAAM,UAAU;;;EAGd,CAAC;AAEH,eAAO,MAAM,gCAAgC;;;CAGnC,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AA8BD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wGAAwG;IACxG,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2DAA2D;IAC3D,SAAS,CAAC,EAAE,aAAa,CAAC;CAC1B;AAKD,MAAM,MAAM,eAAe,GAAG;IAC7B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;CACrC,CAAC;AAoHF,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,eAAe,EACvB,OAAO,CAAC,EAAE,eAAe,GACvB,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CA0LjF;AAYD,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAEjF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAQnG","sourcesContent":["// Migrated from packages/agent-forge/src/core/tools/bash.ts (batch 1, copy-then-delete);\n// host modules are imported through supply keys (@agent-forge/host/*).\n\nimport {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\tcreateLocalBashOperations,\n\tcreateLocalShellOperations,\n} from \"@agent-forge/host/bash-operations\";\nimport { t } from \"@agent-forge/host/i18n\";\nimport { keyHint } from \"@agent-forge/host/keybinding-hints\";\nimport { OutputAccumulator } from \"@agent-forge/host/output-accumulator\";\nimport { getTextOutput, invalidArgText, str } from \"@agent-forge/host/render-utils\";\nimport { getShellEnv } from \"@agent-forge/host/shell\";\nimport { theme } from \"@agent-forge/host/theme\";\nimport type { ToolDefinition, ToolExecuteContext, ToolRenderResultOptions } from \"@agent-forge/host/tool-definition\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from \"@agent-forge/host/truncate\";\nimport { truncateToVisualLines } from \"@agent-forge/host/visual-truncate\";\nimport { Container, Text, truncateToWidth } from \"@agent-forge/tui\";\nimport { type Static, Type } from \"typebox\";\nimport { type AgentTool, wrapToolDefinition } from \"./types.ts\";\n\n// Operations layer shared with plugins via the \"@agent-forge/host/bash-operations\"\n// virtual module; re-exported so the existing host import surface keeps resolving.\nexport {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\tcreateLocalBashOperations,\n\tcreateLocalShellOperations,\n};\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Shell command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\nexport const bashToolSystemPromptContribution = {\n\tsnippet: \"Execute bash commands (ls, grep, find, etc.)\",\n\tguidelines: [\"You can inspect AGENT_FORGE_* environment variables for current model and session details.\"],\n} as const;\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n}\n\nfunction resolveSpawnContext(\n\tcommand: string,\n\tcwd: string,\n\tspawnHook: BashSpawnHook | undefined,\n\texposeSessionEnvironment: boolean,\n\tctx: ToolExecuteContext | undefined,\n): BashSpawnContext {\n\tconst env = { ...getShellEnv() };\n\tdelete env.AGENT_FORGE_SESSION_ID;\n\tdelete env.AGENT_FORGE_SESSION_FILE;\n\tdelete env.AGENT_FORGE_PROVIDER;\n\tdelete env.AGENT_FORGE_MODEL;\n\tdelete env.AGENT_FORGE_REASONING_LEVEL;\n\tif (exposeSessionEnvironment && ctx) {\n\t\tconst model = ctx.model;\n\t\tenv.AGENT_FORGE_SESSION_ID = ctx.sessionManager.getSessionId();\n\t\tconst sessionFile = ctx.sessionManager.getSessionFile();\n\t\tif (sessionFile) env.AGENT_FORGE_SESSION_FILE = sessionFile;\n\t\tif (model) {\n\t\t\tenv.AGENT_FORGE_PROVIDER = model.provider;\n\t\t\tenv.AGENT_FORGE_MODEL = model.id;\n\t\t}\n\t\tif (ctx.thinkingLevel) env.AGENT_FORGE_REASONING_LEVEL = ctx.thinkingLevel;\n\t}\n\tconst baseContext: BashSpawnContext = { command, cwd, env };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Expose current Agent Forge session metadata as AGENT_FORGE_* environment variables. Default: true */\n\texposeSessionEnvironment?: boolean;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n}\n\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\n\nexport type BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\n\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n};\n\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t};\n}\n\nfunction formatDuration(ms: number): string {\n\tconst seconds = ms / 1000;\n\tif (seconds < 60) return `${seconds.toFixed(1)}s`;\n\n\tconst totalSeconds = Math.floor(seconds);\n\tconst minutes = Math.floor(totalSeconds / 60);\n\tconst remainder = totalSeconds % 60;\n\tif (minutes < 60) return `${minutes}m ${remainder}s`;\n\n\treturn `${Math.floor(minutes / 60)}h ${minutes % 60}m ${remainder}s`;\n}\n\nfunction formatShellCall(args: { command?: string; timeout?: number } | undefined, prompt: string): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`${prompt} ${commandDisplay}`)) + timeoutSuffix;\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\t// Cache the complete output: this renders on every frame for every bash result in the transcript.\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tconst hintLines: string[] = [];\n\t\t\t\t\t\tif (preview.skippedCount > 0) {\n\t\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${preview.skippedCount} earlier lines,`) +\n\t\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"to expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t\t\t\t\t\thintLines.push(truncateToWidth(hint, width, \"...\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.cachedLines = [\"\", ...hintLines, ...preview.visualLines];\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\treturn state.cachedLines;\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\n\nexport interface ShellToolConfig {\n\tname: string;\n\tlabel: string;\n\tshellName: string;\n\tprompt: string;\n\tpromptSnippet: string;\n\tpromptGuidelines?: readonly string[];\n\ttempFilePrefix: string;\n}\n\nexport function createShellToolDefinition(\n\tcwd: string,\n\tconfig: ShellToolConfig,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\n\tconst spawnHook = options?.spawnHook;\n\treturn {\n\t\tname: config.name,\n\t\tlabel: config.label,\n\t\tdescription: `Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tpromptSnippet: config.promptSnippet,\n\t\tpromptGuidelines: exposeSessionEnvironment && config.promptGuidelines ? [...config.promptGuidelines] : undefined,\n\t\tparameters: bashSchema,\n\t\tconstrainedSampling: { type: \"json_schema\", strict: \"prefer\" },\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ command, timeout }: { command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\tctx?: ToolExecuteContext,\n\t\t) {\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(\n\t\t\t\tresolvedCommand,\n\t\t\t\tctx?.cwd || cwd,\n\t\t\t\tspawnHook,\n\t\t\t\texposeSessionEnvironment,\n\t\t\t\tctx,\n\t\t\t);\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: config.tempFilePrefix });\n\t\t\tlet acceptingOutput = true;\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\tif (!acceptingOutput) return;\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\n\t\t\tconst finishOutput = async () => {\n\t\t\t\tacceptingOutput = false;\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, t(\"Command aborted\")));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\tappendStatus(text, t(\"Command timed out after {seconds} seconds\", { seconds: timeoutSecs })),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode === null) {\n\t\t\t\t\tthrow new Error(appendStatus(outputText, t(\"Command terminated without an exit code\")));\n\t\t\t\t}\n\t\t\t\tif (exitCode !== 0) {\n\t\t\t\t\tthrow new Error(appendStatus(outputText, t(\"Command exited with code {exitCode}\", { exitCode })));\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details };\n\t\t\t} finally {\n\t\t\t\tclearUpdateTimer();\n\t\t\t}\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatShellCall(args, config.prompt));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nconst bashToolConfig: ShellToolConfig = {\n\tname: \"bash\",\n\tlabel: \"bash\",\n\tshellName: \"bash\",\n\tprompt: \"$\",\n\tpromptSnippet: bashToolSystemPromptContribution.snippet,\n\tpromptGuidelines: bashToolSystemPromptContribution.guidelines,\n\ttempFilePrefix: \"agent-forge-bash\",\n};\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\treturn createShellToolDefinition(cwd, bashToolConfig, options);\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\tconst definition = createBashToolDefinition(cwd, options);\n\tconst tool = wrapToolDefinition(definition);\n\tObject.assign(tool, {\n\t\tpromptSnippet: definition.promptSnippet,\n\t\tpromptGuidelines: definition.promptGuidelines,\n\t});\n\treturn tool;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../src/bash.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,yBAAyB,EACzB,0BAA0B,EAC1B,MAAM,mCAAmC,CAAC;AAO3C,OAAO,KAAK,EAAE,cAAc,EAA+C,MAAM,mCAAmC,CAAC;AACrH,OAAO,EAAoD,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGrH,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,KAAK,SAAS,EAAsB,MAAM,YAAY,CAAC;AAIhE,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,yBAAyB,EACzB,0BAA0B,GAC1B,CAAC;AAEF,QAAA,MAAM,UAAU;;;EAGd,CAAC;AAEH,eAAO,MAAM,gCAAgC;;;CAGnC,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AA8BD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wGAAwG;IACxG,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2DAA2D;IAC3D,SAAS,CAAC,EAAE,aAAa,CAAC;CAC1B;AAmGD,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,cAAc,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,eAAe,EACvB,OAAO,CAAC,EAAE,eAAe,GACvB,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,CAAC,CAmKhE;AAYD,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,CAAC,CAEhE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAQnG","sourcesContent":["// Migrated from packages/agent-forge/src/core/tools/bash.ts (batch 1, copy-then-delete);\n// host modules are imported through supply keys (@agent-forge/host/*).\n\nimport {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\tcreateLocalBashOperations,\n\tcreateLocalShellOperations,\n} from \"@agent-forge/host/bash-operations\";\nimport { t } from \"@agent-forge/host/i18n\";\nimport { keyHint } from \"@agent-forge/host/keybinding-hints\";\nimport { OutputAccumulator } from \"@agent-forge/host/output-accumulator\";\nimport { getTextOutput, invalidArgText, str } from \"@agent-forge/host/render-utils\";\nimport { getShellEnv } from \"@agent-forge/host/shell\";\nimport { theme } from \"@agent-forge/host/theme\";\nimport type { ToolDefinition, ToolExecuteContext, ToolRenderResultOptions } from \"@agent-forge/host/tool-definition\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from \"@agent-forge/host/truncate\";\nimport { truncateToVisualLines } from \"@agent-forge/host/visual-truncate\";\nimport { Container, Text, truncateToWidth } from \"@agent-forge/tui\";\nimport { type Static, Type } from \"typebox\";\nimport { type AgentTool, wrapToolDefinition } from \"./types.ts\";\n\n// Operations layer shared with plugins via the \"@agent-forge/host/bash-operations\"\n// virtual module; re-exported so the existing host import surface keeps resolving.\nexport {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\tcreateLocalBashOperations,\n\tcreateLocalShellOperations,\n};\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Shell command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\nexport const bashToolSystemPromptContribution = {\n\tsnippet: \"Execute bash commands (ls, grep, find, etc.)\",\n\tguidelines: [\"You can inspect AGENT_FORGE_* environment variables for current model and session details.\"],\n} as const;\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n}\n\nfunction resolveSpawnContext(\n\tcommand: string,\n\tcwd: string,\n\tspawnHook: BashSpawnHook | undefined,\n\texposeSessionEnvironment: boolean,\n\tctx: ToolExecuteContext | undefined,\n): BashSpawnContext {\n\tconst env = { ...getShellEnv() };\n\tdelete env.AGENT_FORGE_SESSION_ID;\n\tdelete env.AGENT_FORGE_SESSION_FILE;\n\tdelete env.AGENT_FORGE_PROVIDER;\n\tdelete env.AGENT_FORGE_MODEL;\n\tdelete env.AGENT_FORGE_REASONING_LEVEL;\n\tif (exposeSessionEnvironment && ctx) {\n\t\tconst model = ctx.model;\n\t\tenv.AGENT_FORGE_SESSION_ID = ctx.sessionManager.getSessionId();\n\t\tconst sessionFile = ctx.sessionManager.getSessionFile();\n\t\tif (sessionFile) env.AGENT_FORGE_SESSION_FILE = sessionFile;\n\t\tif (model) {\n\t\t\tenv.AGENT_FORGE_PROVIDER = model.provider;\n\t\t\tenv.AGENT_FORGE_MODEL = model.id;\n\t\t}\n\t\tif (ctx.thinkingLevel) env.AGENT_FORGE_REASONING_LEVEL = ctx.thinkingLevel;\n\t}\n\tconst baseContext: BashSpawnContext = { command, cwd, env };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Expose current Agent Forge session metadata as AGENT_FORGE_* environment variables. Default: true */\n\texposeSessionEnvironment?: boolean;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n}\n\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\n\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n};\n\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t};\n}\n\nfunction formatShellCall(args: { command?: string; timeout?: number } | undefined, prompt: string): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`${prompt} ${commandDisplay}`)) + timeoutSuffix;\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\t// Cache the complete output: this renders on every frame for every bash result in the transcript.\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tconst hintLines: string[] = [];\n\t\t\t\t\t\tif (preview.skippedCount > 0) {\n\t\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${preview.skippedCount} earlier lines,`) +\n\t\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"to expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t\t\t\t\t\thintLines.push(truncateToWidth(hint, width, \"...\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstate.cachedLines = [\"\", ...hintLines, ...preview.visualLines];\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\treturn state.cachedLines;\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n}\n\nexport interface ShellToolConfig {\n\tname: string;\n\tlabel: string;\n\tshellName: string;\n\tprompt: string;\n\tpromptSnippet: string;\n\tpromptGuidelines?: readonly string[];\n\ttempFilePrefix: string;\n}\n\nexport function createShellToolDefinition(\n\tcwd: string,\n\tconfig: ShellToolConfig,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined> {\n\tconst ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\n\tconst spawnHook = options?.spawnHook;\n\treturn {\n\t\tname: config.name,\n\t\tlabel: config.label,\n\t\tdescription: `Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tpromptSnippet: config.promptSnippet,\n\t\tpromptGuidelines: exposeSessionEnvironment && config.promptGuidelines ? [...config.promptGuidelines] : undefined,\n\t\tparameters: bashSchema,\n\t\tconstrainedSampling: { type: \"json_schema\", strict: \"prefer\" },\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ command, timeout }: { command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\tctx?: ToolExecuteContext,\n\t\t) {\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(\n\t\t\t\tresolvedCommand,\n\t\t\t\tctx?.cwd || cwd,\n\t\t\t\tspawnHook,\n\t\t\t\texposeSessionEnvironment,\n\t\t\t\tctx,\n\t\t\t);\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: config.tempFilePrefix });\n\t\t\tlet acceptingOutput = true;\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\tif (!acceptingOutput) return;\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\n\t\t\tconst finishOutput = async () => {\n\t\t\t\tacceptingOutput = false;\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, t(\"Command aborted\")));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\tappendStatus(text, t(\"Command timed out after {seconds} seconds\", { seconds: timeoutSecs })),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode === null) {\n\t\t\t\t\tthrow new Error(appendStatus(outputText, t(\"Command terminated without an exit code\")));\n\t\t\t\t}\n\t\t\t\tif (exitCode !== 0) {\n\t\t\t\t\tthrow new Error(appendStatus(outputText, t(\"Command exited with code {exitCode}\", { exitCode })));\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details };\n\t\t\t} finally {\n\t\t\t\tclearUpdateTimer();\n\t\t\t}\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatShellCall(args, config.prompt));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(component, result, options, context.showImages);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nconst bashToolConfig: ShellToolConfig = {\n\tname: \"bash\",\n\tlabel: \"bash\",\n\tshellName: \"bash\",\n\tprompt: \"$\",\n\tpromptSnippet: bashToolSystemPromptContribution.snippet,\n\tpromptGuidelines: bashToolSystemPromptContribution.guidelines,\n\ttempFilePrefix: \"agent-forge-bash\",\n};\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined> {\n\treturn createShellToolDefinition(cwd, bashToolConfig, options);\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\tconst definition = createBashToolDefinition(cwd, options);\n\tconst tool = wrapToolDefinition(definition);\n\tObject.assign(tool, {\n\t\tpromptSnippet: definition.promptSnippet,\n\t\tpromptGuidelines: definition.promptGuidelines,\n\t});\n\treturn tool;\n}\n"]}
|
|
@@ -54,17 +54,6 @@ class BashResultRenderComponent extends Container {
|
|
|
54
54
|
cachedLines: undefined,
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
-
function formatDuration(ms) {
|
|
58
|
-
const seconds = ms / 1000;
|
|
59
|
-
if (seconds < 60)
|
|
60
|
-
return `${seconds.toFixed(1)}s`;
|
|
61
|
-
const totalSeconds = Math.floor(seconds);
|
|
62
|
-
const minutes = Math.floor(totalSeconds / 60);
|
|
63
|
-
const remainder = totalSeconds % 60;
|
|
64
|
-
if (minutes < 60)
|
|
65
|
-
return `${minutes}m ${remainder}s`;
|
|
66
|
-
return `${Math.floor(minutes / 60)}h ${minutes % 60}m ${remainder}s`;
|
|
67
|
-
}
|
|
68
57
|
function formatShellCall(args, prompt) {
|
|
69
58
|
const command = str(args?.command);
|
|
70
59
|
const timeout = args?.timeout;
|
|
@@ -72,7 +61,7 @@ function formatShellCall(args, prompt) {
|
|
|
72
61
|
const commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg("toolOutput", "...");
|
|
73
62
|
return theme.fg("toolTitle", theme.bold(`${prompt} ${commandDisplay}`)) + timeoutSuffix;
|
|
74
63
|
}
|
|
75
|
-
function rebuildBashResultRenderComponent(component, result, options, showImages
|
|
64
|
+
function rebuildBashResultRenderComponent(component, result, options, showImages) {
|
|
76
65
|
const state = component.state;
|
|
77
66
|
component.clear();
|
|
78
67
|
let output = getTextOutput(result, showImages).trim();
|
|
@@ -131,11 +120,6 @@ function rebuildBashResultRenderComponent(component, result, options, showImages
|
|
|
131
120
|
}
|
|
132
121
|
component.addChild(new Text(`\n${theme.fg("warning", `[${warnings.join(". ")}]`)}`, 0, 0));
|
|
133
122
|
}
|
|
134
|
-
if (startedAt !== undefined) {
|
|
135
|
-
const label = options.isPartial ? "Elapsed" : "Took";
|
|
136
|
-
const endTime = endedAt ?? Date.now();
|
|
137
|
-
component.addChild(new Text(`\n${theme.fg("muted", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));
|
|
138
|
-
}
|
|
139
123
|
}
|
|
140
124
|
export function createShellToolDefinition(cwd, config, options) {
|
|
141
125
|
const ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });
|
|
@@ -271,29 +255,13 @@ export function createShellToolDefinition(cwd, config, options) {
|
|
|
271
255
|
}
|
|
272
256
|
},
|
|
273
257
|
renderCall(args, _theme, context) {
|
|
274
|
-
const state = context.state;
|
|
275
|
-
if (context.executionStarted && state.startedAt === undefined) {
|
|
276
|
-
state.startedAt = Date.now();
|
|
277
|
-
state.endedAt = undefined;
|
|
278
|
-
}
|
|
279
258
|
const text = context.lastComponent ?? new Text("", 0, 0);
|
|
280
259
|
text.setText(formatShellCall(args, config.prompt));
|
|
281
260
|
return text;
|
|
282
261
|
},
|
|
283
262
|
renderResult(result, options, _theme, context) {
|
|
284
|
-
const state = context.state;
|
|
285
|
-
if (state.startedAt !== undefined && options.isPartial && !state.interval) {
|
|
286
|
-
state.interval = setInterval(() => context.invalidate(), 1000);
|
|
287
|
-
}
|
|
288
|
-
if (!options.isPartial || context.isError) {
|
|
289
|
-
state.endedAt ??= Date.now();
|
|
290
|
-
if (state.interval) {
|
|
291
|
-
clearInterval(state.interval);
|
|
292
|
-
state.interval = undefined;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
263
|
const component = context.lastComponent ?? new BashResultRenderComponent();
|
|
296
|
-
rebuildBashResultRenderComponent(component, result, options, context.showImages
|
|
264
|
+
rebuildBashResultRenderComponent(component, result, options, context.showImages);
|
|
297
265
|
component.invalidate();
|
|
298
266
|
return component;
|
|
299
267
|
},
|