@pentoshi/clai 2.0.61 → 3.0.0
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 +262 -368
- package/dist/agent/context-manager.d.ts +5 -0
- package/dist/agent/context-manager.js +14 -2
- package/dist/agent/context-manager.js.map +1 -1
- package/dist/agent/events.d.ts +4 -1
- package/dist/agent/runner.js +210 -91
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/tool-call-parser.d.ts +15 -0
- package/dist/agent/tool-call-parser.js +171 -2
- package/dist/agent/tool-call-parser.js.map +1 -1
- package/dist/app/adapters/agent-event-adapter.d.ts +29 -0
- package/dist/app/adapters/agent-event-adapter.js +143 -0
- package/dist/app/adapters/agent-event-adapter.js.map +1 -0
- package/dist/app/adapters/current-agent-adapter.d.ts +7 -0
- package/dist/app/adapters/current-agent-adapter.js +27 -0
- package/dist/app/adapters/current-agent-adapter.js.map +1 -0
- package/dist/app/adapters/current-jobs-adapter.d.ts +4 -0
- package/dist/app/adapters/current-jobs-adapter.js +13 -0
- package/dist/app/adapters/current-jobs-adapter.js.map +1 -0
- package/dist/app/adapters/current-store-adapter.d.ts +3 -0
- package/dist/app/adapters/current-store-adapter.js +22 -0
- package/dist/app/adapters/current-store-adapter.js.map +1 -0
- package/dist/app/adapters/current-terminal-adapter.d.ts +9 -0
- package/dist/app/adapters/current-terminal-adapter.js +31 -0
- package/dist/app/adapters/current-terminal-adapter.js.map +1 -0
- package/dist/app/adapters/current-updates-adapter.d.ts +7 -0
- package/dist/app/adapters/current-updates-adapter.js +31 -0
- package/dist/app/adapters/current-updates-adapter.js.map +1 -0
- package/dist/app/adapters/in-memory-clipboard-adapter.d.ts +10 -0
- package/dist/app/adapters/in-memory-clipboard-adapter.js +20 -0
- package/dist/app/adapters/in-memory-clipboard-adapter.js.map +1 -0
- package/dist/app/commands/command.d.ts +24 -0
- package/dist/app/commands/command.js +4 -0
- package/dist/app/commands/command.js.map +1 -0
- package/dist/app/commands/registry.d.ts +45 -0
- package/dist/app/commands/registry.js +164 -0
- package/dist/app/commands/registry.js.map +1 -0
- package/dist/app/controllers/disposable.d.ts +15 -0
- package/dist/app/controllers/disposable.js +38 -0
- package/dist/app/controllers/disposable.js.map +1 -0
- package/dist/app/controllers/job-controller.d.ts +22 -0
- package/dist/app/controllers/job-controller.js +35 -0
- package/dist/app/controllers/job-controller.js.map +1 -0
- package/dist/app/controllers/plan-controller.d.ts +31 -0
- package/dist/app/controllers/plan-controller.js +69 -0
- package/dist/app/controllers/plan-controller.js.map +1 -0
- package/dist/app/controllers/session-controller.d.ts +167 -0
- package/dist/app/controllers/session-controller.js +467 -0
- package/dist/app/controllers/session-controller.js.map +1 -0
- package/dist/app/controllers/turn-controller.d.ts +52 -0
- package/dist/app/controllers/turn-controller.js +118 -0
- package/dist/app/controllers/turn-controller.js.map +1 -0
- package/dist/app/events/app-event.d.ts +118 -0
- package/dist/app/events/app-event.js +25 -0
- package/dist/app/events/app-event.js.map +1 -0
- package/dist/app/events/event-buffer.d.ts +51 -0
- package/dist/app/events/event-buffer.js +109 -0
- package/dist/app/events/event-buffer.js.map +1 -0
- package/dist/app/events/sequencer.d.ts +32 -0
- package/dist/app/events/sequencer.js +55 -0
- package/dist/app/events/sequencer.js.map +1 -0
- package/dist/app/ports/agent-port.d.ts +29 -0
- package/dist/app/ports/agent-port.js +2 -0
- package/dist/app/ports/agent-port.js.map +1 -0
- package/dist/app/ports/clipboard-port.d.ts +9 -0
- package/dist/app/ports/clipboard-port.js +2 -0
- package/dist/app/ports/clipboard-port.js.map +1 -0
- package/dist/app/ports/confirm-port.d.ts +17 -0
- package/dist/app/ports/confirm-port.js +2 -0
- package/dist/app/ports/confirm-port.js.map +1 -0
- package/dist/app/ports/jobs-port.d.ts +18 -0
- package/dist/app/ports/jobs-port.js +2 -0
- package/dist/app/ports/jobs-port.js.map +1 -0
- package/dist/app/ports/persistence-port.d.ts +21 -0
- package/dist/app/ports/persistence-port.js +2 -0
- package/dist/app/ports/persistence-port.js.map +1 -0
- package/dist/app/ports/secret-port.d.ts +12 -0
- package/dist/app/ports/secret-port.js +2 -0
- package/dist/app/ports/secret-port.js.map +1 -0
- package/dist/app/ports/terminal-port.d.ts +18 -0
- package/dist/app/ports/terminal-port.js +2 -0
- package/dist/app/ports/terminal-port.js.map +1 -0
- package/dist/app/ports/updates-port.d.ts +12 -0
- package/dist/app/ports/updates-port.js +2 -0
- package/dist/app/ports/updates-port.js.map +1 -0
- package/dist/commands/doctor.js +9 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/update.js +1 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/llm/router.js +4 -2
- package/dist/llm/router.js.map +1 -1
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.js +5 -3
- package/dist/prompts/index.js.map +1 -1
- package/dist/repl/slash-commands.js +1 -1
- package/dist/repl/slash-commands.js.map +1 -1
- package/dist/repl.js +35 -107
- package/dist/repl.js.map +1 -1
- package/dist/store/config.js +3 -1
- package/dist/store/config.js.map +1 -1
- package/dist/store/history.d.ts +26 -2
- package/dist/store/history.js +383 -72
- package/dist/store/history.js.map +1 -1
- package/dist/store/logs.js +3 -3
- package/dist/store/logs.js.map +1 -1
- package/dist/store/paths.d.ts +6 -0
- package/dist/store/paths.js +38 -0
- package/dist/store/paths.js.map +1 -0
- package/dist/store/plan.js +8 -5
- package/dist/store/plan.js.map +1 -1
- package/dist/tools/jobs.js +2 -2
- package/dist/tools/jobs.js.map +1 -1
- package/dist/tools/registry.js +117 -46
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/shell.js +2 -2
- package/dist/tools/shell.js.map +1 -1
- package/dist/tui/state.js +20 -17
- package/dist/tui/state.js.map +1 -1
- package/dist/tui-v2/actions/action-id.d.ts +14 -0
- package/dist/tui-v2/actions/action-id.js +109 -0
- package/dist/tui-v2/actions/action-id.js.map +1 -0
- package/dist/tui-v2/actions/action-router.d.ts +18 -0
- package/dist/tui-v2/actions/action-router.js +62 -0
- package/dist/tui-v2/actions/action-router.js.map +1 -0
- package/dist/tui-v2/actions/chord-from-key.d.ts +26 -0
- package/dist/tui-v2/actions/chord-from-key.js +45 -0
- package/dist/tui-v2/actions/chord-from-key.js.map +1 -0
- package/dist/tui-v2/actions/keymap.d.ts +24 -0
- package/dist/tui-v2/actions/keymap.js +134 -0
- package/dist/tui-v2/actions/keymap.js.map +1 -0
- package/dist/tui-v2/app/App.d.ts +13 -0
- package/dist/tui-v2/app/App.js +320 -0
- package/dist/tui-v2/app/App.js.map +1 -0
- package/dist/tui-v2/app/command-handlers.d.ts +8 -0
- package/dist/tui-v2/app/command-handlers.js +66 -0
- package/dist/tui-v2/app/command-handlers.js.map +1 -0
- package/dist/tui-v2/app/commands/config-commands.d.ts +14 -0
- package/dist/tui-v2/app/commands/config-commands.js +161 -0
- package/dist/tui-v2/app/commands/config-commands.js.map +1 -0
- package/dist/tui-v2/app/commands/key-commands.d.ts +9 -0
- package/dist/tui-v2/app/commands/key-commands.js +263 -0
- package/dist/tui-v2/app/commands/key-commands.js.map +1 -0
- package/dist/tui-v2/app/commands/picker-commands.d.ts +24 -0
- package/dist/tui-v2/app/commands/picker-commands.js +423 -0
- package/dist/tui-v2/app/commands/picker-commands.js.map +1 -0
- package/dist/tui-v2/app/commands/session-commands.d.ts +19 -0
- package/dist/tui-v2/app/commands/session-commands.js +162 -0
- package/dist/tui-v2/app/commands/session-commands.js.map +1 -0
- package/dist/tui-v2/app/plan-lifecycle.d.ts +16 -0
- package/dist/tui-v2/app/plan-lifecycle.js +59 -0
- package/dist/tui-v2/app/plan-lifecycle.js.map +1 -0
- package/dist/tui-v2/app/providers.d.ts +17 -0
- package/dist/tui-v2/app/providers.js +32 -0
- package/dist/tui-v2/app/providers.js.map +1 -0
- package/dist/tui-v2/bootstrap/capabilities.d.ts +35 -0
- package/dist/tui-v2/bootstrap/capabilities.js +93 -0
- package/dist/tui-v2/bootstrap/capabilities.js.map +1 -0
- package/dist/tui-v2/bootstrap/composition-root.d.ts +85 -0
- package/dist/tui-v2/bootstrap/composition-root.js +131 -0
- package/dist/tui-v2/bootstrap/composition-root.js.map +1 -0
- package/dist/tui-v2/bootstrap/disable-native-selection.d.ts +11 -0
- package/dist/tui-v2/bootstrap/disable-native-selection.js +13 -0
- package/dist/tui-v2/bootstrap/disable-native-selection.js.map +1 -0
- package/dist/tui-v2/bootstrap/lifecycle.d.ts +62 -0
- package/dist/tui-v2/bootstrap/lifecycle.js +123 -0
- package/dist/tui-v2/bootstrap/lifecycle.js.map +1 -0
- package/dist/tui-v2/bootstrap/osc52-clipboard.d.ts +28 -0
- package/dist/tui-v2/bootstrap/osc52-clipboard.js +44 -0
- package/dist/tui-v2/bootstrap/osc52-clipboard.js.map +1 -0
- package/dist/tui-v2/bootstrap/overlay-ports.d.ts +12 -0
- package/dist/{tui/confirm.js → tui-v2/bootstrap/overlay-ports.js} +17 -25
- package/dist/tui-v2/bootstrap/overlay-ports.js.map +1 -0
- package/dist/tui-v2/bootstrap/pager-export.d.ts +24 -0
- package/dist/tui-v2/bootstrap/pager-export.js +87 -0
- package/dist/tui-v2/bootstrap/pager-export.js.map +1 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.d.ts +15 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js +95 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -0
- package/dist/tui-v2/bootstrap/ui-selection.d.ts +30 -0
- package/dist/tui-v2/bootstrap/ui-selection.js +59 -0
- package/dist/tui-v2/bootstrap/ui-selection.js.map +1 -0
- package/dist/tui-v2/components/completion/completion-menu.d.ts +23 -0
- package/dist/tui-v2/components/completion/completion-menu.js +84 -0
- package/dist/tui-v2/components/completion/completion-menu.js.map +1 -0
- package/dist/tui-v2/components/jobs/jobs-panel.d.ts +16 -0
- package/dist/tui-v2/components/jobs/jobs-panel.js +92 -0
- package/dist/tui-v2/components/jobs/jobs-panel.js.map +1 -0
- package/dist/tui-v2/components/modal/confirm-modal.d.ts +21 -0
- package/dist/tui-v2/components/modal/confirm-modal.js +71 -0
- package/dist/tui-v2/components/modal/confirm-modal.js.map +1 -0
- package/dist/tui-v2/components/modal/prompt-actions-modal.d.ts +15 -0
- package/dist/tui-v2/components/modal/prompt-actions-modal.js +80 -0
- package/dist/tui-v2/components/modal/prompt-actions-modal.js.map +1 -0
- package/dist/tui-v2/components/modal/secret-modal.d.ts +24 -0
- package/dist/tui-v2/components/modal/secret-modal.js +50 -0
- package/dist/tui-v2/components/modal/secret-modal.js.map +1 -0
- package/dist/tui-v2/components/overlay/overlay-host.d.ts +17 -0
- package/dist/tui-v2/components/overlay/overlay-host.js +28 -0
- package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -0
- package/dist/tui-v2/components/pager/pager.d.ts +20 -0
- package/dist/tui-v2/components/pager/pager.js +396 -0
- package/dist/tui-v2/components/pager/pager.js.map +1 -0
- package/dist/tui-v2/components/picker/picker.d.ts +17 -0
- package/dist/tui-v2/components/picker/picker.js +222 -0
- package/dist/tui-v2/components/picker/picker.js.map +1 -0
- package/dist/tui-v2/components/plan/plan-view.d.ts +20 -0
- package/dist/tui-v2/components/plan/plan-view.js +116 -0
- package/dist/tui-v2/components/plan/plan-view.js.map +1 -0
- package/dist/tui-v2/components/queue/queue-panel.d.ts +23 -0
- package/dist/tui-v2/components/queue/queue-panel.js +58 -0
- package/dist/tui-v2/components/queue/queue-panel.js.map +1 -0
- package/dist/tui-v2/components/status/status-line.d.ts +27 -0
- package/dist/tui-v2/components/status/status-line.js +158 -0
- package/dist/tui-v2/components/status/status-line.js.map +1 -0
- package/dist/tui-v2/components/toast/toast-host.d.ts +15 -0
- package/dist/tui-v2/components/toast/toast-host.js +48 -0
- package/dist/tui-v2/components/toast/toast-host.js.map +1 -0
- package/dist/tui-v2/components/transcript/assistant-message.d.ts +20 -0
- package/dist/tui-v2/components/transcript/assistant-message.js +35 -0
- package/dist/tui-v2/components/transcript/assistant-message.js.map +1 -0
- package/dist/tui-v2/components/transcript/compacted-row.d.ts +19 -0
- package/dist/tui-v2/components/transcript/compacted-row.js +94 -0
- package/dist/tui-v2/components/transcript/compacted-row.js.map +1 -0
- package/dist/tui-v2/components/transcript/intro-card.d.ts +19 -0
- package/dist/tui-v2/components/transcript/intro-card.js +50 -0
- package/dist/tui-v2/components/transcript/intro-card.js.map +1 -0
- package/dist/tui-v2/components/transcript/linkable-text.d.ts +21 -0
- package/dist/tui-v2/components/transcript/linkable-text.js +46 -0
- package/dist/tui-v2/components/transcript/linkable-text.js.map +1 -0
- package/dist/tui-v2/components/transcript/notice-row.d.ts +14 -0
- package/dist/tui-v2/components/transcript/notice-row.js +40 -0
- package/dist/tui-v2/components/transcript/notice-row.js.map +1 -0
- package/dist/tui-v2/components/transcript/search-bar.d.ts +19 -0
- package/dist/tui-v2/components/transcript/search-bar.js +7 -0
- package/dist/tui-v2/components/transcript/search-bar.js.map +1 -0
- package/dist/tui-v2/components/transcript/thinking-block.d.ts +22 -0
- package/dist/tui-v2/components/transcript/thinking-block.js +27 -0
- package/dist/tui-v2/components/transcript/thinking-block.js.map +1 -0
- package/dist/tui-v2/components/transcript/tool-card.d.ts +26 -0
- package/dist/tui-v2/components/transcript/tool-card.js +175 -0
- package/dist/tui-v2/components/transcript/tool-card.js.map +1 -0
- package/dist/tui-v2/components/transcript/transcript-row.d.ts +25 -0
- package/dist/tui-v2/components/transcript/transcript-row.js +30 -0
- package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -0
- package/dist/tui-v2/components/transcript/transcript-scroll-port.d.ts +52 -0
- package/dist/tui-v2/components/transcript/transcript-scroll-port.js +86 -0
- package/dist/tui-v2/components/transcript/transcript-scroll-port.js.map +1 -0
- package/dist/tui-v2/components/transcript/transcript-view.d.ts +24 -0
- package/dist/tui-v2/components/transcript/transcript-view.js +403 -0
- package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -0
- package/dist/tui-v2/components/transcript/use-click-without-drag.d.ts +13 -0
- package/dist/tui-v2/components/transcript/use-click-without-drag.js +35 -0
- package/dist/tui-v2/components/transcript/use-click-without-drag.js.map +1 -0
- package/dist/tui-v2/components/transcript/use-native-selection-copy.d.ts +10 -0
- package/dist/tui-v2/components/transcript/use-native-selection-copy.js +37 -0
- package/dist/tui-v2/components/transcript/use-native-selection-copy.js.map +1 -0
- package/dist/tui-v2/components/transcript/use-transcript-selection.d.ts +23 -0
- package/dist/tui-v2/components/transcript/use-transcript-selection.js +136 -0
- package/dist/tui-v2/components/transcript/use-transcript-selection.js.map +1 -0
- package/dist/tui-v2/components/transcript/user-message.d.ts +10 -0
- package/dist/tui-v2/components/transcript/user-message.js +23 -0
- package/dist/tui-v2/components/transcript/user-message.js.map +1 -0
- package/dist/tui-v2/composer/arrow-intent.d.ts +23 -0
- package/dist/tui-v2/composer/arrow-intent.js +35 -0
- package/dist/tui-v2/composer/arrow-intent.js.map +1 -0
- package/dist/tui-v2/composer/completion.d.ts +37 -0
- package/dist/tui-v2/composer/completion.js +67 -0
- package/dist/tui-v2/composer/completion.js.map +1 -0
- package/dist/tui-v2/composer/composer-editor.d.ts +33 -0
- package/dist/tui-v2/composer/composer-editor.js +620 -0
- package/dist/tui-v2/composer/composer-editor.js.map +1 -0
- package/dist/tui-v2/composer/composer-height.d.ts +21 -0
- package/dist/tui-v2/composer/composer-height.js +29 -0
- package/dist/tui-v2/composer/composer-height.js.map +1 -0
- package/dist/tui-v2/composer/composer-meta.d.ts +9 -0
- package/dist/tui-v2/composer/composer-meta.js +38 -0
- package/dist/tui-v2/composer/composer-meta.js.map +1 -0
- package/dist/tui-v2/composer/history-nav.d.ts +15 -0
- package/dist/tui-v2/composer/history-nav.js +16 -0
- package/dist/tui-v2/composer/history-nav.js.map +1 -0
- package/dist/tui-v2/composer/newline-hint.d.ts +13 -0
- package/dist/tui-v2/composer/newline-hint.js +13 -0
- package/dist/tui-v2/composer/newline-hint.js.map +1 -0
- package/dist/tui-v2/composer/paste-placeholder.d.ts +35 -0
- package/dist/tui-v2/composer/paste-placeholder.js +55 -0
- package/dist/tui-v2/composer/paste-placeholder.js.map +1 -0
- package/dist/tui-v2/composer/prompt-history.d.ts +22 -0
- package/dist/tui-v2/composer/prompt-history.js +51 -0
- package/dist/tui-v2/composer/prompt-history.js.map +1 -0
- package/dist/tui-v2/composer/secret-buffer.d.ts +20 -0
- package/dist/tui-v2/composer/secret-buffer.js +42 -0
- package/dist/tui-v2/composer/secret-buffer.js.map +1 -0
- package/dist/tui-v2/composer/textarea-keybindings.d.ts +22 -0
- package/dist/tui-v2/composer/textarea-keybindings.js +27 -0
- package/dist/tui-v2/composer/textarea-keybindings.js.map +1 -0
- package/dist/tui-v2/controllers/focus-controller.d.ts +30 -0
- package/dist/tui-v2/controllers/focus-controller.js +80 -0
- package/dist/tui-v2/controllers/focus-controller.js.map +1 -0
- package/dist/tui-v2/controllers/overlay-controller.d.ts +99 -0
- package/dist/tui-v2/controllers/overlay-controller.js +195 -0
- package/dist/tui-v2/controllers/overlay-controller.js.map +1 -0
- package/dist/tui-v2/controllers/selection-controller.d.ts +76 -0
- package/dist/tui-v2/controllers/selection-controller.js +238 -0
- package/dist/tui-v2/controllers/selection-controller.js.map +1 -0
- package/dist/tui-v2/controllers/toast-controller.d.ts +35 -0
- package/dist/tui-v2/controllers/toast-controller.js +88 -0
- package/dist/tui-v2/controllers/toast-controller.js.map +1 -0
- package/dist/tui-v2/layout/compute-layout.d.ts +59 -0
- package/dist/tui-v2/layout/compute-layout.js +170 -0
- package/dist/tui-v2/layout/compute-layout.js.map +1 -0
- package/dist/tui-v2/rendering/ansi-to-styled.d.ts +17 -0
- package/dist/tui-v2/rendering/ansi-to-styled.js +217 -0
- package/dist/tui-v2/rendering/ansi-to-styled.js.map +1 -0
- package/dist/tui-v2/rendering/batch-sections.d.ts +45 -0
- package/dist/tui-v2/rendering/batch-sections.js +109 -0
- package/dist/tui-v2/rendering/batch-sections.js.map +1 -0
- package/dist/tui-v2/rendering/link-detector.d.ts +16 -0
- package/dist/tui-v2/rendering/link-detector.js +43 -0
- package/dist/tui-v2/rendering/link-detector.js.map +1 -0
- package/dist/tui-v2/rendering/open-tool-output.d.ts +28 -0
- package/dist/tui-v2/rendering/open-tool-output.js +138 -0
- package/dist/tui-v2/rendering/open-tool-output.js.map +1 -0
- package/dist/tui-v2/rendering/picker-filter.d.ts +22 -0
- package/dist/tui-v2/rendering/picker-filter.js +68 -0
- package/dist/tui-v2/rendering/picker-filter.js.map +1 -0
- package/dist/tui-v2/rendering/plan-view.d.ts +32 -0
- package/dist/tui-v2/rendering/plan-view.js +196 -0
- package/dist/tui-v2/rendering/plan-view.js.map +1 -0
- package/dist/tui-v2/rendering/render-markdown-lines.d.ts +29 -0
- package/dist/tui-v2/rendering/render-markdown-lines.js +46 -0
- package/dist/tui-v2/rendering/render-markdown-lines.js.map +1 -0
- package/dist/tui-v2/rendering/sanitize-display.d.ts +13 -0
- package/dist/tui-v2/rendering/sanitize-display.js +24 -0
- package/dist/tui-v2/rendering/sanitize-display.js.map +1 -0
- package/dist/tui-v2/rendering/theme.d.ts +67 -0
- package/dist/tui-v2/rendering/theme.js +74 -0
- package/dist/tui-v2/rendering/theme.js.map +1 -0
- package/dist/tui-v2/rendering/tool-presenter.d.ts +39 -0
- package/dist/tui-v2/rendering/tool-presenter.js +207 -0
- package/dist/tui-v2/rendering/tool-presenter.js.map +1 -0
- package/dist/tui-v2/rendering/transcript-export.d.ts +11 -0
- package/dist/tui-v2/rendering/transcript-export.js +18 -0
- package/dist/tui-v2/rendering/transcript-export.js.map +1 -0
- package/dist/tui-v2/rendering/transcript-semantic.d.ts +17 -0
- package/dist/tui-v2/rendering/transcript-semantic.js +67 -0
- package/dist/tui-v2/rendering/transcript-semantic.js.map +1 -0
- package/dist/tui-v2/state/pager-search.d.ts +22 -0
- package/dist/tui-v2/state/pager-search.js +78 -0
- package/dist/tui-v2/state/pager-search.js.map +1 -0
- package/dist/tui-v2/state/semantic-document.d.ts +34 -0
- package/dist/tui-v2/state/semantic-document.js +201 -0
- package/dist/tui-v2/state/semantic-document.js.map +1 -0
- package/dist/tui-v2/state/transcript-compaction.d.ts +24 -0
- package/dist/tui-v2/state/transcript-compaction.js +79 -0
- package/dist/tui-v2/state/transcript-compaction.js.map +1 -0
- package/dist/tui-v2/state/transcript-hydrate.d.ts +27 -0
- package/dist/tui-v2/state/transcript-hydrate.js +272 -0
- package/dist/tui-v2/state/transcript-hydrate.js.map +1 -0
- package/dist/tui-v2/state/transcript-reducer.d.ts +10 -0
- package/dist/tui-v2/state/transcript-reducer.js +281 -0
- package/dist/tui-v2/state/transcript-reducer.js.map +1 -0
- package/dist/tui-v2/state/transcript-search.d.ts +17 -0
- package/dist/tui-v2/state/transcript-search.js +38 -0
- package/dist/tui-v2/state/transcript-search.js.map +1 -0
- package/dist/tui-v2/state/transcript-store.d.ts +32 -0
- package/dist/tui-v2/state/transcript-store.js +66 -0
- package/dist/tui-v2/state/transcript-store.js.map +1 -0
- package/dist/tui-v2/state/transcript-struct.d.ts +15 -0
- package/dist/tui-v2/state/transcript-struct.js +133 -0
- package/dist/tui-v2/state/transcript-struct.js.map +1 -0
- package/dist/tui-v2/state/transcript-types.d.ts +76 -0
- package/dist/tui-v2/state/transcript-types.js +65 -0
- package/dist/tui-v2/state/transcript-types.js.map +1 -0
- package/dist/tui-v2/state/use-overlay.d.ts +3 -0
- package/dist/tui-v2/state/use-overlay.js +6 -0
- package/dist/tui-v2/state/use-overlay.js.map +1 -0
- package/dist/tui-v2/state/use-plan.d.ts +4 -0
- package/dist/tui-v2/state/use-plan.js +6 -0
- package/dist/tui-v2/state/use-plan.js.map +1 -0
- package/dist/tui-v2/state/use-session-state.d.ts +2 -0
- package/dist/tui-v2/state/use-session-state.js +7 -0
- package/dist/tui-v2/state/use-session-state.js.map +1 -0
- package/dist/tui-v2/state/use-toast.d.ts +3 -0
- package/dist/tui-v2/state/use-toast.js +15 -0
- package/dist/tui-v2/state/use-toast.js.map +1 -0
- package/dist/tui-v2/state/use-transcript-store.d.ts +10 -0
- package/dist/tui-v2/state/use-transcript-store.js +12 -0
- package/dist/tui-v2/state/use-transcript-store.js.map +1 -0
- package/dist/ui/intro-card.js +3 -3
- package/dist/ui/intro-card.js.map +1 -1
- package/dist/ui/intro-header.d.ts +23 -0
- package/dist/ui/intro-header.js +232 -0
- package/dist/ui/intro-header.js.map +1 -0
- package/dist/ui/markdown.js +0 -1
- package/dist/ui/markdown.js.map +1 -1
- package/dist/ui/mentions.d.ts +9 -2
- package/dist/ui/mentions.js +102 -4
- package/dist/ui/mentions.js.map +1 -1
- package/dist/ui/output-pane.js +1 -1
- package/dist/ui/output-pane.js.map +1 -1
- package/dist/ui/plan-pane.d.ts +8 -0
- package/dist/ui/plan-pane.js +38 -0
- package/dist/ui/plan-pane.js.map +1 -1
- package/dist/ui/wordmark.d.ts +5 -0
- package/dist/ui/wordmark.js +6 -1
- package/dist/ui/wordmark.js.map +1 -1
- package/package.json +14 -10
- package/dist/tui/App.d.ts +0 -12
- package/dist/tui/App.js +0 -2174
- package/dist/tui/App.js.map +0 -1
- package/dist/tui/components/ConfirmModal.d.ts +0 -9
- package/dist/tui/components/ConfirmModal.js +0 -55
- package/dist/tui/components/ConfirmModal.js.map +0 -1
- package/dist/tui/components/JobsPanel.d.ts +0 -11
- package/dist/tui/components/JobsPanel.js +0 -55
- package/dist/tui/components/JobsPanel.js.map +0 -1
- package/dist/tui/components/Pager.d.ts +0 -14
- package/dist/tui/components/Pager.js +0 -56
- package/dist/tui/components/Pager.js.map +0 -1
- package/dist/tui/components/PickerPanel.d.ts +0 -15
- package/dist/tui/components/PickerPanel.js +0 -126
- package/dist/tui/components/PickerPanel.js.map +0 -1
- package/dist/tui/components/PlanSidebar.d.ts +0 -6
- package/dist/tui/components/PlanSidebar.js +0 -99
- package/dist/tui/components/PlanSidebar.js.map +0 -1
- package/dist/tui/components/SecretInputPanel.d.ts +0 -7
- package/dist/tui/components/SecretInputPanel.js +0 -38
- package/dist/tui/components/SecretInputPanel.js.map +0 -1
- package/dist/tui/confirm.d.ts +0 -16
- package/dist/tui/confirm.js.map +0 -1
- package/dist/tui/default.d.ts +0 -6
- package/dist/tui/default.js +0 -11
- package/dist/tui/default.js.map +0 -1
- package/dist/tui/hooks/useAgentRunner.d.ts +0 -73
- package/dist/tui/hooks/useAgentRunner.js +0 -277
- package/dist/tui/hooks/useAgentRunner.js.map +0 -1
- package/dist/tui/hooks/useJobs.d.ts +0 -7
- package/dist/tui/hooks/useJobs.js +0 -39
- package/dist/tui/hooks/useJobs.js.map +0 -1
- package/dist/tui/hooks/useSpinner.d.ts +0 -5
- package/dist/tui/hooks/useSpinner.js +0 -21
- package/dist/tui/hooks/useSpinner.js.map +0 -1
- package/dist/tui/hooks/useTerminalSize.d.ts +0 -9
- package/dist/tui/hooks/useTerminalSize.js +0 -26
- package/dist/tui/hooks/useTerminalSize.js.map +0 -1
- package/dist/tui/index.d.ts +0 -10
- package/dist/tui/index.js +0 -37
- package/dist/tui/index.js.map +0 -1
- package/dist/tui/key-intent.d.ts +0 -36
- package/dist/tui/key-intent.js +0 -54
- package/dist/tui/key-intent.js.map +0 -1
- package/dist/tui/mouse.d.ts +0 -8
- package/dist/tui/mouse.js +0 -34
- package/dist/tui/mouse.js.map +0 -1
- package/dist/tui/plan-sidebar-lines.d.ts +0 -2
- package/dist/tui/plan-sidebar-lines.js +0 -140
- package/dist/tui/plan-sidebar-lines.js.map +0 -1
- package/dist/tui/render-lines.d.ts +0 -22
- package/dist/tui/render-lines.js +0 -611
- package/dist/tui/render-lines.js.map +0 -1
|
@@ -8,6 +8,11 @@ import type { ChatMessage } from "../types.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function estimateTokens(text: string): number;
|
|
10
10
|
export declare function estimateMessagesTokens(messages: ChatMessage[]): number;
|
|
11
|
+
/**
|
|
12
|
+
* Agent-loop auto-compact threshold (estimated tokens). Shared with `/context`
|
|
13
|
+
* so the reported % of budget matches when auto-compaction fires.
|
|
14
|
+
*/
|
|
15
|
+
export declare const AUTO_COMPACT_TOKEN_BUDGET = 150000;
|
|
11
16
|
export interface CompactOptions {
|
|
12
17
|
/** Soft budget (tokens). When estimated tokens exceed this, compact. */
|
|
13
18
|
budgetTokens?: number | undefined;
|
|
@@ -21,6 +21,11 @@ export function estimateMessagesTokens(messages) {
|
|
|
21
21
|
}
|
|
22
22
|
return sum;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Agent-loop auto-compact threshold (estimated tokens). Shared with `/context`
|
|
26
|
+
* so the reported % of budget matches when auto-compaction fires.
|
|
27
|
+
*/
|
|
28
|
+
export const AUTO_COMPACT_TOKEN_BUDGET = 150_000;
|
|
24
29
|
const DEFAULT_BUDGET_TOKENS = 32_000;
|
|
25
30
|
const DEFAULT_KEEP_RECENT = 6;
|
|
26
31
|
/**
|
|
@@ -131,11 +136,18 @@ export async function compactMessagesWithSummary(messages, summarize, options =
|
|
|
131
136
|
return `${message.role.toUpperCase()}: ${content}`;
|
|
132
137
|
})
|
|
133
138
|
.join("\n\n");
|
|
134
|
-
|
|
139
|
+
// Prefer combining visual session material (tools/prompts) with older model
|
|
140
|
+
// turns so /compact after /history + new messages never loses either side.
|
|
141
|
+
const visual = sessionTranscript?.trim()
|
|
135
142
|
? redactSecrets(sessionTranscript.trim())
|
|
136
|
-
:
|
|
143
|
+
: "";
|
|
144
|
+
const fromMessages = messageTranscript.trim();
|
|
145
|
+
const transcript = visual && fromMessages
|
|
146
|
+
? `${visual}\n\n---\n\nOLDER MODEL TURNS:\n\n${fromMessages}`
|
|
147
|
+
: visual || fromMessages;
|
|
137
148
|
const prompt = [
|
|
138
149
|
"Create a complete but compact continuation memory of the entire session below for another assistant that will continue it.",
|
|
150
|
+
"The material may include a resumed history session plus newer turns — treat it as one continuous conversation.",
|
|
139
151
|
"Preserve user intentions and prompts, decisions, constraints, file paths, commands/tools run, steps taken, task states, outputs and results, errors and failed approaches, completed work, and exactly what remains.",
|
|
140
152
|
"Organize the memory under concise sections: User goals, Decisions and constraints, Work completed, Commands/tools and results, Current state, Remaining work.",
|
|
141
153
|
"Do not add facts, commentary, or markdown framing. Be concise but specific. Never include secrets or credentials.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/agent/context-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAuB;IAC5D,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB;QAC5D,gEAAgE;QAChE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;
|
|
1
|
+
{"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/agent/context-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAAuB;IAC5D,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB;QAC5D,gEAAgE;QAChE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,OAAO,CAAC;AAkBjD,MAAM,qBAAqB,GAAG,MAAM,CAAC;AACrC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GACnC,8CAA8C,CAAC;AACjD,MAAM,CAAC,MAAM,wBAAwB,GACnC,2CAA2C,CAAC;AAE9C,MAAM,UAAU,yBAAyB,CAAC,OAAoB;IAC5D,OAAO,CACL,OAAO,CAAC,IAAI,KAAK,QAAQ;QACzB,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,wBAAwB,CAAC;YACnD,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,wBAAwB,CAAC,CAAC,CACxD,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAuB,EACvB,UAA0B,EAAE;IAE5B,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,IAAI,qBAAqB,CAAC;IAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;IAC1E,IAAI,QAAQ,CAAC,MAAM,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IACvD,IAAI,sBAAsB,CAAC,QAAQ,CAAC,IAAI,MAAM;QAAE,OAAO,QAAQ,CAAC;IAEhE,oEAAoE;IACpE,MAAM,IAAI,GAAkB,EAAE,CAAC;IAC/B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACvB,KAAK,GAAG,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IACpE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEzC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACvC,IAAI,IAAI;gBAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,kBAAkB,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAgB;QACxB,IAAI,EAAE,QAAQ;QACd,OAAO,EACL,GAAG,wBAAwB,oHAAoH;YAC/I,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;KACrB,CAAC;IAEF,OAAO,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,QAAuB,EACvB,SAA8C,EAC9C,UAA0B,EAAE,EAC5B,iBAAsC;IAEtC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC/B,MAAM,YAAY,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,KAAK,CAAC,CAAC;IAE5C,IAAI,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;IAC9D,IAAI,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAE7C,yEAAyE;IACzE,qFAAqF;IACrF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACnE,UAAU,GAAG,CAAC,CAAC;QACf,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QAChC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,EAAE,EAAE,CAAC;QACrD,4DAA4D;QAC5D,OAAO;YACL,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC;YACvB,MAAM;YACN,KAAK,EAAE,MAAM;YACb,YAAY;YACZ,WAAW,EAAE,YAAY;YACzB,UAAU,EAAE,KAAK;SAClB,CAAC;IACJ,CAAC;IAED,MAAM,iBAAiB,GAAG,KAAK;SAC5B,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QACf,IAAI,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7C,iEAAiE;QACjE,4DAA4D;QAC5D,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACjC,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;QAC3C,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,CAAC;IACrD,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;IAChB,4EAA4E;IAC5E,2EAA2E;IAC3E,MAAM,MAAM,GAAG,iBAAiB,EAAE,IAAI,EAAE;QACtC,CAAC,CAAC,aAAa,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;QACzC,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC;IAC9C,MAAM,UAAU,GACd,MAAM,IAAI,YAAY;QACpB,CAAC,CAAC,GAAG,MAAM,oCAAoC,YAAY,EAAE;QAC7D,CAAC,CAAC,MAAM,IAAI,YAAY,CAAC;IAC7B,MAAM,MAAM,GAAG;QACb,4HAA4H;QAC5H,gHAAgH;QAChH,sNAAsN;QACtN,+JAA+J;QAC/J,mHAAmH;QACnH,EAAE;QACF,UAAU;KACX,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,uEAAuE;IACvE,mDAAmD;IACnD,wEAAwE;IACxE,qEAAqE;IACrE,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACzD,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAEpF,MAAM,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,kEAAkE;IAClE,gDAAgD;IAChD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACjD,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5D,OAAO,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;QACjE,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC,CAAC;IACH,MAAM,SAAS,GAAkB;QAC/B,GAAG,IAAI;QACP,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,wBAAwB,OAAO,OAAO,EAAE,EAAE;QACxE,GAAG,IAAI;KACR,CAAC;IACF,MAAM,WAAW,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;IACtD,OAAO;QACL,QAAQ,EAAE,SAAS;QACnB,MAAM;QACN,KAAK,EAAE,SAAS,CAAC,MAAM;QACvB,YAAY;QACZ,WAAW;QACX,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,IAAY,EAAE,QAAgB;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,IAAI,OAAO,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,OAAO,CAAC;IAC/C,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC;AAC9C,CAAC"}
|
package/dist/agent/events.d.ts
CHANGED
|
@@ -26,10 +26,13 @@ export type AgentEvent = {
|
|
|
26
26
|
id: string;
|
|
27
27
|
name: string;
|
|
28
28
|
argsDisplay: string;
|
|
29
|
-
}
|
|
29
|
+
}
|
|
30
|
+
/** `replace: true` sets the full body (never append) so the UI never keeps a truncated live preview. */
|
|
31
|
+
| {
|
|
30
32
|
type: "tool-output";
|
|
31
33
|
id: string;
|
|
32
34
|
chunk: string;
|
|
35
|
+
replace?: boolean;
|
|
33
36
|
} | {
|
|
34
37
|
type: "tool-result";
|
|
35
38
|
id: string;
|
package/dist/agent/runner.js
CHANGED
|
@@ -11,7 +11,7 @@ import { classifyToolCall, isPentestToolCall, scopeHint, scopeTargetForToolCall,
|
|
|
11
11
|
import { availableToolNames, normalizeToolCall, runToolCall, BATCH_SAFE_TOOLS, } from "../tools/registry.js";
|
|
12
12
|
import { looksInteractiveStdin } from "../tools/shell.js";
|
|
13
13
|
import { formatViewportHint, registerViewport } from "../ui/output-pane.js";
|
|
14
|
-
import { compactMessagesWithSummary, estimateTokens, estimateMessagesTokens, COMPACTION_MEMORY_PREFIX, } from "./context-manager.js";
|
|
14
|
+
import { compactMessagesWithSummary, estimateTokens, estimateMessagesTokens, AUTO_COMPACT_TOKEN_BUDGET, COMPACTION_MEMORY_PREFIX, } from "./context-manager.js";
|
|
15
15
|
import { auditLog } from "../store/logs.js";
|
|
16
16
|
import { loadProjectContext } from "../store/project.js";
|
|
17
17
|
import { loadScope, isScopeActive, targetInScope } from "../store/scope.js";
|
|
@@ -24,7 +24,7 @@ import { analyzeTask } from "./task-analyzer.js";
|
|
|
24
24
|
import { LoopGuard } from "./loop-guard.js";
|
|
25
25
|
import { loadPlan } from "../store/plan.js";
|
|
26
26
|
import { pathInsideSandbox, fsWrite } from "../tools/fs.js";
|
|
27
|
-
import { stripSentinelTokens, parseToolCall, recognizeBareToolJson, looksLikeTruncatedToolCall, salvageTruncatedWrite, countToolFences, parseAllToolCalls, groupToolCallsForExecution, buildTurnHistory, collapseRepeatedText, textBeforeToolCall, formatToolArgs, looksLikePentestTask, looksLikeBuildTask, looksLikeInformationalQuery, looksLikeActionNarration, looksLikePlanNarration, requiresFreshWebSearch, freshnessGuardMessage, buildWorkflowDirective, pentestWorkflowDirective, shouldDimToolChatter, looksLikePromptLeak, } from "./tool-call-parser.js";
|
|
27
|
+
import { stripSentinelTokens, parseToolCall, recognizeBareToolJson, looksLikeTruncatedToolCall, salvageTruncatedWrite, countToolFences, parseAllToolCalls, groupToolCallsForExecution, buildTurnHistory, collapseRepeatedText, textBeforeToolCall, formatToolArgs, looksLikePentestTask, looksLikeBuildTask, looksLikeInformationalQuery, looksLikeIdleOrSocialPrompt, looksLikeActionNarration, looksLikeWebActionNarration, looksLikePlanNarration, requiresFreshWebSearch, freshnessGuardMessage, buildWorkflowDirective, pentestWorkflowDirective, shouldDimToolChatter, looksLikePromptLeak, } from "./tool-call-parser.js";
|
|
28
28
|
import { createSessionPolicy, isPreApprovalAllowedTool, isPlanApprovedByStatus, planHasOpenWork, isAbortError, shouldEnableImageOcr, } from "./session-policy.js";
|
|
29
29
|
import { saveToolOutput, summarizeOutput, formatToolContext, } from "./tool-output-formatting.js";
|
|
30
30
|
import { planContextMessage, handlePlanTool, } from "./plan-tool.js";
|
|
@@ -114,6 +114,13 @@ function isScratchOnlyWrite(call, scratchDir) {
|
|
|
114
114
|
export async function runAgentLoop(prompt, options = {}) {
|
|
115
115
|
const writesDirectly = !options.onEvent;
|
|
116
116
|
const emit = (event) => options.onEvent?.(event);
|
|
117
|
+
// Whether the CURRENT model iteration has already committed its visible
|
|
118
|
+
// prose to the transcript with an `assistant-message` event. The recovery
|
|
119
|
+
// paths preserve streamed prose before retrying (so it isn't wiped by the
|
|
120
|
+
// next tool-call/turn event); this flag stops them from re-committing prose
|
|
121
|
+
// the normal tool path already surfaced, which would render it twice. Reset
|
|
122
|
+
// at the top of every loop iteration.
|
|
123
|
+
let visibleCommitted = false;
|
|
117
124
|
const noopSpinner = {
|
|
118
125
|
setLabel: () => { },
|
|
119
126
|
bumpReasoning: () => { },
|
|
@@ -121,7 +128,9 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
121
128
|
stop: () => { },
|
|
122
129
|
};
|
|
123
130
|
const writeStatus = (text, rendered = chalk.dim(text)) => {
|
|
124
|
-
|
|
131
|
+
// Footer activity is single-line; strip classic stdout newlines/indents.
|
|
132
|
+
const cleaned = text.replace(/\s+/g, " ").trim();
|
|
133
|
+
emit({ type: "status", text: cleaned || text });
|
|
125
134
|
if (writesDirectly)
|
|
126
135
|
process.stdout.write(rendered);
|
|
127
136
|
};
|
|
@@ -131,6 +140,11 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
131
140
|
process.stdout.write(rendered);
|
|
132
141
|
};
|
|
133
142
|
const writeAssistantMessage = (text) => {
|
|
143
|
+
// Never surface an empty message: the reducer drops it and a direct
|
|
144
|
+
// stdout writer would print a stray blank line.
|
|
145
|
+
if (!text.trim())
|
|
146
|
+
return;
|
|
147
|
+
visibleCommitted = true;
|
|
134
148
|
emit({ type: "assistant-message", text });
|
|
135
149
|
const rendered = renderMarkdown(text);
|
|
136
150
|
if (writesDirectly) {
|
|
@@ -142,9 +156,14 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
142
156
|
if (writesDirectly)
|
|
143
157
|
process.stdout.write(`${renderThinkingSummary(content)}\n`);
|
|
144
158
|
};
|
|
145
|
-
const writeToolOutput = (id, chunk, rendered) => {
|
|
146
|
-
emit({
|
|
147
|
-
|
|
159
|
+
const writeToolOutput = (id, chunk, rendered, options) => {
|
|
160
|
+
emit({
|
|
161
|
+
type: "tool-output",
|
|
162
|
+
id,
|
|
163
|
+
chunk,
|
|
164
|
+
...(options?.replace ? { replace: true } : {}),
|
|
165
|
+
});
|
|
166
|
+
if (writesDirectly && rendered)
|
|
148
167
|
process.stdout.write(rendered);
|
|
149
168
|
};
|
|
150
169
|
const writeToolCall = (id, call, rendered) => {
|
|
@@ -245,8 +264,13 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
245
264
|
// brand-new plan (the exact failure where "what do u know till now"
|
|
246
265
|
// triggered explore→plan and created an unrelated "Enhance clai" plan).
|
|
247
266
|
const informationalQuery = looksLikeInformationalQuery(prompt);
|
|
267
|
+
// Greetings / thanks / short acks must never force tools, plans, or
|
|
268
|
+
// freshness retries — a false "act don't narrate" path burned tokens on
|
|
269
|
+
// web.search recovery loops after a simple "hi".
|
|
270
|
+
const idleOrSocialPrompt = looksLikeIdleOrSocialPrompt(prompt);
|
|
248
271
|
const freshWebSearchRequired = !buildLikeTurn &&
|
|
249
272
|
!pentestLikeTurn &&
|
|
273
|
+
!idleOrSocialPrompt &&
|
|
250
274
|
toolNames.includes("web.search") &&
|
|
251
275
|
requiresFreshWebSearch(prompt);
|
|
252
276
|
let provider = options.provider ?? config.defaultProvider;
|
|
@@ -295,7 +319,10 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
295
319
|
// what's already there, create a comprehensive multi-task plan, then
|
|
296
320
|
// implement task by task until the goal is met. This mirrors how a careful
|
|
297
321
|
// coding agent (Claude Code) operates.
|
|
298
|
-
if (buildLikeTurn &&
|
|
322
|
+
if (buildLikeTurn &&
|
|
323
|
+
!activePlan &&
|
|
324
|
+
!informationalQuery &&
|
|
325
|
+
!idleOrSocialPrompt) {
|
|
299
326
|
systemSections.push(buildWorkflowDirective());
|
|
300
327
|
}
|
|
301
328
|
// Pentest / security engagements need a different shape than a coding
|
|
@@ -304,7 +331,10 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
304
331
|
// directive is only injected before a plan exists; once a plan is in
|
|
305
332
|
// place (or being refined), the ACTIVE PLAN block already carries the
|
|
306
333
|
// current task state and recon-vs-active-tool guidance.
|
|
307
|
-
if (pentestLikeTurn &&
|
|
334
|
+
if (pentestLikeTurn &&
|
|
335
|
+
!activePlan &&
|
|
336
|
+
!informationalQuery &&
|
|
337
|
+
!idleOrSocialPrompt) {
|
|
308
338
|
systemSections.push(pentestWorkflowDirective());
|
|
309
339
|
}
|
|
310
340
|
const renderedSystemPrompt = systemSections.join("\n\n");
|
|
@@ -346,7 +376,32 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
346
376
|
// which can cause every retry to return empty as well. Keep hidden thinking
|
|
347
377
|
// out of history, but record a compact non-empty sentinel when there was no
|
|
348
378
|
// visible output.
|
|
379
|
+
//
|
|
380
|
+
// The Ink reducer intentionally keeps streamed text transient until it
|
|
381
|
+
// receives `assistant-message`, because a stream may turn out to be raw
|
|
382
|
+
// tool JSON. Recovery paths used to add prose to model history and retry
|
|
383
|
+
// without that event, so the user could watch a valid-looking response
|
|
384
|
+
// vanish when the retry emitted its first tool call. Surface only prose
|
|
385
|
+
// that is safe to render; malformed/bare tool payloads remain hidden.
|
|
386
|
+
const recoveryProse = (content) => {
|
|
387
|
+
const text = textBeforeToolCall(stripSentinelTokens(content)).trim();
|
|
388
|
+
if (!text ||
|
|
389
|
+
/^```|^\{|<tool_call>|<\|tool_call(?:s_section)?_begin\|>/i.test(text) ||
|
|
390
|
+
/\n\s*\{[\s\S]*\}\s*$/.test(text)) {
|
|
391
|
+
return undefined;
|
|
392
|
+
}
|
|
393
|
+
return text;
|
|
394
|
+
};
|
|
349
395
|
const pushAssistantHistory = (content) => {
|
|
396
|
+
// Preserve genuine streamed prose before a recovery retry so the visible
|
|
397
|
+
// text isn't wiped by the next tool-call/turn event. Skip when this
|
|
398
|
+
// iteration already surfaced its prose (the normal tool path commits
|
|
399
|
+
// `beforeTool` itself) so the same text is never rendered twice.
|
|
400
|
+
if (!visibleCommitted) {
|
|
401
|
+
const prose = recoveryProse(content);
|
|
402
|
+
if (prose)
|
|
403
|
+
writeAssistantMessage(prose);
|
|
404
|
+
}
|
|
350
405
|
messages.push({
|
|
351
406
|
role: "assistant",
|
|
352
407
|
content: content.trim()
|
|
@@ -687,38 +742,20 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
687
742
|
parentSignal.addEventListener("abort", onParentAbort);
|
|
688
743
|
let result;
|
|
689
744
|
let liveBytes = 0;
|
|
690
|
-
const liveCap = 16_000;
|
|
691
|
-
let liveTruncatedNotified = false;
|
|
692
|
-
let lastProgressAt = 0;
|
|
693
745
|
const shouldDimLive = !interactiveCommand;
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
};
|
|
746
|
+
// Stream every live byte — never drop mid-run. After the tool finishes we
|
|
747
|
+
// still replace the spool with the authoritative full `result.output`.
|
|
697
748
|
const printLive = (chunk) => {
|
|
698
749
|
if (call.name === "fs.read" ||
|
|
699
750
|
call.name === "fs.list" ||
|
|
700
751
|
call.name === "fs.search")
|
|
701
752
|
return;
|
|
702
|
-
if (
|
|
703
|
-
if (!liveTruncatedNotified) {
|
|
704
|
-
liveTruncatedNotified = true;
|
|
705
|
-
writeToolInfo("... live preview truncated, full output saved");
|
|
706
|
-
writeToolInfo("(tool still running — ESC or Ctrl+C to abort)");
|
|
707
|
-
lastProgressAt = Date.now();
|
|
708
|
-
}
|
|
709
|
-
const now = Date.now();
|
|
710
|
-
if (now - lastProgressAt > 5_000) {
|
|
711
|
-
lastProgressAt = now;
|
|
712
|
-
writeToolOutput(toolEventId, ".", chalk.dim("."));
|
|
713
|
-
}
|
|
753
|
+
if (!chunk)
|
|
714
754
|
return;
|
|
715
|
-
|
|
716
|
-
const
|
|
717
|
-
const slice = chunk.length > remaining ? chunk.slice(0, remaining) : chunk;
|
|
718
|
-
liveBytes += slice.length;
|
|
719
|
-
const indented = slice.replace(/\r/g, "").replace(/\n(?!$)/g, "\n ");
|
|
755
|
+
liveBytes += chunk.length;
|
|
756
|
+
const indented = chunk.replace(/\r/g, "").replace(/\n(?!$)/g, "\n ");
|
|
720
757
|
const body = indented.startsWith("\n") ? indented : ` ${indented}`;
|
|
721
|
-
writeToolOutput(toolEventId,
|
|
758
|
+
writeToolOutput(toolEventId, chunk, shouldDimLive ? chalk.dim(body) : body);
|
|
722
759
|
};
|
|
723
760
|
const jobId = randomUUID().slice(0, 8);
|
|
724
761
|
const backgroundJob = {
|
|
@@ -761,7 +798,7 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
761
798
|
confirmed: true,
|
|
762
799
|
userPrompt: prompt,
|
|
763
800
|
});
|
|
764
|
-
if (liveBytes > 0
|
|
801
|
+
if (liveBytes > 0) {
|
|
765
802
|
writeToolOutput(toolEventId, "\n", "\n");
|
|
766
803
|
}
|
|
767
804
|
jobManager.updateJobStatus(jobId, result.ok ? "exited" : "failed", result.exitCode);
|
|
@@ -802,11 +839,10 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
802
839
|
parentSignal.removeEventListener("abort", onParentAbort);
|
|
803
840
|
}
|
|
804
841
|
const output = result.output.trim();
|
|
805
|
-
|
|
842
|
+
// Always keep a full on-disk copy of tool output (any size) so the
|
|
843
|
+
// pager never depends on a truncated in-memory preview.
|
|
806
844
|
const savedOutputPath = result.outputPath ??
|
|
807
|
-
(output
|
|
808
|
-
? await saveToolOutput(call, output)
|
|
809
|
-
: undefined);
|
|
845
|
+
(output ? await saveToolOutput(call, output) : undefined);
|
|
810
846
|
const resultWithArtifact = {
|
|
811
847
|
...result,
|
|
812
848
|
outputPath: savedOutputPath,
|
|
@@ -841,20 +877,30 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
841
877
|
}
|
|
842
878
|
}
|
|
843
879
|
const statusIcon = result.ok ? chalk.green(" ✓") : chalk.red(" ✗");
|
|
844
|
-
|
|
880
|
+
// Classic stdout gets a short status glyph; the event stream / spool
|
|
881
|
+
// must NOT be polluted with "ok"/"failed" (the card already shows status).
|
|
882
|
+
if (writesDirectly) {
|
|
883
|
+
process.stdout.write(statusIcon + "\n");
|
|
884
|
+
}
|
|
845
885
|
if (output) {
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
if (savedOutputPath) {
|
|
852
|
-
writeToolInfo(`full output saved to ${savedOutputPath}`);
|
|
853
|
-
}
|
|
886
|
+
// Authoritative FULL body — replace any live stream so the pager
|
|
887
|
+
// never shows a truncated mid-run preview. Never cap for the UI.
|
|
888
|
+
const fullChunk = output.endsWith("\n") ? output : `${output}\n`;
|
|
889
|
+
if (!writesDirectly) {
|
|
890
|
+
writeToolOutput(toolEventId, fullChunk, "", { replace: true });
|
|
854
891
|
}
|
|
855
892
|
else {
|
|
893
|
+
// Classic stdout: short preview only; full text is on disk.
|
|
894
|
+
const displayMax = 6_000;
|
|
895
|
+
const displaySummary = summarizeOutput(output, displayMax);
|
|
896
|
+
const displayText = displaySummary.truncated
|
|
897
|
+
? `${displaySummary.text}${savedOutputPath ? chalk.dim(`\n ... full output saved to ${savedOutputPath}`) : ""}`
|
|
898
|
+
: displaySummary.text;
|
|
856
899
|
const renderedOutput = indentAndWrapText(displayText);
|
|
857
|
-
|
|
900
|
+
process.stdout.write(styleToolChatter(call, renderedOutput) + "\n");
|
|
901
|
+
if (savedOutputPath && displaySummary.truncated) {
|
|
902
|
+
process.stdout.write(chalk.dim(` full output saved to ${savedOutputPath}\n`));
|
|
903
|
+
}
|
|
858
904
|
}
|
|
859
905
|
}
|
|
860
906
|
if (output) {
|
|
@@ -880,7 +926,6 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
880
926
|
// what is done, and what remains. The estimate is chars/4; the budget is
|
|
881
927
|
// deliberately conservative so we compact a little early rather than hit a
|
|
882
928
|
// provider context-window error mid-task.
|
|
883
|
-
const AUTO_COMPACT_TOKEN_BUDGET = 150_000;
|
|
884
929
|
const AUTO_COMPACT_KEEP_RECENT = 6;
|
|
885
930
|
let lastCompactionMsgCount = 0;
|
|
886
931
|
const summarizeForCompaction = async (summaryPrompt) => {
|
|
@@ -916,6 +961,8 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
916
961
|
return;
|
|
917
962
|
messages.splice(0, messages.length, ...result.messages);
|
|
918
963
|
loopGuard.resetReadOnly();
|
|
964
|
+
// Token stats BEFORE plan re-injection so the reduction is accurate.
|
|
965
|
+
const compactedTokens = estimateMessagesTokens(messages);
|
|
919
966
|
// Re-inject the live plan so the model keeps full plan awareness even
|
|
920
967
|
// after older turns (which carried the plan context) were summarized.
|
|
921
968
|
const livePlan = await loadPlan(session.sessionId).catch(() => undefined);
|
|
@@ -926,13 +973,11 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
926
973
|
});
|
|
927
974
|
}
|
|
928
975
|
lastCompactionMsgCount = messages.length;
|
|
929
|
-
//
|
|
930
|
-
|
|
931
|
-
// final count (which is what the model actually receives) separately.
|
|
932
|
-
const compactedTokens = estimateMessagesTokens(messages);
|
|
976
|
+
// Final count the model actually receives (may include re-injected plan).
|
|
977
|
+
const afterTokens = estimateMessagesTokens(messages);
|
|
933
978
|
await auditLog("agent.compact", {
|
|
934
979
|
newLength: messages.length,
|
|
935
|
-
estimatedTokens:
|
|
980
|
+
estimatedTokens: afterTokens,
|
|
936
981
|
reason,
|
|
937
982
|
});
|
|
938
983
|
// Extract the inserted compaction memory so we can surface the
|
|
@@ -944,12 +989,12 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
944
989
|
const summaryText = insertedSummary.startsWith(`${COMPACTION_MEMORY_PREFIX}\n\n`)
|
|
945
990
|
? insertedText(insertedSummary, `${COMPACTION_MEMORY_PREFIX}\n\n`)
|
|
946
991
|
: insertedText(insertedSummary, COMPACTION_MEMORY_PREFIX);
|
|
947
|
-
|
|
948
|
-
writeCompacted(summaryText, beforeTokens,
|
|
992
|
+
// Card shows pre/post of the summarization; plan re-injection is noted.
|
|
993
|
+
writeCompacted(summaryText, beforeTokens, compactedTokens);
|
|
949
994
|
const planNote = afterTokens > compactedTokens
|
|
950
995
|
? ` (compacted to ~${compactedTokens.toLocaleString()}, +plan → ~${afterTokens.toLocaleString()})`
|
|
951
996
|
: "";
|
|
952
|
-
writeNotice("info", `context auto-compacted to fit the window (~${beforeTokens.toLocaleString()} → ~${
|
|
997
|
+
writeNotice("info", `context auto-compacted to fit the window (~${beforeTokens.toLocaleString()} → ~${compactedTokens.toLocaleString()} tokens${planNote})`, chalk.dim(` ℹ context auto-compacted (~${beforeTokens.toLocaleString()} → ~${compactedTokens.toLocaleString()} tokens${planNote})\n`));
|
|
953
998
|
}
|
|
954
999
|
catch (error) {
|
|
955
1000
|
if (error instanceof Error &&
|
|
@@ -964,6 +1009,10 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
964
1009
|
}
|
|
965
1010
|
}
|
|
966
1011
|
for (let iteration = 0; iteration < maxIterations; iteration += 1) {
|
|
1012
|
+
// Each model round-trip re-decides whether its visible prose has been
|
|
1013
|
+
// committed, so recovery-prose preservation applies to THIS turn's
|
|
1014
|
+
// stream and not a prior one.
|
|
1015
|
+
visibleCommitted = false;
|
|
967
1016
|
// `step` is the productive-step index (used for display + audit). It only
|
|
968
1017
|
// advances when the previous iteration actually executed a tool.
|
|
969
1018
|
step = productiveSteps;
|
|
@@ -1070,10 +1119,11 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1070
1119
|
completion = await streamWithProvider({
|
|
1071
1120
|
provider,
|
|
1072
1121
|
model,
|
|
1073
|
-
//
|
|
1074
|
-
//
|
|
1075
|
-
//
|
|
1076
|
-
|
|
1122
|
+
// Stay on the user's selected provider/model. Cross-provider
|
|
1123
|
+
// hops (e.g. bynara → gemini on a 429) only happen when the
|
|
1124
|
+
// user has explicitly enabled `providerFallback` AND this is
|
|
1125
|
+
// the provider's default model. Never force fallback mid-turn.
|
|
1126
|
+
allowModelFallback: false,
|
|
1077
1127
|
messages,
|
|
1078
1128
|
// MiniMax M3 degenerates at the generic agent temperature. The
|
|
1079
1129
|
// HTTP layer also applies its `top_p` override for both the
|
|
@@ -1440,28 +1490,49 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1440
1490
|
// final answer ends the turn with nothing done and no real plan saved.
|
|
1441
1491
|
// Nudge it to emit a real tool call, with a concrete example.
|
|
1442
1492
|
const narratedAction = looksLikeActionNarration(cleaned);
|
|
1443
|
-
|
|
1444
|
-
//
|
|
1445
|
-
//
|
|
1446
|
-
//
|
|
1447
|
-
//
|
|
1448
|
-
|
|
1449
|
-
//
|
|
1450
|
-
//
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1493
|
+
const narratedWebAction = looksLikeWebActionNarration(cleaned);
|
|
1494
|
+
// `activePlan` is the snapshot loaded at the start of this turn.
|
|
1495
|
+
// A final task.update mutates and persists a separate plan instance,
|
|
1496
|
+
// so re-read it here before deciding whether a final response should
|
|
1497
|
+
// be forced back into execution. Without this, a completed plan
|
|
1498
|
+
// still appeared open and a short final summary such as "I'll
|
|
1499
|
+
// summarize the findings" could be discarded for an unnecessary
|
|
1500
|
+
// recovery turn.
|
|
1501
|
+
const livePlanAtCompletion = await loadPlan(session.sessionId).catch(() => undefined);
|
|
1502
|
+
const planStatusAtCompletion = livePlanAtCompletion?.status ?? activePlan?.status;
|
|
1503
|
+
const completedPlanDuringThisTurn = activePlan?.status !== "completed" &&
|
|
1504
|
+
planStatusAtCompletion === "completed";
|
|
1505
|
+
const planHasOpenWorkNow = planHasOpenWork(planStatusAtCompletion);
|
|
1506
|
+
// User-driven reasons to require tools this turn (build/pentest/
|
|
1507
|
+
// approved plan / freshness). Idle greetings never qualify.
|
|
1508
|
+
const userExpectsWork = freshWebSearchRequired ||
|
|
1456
1509
|
(planHasOpenWorkNow && session.planApproved.value) ||
|
|
1457
|
-
(!informationalQuery &&
|
|
1510
|
+
(!informationalQuery &&
|
|
1511
|
+
!idleOrSocialPrompt &&
|
|
1512
|
+
(buildLikeTurn || pentestLikeTurn));
|
|
1513
|
+
// History-inherited build/pentest intent only forces action when
|
|
1514
|
+
// THIS prompt is not itself a plain question/idle turn. Narration
|
|
1515
|
+
// stalls ("I'll list the files") still force a tool when the user
|
|
1516
|
+
// is not asking an informational question — but capability menus
|
|
1517
|
+
// and greetings are filtered out by looksLikeActionNarration /
|
|
1518
|
+
// idleOrSocialPrompt so they cannot burn recovery turns.
|
|
1519
|
+
const wantsAction = !completedPlanDuringThisTurn &&
|
|
1520
|
+
!idleOrSocialPrompt &&
|
|
1521
|
+
(userExpectsWork ||
|
|
1522
|
+
(narratedAction && !informationalQuery) ||
|
|
1523
|
+
(narratedWebAction && !informationalQuery));
|
|
1458
1524
|
const planNarrated = (buildLikeTurn || pentestLikeTurn) &&
|
|
1459
1525
|
!activePlan &&
|
|
1460
1526
|
looksLikePlanNarration(cleaned);
|
|
1527
|
+
// Once a real tool step has run, a no-plan task has no durable task
|
|
1528
|
+
// state to prove whether another action is needed. A tool-free reply
|
|
1529
|
+
// must therefore be allowed to finalize instead of turning a short
|
|
1530
|
+
// summary containing “I'll” into an implicit recovery request.
|
|
1531
|
+
const shouldRetryBeforeFinalizing = productiveSteps === 0 || planNarrated;
|
|
1461
1532
|
if (wantsAction &&
|
|
1462
1533
|
cleaned.trim().length > 0 &&
|
|
1463
1534
|
actionIntentRetries < 3 &&
|
|
1464
|
-
|
|
1535
|
+
shouldRetryBeforeFinalizing) {
|
|
1465
1536
|
actionIntentRetries += 1;
|
|
1466
1537
|
let nudge;
|
|
1467
1538
|
if (planHasOpenWorkNow && session.planApproved.value) {
|
|
@@ -1476,14 +1547,20 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1476
1547
|
"Every turn MUST contain a ```tool block until the task is done.";
|
|
1477
1548
|
writeNotice("warn", "described a security/pentest action but emitted no tool call — nudging it to run one", chalk.yellow(" ⚠ described a security/pentest action but emitted no tool call — nudging it to run one\n"));
|
|
1478
1549
|
}
|
|
1479
|
-
else if (
|
|
1550
|
+
else if (freshWebSearchRequired || narratedWebAction) {
|
|
1551
|
+
// Web-specific recovery ONLY when the user asked for current
|
|
1552
|
+
// info or the model explicitly claimed a fetch/search step.
|
|
1553
|
+
// Previously every non-build stall used this path, so a "hi"
|
|
1554
|
+
// greeting that said "I'll start executing" was forced into
|
|
1555
|
+
// pointless web.search recovery loops.
|
|
1480
1556
|
nudge =
|
|
1481
1557
|
"You wrote that you would fetch/search/read something but emitted NO ```tool block, so NOTHING ran. Do NOT narrate the next browsing step — DO it. Emit exactly one valid ```tool block now. If you know the exact page, use:\n" +
|
|
1482
1558
|
'```tool\n{"name":"web.fetch","args":{"url":"https://example.com/page","responseMode":"readable"}}\n```\n' +
|
|
1483
1559
|
"If you do not know the exact page URL, use web.search first. After the tool output, answer from the fetched page content.";
|
|
1484
1560
|
writeNotice("warn", "described a web action but emitted no tool call — nudging it to run one", chalk.yellow(" ⚠ described a web action but emitted no tool call — nudging it to run one\n"));
|
|
1485
1561
|
}
|
|
1486
|
-
else if (
|
|
1562
|
+
else if (buildLikeTurn &&
|
|
1563
|
+
(planNarrated || productiveSteps > 0)) {
|
|
1487
1564
|
const kind = pentestLikeTurn ? "pentest" : "coding";
|
|
1488
1565
|
nudge =
|
|
1489
1566
|
"You wrote the plan as PROSE but did NOT call plan.create, so no plan was saved and the user cannot /implement it. Emit it as a real tool call NOW — exactly one ```tool block:\n" +
|
|
@@ -1491,17 +1568,17 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1491
1568
|
"Do not describe the plan again in prose — just emit the plan.create tool block.";
|
|
1492
1569
|
writeNotice("warn", "plan was written as text, not created — nudging it to call plan.create", chalk.yellow(" ⚠ plan was written as text, not created — nudging it to call plan.create\n"));
|
|
1493
1570
|
}
|
|
1571
|
+
else if (buildLikeTurn) {
|
|
1572
|
+
nudge =
|
|
1573
|
+
"You described what you will do but emitted NO ```tool block, so NOTHING actually happened — narration is not action. Emit a real tool call NOW. For this build task, explore first like this:\n" +
|
|
1574
|
+
'```tool\n{"name":"fs.list","args":{"path":"."}}\n```\n' +
|
|
1575
|
+
"Then read key files, and once you understand the directory, call plan.create. Every turn MUST contain a ```tool block until the task is done.";
|
|
1576
|
+
writeNotice("warn", "described an action but emitted no tool call — nudging it to run one", chalk.yellow(" ⚠ described an action but emitted no tool call — nudging it to run one\n"));
|
|
1577
|
+
}
|
|
1494
1578
|
else {
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
}
|
|
1499
|
-
else {
|
|
1500
|
-
nudge =
|
|
1501
|
-
"You described what you will do but emitted NO ```tool block, so NOTHING actually happened — narration is not action. Emit a real tool call NOW. For this build task, explore first like this:\n" +
|
|
1502
|
-
'```tool\n{"name":"fs.list","args":{"path":"."}}\n```\n' +
|
|
1503
|
-
"Then read key files, and once you understand the directory, call plan.create. Every turn MUST contain a ```tool block until the task is done.";
|
|
1504
|
-
}
|
|
1579
|
+
// Generic non-build, non-web stall (e.g. "I'll list the files").
|
|
1580
|
+
nudge =
|
|
1581
|
+
"You described what you will do but emitted NO ```tool block, so NOTHING actually happened — narration is not action. Emit a real tool call NOW for the step you just described. Every turn that claims an action MUST contain a ```tool block.";
|
|
1505
1582
|
writeNotice("warn", "described an action but emitted no tool call — nudging it to run one", chalk.yellow(" ⚠ described an action but emitted no tool call — nudging it to run one\n"));
|
|
1506
1583
|
}
|
|
1507
1584
|
pushAssistantHistory(assistantText.visible);
|
|
@@ -1688,7 +1765,12 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1688
1765
|
`${omittedCallCount} were not run. After reviewing results, issue a small, prioritized next batch.`,
|
|
1689
1766
|
});
|
|
1690
1767
|
}
|
|
1691
|
-
//
|
|
1768
|
+
// Notice BEFORE tool cards so the transcript reads:
|
|
1769
|
+
// thinking → response → "N tool calls…" → tool cards (not tools then info).
|
|
1770
|
+
if (allCalls.length > 1) {
|
|
1771
|
+
writeNotice("info", `${allCalls.length} tool calls in this message — running scoped (independent read-only lookups in parallel, everything else in order)`, chalk.dim(` ℹ ${allCalls.length} tool calls — read-only lookups in parallel, the rest in order\n`));
|
|
1772
|
+
}
|
|
1773
|
+
// Emit only the calls that will actually execute, after thinking
|
|
1692
1774
|
// + assistant text so transcript order remains correct.
|
|
1693
1775
|
for (const deferred of activeDeferredToolCalls.slice(0, allCalls.length)) {
|
|
1694
1776
|
writeToolCall(deferred.eventId, deferred.call, deferred.rendered);
|
|
@@ -1698,9 +1780,6 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1698
1780
|
.map((c) => `\`\`\`tool\n${JSON.stringify(c)}\n\`\`\``)
|
|
1699
1781
|
.join("\n\n");
|
|
1700
1782
|
pushAssistantHistory(standardizedContent);
|
|
1701
|
-
if (allCalls.length > 1) {
|
|
1702
|
-
writeNotice("info", `${allCalls.length} tool calls in this message — running scoped (independent read-only lookups in parallel, everything else in order)`, chalk.dim(` ℹ ${allCalls.length} tool calls — read-only lookups in parallel, the rest in order\n`));
|
|
1703
|
-
}
|
|
1704
1783
|
// Scoped-parallel batch execution
|
|
1705
1784
|
// The model may emit several calls in one message. We partition them,
|
|
1706
1785
|
// IN DOCUMENT ORDER, into segments:
|
|
@@ -1736,7 +1815,12 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1736
1815
|
let blockedResult = null;
|
|
1737
1816
|
let failed = false;
|
|
1738
1817
|
let awaitingPlanApproval = false;
|
|
1818
|
+
/** Indices into allCalls that actually ran (got a tool-result). */
|
|
1819
|
+
const executedIndices = new Set();
|
|
1739
1820
|
const recordResult = (res, continueAfterFailure = false) => {
|
|
1821
|
+
const idx = allCalls.indexOf(res.call);
|
|
1822
|
+
if (idx >= 0)
|
|
1823
|
+
executedIndices.add(idx);
|
|
1740
1824
|
messages.push({
|
|
1741
1825
|
role: "tool",
|
|
1742
1826
|
content: `Tool ${res.call.name} result (exit=${res.result.exitCode ?? 0}, ok=${res.result.ok}):\n${res.contextOutput}`,
|
|
@@ -1801,6 +1885,41 @@ export async function runAgentLoop(prompt, options = {}) {
|
|
|
1801
1885
|
recordResult(res, true);
|
|
1802
1886
|
}
|
|
1803
1887
|
}
|
|
1888
|
+
// Cards were emitted for every call up front. If the batch stopped
|
|
1889
|
+
// early (failure / abort / plan gate), any card still on "running"
|
|
1890
|
+
// must get a terminal result so the TUI never spins forever.
|
|
1891
|
+
for (let i = 0; i < allCalls.length; i += 1) {
|
|
1892
|
+
if (executedIndices.has(i))
|
|
1893
|
+
continue;
|
|
1894
|
+
const call = allCalls[i];
|
|
1895
|
+
if (i >= 0 && !callIds[i]) {
|
|
1896
|
+
callIds[i] = `tool-${++nextToolEventId}`;
|
|
1897
|
+
}
|
|
1898
|
+
const id = callIds[i];
|
|
1899
|
+
if (!alreadyPrintedIds.has(id)) {
|
|
1900
|
+
// Never shown in the transcript — skip.
|
|
1901
|
+
continue;
|
|
1902
|
+
}
|
|
1903
|
+
const reason = aborted
|
|
1904
|
+
? "Cancelled — turn aborted before this call ran."
|
|
1905
|
+
: blocked
|
|
1906
|
+
? "Cancelled — earlier tool was blocked or declined."
|
|
1907
|
+
: awaitingPlanApproval
|
|
1908
|
+
? "Deferred — waiting for plan approval."
|
|
1909
|
+
: failed
|
|
1910
|
+
? "Cancelled — earlier tool in this batch failed."
|
|
1911
|
+
: "Cancelled — not executed.";
|
|
1912
|
+
const result = {
|
|
1913
|
+
ok: false,
|
|
1914
|
+
output: reason,
|
|
1915
|
+
exitCode: 130,
|
|
1916
|
+
};
|
|
1917
|
+
emitToolResult(id, result, reason);
|
|
1918
|
+
messages.push({
|
|
1919
|
+
role: "tool",
|
|
1920
|
+
content: `Tool ${call.name} result (exit=130, ok=false):\n${reason}`,
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1804
1923
|
// plan.create is a hard transaction boundary. Its successful handler
|
|
1805
1924
|
// persists and displays the plan; returning immediately prevents a
|
|
1806
1925
|
// stale pre-loop activePlan snapshot from nudging a duplicate plan and
|