@pentoshi/clai 3.5.1 → 3.7.2
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/README.md +1 -1
- package/dist/agent/compaction-summary.d.ts +17 -0
- package/dist/agent/compaction-summary.js +64 -0
- package/dist/agent/compaction-summary.js.map +1 -0
- package/dist/agent/confirm-port.d.ts +3 -1
- package/dist/agent/confirm-port.js +5 -1
- package/dist/agent/confirm-port.js.map +1 -1
- package/dist/agent/context-manager.js +53 -24
- package/dist/agent/context-manager.js.map +1 -1
- package/dist/agent/events.d.ts +6 -0
- package/dist/agent/evidence-governor.d.ts +37 -0
- package/dist/agent/evidence-governor.js +70 -0
- package/dist/agent/evidence-governor.js.map +1 -0
- package/dist/agent/loop-guard.d.ts +29 -9
- package/dist/agent/loop-guard.js +117 -26
- package/dist/agent/loop-guard.js.map +1 -1
- package/dist/agent/must-continue.d.ts +56 -0
- package/dist/agent/must-continue.js +240 -0
- package/dist/agent/must-continue.js.map +1 -0
- package/dist/agent/outcomes.d.ts +101 -0
- package/dist/agent/outcomes.js +359 -0
- package/dist/agent/outcomes.js.map +1 -0
- package/dist/agent/plan-decision.d.ts +33 -0
- package/dist/agent/plan-decision.js +104 -0
- package/dist/agent/plan-decision.js.map +1 -0
- package/dist/agent/plan-tool.d.ts +34 -0
- package/dist/agent/plan-tool.js +594 -76
- package/dist/agent/plan-tool.js.map +1 -1
- package/dist/agent/project-root.d.ts +33 -0
- package/dist/agent/project-root.js +161 -0
- package/dist/agent/project-root.js.map +1 -0
- package/dist/agent/prompt-composer.d.ts +21 -0
- package/dist/agent/prompt-composer.js +46 -0
- package/dist/agent/prompt-composer.js.map +1 -0
- package/dist/agent/runner.d.ts +11 -1
- package/dist/agent/runner.js +1915 -886
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/scope-context.d.ts +3 -0
- package/dist/agent/scope-context.js +24 -0
- package/dist/agent/scope-context.js.map +1 -0
- package/dist/agent/scratch-write.d.ts +4 -0
- package/dist/agent/scratch-write.js +54 -0
- package/dist/agent/scratch-write.js.map +1 -0
- package/dist/agent/session-policy.d.ts +7 -0
- package/dist/agent/session-policy.js +61 -0
- package/dist/agent/session-policy.js.map +1 -1
- package/dist/agent/session-state.d.ts +41 -0
- package/dist/agent/session-state.js +107 -0
- package/dist/agent/session-state.js.map +1 -0
- package/dist/agent/step-budget.d.ts +14 -0
- package/dist/agent/step-budget.js +26 -0
- package/dist/agent/step-budget.js.map +1 -0
- package/dist/agent/task-analyzer.d.ts +12 -3
- package/dist/agent/task-analyzer.js +263 -23
- package/dist/agent/task-analyzer.js.map +1 -1
- package/dist/agent/task-evidence.d.ts +173 -0
- package/dist/agent/task-evidence.js +802 -0
- package/dist/agent/task-evidence.js.map +1 -0
- package/dist/agent/task-plan.d.ts +57 -0
- package/dist/agent/task-plan.js +147 -1
- package/dist/agent/task-plan.js.map +1 -1
- package/dist/agent/tool-call-parser.d.ts +19 -11
- package/dist/agent/tool-call-parser.js +96 -71
- package/dist/agent/tool-call-parser.js.map +1 -1
- package/dist/agent/tool-history.d.ts +34 -0
- package/dist/agent/tool-history.js +200 -0
- package/dist/agent/tool-history.js.map +1 -0
- package/dist/agent/tool-output-formatting.d.ts +13 -1
- package/dist/agent/tool-output-formatting.js +75 -22
- package/dist/agent/tool-output-formatting.js.map +1 -1
- package/dist/agent/turn-outcome.d.ts +11 -0
- package/dist/agent/turn-outcome.js +17 -0
- package/dist/agent/turn-outcome.js.map +1 -0
- package/dist/agent/turn-state.d.ts +11 -0
- package/dist/agent/turn-state.js +28 -0
- package/dist/agent/turn-state.js.map +1 -0
- package/dist/agent/workspace-orient.d.ts +75 -0
- package/dist/agent/workspace-orient.js +509 -0
- package/dist/agent/workspace-orient.js.map +1 -0
- package/dist/app/adapters/agent-event-adapter.d.ts +2 -13
- package/dist/app/adapters/agent-event-adapter.js +63 -25
- package/dist/app/adapters/agent-event-adapter.js.map +1 -1
- package/dist/app/adapters/current-agent-adapter.d.ts +0 -5
- package/dist/app/adapters/current-agent-adapter.js +4 -7
- package/dist/app/adapters/current-agent-adapter.js.map +1 -1
- package/dist/app/adapters/current-jobs-adapter.js +1 -0
- package/dist/app/adapters/current-jobs-adapter.js.map +1 -1
- package/dist/app/adapters/current-terminal-adapter.d.ts +0 -7
- package/dist/app/adapters/current-terminal-adapter.js +0 -7
- package/dist/app/adapters/current-terminal-adapter.js.map +1 -1
- package/dist/app/adapters/current-updates-adapter.d.ts +0 -5
- package/dist/app/adapters/current-updates-adapter.js +0 -5
- package/dist/app/adapters/current-updates-adapter.js.map +1 -1
- package/dist/app/adapters/in-memory-clipboard-adapter.d.ts +0 -5
- package/dist/app/adapters/in-memory-clipboard-adapter.js +0 -5
- package/dist/app/adapters/in-memory-clipboard-adapter.js.map +1 -1
- package/dist/app/commands/command.d.ts +0 -5
- package/dist/app/commands/command.js.map +1 -1
- package/dist/app/commands/registry.d.ts +0 -14
- package/dist/app/commands/registry.js +0 -20
- package/dist/app/commands/registry.js.map +1 -1
- package/dist/app/controllers/disposable.d.ts +0 -5
- package/dist/app/controllers/disposable.js +0 -5
- package/dist/app/controllers/disposable.js.map +1 -1
- package/dist/app/controllers/job-controller.d.ts +1 -5
- package/dist/app/controllers/job-controller.js +0 -4
- package/dist/app/controllers/job-controller.js.map +1 -1
- package/dist/app/controllers/plan-controller.d.ts +5 -8
- package/dist/app/controllers/plan-controller.js +30 -12
- package/dist/app/controllers/plan-controller.js.map +1 -1
- package/dist/app/controllers/session-controller.d.ts +17 -32
- package/dist/app/controllers/session-controller.js +60 -35
- package/dist/app/controllers/session-controller.js.map +1 -1
- package/dist/app/controllers/turn-controller.d.ts +2 -6
- package/dist/app/controllers/turn-controller.js +8 -8
- package/dist/app/controllers/turn-controller.js.map +1 -1
- package/dist/app/events/app-event.d.ts +4 -7
- package/dist/app/events/app-event.js +0 -6
- package/dist/app/events/app-event.js.map +1 -1
- package/dist/app/events/event-buffer.d.ts +6 -17
- package/dist/app/events/event-buffer.js +27 -24
- package/dist/app/events/event-buffer.js.map +1 -1
- package/dist/app/events/sequencer.d.ts +0 -9
- package/dist/app/events/sequencer.js +0 -4
- package/dist/app/events/sequencer.js.map +1 -1
- package/dist/app/ports/agent-port.d.ts +13 -3
- package/dist/app/ports/clipboard-port.d.ts +0 -5
- package/dist/app/ports/confirm-port.d.ts +0 -7
- package/dist/app/ports/jobs-port.d.ts +2 -5
- package/dist/app/ports/persistence-port.d.ts +0 -4
- package/dist/app/ports/secret-port.d.ts +0 -5
- package/dist/app/ports/terminal-port.d.ts +0 -6
- package/dist/app/ports/updates-port.d.ts +0 -4
- package/dist/attachments/service.d.ts +29 -0
- package/dist/attachments/service.js +47 -0
- package/dist/attachments/service.js.map +1 -0
- package/dist/commands/doctor.js +3 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/providers.js +0 -3
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/search-providers.d.ts +0 -33
- package/dist/commands/search-providers.js +0 -33
- package/dist/commands/search-providers.js.map +1 -1
- package/dist/commands/update.js +1 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js +22 -42
- package/dist/index.js.map +1 -1
- package/dist/llm/adapters/anthropic-tools.d.ts +99 -0
- package/dist/llm/adapters/anthropic-tools.js +225 -0
- package/dist/llm/adapters/anthropic-tools.js.map +1 -0
- package/dist/llm/adapters/gemini-tools.d.ts +54 -0
- package/dist/llm/adapters/gemini-tools.js +139 -0
- package/dist/llm/adapters/gemini-tools.js.map +1 -0
- package/dist/llm/adapters/ollama-tools.d.ts +18 -0
- package/dist/llm/adapters/ollama-tools.js +58 -0
- package/dist/llm/adapters/ollama-tools.js.map +1 -0
- package/dist/llm/adapters/openai-tools.d.ts +39 -0
- package/dist/llm/adapters/openai-tools.js +71 -0
- package/dist/llm/adapters/openai-tools.js.map +1 -0
- package/dist/llm/agentrouter.js +23 -4
- package/dist/llm/agentrouter.js.map +1 -1
- package/dist/llm/anthropic.js +93 -92
- package/dist/llm/anthropic.js.map +1 -1
- package/dist/llm/aws-mantle.js +93 -56
- package/dist/llm/aws-mantle.js.map +1 -1
- package/dist/llm/bynara.js +23 -4
- package/dist/llm/bynara.js.map +1 -1
- package/dist/llm/capabilities.d.ts +13 -6
- package/dist/llm/capabilities.js +113 -13
- package/dist/llm/capabilities.js.map +1 -1
- package/dist/llm/gemini.js +63 -48
- package/dist/llm/gemini.js.map +1 -1
- package/dist/llm/groq.js +23 -10
- package/dist/llm/groq.js.map +1 -1
- package/dist/llm/http.d.ts +22 -34
- package/dist/llm/http.js +97 -69
- package/dist/llm/http.js.map +1 -1
- package/dist/llm/kimchi.js +23 -4
- package/dist/llm/kimchi.js.map +1 -1
- package/dist/llm/nvidia.js +23 -4
- package/dist/llm/nvidia.js.map +1 -1
- package/dist/llm/ollama.js +49 -31
- package/dist/llm/ollama.js.map +1 -1
- package/dist/llm/openai.js +23 -4
- package/dist/llm/openai.js.map +1 -1
- package/dist/llm/openrouter.js +23 -4
- package/dist/llm/openrouter.js.map +1 -1
- package/dist/llm/qwen-cloud.js +23 -4
- package/dist/llm/qwen-cloud.js.map +1 -1
- package/dist/llm/router.d.ts +0 -6
- package/dist/llm/router.js +48 -21
- package/dist/llm/router.js.map +1 -1
- package/dist/llm/tool-protocol.d.ts +67 -0
- package/dist/llm/tool-protocol.js +278 -0
- package/dist/llm/tool-protocol.js.map +1 -0
- package/dist/modes/agent.d.ts +2 -1
- package/dist/modes/agent.js +4 -2
- package/dist/modes/agent.js.map +1 -1
- package/dist/modes/ask.d.ts +0 -18
- package/dist/modes/ask.js +71 -66
- package/dist/modes/ask.js.map +1 -1
- package/dist/os/cwd.d.ts +0 -21
- package/dist/os/cwd.js +0 -24
- package/dist/os/cwd.js.map +1 -1
- package/dist/os/pkgmgr.js +0 -6
- package/dist/os/pkgmgr.js.map +1 -1
- package/dist/prompts/index.d.ts +17 -21
- package/dist/prompts/index.js +131 -259
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/system.agent.md +242 -0
- package/dist/prompts/system.ask.md +56 -0
- package/dist/repl/prompt-line.js +0 -36
- package/dist/repl/prompt-line.js.map +1 -1
- package/dist/repl/slash-commands.d.ts +0 -9
- package/dist/repl/slash-commands.js +2 -23
- package/dist/repl/slash-commands.js.map +1 -1
- package/dist/repl.d.ts +5 -0
- package/dist/repl.js +176 -55
- package/dist/repl.js.map +1 -1
- package/dist/safety/classifier.js +17 -9
- package/dist/safety/classifier.js.map +1 -1
- package/dist/safety/engagement-policy.d.ts +46 -0
- package/dist/safety/engagement-policy.js +198 -0
- package/dist/safety/engagement-policy.js.map +1 -0
- package/dist/store/config.d.ts +7 -0
- package/dist/store/config.js +1 -0
- package/dist/store/config.js.map +1 -1
- package/dist/store/engagement.d.ts +115 -0
- package/dist/store/engagement.js +278 -0
- package/dist/store/engagement.js.map +1 -0
- package/dist/store/logs.d.ts +5 -0
- package/dist/store/logs.js +52 -2
- package/dist/store/logs.js.map +1 -1
- package/dist/store/plan.d.ts +59 -5
- package/dist/store/plan.js +182 -8
- package/dist/store/plan.js.map +1 -1
- package/dist/store/scope.d.ts +4 -1
- package/dist/store/scope.js +2 -2
- package/dist/store/scope.js.map +1 -1
- package/dist/tools/capabilities.d.ts +2 -0
- package/dist/tools/capabilities.js +101 -6
- package/dist/tools/capabilities.js.map +1 -1
- package/dist/tools/command-intent.d.ts +1 -0
- package/dist/tools/command-intent.js +31 -0
- package/dist/tools/command-intent.js.map +1 -1
- package/dist/tools/definitions.d.ts +20 -0
- package/dist/tools/definitions.js +578 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/elevated-shell.d.ts +60 -0
- package/dist/tools/elevated-shell.js +233 -0
- package/dist/tools/elevated-shell.js.map +1 -0
- package/dist/tools/file-diff.d.ts +125 -0
- package/dist/tools/file-diff.js +495 -0
- package/dist/tools/file-diff.js.map +1 -0
- package/dist/tools/fs.d.ts +11 -13
- package/dist/tools/fs.js +280 -80
- package/dist/tools/fs.js.map +1 -1
- package/dist/tools/http.d.ts +15 -0
- package/dist/tools/http.js +202 -61
- package/dist/tools/http.js.map +1 -1
- package/dist/tools/jobs.d.ts +71 -10
- package/dist/tools/jobs.js +403 -124
- package/dist/tools/jobs.js.map +1 -1
- package/dist/tools/net-ping-sweep.js +69 -16
- package/dist/tools/net-ping-sweep.js.map +1 -1
- package/dist/tools/nmap-runner.d.ts +19 -7
- package/dist/tools/nmap-runner.js +182 -80
- package/dist/tools/nmap-runner.js.map +1 -1
- package/dist/tools/pentest-workflows.d.ts +8 -0
- package/dist/tools/pentest-workflows.js +71 -0
- package/dist/tools/pentest-workflows.js.map +1 -0
- package/dist/tools/registry.d.ts +9 -0
- package/dist/tools/registry.js +272 -63
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/shell.d.ts +3 -0
- package/dist/tools/shell.js +35 -13
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/tool-types.d.ts +11 -0
- package/dist/tools/validate.d.ts +11 -0
- package/dist/tools/validate.js +53 -0
- package/dist/tools/validate.js.map +1 -1
- package/dist/tools/web/search.js +48 -4
- package/dist/tools/web/search.js.map +1 -1
- package/dist/tui-v2/app/App.js +25 -39
- package/dist/tui-v2/app/App.js.map +1 -1
- package/dist/tui-v2/app/command-handlers.js +20 -1
- package/dist/tui-v2/app/command-handlers.js.map +1 -1
- package/dist/tui-v2/app/commands/picker-commands.js +3 -0
- package/dist/tui-v2/app/commands/picker-commands.js.map +1 -1
- package/dist/tui-v2/app/commands/session-commands.js +5 -0
- package/dist/tui-v2/app/commands/session-commands.js.map +1 -1
- package/dist/tui-v2/app/plan-lifecycle.d.ts +25 -3
- package/dist/tui-v2/app/plan-lifecycle.js +87 -24
- package/dist/tui-v2/app/plan-lifecycle.js.map +1 -1
- package/dist/tui-v2/bootstrap/patch-opentui-text.d.ts +6 -0
- package/dist/tui-v2/bootstrap/patch-opentui-text.js +53 -0
- package/dist/tui-v2/bootstrap/patch-opentui-text.js.map +1 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js +7 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
- package/dist/tui-v2/components/jobs/jobs-panel.js +23 -14
- package/dist/tui-v2/components/jobs/jobs-panel.js.map +1 -1
- package/dist/tui-v2/components/modal/confirm-modal.d.ts +1 -1
- package/dist/tui-v2/components/modal/confirm-modal.js +18 -7
- package/dist/tui-v2/components/modal/confirm-modal.js.map +1 -1
- package/dist/tui-v2/components/overlay/overlay-host.js +1 -1
- package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -1
- package/dist/tui-v2/components/pager/pager.d.ts +6 -0
- package/dist/tui-v2/components/pager/pager.js +313 -67
- package/dist/tui-v2/components/pager/pager.js.map +1 -1
- package/dist/tui-v2/components/status/status-line.d.ts +9 -0
- package/dist/tui-v2/components/status/status-line.js +17 -3
- package/dist/tui-v2/components/status/status-line.js.map +1 -1
- package/dist/tui-v2/components/transcript/assistant-message.js +1 -1
- package/dist/tui-v2/components/transcript/assistant-message.js.map +1 -1
- package/dist/tui-v2/components/transcript/compacted-row.js +1 -1
- package/dist/tui-v2/components/transcript/compacted-row.js.map +1 -1
- package/dist/tui-v2/components/transcript/tool-card.d.ts +9 -1
- package/dist/tui-v2/components/transcript/tool-card.js +115 -10
- package/dist/tui-v2/components/transcript/tool-card.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-row.js +2 -2
- package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
- package/dist/tui-v2/composer/composer-editor.js +16 -0
- package/dist/tui-v2/composer/composer-editor.js.map +1 -1
- package/dist/tui-v2/controllers/overlay-controller.d.ts +16 -2
- package/dist/tui-v2/controllers/overlay-controller.js +92 -12
- package/dist/tui-v2/controllers/overlay-controller.js.map +1 -1
- package/dist/tui-v2/rendering/artifact-pager-source.d.ts +19 -0
- package/dist/tui-v2/rendering/artifact-pager-source.js +103 -0
- package/dist/tui-v2/rendering/artifact-pager-source.js.map +1 -0
- package/dist/tui-v2/rendering/file-diff-view.d.ts +63 -0
- package/dist/tui-v2/rendering/file-diff-view.js +263 -0
- package/dist/tui-v2/rendering/file-diff-view.js.map +1 -0
- package/dist/tui-v2/rendering/open-tool-output.d.ts +9 -1
- package/dist/tui-v2/rendering/open-tool-output.js +65 -12
- package/dist/tui-v2/rendering/open-tool-output.js.map +1 -1
- package/dist/tui-v2/rendering/pager-chrome.d.ts +12 -0
- package/dist/tui-v2/rendering/pager-chrome.js +56 -0
- package/dist/tui-v2/rendering/pager-chrome.js.map +1 -0
- package/dist/tui-v2/rendering/plan-view.js +1 -1
- package/dist/tui-v2/rendering/plan-view.js.map +1 -1
- package/dist/tui-v2/rendering/syntax-highlight.d.ts +37 -0
- package/dist/tui-v2/rendering/syntax-highlight.js +1303 -0
- package/dist/tui-v2/rendering/syntax-highlight.js.map +1 -0
- package/dist/tui-v2/rendering/theme.d.ts +28 -0
- package/dist/tui-v2/rendering/theme.js +28 -0
- package/dist/tui-v2/rendering/theme.js.map +1 -1
- package/dist/tui-v2/rendering/tool-presenter.d.ts +11 -1
- package/dist/tui-v2/rendering/tool-presenter.js +101 -5
- package/dist/tui-v2/rendering/tool-presenter.js.map +1 -1
- package/dist/tui-v2/state/transcript-hydrate.js +5 -0
- package/dist/tui-v2/state/transcript-hydrate.js.map +1 -1
- package/dist/tui-v2/state/transcript-reducer.js +12 -2
- package/dist/tui-v2/state/transcript-reducer.js.map +1 -1
- package/dist/tui-v2/state/transcript-store.d.ts +7 -0
- package/dist/tui-v2/state/transcript-store.js +46 -0
- package/dist/tui-v2/state/transcript-store.js.map +1 -1
- package/dist/tui-v2/state/transcript-types.d.ts +12 -0
- package/dist/tui-v2/state/transcript-types.js +9 -0
- package/dist/tui-v2/state/transcript-types.js.map +1 -1
- package/dist/types.d.ts +75 -1
- package/dist/ui/ansi-box.d.ts +2 -0
- package/dist/ui/ansi-box.js +8 -1
- package/dist/ui/ansi-box.js.map +1 -1
- package/dist/ui/mentions.d.ts +6 -0
- package/dist/ui/mentions.js +50 -12
- package/dist/ui/mentions.js.map +1 -1
- package/dist/ui/plan-pane.js +1 -1
- package/dist/ui/plan-pane.js.map +1 -1
- package/package.json +16 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nmap-runner.js","sourceRoot":"","sources":["../../src/tools/nmap-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"nmap-runner.js","sourceRoot":"","sources":["../../src/tools/nmap-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ToolResult } from "../types.js";
|
|
2
|
+
import type { ToolRunOptions } from "./tool-types.js";
|
|
3
|
+
export declare function discoverWebSurface(baseUrl: string, paths: readonly string[], options?: ToolRunOptions): Promise<ToolResult>;
|
|
4
|
+
export declare function enumerateApi(specUrl: string, options?: ToolRunOptions): Promise<ToolResult>;
|
|
5
|
+
export declare function compareAuthorizationContexts(url: string, contexts: readonly {
|
|
6
|
+
label: string;
|
|
7
|
+
headers: Record<string, string>;
|
|
8
|
+
}[], options?: ToolRunOptions): Promise<ToolResult>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { httpFetch } from "./http.js";
|
|
2
|
+
async function runBoundedRequests(requests, options, concurrency = 4) {
|
|
3
|
+
const results = [];
|
|
4
|
+
let cursor = 0;
|
|
5
|
+
const workers = Array.from({ length: Math.min(concurrency, requests.length) }, async () => {
|
|
6
|
+
for (;;) {
|
|
7
|
+
const index = cursor++;
|
|
8
|
+
const request = requests[index];
|
|
9
|
+
if (!request)
|
|
10
|
+
return;
|
|
11
|
+
const result = await httpFetch(request.url, {
|
|
12
|
+
method: "GET",
|
|
13
|
+
headers: request.headers,
|
|
14
|
+
maxBytes: 128 * 1024,
|
|
15
|
+
signal: options?.signal,
|
|
16
|
+
authorizeHop: options?.authorizeNetworkHop,
|
|
17
|
+
});
|
|
18
|
+
results[index] = { request, result };
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
await Promise.all(workers);
|
|
22
|
+
return results;
|
|
23
|
+
}
|
|
24
|
+
export async function discoverWebSurface(baseUrl, paths, options) {
|
|
25
|
+
const base = new URL(baseUrl);
|
|
26
|
+
const unique = Array.from(new Set(["/", "/robots.txt", "/sitemap.xml", ...paths])).slice(0, 100);
|
|
27
|
+
const requests = unique.map((path) => ({
|
|
28
|
+
label: path,
|
|
29
|
+
url: new URL(path.startsWith("/") ? path : `/${path}`, base).toString(),
|
|
30
|
+
}));
|
|
31
|
+
const results = await runBoundedRequests(requests, options);
|
|
32
|
+
const observations = results.map(({ request, result }) => `${request.label}: ${result.ok ? "reachable" : "failed"}\n${result.output.slice(0, 2_000)}`);
|
|
33
|
+
return {
|
|
34
|
+
ok: results.some(({ result }) => result.ok),
|
|
35
|
+
output: `Web surface discovery (${results.length} bounded requests)\n\n${observations.join("\n\n")}`,
|
|
36
|
+
exitCode: results.some(({ result }) => result.ok) ? 0 : 1,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export async function enumerateApi(specUrl, options) {
|
|
40
|
+
const result = await httpFetch(specUrl, {
|
|
41
|
+
method: "GET",
|
|
42
|
+
maxBytes: 1024 * 1024,
|
|
43
|
+
signal: options?.signal,
|
|
44
|
+
authorizeHop: options?.authorizeNetworkHop,
|
|
45
|
+
});
|
|
46
|
+
if (!result.ok)
|
|
47
|
+
return result;
|
|
48
|
+
const pathMatches = Array.from(result.output.matchAll(/^\s{0,8}["']?(\/[^\s"']*)["']?\s*:/gm), (match) => match[1]);
|
|
49
|
+
const endpoints = Array.from(new Set(pathMatches.filter((value) => Boolean(value)))).slice(0, 500);
|
|
50
|
+
return {
|
|
51
|
+
...result,
|
|
52
|
+
output: `${result.output}\n\nDiscovered API paths (${endpoints.length}):\n${endpoints.map((path) => `- ${path}`).join("\n") || "- None parsed; inspect the retained specification body."}`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export async function compareAuthorizationContexts(url, contexts, options) {
|
|
56
|
+
if (contexts.length < 2)
|
|
57
|
+
return { ok: false, output: "auth.compare requires at least two authorization contexts", exitCode: 1 };
|
|
58
|
+
const results = await runBoundedRequests(contexts.slice(0, 10).map((context) => ({ url, label: context.label, headers: context.headers })), options, 2);
|
|
59
|
+
const fingerprints = results.map(({ request, result }) => ({
|
|
60
|
+
label: request.label,
|
|
61
|
+
ok: result.ok,
|
|
62
|
+
bytes: Buffer.byteLength(result.output),
|
|
63
|
+
preview: result.output.slice(0, 500),
|
|
64
|
+
}));
|
|
65
|
+
return {
|
|
66
|
+
ok: results.some(({ result }) => result.ok),
|
|
67
|
+
output: `Authorization-context comparison (credentials redacted; scanner lead only)\n${JSON.stringify(fingerprints, null, 2)}`,
|
|
68
|
+
exitCode: results.some(({ result }) => result.ok) ? 0 : 1,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=pentest-workflows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pentest-workflows.js","sourceRoot":"","sources":["../../src/tools/pentest-workflows.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import type { ToolCall, ToolResult } from "../types.js";
|
|
2
2
|
import { type ToolRunOptions, type ToolHandler } from "./tool-types.js";
|
|
3
3
|
export type { ToolRunOptions, ToolHandler };
|
|
4
|
+
export interface ScanResourceEstimate {
|
|
5
|
+
profile: "standard" | "deep" | "full";
|
|
6
|
+
estimatedSeconds: number;
|
|
7
|
+
timeoutMs: number;
|
|
8
|
+
durableRecommended: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function estimateScanResources(argv: readonly string[]): ScanResourceEstimate;
|
|
11
|
+
/** nmap argv for pentest.recon — ports configurable (default top-100). */
|
|
12
|
+
export declare function buildPentestReconNmapArgv(args: Record<string, unknown>, host: string): string[];
|
|
4
13
|
export declare const toolRegistry: Record<string, ToolHandler>;
|
|
5
14
|
export declare function availableToolNames(): string[];
|
|
6
15
|
/**
|
package/dist/tools/registry.js
CHANGED
|
@@ -4,6 +4,7 @@ import { safeCwd } from "../os/cwd.js";
|
|
|
4
4
|
import { fsEdit, fsDelete, fsList, fsRead, fsSearch, fsWrite, fsWriteMany, fsReplaceLines, fsAppend, } from "./fs.js";
|
|
5
5
|
import { httpFetch } from "./http.js";
|
|
6
6
|
import { shellExec, spawnArgv } from "./shell.js";
|
|
7
|
+
import { isLongQuietInstallOrScaffoldCommand, } from "../agent/task-evidence.js";
|
|
7
8
|
import { imageOcr } from "./image.js";
|
|
8
9
|
import { pdfRead } from "./pdf.js";
|
|
9
10
|
import { webFetch } from "./web/fetch.js";
|
|
@@ -11,7 +12,7 @@ import { webSearch } from "./web/search.js";
|
|
|
11
12
|
import { RESPONSE_MODES } from "./web/types.js";
|
|
12
13
|
import { classifyToolCall } from "../safety/classifier.js";
|
|
13
14
|
import { loadScope } from "../store/scope.js";
|
|
14
|
-
import { parseHost, parsePortSpec, parseLegacyFlags, profileToNmapArgs, } from "./validate.js";
|
|
15
|
+
import { parseHost, parsePortSpec, parseLegacyFlags, profileToNmapArgs, nmapScanNeedsPrivilege, } from "./validate.js";
|
|
15
16
|
import { getNetworkContext } from "./network-context.js";
|
|
16
17
|
import { pingSweep } from "./net-ping-sweep.js";
|
|
17
18
|
import { toolCheckHandler } from "./capabilities.js";
|
|
@@ -19,7 +20,11 @@ import { wordlistFind } from "./wordlists.js";
|
|
|
19
20
|
import { jobManager } from "./jobs.js";
|
|
20
21
|
import { looksLongRunning } from "./command-intent.js";
|
|
21
22
|
import { packageBinaryName } from "./package-binary.js";
|
|
22
|
-
import { runNmapScan } from "./nmap-runner.js";
|
|
23
|
+
import { resolveNmapTimeoutPolicy, runNmapScan } from "./nmap-runner.js";
|
|
24
|
+
import { compareAuthorizationContexts, discoverWebSurface, enumerateApi } from "./pentest-workflows.js";
|
|
25
|
+
import { fromWireName, sanitizeToolName } from "../llm/tool-protocol.js";
|
|
26
|
+
import { prepareElevatedBackgroundCommand, preparePrivilegedBackgroundArgv, tryRunElevatedWithoutTty, } from "./elevated-shell.js";
|
|
27
|
+
import { getAllowInteractiveStdinInherit, looksInteractiveStdin, } from "./shell.js";
|
|
23
28
|
function requireString(args, key) {
|
|
24
29
|
const value = args[key];
|
|
25
30
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -27,6 +32,14 @@ function requireString(args, key) {
|
|
|
27
32
|
}
|
|
28
33
|
return value;
|
|
29
34
|
}
|
|
35
|
+
/** Like requireString but allows empty string (e.g. replaceLines delete). */
|
|
36
|
+
function requireStringAllowEmpty(args, key) {
|
|
37
|
+
const value = args[key];
|
|
38
|
+
if (typeof value !== "string") {
|
|
39
|
+
throw new Error(`Tool argument "${key}" must be a string`);
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
30
43
|
function optionalString(args, key) {
|
|
31
44
|
const value = args[key];
|
|
32
45
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
@@ -46,6 +59,43 @@ function optionalBoolean(args, key) {
|
|
|
46
59
|
const value = args[key];
|
|
47
60
|
return typeof value === "boolean" ? value : undefined;
|
|
48
61
|
}
|
|
62
|
+
export function estimateScanResources(argv) {
|
|
63
|
+
const policy = resolveNmapTimeoutPolicy(argv, {});
|
|
64
|
+
const estimatedSeconds = policy.depth === "full" ? 1_800 : policy.depth === "deep" ? 600 : 120;
|
|
65
|
+
return {
|
|
66
|
+
profile: policy.depth,
|
|
67
|
+
estimatedSeconds,
|
|
68
|
+
timeoutMs: policy.timeoutMs,
|
|
69
|
+
durableRecommended: policy.depth !== "standard",
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** nmap argv for pentest.recon — ports configurable (default top-100). */
|
|
73
|
+
export function buildPentestReconNmapArgv(args, host) {
|
|
74
|
+
const argv = ["-sS", "-sV"];
|
|
75
|
+
const full = args.full === true || args.full === "true";
|
|
76
|
+
const ports = typeof args.ports === "string" && args.ports.trim()
|
|
77
|
+
? args.ports.trim()
|
|
78
|
+
: undefined;
|
|
79
|
+
let topPorts;
|
|
80
|
+
if (typeof args.topPorts === "number" && Number.isFinite(args.topPorts)) {
|
|
81
|
+
topPorts = Math.max(1, Math.min(65535, Math.floor(args.topPorts)));
|
|
82
|
+
}
|
|
83
|
+
else if (typeof args.topPorts === "string" && /^\d+$/.test(args.topPorts)) {
|
|
84
|
+
topPorts = Math.max(1, Math.min(65535, Number(args.topPorts)));
|
|
85
|
+
}
|
|
86
|
+
if (full) {
|
|
87
|
+
argv.push("-p-");
|
|
88
|
+
}
|
|
89
|
+
else if (ports) {
|
|
90
|
+
const spec = parsePortSpec(ports);
|
|
91
|
+
argv.push("-p", spec);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
argv.push("--top-ports", String(topPorts ?? 100));
|
|
95
|
+
}
|
|
96
|
+
argv.push(host);
|
|
97
|
+
return argv;
|
|
98
|
+
}
|
|
49
99
|
function optionalResponseMode(args, key) {
|
|
50
100
|
const value = args[key];
|
|
51
101
|
if (typeof value === "string" &&
|
|
@@ -67,9 +117,14 @@ export const toolRegistry = {
|
|
|
67
117
|
// The model is still encouraged to use shell.start directly; this just
|
|
68
118
|
// catches the common mistake of using shell.exec for a server.
|
|
69
119
|
if (looksLongRunning(command)) {
|
|
70
|
-
const
|
|
71
|
-
|
|
120
|
+
const elevated = await prepareElevatedBackgroundCommand(command, {
|
|
121
|
+
signal: options?.signal,
|
|
122
|
+
onOutput: options?.onOutput,
|
|
123
|
+
requestSecret: options?.requestSecret,
|
|
72
124
|
});
|
|
125
|
+
if (elevated && !elevated.prepared)
|
|
126
|
+
return elevated.result;
|
|
127
|
+
const job = await jobManager.startJob(elevated?.prepared ? elevated.spec : command, { cwd: optionalString(args, "cwd") });
|
|
73
128
|
if (job.ok) {
|
|
74
129
|
return {
|
|
75
130
|
...job,
|
|
@@ -82,12 +137,41 @@ export const toolRegistry = {
|
|
|
82
137
|
}
|
|
83
138
|
return job;
|
|
84
139
|
}
|
|
140
|
+
// create-next-app / npm install often exceed the default 3 min shell timeout
|
|
141
|
+
// when the model omits timeoutMs — bump automatically for known long jobs.
|
|
142
|
+
const explicitTimeout = optionalNumber(args, "timeoutMs");
|
|
143
|
+
const timeoutMs = explicitTimeout ??
|
|
144
|
+
(isLongQuietInstallOrScaffoldCommand(command) ? 900_000 : undefined);
|
|
145
|
+
// Password tools must never steal the TTY in OpenTUI (freezes Esc/clicks).
|
|
146
|
+
// Prefer secure modal + sudo -S; otherwise refuse interactive elevation.
|
|
147
|
+
if (looksInteractiveStdin(command)) {
|
|
148
|
+
const elevated = await tryRunElevatedWithoutTty(command, {
|
|
149
|
+
cwd: optionalString(args, "cwd"),
|
|
150
|
+
timeoutMs,
|
|
151
|
+
signal: options?.signal,
|
|
152
|
+
onOutput: options?.onOutput,
|
|
153
|
+
requestSecret: options?.requestSecret,
|
|
154
|
+
});
|
|
155
|
+
if (elevated)
|
|
156
|
+
return elevated;
|
|
157
|
+
if (!getAllowInteractiveStdinInherit()) {
|
|
158
|
+
return {
|
|
159
|
+
ok: false,
|
|
160
|
+
exitCode: 1,
|
|
161
|
+
output: "This command needs an interactive password prompt, which would freeze the TUI. " +
|
|
162
|
+
"Use a simple `sudo <command>` so clai can open the secure password modal, " +
|
|
163
|
+
"or run without elevation (e.g. nmap -sT).",
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
85
167
|
return shellExec({
|
|
86
168
|
command,
|
|
87
169
|
cwd: optionalString(args, "cwd"),
|
|
88
|
-
timeoutMs
|
|
170
|
+
timeoutMs,
|
|
89
171
|
signal: options?.signal,
|
|
90
172
|
onOutput: options?.onOutput,
|
|
173
|
+
// Explicit: never inherit unless classic REPL policy allows it.
|
|
174
|
+
interactiveStdin: getAllowInteractiveStdinInherit() ? "auto" : false,
|
|
91
175
|
});
|
|
92
176
|
},
|
|
93
177
|
async "fs.read"(args, options) {
|
|
@@ -177,6 +261,27 @@ export const toolRegistry = {
|
|
|
177
261
|
if (ports)
|
|
178
262
|
argv.push("-p", ports);
|
|
179
263
|
argv.push(...profileArgs, ...legacyArgs, host.value);
|
|
264
|
+
const estimate = estimateScanResources(argv);
|
|
265
|
+
const durable = args.background === true || estimate.durableRecommended;
|
|
266
|
+
if (durable) {
|
|
267
|
+
const prepared = nmapScanNeedsPrivilege(argv)
|
|
268
|
+
? await preparePrivilegedBackgroundArgv("nmap", argv, {
|
|
269
|
+
signal: options?.signal,
|
|
270
|
+
onOutput: options?.onOutput,
|
|
271
|
+
requestSecret: options?.requestSecret,
|
|
272
|
+
title: "Administrator access for nmap",
|
|
273
|
+
prompt: "Enter your password for the nmap raw-socket scan. It is sent only to sudo stdin and is never stored. Esc cancels.",
|
|
274
|
+
})
|
|
275
|
+
: { prepared: true, spec: { command: "nmap", argv: [...argv] } };
|
|
276
|
+
if (!prepared.prepared)
|
|
277
|
+
return prepared.result;
|
|
278
|
+
return jobManager.startJob(prepared.spec, {
|
|
279
|
+
name: `nmap-${estimate.profile}-${host.value}`,
|
|
280
|
+
profile: estimate.profile,
|
|
281
|
+
estimatedSeconds: estimate.estimatedSeconds,
|
|
282
|
+
...(options?.engagementAuthorization ? { authorization: options.engagementAuthorization } : {}),
|
|
283
|
+
});
|
|
284
|
+
}
|
|
180
285
|
return runNmapScan(argv, options);
|
|
181
286
|
},
|
|
182
287
|
async "http.fetch"(args, options) {
|
|
@@ -185,14 +290,43 @@ export const toolRegistry = {
|
|
|
185
290
|
!Array.isArray(args.headers)
|
|
186
291
|
? args.headers
|
|
187
292
|
: undefined;
|
|
188
|
-
|
|
293
|
+
const url = requireString(args, "url");
|
|
294
|
+
const method = (optionalString(args, "method") ?? "GET").toUpperCase();
|
|
295
|
+
// Local app verify: loopback GET/HEAD is the owner's own process — auto-own
|
|
296
|
+
// so models are not stuck without iOwnThis. Mutating methods and non-loopback
|
|
297
|
+
// private/metadata addresses still require explicit ownership.
|
|
298
|
+
let iOwnThis = args.iOwnThis === true || args.own === true;
|
|
299
|
+
// Keep the caller's host (localhost). httpFetch dual-stacks 127.0.0.1/::1
|
|
300
|
+
// on connection failure — rewriting to 127.0.0.1 alone broke Vite on
|
|
301
|
+
// IPv6-only macOS binds while the browser still worked.
|
|
302
|
+
if (!iOwnThis && (method === "GET" || method === "HEAD")) {
|
|
303
|
+
try {
|
|
304
|
+
const parsed = new URL(url);
|
|
305
|
+
const host = parsed.hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
306
|
+
if (host === "localhost" ||
|
|
307
|
+
host === "127.0.0.1" ||
|
|
308
|
+
host === "::1" ||
|
|
309
|
+
host === "localhost.localdomain" ||
|
|
310
|
+
host === "ip6-localhost" ||
|
|
311
|
+
/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host)) {
|
|
312
|
+
iOwnThis = true;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
/* invalid URL handled inside httpFetch */
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return httpFetch(url, {
|
|
189
320
|
method: optionalString(args, "method"),
|
|
190
321
|
body: optionalString(args, "body"),
|
|
191
322
|
headers,
|
|
192
323
|
maxBytes: optionalNumber(args, "maxBytes"),
|
|
193
|
-
iOwnThis
|
|
324
|
+
iOwnThis,
|
|
194
325
|
retries: optionalNumber(args, "retries"),
|
|
195
326
|
signal: options?.signal,
|
|
327
|
+
// Never attach engagement hop checks for owned loopback — leftover
|
|
328
|
+
// pentest scope must not fail local app verify.
|
|
329
|
+
authorizeHop: iOwnThis ? undefined : options?.authorizeNetworkHop,
|
|
196
330
|
});
|
|
197
331
|
},
|
|
198
332
|
async "web.search"(args, options) {
|
|
@@ -309,13 +443,10 @@ export const toolRegistry = {
|
|
|
309
443
|
},
|
|
310
444
|
async "pentest.recon"(args, options) {
|
|
311
445
|
const host = parseHost(requireString(args, "target"));
|
|
312
|
-
// Per-step opt-in flags so callers can ask for ONLY the recon they
|
|
313
|
-
// need. When no flags are supplied the legacy behavior runs (all
|
|
314
|
-
// three steps), preserving backwards compatibility for prompts that
|
|
315
|
-
// expect a full sweep.
|
|
316
446
|
const wantWhois = args.whois !== false;
|
|
317
447
|
const wantDns = args.dns !== false;
|
|
318
448
|
const wantNmap = args.nmap !== false;
|
|
449
|
+
const nmapArgv = buildPentestReconNmapArgv(args, host.value);
|
|
319
450
|
const allSteps = [
|
|
320
451
|
{ key: "whois", command: "whois", argv: [host.value] },
|
|
321
452
|
{
|
|
@@ -326,11 +457,7 @@ export const toolRegistry = {
|
|
|
326
457
|
{
|
|
327
458
|
key: "nmap",
|
|
328
459
|
command: "nmap",
|
|
329
|
-
|
|
330
|
-
// sockets, so runNmapScan wraps it in sudo / elevation and falls
|
|
331
|
-
// back to an unprivileged TCP connect scan (-sT) when privilege
|
|
332
|
-
// can't be obtained.
|
|
333
|
-
argv: ["-sS", "-sV", "--top-ports", "100", host.value],
|
|
460
|
+
argv: nmapArgv,
|
|
334
461
|
},
|
|
335
462
|
];
|
|
336
463
|
const steps = allSteps.filter((step) => {
|
|
@@ -372,55 +499,71 @@ export const toolRegistry = {
|
|
|
372
499
|
const transcript = [];
|
|
373
500
|
let anyOk = false;
|
|
374
501
|
const userAborted = () => Boolean(options?.signal?.aborted);
|
|
375
|
-
|
|
376
|
-
if (userAborted())
|
|
377
|
-
break;
|
|
502
|
+
const runStep = async (step) => {
|
|
378
503
|
const display = `${step.command} ${step.argv.join(" ")}`;
|
|
379
|
-
transcript.push(`$ ${display}`);
|
|
380
|
-
// Announce each sub-step so users see progress through long recons.
|
|
381
504
|
options?.onOutput?.(`\n$ ${display}\n`, "stdout");
|
|
382
|
-
// Heartbeat so the outer 60s stall watchdog doesn't kill a quiet whois.
|
|
383
505
|
const beat = setInterval(() => {
|
|
384
506
|
options?.onOutput?.(`[recon] ${step.key} still running…\n`, "stdout");
|
|
385
507
|
}, 5_000);
|
|
386
508
|
beat.unref?.();
|
|
387
|
-
// Per-step caps: whois often hangs; nmap needs longer; dns is quick.
|
|
388
|
-
const stepTimeoutMs = step.key === "whois" ? 20_000 : step.key === "dns" ? 30_000 : 180_000;
|
|
389
|
-
let result;
|
|
390
509
|
try {
|
|
391
|
-
|
|
392
|
-
step.
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
510
|
+
if (step.key === "nmap") {
|
|
511
|
+
const estimate = estimateScanResources(step.argv);
|
|
512
|
+
if (estimate.durableRecommended || args.background === true) {
|
|
513
|
+
const prepared = nmapScanNeedsPrivilege(step.argv)
|
|
514
|
+
? await preparePrivilegedBackgroundArgv("nmap", step.argv, {
|
|
515
|
+
signal: options?.signal,
|
|
516
|
+
onOutput: options?.onOutput,
|
|
517
|
+
requestSecret: options?.requestSecret,
|
|
518
|
+
title: "Administrator access for nmap",
|
|
519
|
+
prompt: "Enter your password for the durable nmap raw-socket scan. It is sent only to sudo stdin and is never stored. Esc cancels.",
|
|
520
|
+
})
|
|
521
|
+
: { prepared: true, spec: { command: "nmap", argv: [...step.argv] } };
|
|
522
|
+
const result = prepared.prepared
|
|
523
|
+
? await jobManager.startJob(prepared.spec, {
|
|
524
|
+
name: `recon-${estimate.profile}-${host.value}`,
|
|
525
|
+
profile: estimate.profile,
|
|
526
|
+
estimatedSeconds: estimate.estimatedSeconds,
|
|
527
|
+
...(options?.engagementAuthorization ? { authorization: options.engagementAuthorization } : {}),
|
|
528
|
+
})
|
|
529
|
+
: prepared.result;
|
|
530
|
+
return { key: step.key, display, result };
|
|
531
|
+
}
|
|
532
|
+
return { key: step.key, display, result: await runNmapScan(step.argv, options) };
|
|
533
|
+
}
|
|
534
|
+
const timeoutMs = step.key === "whois" ? 20_000 : 30_000;
|
|
535
|
+
return {
|
|
536
|
+
key: step.key,
|
|
537
|
+
display,
|
|
538
|
+
result: await spawnArgv({
|
|
539
|
+
command: step.command,
|
|
540
|
+
argv: step.argv,
|
|
541
|
+
timeoutMs,
|
|
542
|
+
signal: options?.signal,
|
|
543
|
+
onOutput: options?.onOutput,
|
|
544
|
+
}),
|
|
545
|
+
};
|
|
401
546
|
}
|
|
402
547
|
catch (error) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
output: `${step.key} error: ${
|
|
407
|
-
exitCode: 1,
|
|
548
|
+
return {
|
|
549
|
+
key: step.key,
|
|
550
|
+
display,
|
|
551
|
+
result: { ok: false, output: `${step.key} error: ${error instanceof Error ? error.message : String(error)}`, exitCode: 1 },
|
|
408
552
|
};
|
|
409
553
|
}
|
|
410
554
|
finally {
|
|
411
555
|
clearInterval(beat);
|
|
412
556
|
}
|
|
413
|
-
|
|
414
|
-
|
|
557
|
+
};
|
|
558
|
+
// Passive WHOIS/DNS and the selected scan run independently. Deep/full
|
|
559
|
+
// scans return a durable job receipt immediately while passive results
|
|
560
|
+
// continue to completion in this foreground turn.
|
|
561
|
+
const completed = await Promise.all(steps.map(runStep));
|
|
562
|
+
for (const { display, result } of completed) {
|
|
563
|
+
transcript.push(`$ ${display}`, result.output);
|
|
564
|
+
outputs.push(result.output);
|
|
415
565
|
if (result.ok)
|
|
416
566
|
anyOk = true;
|
|
417
|
-
const body = result.ok
|
|
418
|
-
? result.output
|
|
419
|
-
: `${result.output || `${step.key} failed`}${result.exitCode !== undefined ? ` (exit ${result.exitCode})` : ""}`;
|
|
420
|
-
outputs.push(body);
|
|
421
|
-
transcript.push(body);
|
|
422
|
-
if (userAborted())
|
|
423
|
-
break;
|
|
424
567
|
}
|
|
425
568
|
if (artifactPath) {
|
|
426
569
|
const body = transcript.join("\n\n");
|
|
@@ -431,18 +574,54 @@ export const toolRegistry = {
|
|
|
431
574
|
artifactPath = undefined;
|
|
432
575
|
}
|
|
433
576
|
}
|
|
434
|
-
//
|
|
435
|
-
//
|
|
577
|
+
// Passive successes remain useful evidence, but a requested nmap step
|
|
578
|
+
// that failed authentication or never started must make the composite
|
|
579
|
+
// operation fail rather than disguising it as a successful recon.
|
|
436
580
|
const aborted = userAborted();
|
|
581
|
+
const nmapResult = completed.find((entry) => entry.key === "nmap")?.result;
|
|
582
|
+
const requestedScanFailed = wantNmap && Boolean(nmapResult && !nmapResult.ok);
|
|
583
|
+
const backgroundJob = completed.find((entry) => entry.result.backgroundJob)?.result.backgroundJob;
|
|
584
|
+
const output = outputs.join("\n\n");
|
|
437
585
|
return {
|
|
438
|
-
ok: aborted
|
|
586
|
+
ok: !aborted && anyOk && !requestedScanFailed,
|
|
439
587
|
output: aborted
|
|
440
|
-
? `${
|
|
441
|
-
:
|
|
442
|
-
|
|
588
|
+
? `${output}\n\nCommand aborted.`.trim()
|
|
589
|
+
: requestedScanFailed
|
|
590
|
+
? `${output}\n\nThe requested nmap scan failed or was not started; passive recon results above are partial only.`.trim()
|
|
591
|
+
: output,
|
|
592
|
+
exitCode: aborted ? 130 : anyOk && !requestedScanFailed ? 0 : 1,
|
|
443
593
|
...(artifactPath ? { outputPath: artifactPath } : {}),
|
|
594
|
+
...(backgroundJob ? { backgroundJob } : {}),
|
|
444
595
|
};
|
|
445
596
|
},
|
|
597
|
+
async "pentest.webDiscover"(args, options) {
|
|
598
|
+
const paths = Array.isArray(args.paths) ? args.paths.filter((value) => typeof value === "string") : [];
|
|
599
|
+
return discoverWebSurface(requireString(args, "baseUrl"), paths, options);
|
|
600
|
+
},
|
|
601
|
+
async "pentest.apiEnumerate"(args, options) {
|
|
602
|
+
return enumerateApi(requireString(args, "specUrl"), options);
|
|
603
|
+
},
|
|
604
|
+
async "pentest.authCompare"(args, options) {
|
|
605
|
+
const contexts = Array.isArray(args.contexts)
|
|
606
|
+
? args.contexts.filter((value) => {
|
|
607
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
608
|
+
return false;
|
|
609
|
+
const candidate = value;
|
|
610
|
+
return typeof candidate.label === "string" && Boolean(candidate.headers) && typeof candidate.headers === "object" && !Array.isArray(candidate.headers);
|
|
611
|
+
})
|
|
612
|
+
: [];
|
|
613
|
+
return compareAuthorizationContexts(requireString(args, "url"), contexts, options);
|
|
614
|
+
},
|
|
615
|
+
async "pentest.scanStatus"(args) {
|
|
616
|
+
const offset = optionalNumber(args, "offset");
|
|
617
|
+
const bytes = optionalNumber(args, "bytes");
|
|
618
|
+
const stream = optionalString(args, "stream");
|
|
619
|
+
return jobManager.tailJob(requireString(args, "id"), {
|
|
620
|
+
...(offset !== undefined ? { offset } : {}),
|
|
621
|
+
...(bytes !== undefined ? { bytes } : {}),
|
|
622
|
+
...(stream !== undefined ? { stream } : {}),
|
|
623
|
+
});
|
|
624
|
+
},
|
|
446
625
|
async "tool.batch"(args, options) {
|
|
447
626
|
return runToolBatch(args, options);
|
|
448
627
|
},
|
|
@@ -473,9 +652,16 @@ export const toolRegistry = {
|
|
|
473
652
|
async "pdf.read"(args, options) {
|
|
474
653
|
return pdfRead(args, options);
|
|
475
654
|
},
|
|
476
|
-
async "shell.start"(args) {
|
|
655
|
+
async "shell.start"(args, options) {
|
|
477
656
|
const command = requireString(args, "command");
|
|
478
|
-
|
|
657
|
+
const elevated = await prepareElevatedBackgroundCommand(command, {
|
|
658
|
+
signal: options?.signal,
|
|
659
|
+
onOutput: options?.onOutput,
|
|
660
|
+
requestSecret: options?.requestSecret,
|
|
661
|
+
});
|
|
662
|
+
if (elevated && !elevated.prepared)
|
|
663
|
+
return elevated.result;
|
|
664
|
+
return jobManager.startJob(elevated?.prepared ? elevated.spec : command, {
|
|
479
665
|
cwd: optionalString(args, "cwd"),
|
|
480
666
|
name: optionalString(args, "name"),
|
|
481
667
|
});
|
|
@@ -493,7 +679,18 @@ export const toolRegistry = {
|
|
|
493
679
|
return fsEdit(requireString(args, "path"), requireString(args, "oldText"), requireString(args, "newText"), optionalNumber(args, "expectedReplacements"), { confirmed: options?.confirmed });
|
|
494
680
|
},
|
|
495
681
|
async "fs.replaceLines"(args, options) {
|
|
496
|
-
|
|
682
|
+
// Empty content / delete:true removes the line range (X6).
|
|
683
|
+
let content;
|
|
684
|
+
if (args.delete === true) {
|
|
685
|
+
content = "";
|
|
686
|
+
}
|
|
687
|
+
else if (typeof args.content === "string") {
|
|
688
|
+
content = requireStringAllowEmpty(args, "content");
|
|
689
|
+
}
|
|
690
|
+
else {
|
|
691
|
+
throw new Error('Tool argument "content" must be a string (use "" or delete:true to delete the line range)');
|
|
692
|
+
}
|
|
693
|
+
return fsReplaceLines(requireString(args, "path"), requireNumber(args, "startLine"), requireNumber(args, "endLine"), content, { confirmed: options?.confirmed });
|
|
497
694
|
},
|
|
498
695
|
async "fs.append"(args, options) {
|
|
499
696
|
return fsAppend(requireString(args, "path"), requireString(args, "content"), {
|
|
@@ -569,13 +766,25 @@ function buildShellCommandFromCall(name, args) {
|
|
|
569
766
|
* dangerous commands are gated exactly as a hand-written shell.exec would be.
|
|
570
767
|
*/
|
|
571
768
|
export function normalizeToolCall(call) {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
769
|
+
// X1: strip channel/commentary tokens before registry lookup.
|
|
770
|
+
let name = typeof call.name === "string" ? call.name.trim() : "";
|
|
771
|
+
if (name && !toolRegistry[name]) {
|
|
772
|
+
const cleaned = sanitizeToolName(name);
|
|
773
|
+
const mapped = fromWireName(cleaned) ?? fromWireName(name) ?? cleaned;
|
|
774
|
+
if (mapped && toolRegistry[mapped]) {
|
|
775
|
+
return { name: mapped, args: call.args ?? {} };
|
|
776
|
+
}
|
|
777
|
+
if (cleaned && cleaned !== name)
|
|
778
|
+
name = cleaned;
|
|
779
|
+
}
|
|
780
|
+
if (toolRegistry[name]) {
|
|
781
|
+
return name === call.name ? call : { name, args: call.args ?? {} };
|
|
782
|
+
}
|
|
575
783
|
// Leave genuinely unknown namespaced tools (e.g. a typo'd "fs.reed") to
|
|
576
784
|
// surface a clear error rather than guessing at a shell command.
|
|
577
|
-
if (!name || name.includes(".") || name.includes("/"))
|
|
578
|
-
return call;
|
|
785
|
+
if (!name || name.includes(".") || name.includes("/")) {
|
|
786
|
+
return name === call.name ? call : { name, args: call.args ?? {} };
|
|
787
|
+
}
|
|
579
788
|
const args = call.args ?? {};
|
|
580
789
|
const command = buildShellCommandFromCall(name, args);
|
|
581
790
|
if (!command)
|