@calliopelabs/cli 2.5.0 → 3.1.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 +45 -661
- package/dist/acp.d.ts +78 -0
- package/dist/acp.d.ts.map +1 -0
- package/dist/acp.js +572 -0
- package/dist/acp.js.map +1 -0
- package/dist/bin.d.ts +3 -7
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +56 -79
- package/dist/bin.js.map +1 -1
- package/dist/budget.d.ts +64 -0
- package/dist/budget.d.ts.map +1 -0
- package/dist/budget.js +157 -0
- package/dist/budget.js.map +1 -0
- package/dist/checkpoint.d.ts +63 -30
- package/dist/checkpoint.d.ts.map +1 -1
- package/dist/checkpoint.js +247 -160
- package/dist/checkpoint.js.map +1 -1
- package/dist/circuit-breaker/breaker.d.ts.map +1 -1
- package/dist/circuit-breaker/breaker.js.map +1 -1
- package/dist/config.d.ts +86 -81
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +236 -304
- package/dist/config.js.map +1 -1
- package/dist/cost.d.ts +114 -0
- package/dist/cost.d.ts.map +1 -0
- package/dist/cost.js +499 -0
- package/dist/cost.js.map +1 -0
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +11 -7
- package/dist/diff.js.map +1 -1
- package/dist/env-expansion.js.map +1 -1
- package/dist/errors.js +3 -3
- package/dist/errors.js.map +1 -1
- package/dist/files.js.map +1 -1
- package/dist/fleet.d.ts +30 -0
- package/dist/fleet.d.ts.map +1 -0
- package/dist/fleet.js +86 -0
- package/dist/fleet.js.map +1 -0
- package/dist/fuzzy-search.d.ts.map +1 -1
- package/dist/fuzzy-search.js +2 -1
- package/dist/fuzzy-search.js.map +1 -1
- package/dist/git-status.js.map +1 -1
- package/dist/headless.d.ts +1 -2
- package/dist/headless.d.ts.map +1 -1
- package/dist/headless.js +166 -24
- package/dist/headless.js.map +1 -1
- package/dist/hud/api.d.ts +3 -18
- package/dist/hud/api.d.ts.map +1 -1
- package/dist/hud/api.js +9 -352
- package/dist/hud/api.js.map +1 -1
- package/dist/hud/palettes.d.ts.map +1 -1
- package/dist/hud/palettes.js +0 -180
- package/dist/hud/palettes.js.map +1 -1
- package/dist/hud/skins.d.ts.map +1 -1
- package/dist/hud/skins.js +0 -263
- package/dist/hud/skins.js.map +1 -1
- package/dist/hud/types.d.ts +2 -5
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -4
- package/dist/index.js.map +1 -1
- package/dist/iteration-ledger.d.ts.map +1 -1
- package/dist/iteration-ledger.js +3 -2
- package/dist/iteration-ledger.js.map +1 -1
- package/dist/local-model.d.ts +150 -0
- package/dist/local-model.d.ts.map +1 -0
- package/dist/local-model.js +408 -0
- package/dist/local-model.js.map +1 -0
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +5 -2
- package/dist/mcp.js.map +1 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +6 -4
- package/dist/memory.js.map +1 -1
- package/dist/model-detection.js +2 -2
- package/dist/model-detection.js.map +1 -1
- package/dist/parallel-tools.js.map +1 -1
- package/dist/plugins.d.ts +32 -1
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +116 -5
- package/dist/plugins.js.map +1 -1
- package/dist/policy.d.ts +43 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +139 -0
- package/dist/policy.js.map +1 -0
- package/dist/project-config.d.ts +1 -2
- package/dist/project-config.d.ts.map +1 -1
- package/dist/project-config.js +0 -3
- package/dist/project-config.js.map +1 -1
- package/dist/providers/bedrock.d.ts.map +1 -1
- package/dist/providers/bedrock.js +2 -5
- package/dist/providers/bedrock.js.map +1 -1
- package/dist/providers/compat.d.ts +21 -0
- package/dist/providers/compat.d.ts.map +1 -1
- package/dist/providers/compat.js +176 -6
- package/dist/providers/compat.js.map +1 -1
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/index.d.ts +19 -4
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +61 -10
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/ollama.d.ts +2 -2
- package/dist/providers/ollama.d.ts.map +1 -1
- package/dist/providers/ollama.js +26 -6
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.d.ts +10 -10
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +18 -10
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/types.d.ts +8 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/types.js.map +1 -1
- package/dist/replay.d.ts +37 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +168 -0
- package/dist/replay.js.map +1 -0
- package/dist/router.d.ts +133 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/{model-router.js → router.js} +329 -3
- package/dist/router.js.map +1 -0
- package/dist/runlog.d.ts +185 -0
- package/dist/runlog.d.ts.map +1 -0
- package/dist/runlog.js +398 -0
- package/dist/runlog.js.map +1 -0
- package/dist/{sandbox.d.ts → sandbox/docker.d.ts} +1 -1
- package/dist/sandbox/docker.d.ts.map +1 -0
- package/dist/{sandbox.js → sandbox/docker.js} +1 -1
- package/dist/sandbox/docker.js.map +1 -0
- package/dist/sandbox/index.d.ts +36 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +62 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/{sandbox-native.d.ts → sandbox/native.d.ts} +1 -1
- package/dist/sandbox/native.d.ts.map +1 -0
- package/dist/{sandbox-native.js → sandbox/native.js} +1 -1
- package/dist/sandbox/native.js.map +1 -0
- package/dist/scope.d.ts.map +1 -1
- package/dist/scope.js +1 -1
- package/dist/scope.js.map +1 -1
- package/dist/scuttlebot/client.d.ts.map +1 -1
- package/dist/scuttlebot/client.js.map +1 -1
- package/dist/scuttlebot/config.js.map +1 -1
- package/dist/scuttlebot/http-client.d.ts.map +1 -1
- package/dist/scuttlebot/irc-client.d.ts +5 -5
- package/dist/scuttlebot/irc-client.d.ts.map +1 -1
- package/dist/scuttlebot/irc-client.js.map +1 -1
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +25 -54
- package/dist/setup.js.map +1 -1
- package/dist/skills.d.ts +39 -0
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +90 -8
- package/dist/skills.js.map +1 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +6 -3
- package/dist/storage.js.map +1 -1
- package/dist/streaming.d.ts +25 -0
- package/dist/streaming.d.ts.map +1 -1
- package/dist/streaming.js +59 -0
- package/dist/streaming.js.map +1 -1
- package/dist/styles.d.ts +62 -56
- package/dist/styles.d.ts.map +1 -1
- package/dist/styles.js +11 -0
- package/dist/styles.js.map +1 -1
- package/dist/summarization.d.ts.map +1 -1
- package/dist/summarization.js.map +1 -1
- package/dist/terminal-image.js +1 -1
- package/dist/terminal-image.js.map +1 -1
- package/dist/themes.d.ts +5 -4
- package/dist/themes.d.ts.map +1 -1
- package/dist/themes.js +35 -90
- package/dist/themes.js.map +1 -1
- package/dist/tools.d.ts +27 -3
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +128 -179
- package/dist/tools.js.map +1 -1
- package/dist/trust.js.map +1 -1
- package/dist/types.d.ts +4 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +21 -40
- package/dist/types.js.map +1 -1
- package/dist/ui/agent.d.ts +3 -6
- package/dist/ui/agent.d.ts.map +1 -1
- package/dist/ui/agent.js +328 -38
- package/dist/ui/agent.js.map +1 -1
- package/dist/ui/animations.d.ts +37 -0
- package/dist/ui/animations.d.ts.map +1 -0
- package/dist/ui/animations.js +227 -0
- package/dist/ui/animations.js.map +1 -0
- package/dist/ui/chat-input-keys.d.ts +42 -0
- package/dist/ui/chat-input-keys.d.ts.map +1 -0
- package/dist/ui/chat-input-keys.js +360 -0
- package/dist/ui/chat-input-keys.js.map +1 -0
- package/dist/ui/chat-input.d.ts +4 -2
- package/dist/ui/chat-input.d.ts.map +1 -1
- package/dist/ui/chat-input.js +31 -350
- package/dist/ui/chat-input.js.map +1 -1
- package/dist/ui/commands.d.ts +14 -46
- package/dist/ui/commands.d.ts.map +1 -1
- package/dist/ui/commands.js +416 -2899
- package/dist/ui/commands.js.map +1 -1
- package/dist/ui/completions.d.ts +1 -0
- package/dist/ui/completions.d.ts.map +1 -1
- package/dist/ui/completions.js +36 -107
- package/dist/ui/completions.js.map +1 -1
- package/dist/ui/components.d.ts +20 -12
- package/dist/ui/components.d.ts.map +1 -1
- package/dist/ui/components.js +17 -226
- package/dist/ui/components.js.map +1 -1
- package/dist/ui/context.js +6 -6
- package/dist/ui/context.js.map +1 -1
- package/dist/ui/debug-log.d.ts +11 -0
- package/dist/ui/debug-log.d.ts.map +1 -0
- package/dist/ui/debug-log.js +21 -0
- package/dist/ui/debug-log.js.map +1 -0
- package/dist/ui/error-boundary.d.ts +1 -1
- package/dist/ui/error-boundary.d.ts.map +1 -1
- package/dist/ui/error-boundary.js.map +1 -1
- package/dist/ui/frame.d.ts +1 -1
- package/dist/ui/frame.d.ts.map +1 -1
- package/dist/ui/frame.js +1 -3
- package/dist/ui/frame.js.map +1 -1
- package/dist/ui/index.d.ts +11 -3
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +45 -1076
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/messages.d.ts +5 -8
- package/dist/ui/messages.d.ts.map +1 -1
- package/dist/ui/messages.js +15 -30
- package/dist/ui/messages.js.map +1 -1
- package/dist/ui/modals/index.d.ts +11 -0
- package/dist/ui/modals/index.d.ts.map +1 -0
- package/dist/ui/modals/index.js +10 -0
- package/dist/ui/modals/index.js.map +1 -0
- package/dist/ui/modals/prompts.d.ts +38 -0
- package/dist/ui/modals/prompts.d.ts.map +1 -0
- package/dist/ui/modals/prompts.js +124 -0
- package/dist/ui/modals/prompts.js.map +1 -0
- package/dist/ui/modals/selectors.d.ts +34 -0
- package/dist/ui/modals/selectors.d.ts.map +1 -0
- package/dist/ui/modals/selectors.js +111 -0
- package/dist/ui/modals/selectors.js.map +1 -0
- package/dist/ui/modals/setup.d.ts +18 -0
- package/dist/ui/modals/setup.d.ts.map +1 -0
- package/dist/ui/modals/setup.js +51 -0
- package/dist/ui/modals/setup.js.map +1 -0
- package/dist/ui/regions/input-region.d.ts +40 -0
- package/dist/ui/regions/input-region.d.ts.map +1 -0
- package/dist/ui/regions/input-region.js +116 -0
- package/dist/ui/regions/input-region.js.map +1 -0
- package/dist/ui/regions/modal-host.d.ts +41 -0
- package/dist/ui/regions/modal-host.d.ts.map +1 -0
- package/dist/ui/regions/modal-host.js +51 -0
- package/dist/ui/regions/modal-host.js.map +1 -0
- package/dist/ui/regions/render-probe.d.ts +22 -0
- package/dist/ui/regions/render-probe.d.ts.map +1 -0
- package/dist/ui/regions/render-probe.js +45 -0
- package/dist/ui/regions/render-probe.js.map +1 -0
- package/dist/ui/regions/static-scrollback.d.ts +39 -0
- package/dist/ui/regions/static-scrollback.d.ts.map +1 -0
- package/dist/ui/regions/static-scrollback.js +68 -0
- package/dist/ui/regions/static-scrollback.js.map +1 -0
- package/dist/ui/regions/status-region.d.ts +24 -0
- package/dist/ui/regions/status-region.d.ts.map +1 -0
- package/dist/ui/regions/status-region.js +17 -0
- package/dist/ui/regions/status-region.js.map +1 -0
- package/dist/ui/regions/transcript-region.d.ts +41 -0
- package/dist/ui/regions/transcript-region.d.ts.map +1 -0
- package/dist/ui/regions/transcript-region.js +52 -0
- package/dist/ui/regions/transcript-region.js.map +1 -0
- package/dist/ui/self-restart.d.ts +9 -0
- package/dist/ui/self-restart.d.ts.map +1 -0
- package/dist/ui/self-restart.js +24 -0
- package/dist/ui/self-restart.js.map +1 -0
- package/dist/ui/state/use-chat-controller.d.ts +23 -0
- package/dist/ui/state/use-chat-controller.d.ts.map +1 -0
- package/dist/ui/state/use-chat-controller.js +643 -0
- package/dist/ui/state/use-chat-controller.js.map +1 -0
- package/dist/ui/state/use-loop-state.d.ts +23 -0
- package/dist/ui/state/use-loop-state.d.ts.map +1 -0
- package/dist/ui/state/use-loop-state.js +39 -0
- package/dist/ui/state/use-loop-state.js.map +1 -0
- package/dist/ui/state/use-modal-state.d.ts +52 -0
- package/dist/ui/state/use-modal-state.d.ts.map +1 -0
- package/dist/ui/state/use-modal-state.js +44 -0
- package/dist/ui/state/use-modal-state.js.map +1 -0
- package/dist/ui/state/use-model-state.d.ts +29 -0
- package/dist/ui/state/use-model-state.d.ts.map +1 -0
- package/dist/ui/state/use-model-state.js +47 -0
- package/dist/ui/state/use-model-state.js.map +1 -0
- package/dist/ui/state/use-processing-state.d.ts +24 -0
- package/dist/ui/state/use-processing-state.d.ts.map +1 -0
- package/dist/ui/state/use-processing-state.js +46 -0
- package/dist/ui/state/use-processing-state.js.map +1 -0
- package/dist/ui/state/use-queue-state.d.ts +19 -0
- package/dist/ui/state/use-queue-state.d.ts.map +1 -0
- package/dist/ui/state/use-queue-state.js +30 -0
- package/dist/ui/state/use-queue-state.js.map +1 -0
- package/dist/ui/state/use-session-init.d.ts +22 -0
- package/dist/ui/state/use-session-init.d.ts.map +1 -0
- package/dist/ui/state/use-session-init.js +77 -0
- package/dist/ui/state/use-session-init.js.map +1 -0
- package/dist/ui/state/use-session-stats.d.ts +16 -0
- package/dist/ui/state/use-session-stats.d.ts.map +1 -0
- package/dist/ui/state/use-session-stats.js +18 -0
- package/dist/ui/state/use-session-stats.js.map +1 -0
- package/dist/ui/state/use-terminal-width.d.ts +8 -0
- package/dist/ui/state/use-terminal-width.d.ts.map +1 -0
- package/dist/ui/state/use-terminal-width.js +22 -0
- package/dist/ui/state/use-terminal-width.js.map +1 -0
- package/dist/ui/state/use-transcript-state.d.ts +21 -0
- package/dist/ui/state/use-transcript-state.d.ts.map +1 -0
- package/dist/ui/state/use-transcript-state.js +49 -0
- package/dist/ui/state/use-transcript-state.js.map +1 -0
- package/dist/ui/status-bar.d.ts +1 -1
- package/dist/ui/status-bar.d.ts.map +1 -1
- package/dist/ui/status-bar.js +3 -4
- package/dist/ui/status-bar.js.map +1 -1
- package/dist/version-check.d.ts.map +1 -1
- package/dist/version-check.js +10 -0
- package/dist/version-check.js.map +1 -1
- package/package.json +17 -10
- package/dist/agents/agent-config-loader.d.ts +0 -60
- package/dist/agents/agent-config-loader.d.ts.map +0 -1
- package/dist/agents/agent-config-loader.js +0 -402
- package/dist/agents/agent-config-loader.js.map +0 -1
- package/dist/agents/agent-config-presets.d.ts +0 -10
- package/dist/agents/agent-config-presets.d.ts.map +0 -1
- package/dist/agents/agent-config-presets.js +0 -940
- package/dist/agents/agent-config-presets.js.map +0 -1
- package/dist/agents/agent-config-types.d.ts +0 -145
- package/dist/agents/agent-config-types.d.ts.map +0 -1
- package/dist/agents/agent-config-types.js +0 -12
- package/dist/agents/agent-config-types.js.map +0 -1
- package/dist/agents/agent-detection.d.ts +0 -35
- package/dist/agents/agent-detection.d.ts.map +0 -1
- package/dist/agents/agent-detection.js +0 -110
- package/dist/agents/agent-detection.js.map +0 -1
- package/dist/agents/aggregator.d.ts +0 -19
- package/dist/agents/aggregator.d.ts.map +0 -1
- package/dist/agents/aggregator.js +0 -141
- package/dist/agents/aggregator.js.map +0 -1
- package/dist/agents/cli-backend.d.ts +0 -32
- package/dist/agents/cli-backend.d.ts.map +0 -1
- package/dist/agents/cli-backend.js +0 -271
- package/dist/agents/cli-backend.js.map +0 -1
- package/dist/agents/council-types.d.ts +0 -115
- package/dist/agents/council-types.d.ts.map +0 -1
- package/dist/agents/council-types.js +0 -81
- package/dist/agents/council-types.js.map +0 -1
- package/dist/agents/council.d.ts +0 -112
- package/dist/agents/council.d.ts.map +0 -1
- package/dist/agents/council.js +0 -722
- package/dist/agents/council.js.map +0 -1
- package/dist/agents/decomposer.d.ts +0 -33
- package/dist/agents/decomposer.d.ts.map +0 -1
- package/dist/agents/decomposer.js +0 -138
- package/dist/agents/decomposer.js.map +0 -1
- package/dist/agents/dynamic-tools.d.ts +0 -52
- package/dist/agents/dynamic-tools.d.ts.map +0 -1
- package/dist/agents/dynamic-tools.js +0 -424
- package/dist/agents/dynamic-tools.js.map +0 -1
- package/dist/agents/index.d.ts +0 -29
- package/dist/agents/index.d.ts.map +0 -1
- package/dist/agents/index.js +0 -29
- package/dist/agents/index.js.map +0 -1
- package/dist/agents/installer.d.ts +0 -39
- package/dist/agents/installer.d.ts.map +0 -1
- package/dist/agents/installer.js +0 -205
- package/dist/agents/installer.js.map +0 -1
- package/dist/agents/orchestrator.d.ts +0 -106
- package/dist/agents/orchestrator.d.ts.map +0 -1
- package/dist/agents/orchestrator.js +0 -363
- package/dist/agents/orchestrator.js.map +0 -1
- package/dist/agents/sdk-backend.d.ts +0 -63
- package/dist/agents/sdk-backend.d.ts.map +0 -1
- package/dist/agents/sdk-backend.js +0 -489
- package/dist/agents/sdk-backend.js.map +0 -1
- package/dist/agents/swarm-types.d.ts +0 -84
- package/dist/agents/swarm-types.d.ts.map +0 -1
- package/dist/agents/swarm-types.js +0 -20
- package/dist/agents/swarm-types.js.map +0 -1
- package/dist/agents/swarm.d.ts +0 -79
- package/dist/agents/swarm.d.ts.map +0 -1
- package/dist/agents/swarm.js +0 -375
- package/dist/agents/swarm.js.map +0 -1
- package/dist/agents/tools.d.ts +0 -26
- package/dist/agents/tools.d.ts.map +0 -1
- package/dist/agents/tools.js +0 -776
- package/dist/agents/tools.js.map +0 -1
- package/dist/agents/types.d.ts +0 -108
- package/dist/agents/types.d.ts.map +0 -1
- package/dist/agents/types.js +0 -43
- package/dist/agents/types.js.map +0 -1
- package/dist/api-server.d.ts +0 -45
- package/dist/api-server.d.ts.map +0 -1
- package/dist/api-server.js +0 -326
- package/dist/api-server.js.map +0 -1
- package/dist/auto-checkpoint.d.ts +0 -35
- package/dist/auto-checkpoint.d.ts.map +0 -1
- package/dist/auto-checkpoint.js +0 -176
- package/dist/auto-checkpoint.js.map +0 -1
- package/dist/background-jobs.d.ts +0 -45
- package/dist/background-jobs.d.ts.map +0 -1
- package/dist/background-jobs.js +0 -127
- package/dist/background-jobs.js.map +0 -1
- package/dist/branching.d.ts +0 -56
- package/dist/branching.d.ts.map +0 -1
- package/dist/branching.js +0 -224
- package/dist/branching.js.map +0 -1
- package/dist/cli/agent.d.ts +0 -9
- package/dist/cli/agent.d.ts.map +0 -1
- package/dist/cli/agent.js +0 -330
- package/dist/cli/agent.js.map +0 -1
- package/dist/cli/commands.d.ts +0 -12
- package/dist/cli/commands.d.ts.map +0 -1
- package/dist/cli/commands.js +0 -1042
- package/dist/cli/commands.js.map +0 -1
- package/dist/cli/index.d.ts +0 -8
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -268
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/types.d.ts +0 -33
- package/dist/cli/types.d.ts.map +0 -1
- package/dist/cli/types.js +0 -21
- package/dist/cli/types.js.map +0 -1
- package/dist/companions.d.ts +0 -54
- package/dist/companions.d.ts.map +0 -1
- package/dist/companions.js +0 -440
- package/dist/companions.js.map +0 -1
- package/dist/file-watcher.d.ts +0 -91
- package/dist/file-watcher.d.ts.map +0 -1
- package/dist/file-watcher.js +0 -269
- package/dist/file-watcher.js.map +0 -1
- package/dist/hud/theme-packs/api.d.ts +0 -51
- package/dist/hud/theme-packs/api.d.ts.map +0 -1
- package/dist/hud/theme-packs/api.js +0 -145
- package/dist/hud/theme-packs/api.js.map +0 -1
- package/dist/hud/theme-packs/index.d.ts +0 -18
- package/dist/hud/theme-packs/index.d.ts.map +0 -1
- package/dist/hud/theme-packs/index.js +0 -38
- package/dist/hud/theme-packs/index.js.map +0 -1
- package/dist/hud/theme-packs/types.d.ts +0 -29
- package/dist/hud/theme-packs/types.d.ts.map +0 -1
- package/dist/hud/theme-packs/types.js +0 -9
- package/dist/hud/theme-packs/types.js.map +0 -1
- package/dist/idle-eviction.d.ts +0 -34
- package/dist/idle-eviction.d.ts.map +0 -1
- package/dist/idle-eviction.js +0 -85
- package/dist/idle-eviction.js.map +0 -1
- package/dist/model-router.d.ts +0 -67
- package/dist/model-router.d.ts.map +0 -1
- package/dist/model-router.js.map +0 -1
- package/dist/providers/openai-compat-shims.d.ts +0 -31
- package/dist/providers/openai-compat-shims.d.ts.map +0 -1
- package/dist/providers/openai-compat-shims.js +0 -179
- package/dist/providers/openai-compat-shims.js.map +0 -1
- package/dist/sandbox-native.d.ts.map +0 -1
- package/dist/sandbox-native.js.map +0 -1
- package/dist/sandbox.d.ts.map +0 -1
- package/dist/sandbox.js.map +0 -1
- package/dist/session-timeout.d.ts +0 -31
- package/dist/session-timeout.d.ts.map +0 -1
- package/dist/session-timeout.js +0 -100
- package/dist/session-timeout.js.map +0 -1
- package/dist/smart-router.d.ts +0 -73
- package/dist/smart-router.d.ts.map +0 -1
- package/dist/smart-router.js +0 -332
- package/dist/smart-router.js.map +0 -1
- package/dist/terminal-recording.d.ts +0 -55
- package/dist/terminal-recording.d.ts.map +0 -1
- package/dist/terminal-recording.js +0 -182
- package/dist/terminal-recording.js.map +0 -1
- package/dist/tmux.d.ts +0 -35
- package/dist/tmux.d.ts.map +0 -1
- package/dist/tmux.js +0 -106
- package/dist/tmux.js.map +0 -1
- package/dist/ui/modals.d.ts +0 -72
- package/dist/ui/modals.d.ts.map +0 -1
- package/dist/ui/modals.js +0 -266
- package/dist/ui/modals.js.map +0 -1
- package/dist/ui/pack-picker.d.ts +0 -12
- package/dist/ui/pack-picker.d.ts.map +0 -1
- package/dist/ui/pack-picker.js +0 -101
- package/dist/ui/pack-picker.js.map +0 -1
- package/dist/ui/theme-picker.d.ts +0 -24
- package/dist/ui/theme-picker.d.ts.map +0 -1
- package/dist/ui/theme-picker.js +0 -190
- package/dist/ui/theme-picker.js.map +0 -1
package/dist/tools.js
CHANGED
|
@@ -8,16 +8,13 @@ import * as fs from 'fs';
|
|
|
8
8
|
import * as path from 'path';
|
|
9
9
|
import * as os from 'os';
|
|
10
10
|
import { StringDecoder } from 'string_decoder';
|
|
11
|
-
import * as sandbox from './sandbox.js';
|
|
12
|
-
import * as nativeSandbox from './sandbox-native.js';
|
|
13
|
-
import { getAgtermTools, isAgtermTool, executeAgtermTool } from './agents/index.js';
|
|
11
|
+
import * as sandbox from './sandbox/index.js';
|
|
14
12
|
import { validatePath as scopeValidatePath, isInScope } from './scope.js';
|
|
15
13
|
import { getPluginTools, isPluginTool, executePluginTool } from './plugins.js';
|
|
16
14
|
import config from './config.js';
|
|
17
|
-
import { applySkin, applyPalette, listSkins, listPalettes } from './hud/api.js';
|
|
18
|
-
import { listCompanions } from './companions.js';
|
|
19
15
|
import { generateDiff as generateFileDiff } from './diff.js';
|
|
20
|
-
import {
|
|
16
|
+
import { fleetActive, fleetMirrorToolCall } from './fleet.js';
|
|
17
|
+
import { computeAnchorHash, anchorHashFooter } from './local-model.js';
|
|
21
18
|
/**
|
|
22
19
|
* Available tools for the agent
|
|
23
20
|
*/
|
|
@@ -273,36 +270,21 @@ export const TOOLS = [
|
|
|
273
270
|
},
|
|
274
271
|
{
|
|
275
272
|
name: 'configure',
|
|
276
|
-
description: `Read, set, or list Calliope configuration options. Use this when the user asks to change settings, switch themes, providers, models,
|
|
273
|
+
description: `Read, set, or list Calliope configuration options. Use this when the user asks to change settings, switch themes, providers, models, or any preference through natural conversation. Always use action "list" first if you need to show available options.
|
|
277
274
|
|
|
278
275
|
CONFIGURABLE SETTINGS:
|
|
279
276
|
- defaultProvider: AI provider (anthropic, google, openai, together, openrouter, groq, fireworks, mistral, ollama, ai21, huggingface, litellm, bedrock, auto)
|
|
280
277
|
- defaultModel: Model name string (provider-specific, e.g. "claude-sonnet-4-6", "gemini-2.0-flash", "gpt-4o")
|
|
281
|
-
- persona: Agent persona style (calliope, muse, minimal)
|
|
282
278
|
- maxIterations: Max agent loop iterations (0 = unlimited)
|
|
283
279
|
- maxIterationTime: Max seconds per iteration (0 = no limit, default: 600)
|
|
284
|
-
- fancyOutput: Enable rich formatting (true/false)
|
|
285
280
|
- autoSaveHistory: Auto-save session history (true/false)
|
|
286
281
|
- autoUpgrade: Check for updates on startup (true/false)
|
|
287
282
|
- collapseTools: Auto-collapse tool output (true/false)
|
|
288
|
-
- collapseThinking: Auto-collapse think blocks (true/false)
|
|
289
283
|
- toolDisplayLimit: Show last N tools expanded (0 = all)
|
|
290
|
-
- layout: UI layout (classic, response-top, response-bottom, split, zen, focus, dashboard, minimal)
|
|
291
|
-
- density: Display density (normal, compact)
|
|
292
|
-
- activeSkin: Terminal skin/theme name (use action "list" category "skins" to see options)
|
|
293
|
-
- activePalette: Color palette name (use action "list" category "palettes" to see options)
|
|
294
|
-
- activeCompanion: AI companion personality (use action "list" category "companions" to see options)
|
|
295
|
-
- companionIntensity: Companion personality level (professional, immersive)
|
|
296
|
-
- useEmojis: Show emojis in UI (true/false)
|
|
297
284
|
- diffStyle: Diff display format (inline, unified, side-by-side)
|
|
298
|
-
- borderStyle: UI border style (rounded, sharp, double, ascii, none)
|
|
299
|
-
- bannerStyle: Startup banner (full, compact, none)
|
|
300
285
|
- circuitBreakersEnabled: Safety circuit breakers (true/false)
|
|
301
286
|
- sandboxMode: Code execution sandbox (auto, native, docker, off)
|
|
302
|
-
-
|
|
303
|
-
- smartRoutingCostSensitivity: Cost vs quality (0-1, 0=best quality, 1=cheapest)
|
|
304
|
-
- recordSessions: Record session audit logs (true/false)
|
|
305
|
-
- recordingRetentionDays: Auto-delete old recordings after N days (0 = keep forever)`,
|
|
287
|
+
- sessionLogLimit: Cap retained session log items (0 = unlimited)`,
|
|
306
288
|
parameters: {
|
|
307
289
|
type: 'object',
|
|
308
290
|
properties: {
|
|
@@ -321,8 +303,8 @@ CONFIGURABLE SETTINGS:
|
|
|
321
303
|
},
|
|
322
304
|
category: {
|
|
323
305
|
type: 'string',
|
|
324
|
-
description: 'Category to list options for (for list action):
|
|
325
|
-
enum: ['
|
|
306
|
+
description: 'Category to list options for (for list action): providers, layouts, all',
|
|
307
|
+
enum: ['providers', 'layouts', 'all'],
|
|
326
308
|
},
|
|
327
309
|
},
|
|
328
310
|
required: ['action'],
|
|
@@ -354,13 +336,9 @@ CONFIGURABLE SETTINGS:
|
|
|
354
336
|
];
|
|
355
337
|
/**
|
|
356
338
|
* Get all available tools
|
|
357
|
-
* Includes agent tools when agentEnabled is true
|
|
358
339
|
*/
|
|
359
|
-
export function getTools(
|
|
340
|
+
export function getTools() {
|
|
360
341
|
const pluginTools = getPluginTools();
|
|
361
|
-
if (agentEnabled) {
|
|
362
|
-
return [...TOOLS, ...getAgtermTools(), ...pluginTools];
|
|
363
|
-
}
|
|
364
342
|
return [...TOOLS, ...pluginTools];
|
|
365
343
|
}
|
|
366
344
|
/**
|
|
@@ -395,17 +373,11 @@ function validatePath(filePath, cwd) {
|
|
|
395
373
|
/**
|
|
396
374
|
* Execute a tool call
|
|
397
375
|
*/
|
|
398
|
-
export async function executeTool(toolCall, cwd, timeout = 60000, onOutput) {
|
|
376
|
+
export async function executeTool(toolCall, cwd, timeout = 60000, onOutput, options) {
|
|
399
377
|
const { id, name, arguments: args } = toolCall;
|
|
400
|
-
// Mirror tool call to
|
|
401
|
-
if (
|
|
402
|
-
await
|
|
403
|
-
// Silently fail - don't interrupt tool execution
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
// Handle agent tools
|
|
407
|
-
if (isAgtermTool(name)) {
|
|
408
|
-
return executeAgtermTool(toolCall, cwd);
|
|
378
|
+
// Mirror tool call to the fleet channel
|
|
379
|
+
if (fleetActive()) {
|
|
380
|
+
await fleetMirrorToolCall(name, args);
|
|
409
381
|
}
|
|
410
382
|
// Handle plugin tools
|
|
411
383
|
if (isPluginTool(name)) {
|
|
@@ -425,7 +397,7 @@ export async function executeTool(toolCall, cwd, timeout = 60000, onOutput) {
|
|
|
425
397
|
if (typeof args.path !== 'string') {
|
|
426
398
|
return { toolCallId: id, result: 'Error: path must be a string', isError: true };
|
|
427
399
|
}
|
|
428
|
-
result = await readFile(args.path, cwd);
|
|
400
|
+
result = await readFile(args.path, cwd, options?.appendAnchorHash === true, options?.fs);
|
|
429
401
|
break;
|
|
430
402
|
}
|
|
431
403
|
case 'write_file': {
|
|
@@ -435,7 +407,7 @@ export async function executeTool(toolCall, cwd, timeout = 60000, onOutput) {
|
|
|
435
407
|
if (typeof args.content !== 'string') {
|
|
436
408
|
return { toolCallId: id, result: 'Error: content must be a string', isError: true };
|
|
437
409
|
}
|
|
438
|
-
result = await writeFile(args.path, args.content, cwd);
|
|
410
|
+
result = await writeFile(args.path, args.content, cwd, options?.fs);
|
|
439
411
|
break;
|
|
440
412
|
}
|
|
441
413
|
case 'list_files': {
|
|
@@ -520,42 +492,21 @@ export async function executeTool(toolCall, cwd, timeout = 60000, onOutput) {
|
|
|
520
492
|
if (action === 'list') {
|
|
521
493
|
const category = args.category || 'all';
|
|
522
494
|
const sections = [];
|
|
523
|
-
if (category === 'skins' || category === 'all') {
|
|
524
|
-
const skins = listSkins();
|
|
525
|
-
const current = config.get('activeSkin');
|
|
526
|
-
sections.push('SKINS (activeSkin):\n' + skins.map(s => ` ${s.name === current ? '→ ' : ' '}${s.name} - ${s.description}`).join('\n'));
|
|
527
|
-
}
|
|
528
|
-
if (category === 'palettes' || category === 'all') {
|
|
529
|
-
const palettes = listPalettes();
|
|
530
|
-
const current = config.get('activePalette');
|
|
531
|
-
sections.push('PALETTES (activePalette):\n' + palettes.map(p => ` ${p.name === current ? '→ ' : ' '}${p.name} - ${p.description}`).join('\n'));
|
|
532
|
-
}
|
|
533
|
-
if (category === 'companions' || category === 'all') {
|
|
534
|
-
const companions = listCompanions();
|
|
535
|
-
const current = config.get('activeCompanion');
|
|
536
|
-
sections.push('COMPANIONS (activeCompanion):\n' + companions.map(c => ` ${c.name === current ? '→ ' : ' '}${c.name} - ${c.description}`).join('\n'));
|
|
537
|
-
}
|
|
538
495
|
if (category === 'providers' || category === 'all') {
|
|
539
496
|
const providers = ['anthropic', 'google', 'openai', 'together', 'openrouter', 'groq', 'fireworks', 'mistral', 'ollama', 'ai21', 'huggingface', 'litellm', 'bedrock', 'auto'];
|
|
540
497
|
const current = config.get('defaultProvider');
|
|
541
498
|
sections.push('PROVIDERS (defaultProvider):\n' + providers.map(p => ` ${p === current ? '→ ' : ' '}${p}`).join('\n'));
|
|
542
499
|
}
|
|
543
|
-
if (category === 'layouts' || category === 'all') {
|
|
544
|
-
const layouts = ['classic', 'response-top', 'response-bottom', 'split', 'zen', 'focus', 'dashboard', 'minimal'];
|
|
545
|
-
const current = config.get('layout');
|
|
546
|
-
sections.push('LAYOUTS (layout):\n' + layouts.map(l => ` ${l === current ? '→ ' : ' '}${l}`).join('\n'));
|
|
547
|
-
}
|
|
548
500
|
if (category === 'all') {
|
|
549
501
|
// Also show current key settings
|
|
550
502
|
const currentSettings = [
|
|
551
|
-
`density: ${config.get('density')}`,
|
|
552
|
-
`companionIntensity: ${config.get('companionIntensity')}`,
|
|
553
|
-
`useEmojis: ${config.get('useEmojis')}`,
|
|
554
503
|
`diffStyle: ${config.get('diffStyle')}`,
|
|
555
|
-
`borderStyle: ${config.get('borderStyle')}`,
|
|
556
|
-
`bannerStyle: ${config.get('bannerStyle')}`,
|
|
557
504
|
`sandboxMode: ${config.get('sandboxMode')}`,
|
|
558
|
-
`
|
|
505
|
+
`collapseTools: ${config.get('collapseTools')}`,
|
|
506
|
+
`toolDisplayLimit: ${config.get('toolDisplayLimit')}`,
|
|
507
|
+
`maxIterations: ${config.get('maxIterations')}`,
|
|
508
|
+
`sessionLogLimit: ${config.get('sessionLogLimit')}`,
|
|
509
|
+
`routing.enabled: ${config.get('routing')?.enabled ?? false}`,
|
|
559
510
|
`defaultModel: ${config.get('defaultModel') || '(auto)'}`,
|
|
560
511
|
];
|
|
561
512
|
sections.push('CURRENT SETTINGS:\n' + currentSettings.map(s => ` ${s}`).join('\n'));
|
|
@@ -583,16 +534,11 @@ export async function executeTool(toolCall, cwd, timeout = 60000, onOutput) {
|
|
|
583
534
|
}
|
|
584
535
|
// Only allow setting safe keys through conversation (allowlist)
|
|
585
536
|
const SAFE_CONFIG_KEYS = new Set([
|
|
586
|
-
'defaultProvider', 'defaultModel', '
|
|
587
|
-
'
|
|
588
|
-
'collapseTools', '
|
|
589
|
-
'layout', 'density',
|
|
590
|
-
'activeSkin', 'activePalette', 'activeCompanion', 'activeThemePack',
|
|
591
|
-
'companionIntensity', 'useEmojis', 'diffStyle', 'borderStyle', 'bannerStyle',
|
|
537
|
+
'defaultProvider', 'defaultModel', 'maxIterations', 'maxIterationTime',
|
|
538
|
+
'autoSaveHistory', 'autoUpgrade',
|
|
539
|
+
'collapseTools', 'toolDisplayLimit', 'diffStyle',
|
|
592
540
|
'circuitBreakersEnabled', 'sandboxMode',
|
|
593
|
-
'
|
|
594
|
-
'recordSessions', 'recordingRetentionDays', 'sessionLogLimit',
|
|
595
|
-
'awsRegion', 'awsProfile',
|
|
541
|
+
'sessionLogLimit',
|
|
596
542
|
]);
|
|
597
543
|
if (!SAFE_CONFIG_KEYS.has(key)) {
|
|
598
544
|
return { toolCallId: id, result: `Error: "${key}" cannot be set through conversation. Use /keys command, environment variables, or edit the config file directly.`, isError: true };
|
|
@@ -606,31 +552,6 @@ export async function executeTool(toolCall, cwd, timeout = 60000, onOutput) {
|
|
|
606
552
|
else if (/^\d+(\.\d+)?$/.test(rawValue))
|
|
607
553
|
parsedValue = Number(rawValue);
|
|
608
554
|
try {
|
|
609
|
-
// Special handling for HUD settings that need apply functions
|
|
610
|
-
if (key === 'activeSkin') {
|
|
611
|
-
const success = applySkin(rawValue);
|
|
612
|
-
if (!success) {
|
|
613
|
-
return { toolCallId: id, result: `Error: skin "${rawValue}" not found. Use action "list" category "skins" to see available skins.`, isError: true };
|
|
614
|
-
}
|
|
615
|
-
result = `Skin changed to "${rawValue}"`;
|
|
616
|
-
break;
|
|
617
|
-
}
|
|
618
|
-
if (key === 'activePalette') {
|
|
619
|
-
const success = applyPalette(rawValue);
|
|
620
|
-
if (!success) {
|
|
621
|
-
return { toolCallId: id, result: `Error: palette "${rawValue}" not found. Use action "list" category "palettes" to see available palettes.`, isError: true };
|
|
622
|
-
}
|
|
623
|
-
result = `Palette changed to "${rawValue}"`;
|
|
624
|
-
break;
|
|
625
|
-
}
|
|
626
|
-
if (key === 'activeCompanion') {
|
|
627
|
-
if (!listCompanions().some(c => c.name === rawValue)) {
|
|
628
|
-
return { toolCallId: id, result: `Error: companion "${rawValue}" not found. Use action "list" category "companions" to see available companions.`, isError: true };
|
|
629
|
-
}
|
|
630
|
-
config.set('activeCompanion', rawValue);
|
|
631
|
-
result = `Companion changed to "${rawValue}"`;
|
|
632
|
-
break;
|
|
633
|
-
}
|
|
634
555
|
// Generic config set
|
|
635
556
|
config.set(key, parsedValue);
|
|
636
557
|
result = `Set ${key} = ${JSON.stringify(parsedValue)}`;
|
|
@@ -660,7 +581,10 @@ export async function executeTool(toolCall, cwd, timeout = 60000, onOutput) {
|
|
|
660
581
|
return { toolCallId: id, result: 'Error: new_string must be a string', isError: true };
|
|
661
582
|
}
|
|
662
583
|
const replaceAll = args.replace_all === true;
|
|
663
|
-
|
|
584
|
+
// anchor_hash is optional and accepted from any caller; it is only
|
|
585
|
+
// advertised in the simplified local schema (feature 4).
|
|
586
|
+
const anchorHash = typeof args.anchor_hash === 'string' ? args.anchor_hash : undefined;
|
|
587
|
+
result = await editFile(args.path, args.old_string, args.new_string, replaceAll, cwd, anchorHash, options?.fs);
|
|
664
588
|
break;
|
|
665
589
|
}
|
|
666
590
|
case 'glob': {
|
|
@@ -708,7 +632,7 @@ export async function executeTool(toolCall, cwd, timeout = 60000, onOutput) {
|
|
|
708
632
|
* SECURITY NOTE (#132): This denylist is ADVISORY / defense-in-depth only. It is
|
|
709
633
|
* fundamentally unwinnable to perfectly screen an arbitrary `bash -c` string, so
|
|
710
634
|
* treat this as a best-effort tripwire, NOT a security boundary. The real control
|
|
711
|
-
* is the native sandbox (see src/sandbox
|
|
635
|
+
* is the native sandbox (see src/sandbox/native.ts); when no sandbox is available
|
|
712
636
|
* the shell tool fails closed (see shouldUseNativeSandbox / executeShell).
|
|
713
637
|
*/
|
|
714
638
|
const BLOCKED_COMMANDS = [
|
|
@@ -852,29 +776,11 @@ function validateShellPaths(command, cwd) {
|
|
|
852
776
|
for (const p of extractedPaths) {
|
|
853
777
|
const allowed = isInScope(p, cwd);
|
|
854
778
|
if (!allowed) {
|
|
855
|
-
return 'Shell command blocked: "' + p + '" is outside allowed scope. Use /add
|
|
779
|
+
return 'Shell command blocked: "' + p + '" is outside allowed scope. Use /scope add to expand scope.';
|
|
856
780
|
}
|
|
857
781
|
}
|
|
858
782
|
return null;
|
|
859
783
|
}
|
|
860
|
-
/**
|
|
861
|
-
* Determine whether to use native sandboxing for shell commands based on config.
|
|
862
|
-
*
|
|
863
|
-
* sandboxMode values:
|
|
864
|
-
* - 'auto': use native sandbox when available, otherwise run unsandboxed
|
|
865
|
-
* - 'native': require native sandbox (fail if unavailable)
|
|
866
|
-
* - 'docker': defer to Docker sandbox (handled elsewhere)
|
|
867
|
-
* - 'off': no sandboxing
|
|
868
|
-
*/
|
|
869
|
-
function shouldUseNativeSandbox() {
|
|
870
|
-
const mode = config.get('sandboxMode') || 'auto';
|
|
871
|
-
if (mode === 'off' || mode === 'docker')
|
|
872
|
-
return 'skip';
|
|
873
|
-
if (mode === 'native')
|
|
874
|
-
return 'require';
|
|
875
|
-
// 'auto': use if available
|
|
876
|
-
return nativeSandbox.isNativeSandboxAvailable() ? 'use' : 'skip';
|
|
877
|
-
}
|
|
878
784
|
/**
|
|
879
785
|
* Execute a shell command
|
|
880
786
|
*/
|
|
@@ -890,8 +796,8 @@ async function executeShell(command, cwd, timeout, onOutput) {
|
|
|
890
796
|
return `Error: ${scopeError}`;
|
|
891
797
|
}
|
|
892
798
|
// Check if native sandbox should be used
|
|
893
|
-
const sandboxDecision = shouldUseNativeSandbox();
|
|
894
|
-
if (sandboxDecision === 'require' && !
|
|
799
|
+
const sandboxDecision = sandbox.shouldUseNativeSandbox();
|
|
800
|
+
if (sandboxDecision === 'require' && !sandbox.isNativeSandboxAvailable()) {
|
|
895
801
|
return 'Error: Native sandbox required (sandboxMode=native) but not available on this platform.';
|
|
896
802
|
}
|
|
897
803
|
// 'auto' is best-effort: when no native backend exists (e.g. Linux/Windows
|
|
@@ -903,7 +809,7 @@ async function executeShell(command, cwd, timeout, onOutput) {
|
|
|
903
809
|
if (sandboxDecision === 'use' || sandboxDecision === 'require') {
|
|
904
810
|
// Network is OFF by default; opt in via CALLIOPE_SHELL_NETWORK=1 (#133).
|
|
905
811
|
const networkEnabled = process.env.CALLIOPE_SHELL_NETWORK === '1';
|
|
906
|
-
const result = await
|
|
812
|
+
const result = await sandbox.executeInNativeSandbox(command, cwd, {
|
|
907
813
|
timeout,
|
|
908
814
|
networkEnabled,
|
|
909
815
|
});
|
|
@@ -974,27 +880,41 @@ async function executeShell(command, cwd, timeout, onOutput) {
|
|
|
974
880
|
}
|
|
975
881
|
/**
|
|
976
882
|
* Read a file
|
|
883
|
+
*
|
|
884
|
+
* When `appendAnchorHash` is set (local backends only), the current content hash
|
|
885
|
+
* is appended so the model can echo it back on a subsequent anchored edit_file
|
|
886
|
+
* (stale-view protection, feature 4).
|
|
977
887
|
*/
|
|
978
|
-
async function readFile(filePath, cwd) {
|
|
888
|
+
async function readFile(filePath, cwd, appendAnchorHash = false, fsDelegate) {
|
|
979
889
|
const absPath = validatePath(filePath, cwd);
|
|
980
|
-
|
|
981
|
-
|
|
890
|
+
let content;
|
|
891
|
+
if (fsDelegate?.readTextFile) {
|
|
892
|
+
// Client-side fs (e.g. an ACP editor buffer that may hold unsaved changes).
|
|
893
|
+
// The client owns existence/size; a missing file surfaces as a thrown error
|
|
894
|
+
// that executeTool turns into a normal tool error.
|
|
895
|
+
content = await fsDelegate.readTextFile(absPath);
|
|
982
896
|
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
897
|
+
else {
|
|
898
|
+
if (!fs.existsSync(absPath)) {
|
|
899
|
+
throw new Error(`File not found: ${absPath}`);
|
|
900
|
+
}
|
|
901
|
+
const stats = fs.statSync(absPath);
|
|
902
|
+
if (stats.isDirectory()) {
|
|
903
|
+
throw new Error(`Path is a directory: ${absPath}`);
|
|
904
|
+
}
|
|
905
|
+
// Check file size (limit to 1MB)
|
|
906
|
+
if (stats.size > 1024 * 1024) {
|
|
907
|
+
throw new Error(`File too large (${Math.round(stats.size / 1024)}KB). Max 1MB.`);
|
|
908
|
+
}
|
|
909
|
+
content = fs.readFileSync(absPath, 'utf-8');
|
|
990
910
|
}
|
|
991
|
-
const content = fs.readFileSync(absPath, 'utf-8');
|
|
992
911
|
// Inline file preview header (#119). The header carries the line count;
|
|
993
912
|
// the full content follows once — no preview/footer, those duplicated the
|
|
994
913
|
// first 20 lines on every read and cost ~20% extra tokens on short files.
|
|
995
914
|
const totalLines = content.split('\n').length;
|
|
996
915
|
const header = `[file: ${filePath} \u2014 ${totalLines} line${totalLines !== 1 ? 's' : ''}]\n${'─'.repeat(40)}`;
|
|
997
|
-
|
|
916
|
+
const footer = appendAnchorHash ? anchorHashFooter(computeAnchorHash(content)) : '';
|
|
917
|
+
return `${header}\n${content}${footer}`;
|
|
998
918
|
}
|
|
999
919
|
/**
|
|
1000
920
|
* Generate a simple line-diff between old and new content
|
|
@@ -1009,9 +929,7 @@ function generateDiff(oldContent, newContent, maxLines = 20) {
|
|
|
1009
929
|
let deletions = 0;
|
|
1010
930
|
let changesShown = 0;
|
|
1011
931
|
let contextLines = 0;
|
|
1012
|
-
|
|
1013
|
-
const density = config.get('density') || 'normal';
|
|
1014
|
-
const contextWindow = density === 'compact' ? 1 : 3;
|
|
932
|
+
const contextWindow = 3;
|
|
1015
933
|
// Compute line number width
|
|
1016
934
|
const lineNumWidth = Math.max(4, maxIdx.toString().length);
|
|
1017
935
|
const padNum = (n) => String(n).padStart(lineNumWidth, ' ');
|
|
@@ -1059,39 +977,46 @@ function generateDiff(oldContent, newContent, maxLines = 20) {
|
|
|
1059
977
|
/**
|
|
1060
978
|
* Write a file
|
|
1061
979
|
*/
|
|
1062
|
-
async function writeFile(filePath, content, cwd) {
|
|
980
|
+
async function writeFile(filePath, content, cwd, fsDelegate) {
|
|
1063
981
|
const absPath = validatePath(filePath, cwd);
|
|
1064
|
-
// Create directory if needed
|
|
1065
|
-
const dir = path.dirname(absPath);
|
|
1066
|
-
if (!fs.existsSync(dir)) {
|
|
1067
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
1068
|
-
}
|
|
1069
982
|
// Read existing content for diff
|
|
1070
983
|
let oldContent = '';
|
|
1071
984
|
let isNewFile = true;
|
|
1072
|
-
if (
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
985
|
+
if (fsDelegate?.writeTextFile) {
|
|
986
|
+
// Client-side fs: read the current buffer for the diff (absent = new file),
|
|
987
|
+
// then write through the client instead of touching local disk.
|
|
988
|
+
if (fsDelegate.readTextFile) {
|
|
989
|
+
try {
|
|
990
|
+
oldContent = await fsDelegate.readTextFile(absPath);
|
|
1077
991
|
isNewFile = false;
|
|
1078
992
|
}
|
|
993
|
+
catch {
|
|
994
|
+
oldContent = '';
|
|
995
|
+
isNewFile = true;
|
|
996
|
+
}
|
|
1079
997
|
}
|
|
1080
|
-
|
|
1081
|
-
// Ignore errors reading old content
|
|
1082
|
-
}
|
|
998
|
+
await fsDelegate.writeTextFile(absPath, content);
|
|
1083
999
|
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1000
|
+
else {
|
|
1001
|
+
// Create directory if needed
|
|
1002
|
+
const dir = path.dirname(absPath);
|
|
1003
|
+
if (!fs.existsSync(dir)) {
|
|
1004
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
1089
1005
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1006
|
+
if (fs.existsSync(absPath)) {
|
|
1007
|
+
try {
|
|
1008
|
+
const stats = fs.statSync(absPath);
|
|
1009
|
+
if (!stats.isDirectory() && stats.size < 100 * 1024) {
|
|
1010
|
+
oldContent = fs.readFileSync(absPath, 'utf-8');
|
|
1011
|
+
isNewFile = false;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
catch {
|
|
1015
|
+
// Ignore errors reading old content
|
|
1016
|
+
}
|
|
1092
1017
|
}
|
|
1018
|
+
fs.writeFileSync(absPath, content);
|
|
1093
1019
|
}
|
|
1094
|
-
fs.writeFileSync(absPath, content);
|
|
1095
1020
|
// Generate diff output (#119)
|
|
1096
1021
|
const DIFF_CAP = 50;
|
|
1097
1022
|
const header = `[wrote: ${filePath}]\n${'─'.repeat(Math.min(filePath.length + 9, 60))}`;
|
|
@@ -1193,12 +1118,10 @@ function listFilesRecursive(dir, prefix, depth) {
|
|
|
1193
1118
|
* - 'off': no sandboxing
|
|
1194
1119
|
*/
|
|
1195
1120
|
async function executeCode(language, code, cwd, timeout) {
|
|
1196
|
-
const mode = config.get('sandboxMode') || 'auto';
|
|
1197
1121
|
const sandboxLang = language === 'node' ? 'node' : language;
|
|
1198
|
-
// Determine execution strategy
|
|
1199
|
-
const
|
|
1200
|
-
|
|
1201
|
-
if (useDocker) {
|
|
1122
|
+
// Determine execution strategy from sandboxMode config
|
|
1123
|
+
const strategy = sandbox.selectCodeSandbox();
|
|
1124
|
+
if (strategy === 'docker') {
|
|
1202
1125
|
// Docker sandbox path (existing behaviour)
|
|
1203
1126
|
const result = await sandbox.execute(sandboxLang, code, {
|
|
1204
1127
|
timeout,
|
|
@@ -1217,7 +1140,7 @@ async function executeCode(language, code, cwd, timeout) {
|
|
|
1217
1140
|
output += `Duration: ${result.duration}ms`;
|
|
1218
1141
|
return output;
|
|
1219
1142
|
}
|
|
1220
|
-
if (
|
|
1143
|
+
if (strategy === 'native') {
|
|
1221
1144
|
// Native OS sandbox path — write code to temp file and execute
|
|
1222
1145
|
const fs = await import('fs');
|
|
1223
1146
|
const os = await import('os');
|
|
@@ -1230,7 +1153,7 @@ async function executeCode(language, code, cwd, timeout) {
|
|
|
1230
1153
|
: language === 'node' ? `node "${codePath}"`
|
|
1231
1154
|
: `bash "${codePath}"`;
|
|
1232
1155
|
const startTime = Date.now();
|
|
1233
|
-
const result = await
|
|
1156
|
+
const result = await sandbox.executeInNativeSandbox(cmd, cwd, {
|
|
1234
1157
|
timeout,
|
|
1235
1158
|
readOnlyPaths: [tempDir],
|
|
1236
1159
|
});
|
|
@@ -1425,16 +1348,42 @@ ${content}
|
|
|
1425
1348
|
* Edit a file by replacing an exact string (in-place edit).
|
|
1426
1349
|
* Supports single-occurrence enforcement or replace_all mode.
|
|
1427
1350
|
*/
|
|
1428
|
-
async function editFile(filePath, oldString, newString, replaceAll, cwd) {
|
|
1351
|
+
async function editFile(filePath, oldString, newString, replaceAll, cwd, anchorHash, fsDelegate) {
|
|
1429
1352
|
const absPath = validatePath(filePath, cwd);
|
|
1430
|
-
|
|
1431
|
-
|
|
1353
|
+
let content;
|
|
1354
|
+
if (fsDelegate?.readTextFile) {
|
|
1355
|
+
// Client-side fs: edit against the editor's current buffer, not disk.
|
|
1356
|
+
content = await fsDelegate.readTextFile(absPath);
|
|
1432
1357
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1358
|
+
else {
|
|
1359
|
+
if (!fs.existsSync(absPath)) {
|
|
1360
|
+
throw new Error(`File not found: ${absPath}`);
|
|
1361
|
+
}
|
|
1362
|
+
const stats = fs.statSync(absPath);
|
|
1363
|
+
if (stats.isDirectory()) {
|
|
1364
|
+
throw new Error(`Path is a directory: ${absPath}`);
|
|
1365
|
+
}
|
|
1366
|
+
content = fs.readFileSync(absPath, 'utf-8');
|
|
1367
|
+
}
|
|
1368
|
+
// Persist the edited content through the delegate when available, else disk.
|
|
1369
|
+
const writeUpdated = async (updated) => {
|
|
1370
|
+
if (fsDelegate?.writeTextFile) {
|
|
1371
|
+
await fsDelegate.writeTextFile(absPath, updated);
|
|
1372
|
+
}
|
|
1373
|
+
else {
|
|
1374
|
+
fs.writeFileSync(absPath, updated);
|
|
1375
|
+
}
|
|
1376
|
+
};
|
|
1377
|
+
// Stale-view protection (feature 4): if the caller supplied an anchor_hash, it
|
|
1378
|
+
// must match the file's current content. A mismatch means the model is acting
|
|
1379
|
+
// on an out-of-date view — fail loudly and tell it to re-read. Absent hash =
|
|
1380
|
+
// no check (inert for cloud providers, which never see the param).
|
|
1381
|
+
if (anchorHash !== undefined) {
|
|
1382
|
+
const currentHash = computeAnchorHash(content);
|
|
1383
|
+
if (anchorHash !== currentHash) {
|
|
1384
|
+
throw new Error(`anchor_hash mismatch: file has changed since you read it (you sent "${anchorHash}", current is "${currentHash}"). Re-read ${filePath} before editing.`);
|
|
1385
|
+
}
|
|
1436
1386
|
}
|
|
1437
|
-
const content = fs.readFileSync(absPath, 'utf-8');
|
|
1438
1387
|
// Helper to build a compact edit diff from old_string/new_string (#119)
|
|
1439
1388
|
const buildEditDiff = (oldStr, newStr, fPath, count) => {
|
|
1440
1389
|
const DIFF_CAP = 50;
|
|
@@ -1476,7 +1425,7 @@ async function editFile(filePath, oldString, newString, replaceAll, cwd) {
|
|
|
1476
1425
|
if (count === 0) {
|
|
1477
1426
|
throw new Error(`old_string not found in file: ${absPath}`);
|
|
1478
1427
|
}
|
|
1479
|
-
|
|
1428
|
+
await writeUpdated(updated);
|
|
1480
1429
|
return buildEditDiff(oldString, newString, filePath, count);
|
|
1481
1430
|
}
|
|
1482
1431
|
// Count occurrences
|
|
@@ -1488,7 +1437,7 @@ async function editFile(filePath, oldString, newString, replaceAll, cwd) {
|
|
|
1488
1437
|
throw new Error(`old_string matches ${occurrences} occurrences — use replace_all: true or make it more specific`);
|
|
1489
1438
|
}
|
|
1490
1439
|
const updated = content.replace(oldString, newString);
|
|
1491
|
-
|
|
1440
|
+
await writeUpdated(updated);
|
|
1492
1441
|
return buildEditDiff(oldString, newString, filePath, 1);
|
|
1493
1442
|
}
|
|
1494
1443
|
/**
|