@pentoshi/clai 3.6.0 → 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/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 +45 -22
- 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 -11
- package/dist/agent/loop-guard.js +93 -39
- 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 +12 -0
- package/dist/agent/plan-tool.js +309 -104
- package/dist/agent/plan-tool.js.map +1 -1
- package/dist/agent/project-root.js +3 -0
- package/dist/agent/project-root.js.map +1 -1
- 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 +1115 -965
- 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 +99 -29
- package/dist/agent/task-evidence.js +480 -91
- package/dist/agent/task-evidence.js.map +1 -1
- 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 +4 -12
- package/dist/agent/tool-call-parser.js +34 -67
- package/dist/agent/tool-call-parser.js.map +1 -1
- package/dist/agent/tool-history.d.ts +7 -0
- package/dist/agent/tool-history.js +50 -0
- package/dist/agent/tool-history.js.map +1 -1
- 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 +11 -0
- package/dist/agent/workspace-orient.js +103 -12
- package/dist/agent/workspace-orient.js.map +1 -1
- 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 +56 -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/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/ollama-tools.d.ts +0 -4
- package/dist/llm/adapters/ollama-tools.js +0 -4
- package/dist/llm/adapters/ollama-tools.js.map +1 -1
- package/dist/llm/capabilities.d.ts +10 -10
- package/dist/llm/capabilities.js +43 -17
- package/dist/llm/capabilities.js.map +1 -1
- package/dist/llm/groq.js +0 -6
- package/dist/llm/groq.js.map +1 -1
- package/dist/llm/http.d.ts +0 -17
- package/dist/llm/http.js +0 -45
- package/dist/llm/http.js.map +1 -1
- package/dist/llm/router.d.ts +0 -6
- package/dist/llm/router.js +0 -15
- package/dist/llm/router.js.map +1 -1
- package/dist/llm/tool-protocol.d.ts +0 -6
- package/dist/llm/tool-protocol.js +3 -7
- package/dist/llm/tool-protocol.js.map +1 -1
- 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 +0 -49
- 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 +6 -18
- package/dist/prompts/index.js +67 -293
- 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 +169 -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/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 +57 -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/definitions.js +70 -1
- package/dist/tools/definitions.js.map +1 -1
- 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 +269 -78
- 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/nmap-runner.d.ts +11 -0
- package/dist/tools/nmap-runner.js +115 -74
- 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 +227 -56
- 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/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 +114 -9
- 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 +5 -0
- package/dist/tui-v2/rendering/tool-presenter.js +35 -3
- 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 +17 -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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scratch-write.js","sourceRoot":"","sources":["../../src/agent/scratch-write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG9C,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IACrC,UAAU;IACV,cAAc;IACd,SAAS;IACT,iBAAiB;IACjB,WAAW;IACX,WAAW;CACZ,CAAC,CAAC;AAEH,SAAS,eAAe,CAAC,IAAY;IACnC,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,OAAO,EAAE,CAAC;IACnC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAAc;IACpD,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACrC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;gBAC1D,MAAM,CAAC,GAAI,KAA4B,CAAC,IAAI,CAAC;gBAC7C,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACnE,OAAO,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,kBAAkB,CAAC,IAAc,EAAE,UAAkB;IACnE,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACzD,MAAM,KAAK,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACzB,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAChD,OAAO,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -14,6 +14,13 @@ export interface SessionPolicy {
|
|
|
14
14
|
}
|
|
15
15
|
export declare function createSessionPolicy(sessionId?: string): SessionPolicy;
|
|
16
16
|
export declare function isPreApprovalAllowedTool(name: string): boolean;
|
|
17
|
+
/** True when the tool is allowed in plan mode (gather-only). */
|
|
18
|
+
export declare function isPlanModeAllowedTool(name: string): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Shell commands blocked in plan mode: project scaffold/mutate and active
|
|
21
|
+
* exploit/C2. Recon, enum, fuzz, long nmap, installs of scanners are allowed.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isPlanModeAllowedShellCommand(command: string): boolean;
|
|
17
24
|
/**
|
|
18
25
|
* A plan's persisted status is the durable source of truth for "has this
|
|
19
26
|
* plan been approved" — session.planApproved is in-memory only and resets to
|
|
@@ -22,11 +22,72 @@ const PRE_APPROVAL_ALLOWED_TOOLS = new Set([
|
|
|
22
22
|
"fs.search",
|
|
23
23
|
"sysinfo",
|
|
24
24
|
"tool.batch",
|
|
25
|
+
"tool.check",
|
|
25
26
|
"net.context",
|
|
27
|
+
"web.search",
|
|
28
|
+
"web.fetch",
|
|
29
|
+
"dns.lookup",
|
|
30
|
+
"whois.lookup",
|
|
31
|
+
"http.fetch",
|
|
32
|
+
"net.scan",
|
|
33
|
+
"pentest.recon",
|
|
34
|
+
"wordlist.find",
|
|
35
|
+
"image.ocr",
|
|
36
|
+
"pdf.read",
|
|
37
|
+
"shell.jobs",
|
|
38
|
+
"shell.tail",
|
|
39
|
+
]);
|
|
40
|
+
/**
|
|
41
|
+
* Plan mode: gather freely (recon, scans, enum, research, tool installs).
|
|
42
|
+
* Block only project mutation and clear active exploitation — put those in
|
|
43
|
+
* the plan as post-accept tasks.
|
|
44
|
+
*/
|
|
45
|
+
const PLAN_MODE_BLOCKED_TOOLS = new Set([
|
|
46
|
+
"fs.write",
|
|
47
|
+
"fs.writeMany",
|
|
48
|
+
"fs.edit",
|
|
49
|
+
"fs.append",
|
|
50
|
+
"fs.replaceLines",
|
|
51
|
+
"fs.delete",
|
|
26
52
|
]);
|
|
27
53
|
export function isPreApprovalAllowedTool(name) {
|
|
28
54
|
return PRE_APPROVAL_ALLOWED_TOOLS.has(name);
|
|
29
55
|
}
|
|
56
|
+
/** True when the tool is allowed in plan mode (gather-only). */
|
|
57
|
+
export function isPlanModeAllowedTool(name) {
|
|
58
|
+
if (PLAN_MODE_BLOCKED_TOOLS.has(name))
|
|
59
|
+
return false;
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Shell commands blocked in plan mode: project scaffold/mutate and active
|
|
64
|
+
* exploit/C2. Recon, enum, fuzz, long nmap, installs of scanners are allowed.
|
|
65
|
+
*/
|
|
66
|
+
export function isPlanModeAllowedShellCommand(command) {
|
|
67
|
+
const c = command.trim();
|
|
68
|
+
if (!c)
|
|
69
|
+
return false;
|
|
70
|
+
if (/\b(npm\s+create|npx\s+(?:--yes\s+)?create-|yarn\s+create|pnpm\s+create|bun\s+create|cargo\s+new|rails\s+new|poetry\s+new|flutter\s+create|django-admin\s+startproject|composer\s+create-project|npm\s+init\s+vite|create-next-app|create-react-app)\b/i.test(c)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
if (/\b(fs\.write|tee\s+>|>>\s*\/|cat\s*>\s*|printf\s+.*>\s*)/i.test(c) &&
|
|
74
|
+
!/\b(tee\s+\/tmp|tee\s+\$\{?TMP|>>\s*\/tmp|\/var\/folders)\b/i.test(c)) {
|
|
75
|
+
// Writing into user project trees is blocked; tmp artifact writes OK.
|
|
76
|
+
if (!/\b(\/tmp|TMPDIR|scratch|\.clai\/outputs)\b/i.test(c)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (/\b(msfconsole|msfvenom|metasploit|exploit\/|use\s+exploit|revshell|reverse\s+shell|nc\s+-[el].*\d|ncat\s+-[el]|bash\s+-i\s+>&\s*\/dev\/tcp)\b/i.test(c)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
if (/\b(sqlmap\b.*(?:--os-shell|--os-pwn|--sql-shell|--crawl)|hydra\s+.+\s+-l\s|medusa\s+.*-M\s)\b/i.test(c)) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
if (/\brm\s+(-[a-zA-Z]*f|-[a-zA-Z]*r).*(\/|~)/i.test(c)) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
30
91
|
/**
|
|
31
92
|
* A plan's persisted status is the durable source of truth for "has this
|
|
32
93
|
* plan been approved" — session.planApproved is in-memory only and resets to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-policy.js","sourceRoot":"","sources":["../../src/agent/session-policy.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,mBAAmB,CAAC,SAAkB;IACpD,OAAO;QACL,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,iBAAiB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;QACnC,SAAS,EACP,SAAS;YACT,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;QAC7E,YAAY,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;KAC/B,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAS;IACjD,aAAa;IACb,aAAa;IACb,SAAS;IACT,SAAS;IACT,WAAW;IACX,SAAS;IACT,YAAY;IACZ,aAAa;
|
|
1
|
+
{"version":3,"file":"session-policy.js","sourceRoot":"","sources":["../../src/agent/session-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact SESSION STATE / WORKING MEMORY block for the model.
|
|
3
|
+
* Survives as an updatable system message; re-injected after compaction.
|
|
4
|
+
*/
|
|
5
|
+
export declare const SESSION_STATE_PREFIX = "SESSION STATE / WORKING MEMORY";
|
|
6
|
+
export interface SessionStateSnapshot {
|
|
7
|
+
goal?: string | undefined;
|
|
8
|
+
projectRoot?: string | undefined;
|
|
9
|
+
packageManager?: string | undefined;
|
|
10
|
+
planStatus?: string | undefined;
|
|
11
|
+
planKind?: string | undefined;
|
|
12
|
+
/** e.g. t3 in_progress "implement todo" */
|
|
13
|
+
openTask?: string | undefined;
|
|
14
|
+
/** short list of pending task ids/titles */
|
|
15
|
+
pendingTasks?: string[] | undefined;
|
|
16
|
+
/** short list of done task ids */
|
|
17
|
+
doneTasks?: string[] | undefined;
|
|
18
|
+
featureAppRequired?: boolean | undefined;
|
|
19
|
+
featureSeen?: boolean | undefined;
|
|
20
|
+
scaffoldOk?: boolean | undefined;
|
|
21
|
+
serverStarted?: boolean | undefined;
|
|
22
|
+
serverProbedOk?: boolean | undefined;
|
|
23
|
+
lastProbeFailed?: boolean | undefined;
|
|
24
|
+
lastOkTool?: string | undefined;
|
|
25
|
+
nextHint?: string | undefined;
|
|
26
|
+
/** pentest residual one-liner */
|
|
27
|
+
engagementNote?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
/** Build a short, high-signal state block (aim < 400 tokens). */
|
|
30
|
+
export declare function buildSessionStateBlock(s: SessionStateSnapshot): string;
|
|
31
|
+
/** Infer a short next-action hint from flags (no LLM). */
|
|
32
|
+
export declare function inferNextHint(s: SessionStateSnapshot): string | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Upsert SESSION STATE as a system message after the primary system prompt.
|
|
35
|
+
* Mutates the messages array in place.
|
|
36
|
+
*/
|
|
37
|
+
export declare function upsertSessionStateMessage(messages: Array<{
|
|
38
|
+
role: string;
|
|
39
|
+
content: string;
|
|
40
|
+
}>, block: string): void;
|
|
41
|
+
export declare function isSessionStateMessage(content: string): boolean;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact SESSION STATE / WORKING MEMORY block for the model.
|
|
3
|
+
* Survives as an updatable system message; re-injected after compaction.
|
|
4
|
+
*/
|
|
5
|
+
export const SESSION_STATE_PREFIX = "SESSION STATE / WORKING MEMORY";
|
|
6
|
+
/** Build a short, high-signal state block (aim < 400 tokens). */
|
|
7
|
+
export function buildSessionStateBlock(s) {
|
|
8
|
+
const lines = [SESSION_STATE_PREFIX];
|
|
9
|
+
if (s.goal)
|
|
10
|
+
lines.push(`goal: ${oneLine(s.goal, 160)}`);
|
|
11
|
+
if (s.projectRoot)
|
|
12
|
+
lines.push(`project_root: ${s.projectRoot}`);
|
|
13
|
+
if (s.packageManager)
|
|
14
|
+
lines.push(`package_manager: ${s.packageManager}`);
|
|
15
|
+
if (s.planStatus || s.planKind) {
|
|
16
|
+
lines.push(`plan: ${s.planKind ?? "?"} status=${s.planStatus ?? "?"}`.trim());
|
|
17
|
+
}
|
|
18
|
+
if (s.openTask)
|
|
19
|
+
lines.push(`open_task: ${oneLine(s.openTask, 120)}`);
|
|
20
|
+
if (s.doneTasks?.length) {
|
|
21
|
+
lines.push(`done: ${s.doneTasks.slice(0, 8).join("; ")}`);
|
|
22
|
+
}
|
|
23
|
+
if (s.pendingTasks?.length) {
|
|
24
|
+
lines.push(`pending: ${s.pendingTasks.slice(0, 8).join("; ")}`);
|
|
25
|
+
}
|
|
26
|
+
const flags = [];
|
|
27
|
+
if (s.featureAppRequired) {
|
|
28
|
+
flags.push(`feature_needed=true feature_seen=${s.featureSeen ? "true" : "false"}`);
|
|
29
|
+
}
|
|
30
|
+
if (s.scaffoldOk)
|
|
31
|
+
flags.push("scaffold_ok=true");
|
|
32
|
+
if (s.serverStarted)
|
|
33
|
+
flags.push("server_started=true");
|
|
34
|
+
if (s.serverProbedOk)
|
|
35
|
+
flags.push("probe_ok=true");
|
|
36
|
+
if (s.lastProbeFailed)
|
|
37
|
+
flags.push("last_probe_failed=true");
|
|
38
|
+
if (flags.length)
|
|
39
|
+
lines.push(`flags: ${flags.join(" ")}`);
|
|
40
|
+
if (s.lastOkTool)
|
|
41
|
+
lines.push(`last_ok_tool: ${s.lastOkTool}`);
|
|
42
|
+
if (s.engagementNote)
|
|
43
|
+
lines.push(`note: ${oneLine(s.engagementNote, 160)}`);
|
|
44
|
+
if (s.nextHint)
|
|
45
|
+
lines.push(`next: ${oneLine(s.nextHint, 200)}`);
|
|
46
|
+
lines.push("Use this state. Prefer evidence over claims. Update work via tools; do not invent progress.");
|
|
47
|
+
return lines.join("\n");
|
|
48
|
+
}
|
|
49
|
+
function oneLine(s, max) {
|
|
50
|
+
const t = s.replace(/\s+/g, " ").trim();
|
|
51
|
+
return t.length <= max ? t : t.slice(0, max - 1) + "…";
|
|
52
|
+
}
|
|
53
|
+
/** Infer a short next-action hint from flags (no LLM). */
|
|
54
|
+
export function inferNextHint(s) {
|
|
55
|
+
if (s.featureAppRequired && !s.featureSeen) {
|
|
56
|
+
return "Implement the product feature (replace starter boilerplate); do not start the server yet.";
|
|
57
|
+
}
|
|
58
|
+
if (s.lastProbeFailed) {
|
|
59
|
+
return "Fix the app error (fs.edit/write), then re-probe localhost — diagnosis alone is incomplete.";
|
|
60
|
+
}
|
|
61
|
+
// Leave-running / verify open with server already proven → close out, don't restart
|
|
62
|
+
if (s.serverStarted &&
|
|
63
|
+
s.openTask &&
|
|
64
|
+
/\bleave\s+.*running|for\s+user\s+to\s+test|keep\s+.*running/i.test(s.openTask)) {
|
|
65
|
+
return "Runtime already proven: confirm still alive if needed, task.update done, report URL + port + job id — do not restart.";
|
|
66
|
+
}
|
|
67
|
+
if (s.serverStarted && !s.serverProbedOk && !s.lastProbeFailed) {
|
|
68
|
+
return "Confirm ready (shell.tail or lsof LISTEN or localhost GET); leave server running; report URL + job id. Do not thrash ports.";
|
|
69
|
+
}
|
|
70
|
+
if (s.openTask && /\brecon|enumerat|scan|dns|nmap/i.test(s.openTask)) {
|
|
71
|
+
return "Run remote recon tools against the in-scope target (dns/http/net.scan), then mark done with evidence.";
|
|
72
|
+
}
|
|
73
|
+
if (s.openTask) {
|
|
74
|
+
return `Finish open task, verify with tools, mark done only with evidence.`;
|
|
75
|
+
}
|
|
76
|
+
if (s.pendingTasks?.length) {
|
|
77
|
+
return `Open next pending task with task.update in_progress, then execute it.`;
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Upsert SESSION STATE as a system message after the primary system prompt.
|
|
83
|
+
* Mutates the messages array in place.
|
|
84
|
+
*/
|
|
85
|
+
export function upsertSessionStateMessage(messages, block) {
|
|
86
|
+
const content = block.startsWith(SESSION_STATE_PREFIX)
|
|
87
|
+
? block
|
|
88
|
+
: `${SESSION_STATE_PREFIX}\n${block}`;
|
|
89
|
+
const idx = messages.findIndex((m) => m.role === "system" &&
|
|
90
|
+
typeof m.content === "string" &&
|
|
91
|
+
m.content.startsWith(SESSION_STATE_PREFIX));
|
|
92
|
+
if (idx >= 0) {
|
|
93
|
+
messages[idx].content = content;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Insert after first system message if present, else at front.
|
|
97
|
+
if (messages[0]?.role === "system") {
|
|
98
|
+
messages.splice(1, 0, { role: "system", content });
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
messages.unshift({ role: "system", content });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function isSessionStateMessage(content) {
|
|
105
|
+
return content.startsWith(SESSION_STATE_PREFIX);
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=session-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-state.js","sourceRoot":"","sources":["../../src/agent/session-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TaskAnalysis } from "./task-analyzer.js";
|
|
2
|
+
export interface StepBudgetInput {
|
|
3
|
+
analysis: TaskAnalysis;
|
|
4
|
+
maxSteps: number;
|
|
5
|
+
buildLike: boolean;
|
|
6
|
+
pentestLike: boolean;
|
|
7
|
+
hasHistory: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Productive tool-step budget for a turn. Multi-step builds/pentests get the
|
|
11
|
+
* full ceiling; short follow-ups with history stay at least standard-sized.
|
|
12
|
+
*/
|
|
13
|
+
export declare function computeStepBudget(input: StepBudgetInput): number;
|
|
14
|
+
export declare function computeMaxIterations(stepBudget: number): number;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Productive tool-step budget for a turn. Multi-step builds/pentests get the
|
|
3
|
+
* full ceiling; short follow-ups with history stay at least standard-sized.
|
|
4
|
+
*/
|
|
5
|
+
export function computeStepBudget(input) {
|
|
6
|
+
const { analysis, maxSteps, buildLike, pentestLike, hasHistory } = input;
|
|
7
|
+
let budget = analysis.complexity === "simple"
|
|
8
|
+
? 20
|
|
9
|
+
: analysis.complexity === "standard"
|
|
10
|
+
? 40
|
|
11
|
+
: maxSteps;
|
|
12
|
+
if (buildLike || pentestLike || analysis.shouldPlan) {
|
|
13
|
+
budget = Math.max(budget, maxSteps);
|
|
14
|
+
}
|
|
15
|
+
else if (hasHistory) {
|
|
16
|
+
budget = Math.max(budget, 40);
|
|
17
|
+
}
|
|
18
|
+
if (analysis.complexity === "complex") {
|
|
19
|
+
budget = Math.max(budget, Math.min(maxSteps, 80));
|
|
20
|
+
}
|
|
21
|
+
return budget;
|
|
22
|
+
}
|
|
23
|
+
export function computeMaxIterations(stepBudget) {
|
|
24
|
+
return stepBudget * 3;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=step-budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-budget.js","sourceRoot":"","sources":["../../src/agent/step-budget.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAsB;IACtD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IACzE,IAAI,MAAM,GACR,QAAQ,CAAC,UAAU,KAAK,QAAQ;QAC9B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,QAAQ,CAAC,UAAU,KAAK,UAAU;YAClC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,QAAQ,CAAC;IAEjB,IAAI,SAAS,IAAI,WAAW,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QACpD,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAC;SAAM,IAAI,UAAU,EAAE,CAAC;QACtB,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACrD,OAAO,UAAU,GAAG,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { TaskComplexity, TaskKind, PlanStep } from "./task-plan.js";
|
|
2
2
|
export interface TaskAnalysis {
|
|
3
3
|
complexity: TaskComplexity;
|
|
4
|
+
/** True when multi-step durable planning is warranted (soft signal). */
|
|
4
5
|
shouldPlan: boolean;
|
|
5
6
|
category: TaskKind;
|
|
6
7
|
goal: string;
|
|
@@ -8,11 +9,19 @@ export interface TaskAnalysis {
|
|
|
8
9
|
needsToolPreflight: boolean;
|
|
9
10
|
likelyTools: string[];
|
|
10
11
|
stopWhen: string;
|
|
12
|
+
/** Soft high-level steps — never force-executed; empty for trivial asks. */
|
|
11
13
|
suggestedSteps: PlanStep[];
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
16
|
+
* A bounded, explicit nmap operation is not a request for a full pentest.
|
|
17
|
+
* Keep it to one net.scan call unless the user also asks for assessment,
|
|
18
|
+
* reconnaissance, enumeration, exploitation, or multiple named operations.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isNarrowExplicitNmapOperation(prompt: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Lightweight task analysis for step budgets and soft guidance.
|
|
23
|
+
* Does not execute or force a plan — the agent still owns decisions.
|
|
17
24
|
*/
|
|
18
25
|
export declare function analyzeTask(prompt: string): TaskAnalysis;
|
|
26
|
+
/** Compact one-liner for session/system context (optional inject). */
|
|
27
|
+
export declare function formatTaskAnalysisHint(analysis: TaskAnalysis): string;
|
|
@@ -1,33 +1,273 @@
|
|
|
1
|
+
import { createPlanStep } from "./task-plan.js";
|
|
2
|
+
const PENTEST_RE = /\b(?:pentest|pen[\s-]?test|penetration|security\s*(?:test|audit|scan|assess)|vapt|csrf|xss|sqli|sql[\s-]?inject|rce|lfi|rfi|ssrf|idor|xxe|deserialization|brute[\s-]?force|enumerat|exploit|vulnerabilit|recon|bug[\s-]?bounty|ctf|capture[\s-]?the[\s-]?flag|red[\s-]?team|offensive|nmap|nikto|nuclei|ffuf|gobuster|sqlmap|hydra|metasploit)\b/i;
|
|
3
|
+
const BUILD_RE = /\b(?:build|scaffold|create|implement|refactor|migrate|bootstrap|set\s*up|setup)\b/i;
|
|
4
|
+
const APP_RE = /\b(?:app|application|project|website|api|service|cli|dashboard|todo|blog|frontend|backend)\b/i;
|
|
5
|
+
const FIX_RE = /\b(?:fix|debug|broken|error|failing|crash|bug|regression|not\s+work|doesn'?t\s+work|typeerror|exception)\b/i;
|
|
6
|
+
const RESEARCH_RE = /\b(?:what\s+is|how\s+(?:do|does|to)|explain|compare|difference|latest|current|who\s+is|when\s+did|why\s+(?:is|does))\b/i;
|
|
7
|
+
const NETWORK_RE = /\b(?:scan|nmap|ping|subnet|cidr|local\s*network|hosts?|ports?|dns|whois|http|https|url|domain|ip\s*address)\b/i;
|
|
8
|
+
const SHELL_RE = /\b(?:run|execute|install|upgrade|brew|apt|npm\s+i|docker|kubectl|chmod|chown|kill|restart|service)\b/i;
|
|
9
|
+
const FS_RE = /\b(?:read|write|edit|file|directory|folder|path|rename|delete|list\s+files?|open\s+)\b/i;
|
|
1
10
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
11
|
+
* A bounded, explicit nmap operation is not a request for a full pentest.
|
|
12
|
+
* Keep it to one net.scan call unless the user also asks for assessment,
|
|
13
|
+
* reconnaissance, enumeration, exploitation, or multiple named operations.
|
|
4
14
|
*/
|
|
5
|
-
|
|
15
|
+
export function isNarrowExplicitNmapOperation(prompt) {
|
|
16
|
+
const text = prompt.replace(/\s+/g, " ").trim();
|
|
17
|
+
if (!/\bnmap\b/i.test(text))
|
|
18
|
+
return false;
|
|
19
|
+
const explicitRun = /^(?:sudo\s+)?nmap(?:\s|$)/i.test(text) ||
|
|
20
|
+
/\b(?:run|execute|start|perform)\b[\s\S]{0,40}\bnmap\b/i.test(text) ||
|
|
21
|
+
/\bnmap\b[\s\S]{0,20}\bscan\b/i.test(text) ||
|
|
22
|
+
/\bscan\b[\s\S]{0,40}\bwith\s+nmap\b/i.test(text);
|
|
23
|
+
if (!explicitRun)
|
|
24
|
+
return false;
|
|
25
|
+
if (/\b(?:pentest|pen[\s-]?test|penetration|security\s+(?:audit|assessment|test)|vapt|recon(?:naissance)?|enumerat\w*|attack\s+surface|vulnerabilit\w*|exploit\w*|bug\s*bounty|red\s*team|threat\s+model|web\s+assessment)\b/i.test(text)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
if (/\b(?:and|then|also)\b[\s\S]{0,40}\b(?:whois|dns|dig|http|crawl|fuzz|nikto|nuclei|sqlmap|gobuster|ffuf)\b/i.test(text)) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
function wordCount(prompt) {
|
|
34
|
+
return prompt.trim().split(/\s+/).filter(Boolean).length;
|
|
35
|
+
}
|
|
36
|
+
function classifyCategory(prompt) {
|
|
37
|
+
if (PENTEST_RE.test(prompt)) {
|
|
38
|
+
if (/\b(?:dns|whois|subdomain)\b/i.test(prompt))
|
|
39
|
+
return "dns";
|
|
40
|
+
if (/\b(?:whois|registrar|owner)\b/i.test(prompt))
|
|
41
|
+
return "whois";
|
|
42
|
+
if (/\b(?:dir|fuzz|gobuster|ffuf|content\s*discover)\b/i.test(prompt)) {
|
|
43
|
+
return "web-enum";
|
|
44
|
+
}
|
|
45
|
+
if (/\b(?:recon|enumerat|osint|fingerprint)\b/i.test(prompt)) {
|
|
46
|
+
return "pentest-recon";
|
|
47
|
+
}
|
|
48
|
+
return "pentest-recon";
|
|
49
|
+
}
|
|
50
|
+
if (/\b(?:whois)\b/i.test(prompt))
|
|
51
|
+
return "whois";
|
|
52
|
+
if (/\b(?:dns|dig|nslookup|resolve)\b/i.test(prompt))
|
|
53
|
+
return "dns";
|
|
54
|
+
if (NETWORK_RE.test(prompt) && /\b(?:discover|sweep|live\s*hosts?)\b/i.test(prompt)) {
|
|
55
|
+
return "network-discovery";
|
|
56
|
+
}
|
|
57
|
+
if (/\b(?:pkg|package|brew\s+install|apt\s+install|install\s+\w+)\b/i.test(prompt)) {
|
|
58
|
+
return "package";
|
|
59
|
+
}
|
|
60
|
+
if (BUILD_RE.test(prompt) || FIX_RE.test(prompt) || FS_RE.test(prompt)) {
|
|
61
|
+
return "filesystem";
|
|
62
|
+
}
|
|
63
|
+
if (SHELL_RE.test(prompt))
|
|
64
|
+
return "shell";
|
|
65
|
+
if (RESEARCH_RE.test(prompt) || prompt.trim().endsWith("?"))
|
|
66
|
+
return "answer";
|
|
67
|
+
return "other";
|
|
68
|
+
}
|
|
69
|
+
function estimateComplexity(prompt, category, words) {
|
|
70
|
+
if (PENTEST_RE.test(prompt))
|
|
71
|
+
return "complex";
|
|
72
|
+
if (BUILD_RE.test(prompt) && APP_RE.test(prompt))
|
|
73
|
+
return "complex";
|
|
74
|
+
if (/\b(?:multi-?file|across\s+files|refactor|migrate|end-?to-?end|full\s+stack)\b/i.test(prompt)) {
|
|
75
|
+
return "complex";
|
|
76
|
+
}
|
|
77
|
+
if (FIX_RE.test(prompt)) {
|
|
78
|
+
return words > 40 ? "complex" : "standard";
|
|
79
|
+
}
|
|
80
|
+
if (category === "answer" && words <= 20)
|
|
81
|
+
return "simple";
|
|
82
|
+
if (words <= 6 && !BUILD_RE.test(prompt) && !PENTEST_RE.test(prompt)) {
|
|
83
|
+
return "simple";
|
|
84
|
+
}
|
|
85
|
+
if (words <= 28 && !BUILD_RE.test(prompt))
|
|
86
|
+
return "standard";
|
|
87
|
+
return words > 40 || BUILD_RE.test(prompt) ? "complex" : "standard";
|
|
88
|
+
}
|
|
89
|
+
function shouldPlanFor(prompt, complexity, category) {
|
|
90
|
+
if (complexity === "simple")
|
|
91
|
+
return false;
|
|
92
|
+
if (category === "answer")
|
|
93
|
+
return false;
|
|
94
|
+
if (PENTEST_RE.test(prompt))
|
|
95
|
+
return true;
|
|
96
|
+
if (BUILD_RE.test(prompt) && APP_RE.test(prompt))
|
|
97
|
+
return true;
|
|
98
|
+
if (/\b(?:implement|refactor|migrate|multi-?step|several\s+files|end-?to-?end)\b/i.test(prompt)) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
return complexity === "complex" && wordCount(prompt) > 25;
|
|
102
|
+
}
|
|
103
|
+
function inferLikelyTools(prompt, category) {
|
|
104
|
+
const tools = new Set();
|
|
105
|
+
if (category === "answer" || RESEARCH_RE.test(prompt)) {
|
|
106
|
+
tools.add("web.search");
|
|
107
|
+
tools.add("web.fetch");
|
|
108
|
+
}
|
|
109
|
+
if (category === "filesystem" || BUILD_RE.test(prompt) || FIX_RE.test(prompt)) {
|
|
110
|
+
tools.add("fs.list");
|
|
111
|
+
tools.add("fs.read");
|
|
112
|
+
tools.add("fs.write");
|
|
113
|
+
tools.add("fs.edit");
|
|
114
|
+
tools.add("shell.exec");
|
|
115
|
+
}
|
|
116
|
+
if (BUILD_RE.test(prompt) && APP_RE.test(prompt)) {
|
|
117
|
+
tools.add("plan.create");
|
|
118
|
+
tools.add("task.update");
|
|
119
|
+
tools.add("shell.start");
|
|
120
|
+
}
|
|
121
|
+
if (PENTEST_RE.test(prompt) || category.startsWith("pentest") || category === "web-enum") {
|
|
122
|
+
tools.add("dns.lookup");
|
|
123
|
+
tools.add("whois.lookup");
|
|
124
|
+
tools.add("http.fetch");
|
|
125
|
+
tools.add("net.scan");
|
|
126
|
+
tools.add("tool.check");
|
|
127
|
+
tools.add("plan.create");
|
|
128
|
+
}
|
|
129
|
+
if (category === "network-discovery") {
|
|
130
|
+
tools.add("net.context");
|
|
131
|
+
tools.add("net.pingSweep");
|
|
132
|
+
tools.add("net.scan");
|
|
133
|
+
}
|
|
134
|
+
if (category === "dns")
|
|
135
|
+
tools.add("dns.lookup");
|
|
136
|
+
if (category === "whois")
|
|
137
|
+
tools.add("whois.lookup");
|
|
138
|
+
if (category === "package")
|
|
139
|
+
tools.add("pkg.install");
|
|
140
|
+
if (SHELL_RE.test(prompt))
|
|
141
|
+
tools.add("shell.exec");
|
|
142
|
+
if (/\b(?:pdf)\b/i.test(prompt))
|
|
143
|
+
tools.add("pdf.read");
|
|
144
|
+
if (/\b(?:ocr|image|screenshot)\b/i.test(prompt))
|
|
145
|
+
tools.add("image.ocr");
|
|
146
|
+
return [...tools];
|
|
147
|
+
}
|
|
148
|
+
function softSteps(prompt, category) {
|
|
149
|
+
if (PENTEST_RE.test(prompt)) {
|
|
150
|
+
return [
|
|
151
|
+
createPlanStep("Recon and fingerprint stack", "pentest-recon", {
|
|
152
|
+
toolHint: "dns.lookup / http.fetch / net.scan",
|
|
153
|
+
successCriteria: "real findings from tool output",
|
|
154
|
+
}),
|
|
155
|
+
createPlanStep("Plan from findings", "other", {
|
|
156
|
+
toolHint: "plan.create",
|
|
157
|
+
successCriteria: "durable plan with verifiable tasks",
|
|
158
|
+
}),
|
|
159
|
+
createPlanStep("Test high-value vectors", "web-enum", {
|
|
160
|
+
successCriteria: "validated evidence or clean negatives",
|
|
161
|
+
}),
|
|
162
|
+
createPlanStep("Report with evidence", "other", {
|
|
163
|
+
successCriteria: "findings with repro + severity",
|
|
164
|
+
}),
|
|
165
|
+
];
|
|
166
|
+
}
|
|
167
|
+
if (BUILD_RE.test(prompt) && APP_RE.test(prompt)) {
|
|
168
|
+
return [
|
|
169
|
+
createPlanStep("Explore destination and stack", "filesystem", {
|
|
170
|
+
toolHint: "fs.list / fs.read",
|
|
171
|
+
}),
|
|
172
|
+
createPlanStep("Plan multi-step build", "other", {
|
|
173
|
+
toolHint: "plan.create",
|
|
174
|
+
}),
|
|
175
|
+
createPlanStep("Implement requested feature", "filesystem", {
|
|
176
|
+
toolHint: "fs.write / fs.edit",
|
|
177
|
+
}),
|
|
178
|
+
createPlanStep("Verify (build and/or live server)", "shell", {
|
|
179
|
+
toolHint: "shell.start / shell.exec",
|
|
180
|
+
}),
|
|
181
|
+
];
|
|
182
|
+
}
|
|
183
|
+
if (FIX_RE.test(prompt)) {
|
|
184
|
+
return [
|
|
185
|
+
createPlanStep("Reproduce and capture error", "shell"),
|
|
186
|
+
createPlanStep("Localize root cause", "filesystem", {
|
|
187
|
+
toolHint: "fs.read / fs.search",
|
|
188
|
+
}),
|
|
189
|
+
createPlanStep("Apply minimal fix", "filesystem", {
|
|
190
|
+
toolHint: "fs.edit",
|
|
191
|
+
}),
|
|
192
|
+
createPlanStep("Re-run failing check", "shell"),
|
|
193
|
+
];
|
|
194
|
+
}
|
|
195
|
+
if (category === "network-discovery") {
|
|
196
|
+
return [
|
|
197
|
+
createPlanStep("Local network context", "network-discovery", {
|
|
198
|
+
toolHint: "net.context",
|
|
199
|
+
}),
|
|
200
|
+
createPlanStep("Discover live hosts", "network-discovery", {
|
|
201
|
+
toolHint: "net.pingSweep",
|
|
202
|
+
}),
|
|
203
|
+
createPlanStep("Summarize findings", "other"),
|
|
204
|
+
];
|
|
205
|
+
}
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
function stopWhenFor(prompt, category) {
|
|
209
|
+
if (PENTEST_RE.test(prompt)) {
|
|
210
|
+
return "Findings report with evidence; no local dev server; scope respected.";
|
|
211
|
+
}
|
|
212
|
+
if (BUILD_RE.test(prompt) && APP_RE.test(prompt)) {
|
|
213
|
+
return "Requested feature works; verified via build and/or live localhost probe; server left running when applicable.";
|
|
214
|
+
}
|
|
215
|
+
if (FIX_RE.test(prompt)) {
|
|
216
|
+
return "Original failing check now passes; root cause addressed.";
|
|
217
|
+
}
|
|
218
|
+
if (category === "answer") {
|
|
219
|
+
return "Accurate answer grounded in tools when facts are volatile.";
|
|
220
|
+
}
|
|
221
|
+
return "User request completed with tool-backed evidence.";
|
|
222
|
+
}
|
|
6
223
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* No pre-baked steps — the AI decides everything dynamically.
|
|
224
|
+
* Lightweight task analysis for step budgets and soft guidance.
|
|
225
|
+
* Does not execute or force a plan — the agent still owns decisions.
|
|
10
226
|
*/
|
|
11
227
|
export function analyzeTask(prompt) {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
:
|
|
19
|
-
|
|
20
|
-
|
|
228
|
+
const text = prompt.replace(/\s+/g, " ").trim();
|
|
229
|
+
if (isNarrowExplicitNmapOperation(text)) {
|
|
230
|
+
return {
|
|
231
|
+
complexity: "standard",
|
|
232
|
+
shouldPlan: false,
|
|
233
|
+
category: "pentest-recon",
|
|
234
|
+
goal: text.slice(0, 100),
|
|
235
|
+
needsNetworkContext: false,
|
|
236
|
+
needsToolPreflight: true,
|
|
237
|
+
likelyTools: ["net.scan"],
|
|
238
|
+
stopWhen: "The requested nmap operation has started or completed and its canonical job ID, status, and output are reported; do not broaden scope.",
|
|
239
|
+
suggestedSteps: [],
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
const words = wordCount(text);
|
|
243
|
+
const category = classifyCategory(text);
|
|
244
|
+
const complexity = estimateComplexity(text, category, words);
|
|
245
|
+
const shouldPlan = shouldPlanFor(text, complexity, category);
|
|
246
|
+
const likelyTools = inferLikelyTools(text, category);
|
|
247
|
+
const suggestedSteps = complexity === "simple" || category === "answer" ? [] : softSteps(text, category);
|
|
21
248
|
return {
|
|
22
249
|
complexity,
|
|
23
|
-
shouldPlan
|
|
24
|
-
category
|
|
25
|
-
goal:
|
|
26
|
-
needsNetworkContext:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
250
|
+
shouldPlan,
|
|
251
|
+
category,
|
|
252
|
+
goal: text.slice(0, 100),
|
|
253
|
+
needsNetworkContext: category === "network-discovery" ||
|
|
254
|
+
/\b(?:local\s*network|subnet|cidr|lan|my\s+network)\b/i.test(text),
|
|
255
|
+
needsToolPreflight: PENTEST_RE.test(text) ||
|
|
256
|
+
/\b(?:nmap|ffuf|gobuster|sqlmap|nuclei|hydra|nikto)\b/i.test(text),
|
|
257
|
+
likelyTools,
|
|
258
|
+
stopWhen: stopWhenFor(text, category),
|
|
259
|
+
suggestedSteps,
|
|
31
260
|
};
|
|
32
261
|
}
|
|
262
|
+
/** Compact one-liner for session/system context (optional inject). */
|
|
263
|
+
export function formatTaskAnalysisHint(analysis) {
|
|
264
|
+
const tools = analysis.likelyTools.length > 0
|
|
265
|
+
? analysis.likelyTools.slice(0, 8).join(", ")
|
|
266
|
+
: "—";
|
|
267
|
+
const tracking = analysis.shouldPlan
|
|
268
|
+
? "durable task tracking strongly recommended: create one concise plan before mutation, then keep task.update states aligned with real work"
|
|
269
|
+
: "direct execution ok";
|
|
270
|
+
return (`TASK ANALYSIS: category=${analysis.category} complexity=${analysis.complexity} (${tracking}). ` +
|
|
271
|
+
`Likely tools: ${tools}. Done when: ${analysis.stopWhen}`);
|
|
272
|
+
}
|
|
33
273
|
//# sourceMappingURL=task-analyzer.js.map
|