attocode 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -1
- package/dist/src/adapters.d.ts +37 -0
- package/dist/src/adapters.d.ts.map +1 -1
- package/dist/src/adapters.js +146 -19
- package/dist/src/adapters.js.map +1 -1
- package/dist/src/agent/agent-builder.d.ts.map +1 -1
- package/dist/src/agent/agent-builder.js.map +1 -1
- package/dist/src/agent/feature-initializer.d.ts +1 -1
- package/dist/src/agent/feature-initializer.d.ts.map +1 -1
- package/dist/src/agent/feature-initializer.js +40 -41
- package/dist/src/agent/feature-initializer.js.map +1 -1
- package/dist/src/agent/index.d.ts +2 -2
- package/dist/src/agent/index.d.ts.map +1 -1
- package/dist/src/agent/index.js +2 -2
- package/dist/src/agent/index.js.map +1 -1
- package/dist/src/agent/message-builder.d.ts.map +1 -1
- package/dist/src/agent/message-builder.js +8 -5
- package/dist/src/agent/message-builder.js.map +1 -1
- package/dist/src/agent/session-api.d.ts.map +1 -1
- package/dist/src/agent/session-api.js +3 -1
- package/dist/src/agent/session-api.js.map +1 -1
- package/dist/src/agent-tools/lsp-file-tools.d.ts.map +1 -1
- package/dist/src/agent-tools/lsp-file-tools.js +17 -13
- package/dist/src/agent-tools/lsp-file-tools.js.map +1 -1
- package/dist/src/agent.d.ts +12 -2
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +207 -76
- package/dist/src/agent.js.map +1 -1
- package/dist/src/analysis/feedback-loop.d.ts.map +1 -1
- package/dist/src/analysis/feedback-loop.js +13 -9
- package/dist/src/analysis/feedback-loop.js.map +1 -1
- package/dist/src/analysis/index.d.ts +1 -1
- package/dist/src/analysis/index.d.ts.map +1 -1
- package/dist/src/analysis/index.js +1 -1
- package/dist/src/analysis/index.js.map +1 -1
- package/dist/src/analysis/prompt-templates.d.ts.map +1 -1
- package/dist/src/analysis/prompt-templates.js.map +1 -1
- package/dist/src/analysis/trace-summary.d.ts.map +1 -1
- package/dist/src/analysis/trace-summary.js +25 -9
- package/dist/src/analysis/trace-summary.js.map +1 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +3 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/agents-commands.d.ts.map +1 -1
- package/dist/src/commands/agents-commands.js +3 -3
- package/dist/src/commands/agents-commands.js.map +1 -1
- package/dist/src/commands/handler.d.ts.map +1 -1
- package/dist/src/commands/handler.js +60 -37
- package/dist/src/commands/handler.js.map +1 -1
- package/dist/src/commands/init-commands.d.ts.map +1 -1
- package/dist/src/commands/init-commands.js +8 -10
- package/dist/src/commands/init-commands.js.map +1 -1
- package/dist/src/commands/init.js +16 -16
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/skills-commands.d.ts.map +1 -1
- package/dist/src/commands/skills-commands.js +10 -7
- package/dist/src/commands/skills-commands.js.map +1 -1
- package/dist/src/commands/types.d.ts.map +1 -1
- package/dist/src/config/config-manager.d.ts.map +1 -1
- package/dist/src/config/config-manager.js +4 -1
- package/dist/src/config/config-manager.js.map +1 -1
- package/dist/src/config/index.d.ts +1 -1
- package/dist/src/config/index.d.ts.map +1 -1
- package/dist/src/config/schema.d.ts.map +1 -1
- package/dist/src/config/schema.js +6 -2
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/core/agent-state-machine.d.ts.map +1 -1
- package/dist/src/core/agent-state-machine.js +5 -2
- package/dist/src/core/agent-state-machine.js.map +1 -1
- package/dist/src/core/completion-analyzer.d.ts.map +1 -1
- package/dist/src/core/completion-analyzer.js +2 -2
- package/dist/src/core/completion-analyzer.js.map +1 -1
- package/dist/src/core/execution-loop.d.ts +172 -1
- package/dist/src/core/execution-loop.d.ts.map +1 -1
- package/dist/src/core/execution-loop.js +481 -383
- package/dist/src/core/execution-loop.js.map +1 -1
- package/dist/src/core/index.d.ts +2 -2
- package/dist/src/core/index.d.ts.map +1 -1
- package/dist/src/core/index.js +1 -1
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/core/queues/event-queue.d.ts.map +1 -1
- package/dist/src/core/queues/event-queue.js.map +1 -1
- package/dist/src/core/response-handler.d.ts.map +1 -1
- package/dist/src/core/response-handler.js +17 -8
- package/dist/src/core/response-handler.js.map +1 -1
- package/dist/src/core/subagent-spawner.d.ts.map +1 -1
- package/dist/src/core/subagent-spawner.js +85 -53
- package/dist/src/core/subagent-spawner.js.map +1 -1
- package/dist/src/core/tool-executor.d.ts.map +1 -1
- package/dist/src/core/tool-executor.js +56 -25
- package/dist/src/core/tool-executor.js.map +1 -1
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/types.js.map +1 -1
- package/dist/src/costs/model-registry.js +6 -6
- package/dist/src/costs/model-registry.js.map +1 -1
- package/dist/src/defaults.d.ts.map +1 -1
- package/dist/src/defaults.js +67 -20
- package/dist/src/defaults.js.map +1 -1
- package/dist/src/errors/index.d.ts.map +1 -1
- package/dist/src/errors/index.js +6 -8
- package/dist/src/errors/index.js.map +1 -1
- package/dist/src/first-run.d.ts.map +1 -1
- package/dist/src/first-run.js +11 -11
- package/dist/src/first-run.js.map +1 -1
- package/dist/src/integrations/agents/agent-registry.d.ts.map +1 -1
- package/dist/src/integrations/agents/agent-registry.js +16 -16
- package/dist/src/integrations/agents/agent-registry.js.map +1 -1
- package/dist/src/integrations/agents/async-subagent.d.ts.map +1 -1
- package/dist/src/integrations/agents/async-subagent.js +7 -9
- package/dist/src/integrations/agents/async-subagent.js.map +1 -1
- package/dist/src/integrations/agents/complexity-classifier.d.ts.map +1 -1
- package/dist/src/integrations/agents/complexity-classifier.js +46 -15
- package/dist/src/integrations/agents/complexity-classifier.js.map +1 -1
- package/dist/src/integrations/agents/delegation-protocol.d.ts.map +1 -1
- package/dist/src/integrations/agents/delegation-protocol.js +6 -6
- package/dist/src/integrations/agents/delegation-protocol.js.map +1 -1
- package/dist/src/integrations/agents/multi-agent.d.ts.map +1 -1
- package/dist/src/integrations/agents/multi-agent.js +10 -14
- package/dist/src/integrations/agents/multi-agent.js.map +1 -1
- package/dist/src/integrations/agents/result-synthesizer.d.ts.map +1 -1
- package/dist/src/integrations/agents/result-synthesizer.js +8 -6
- package/dist/src/integrations/agents/result-synthesizer.js.map +1 -1
- package/dist/src/integrations/agents/shared-blackboard.d.ts.map +1 -1
- package/dist/src/integrations/agents/shared-blackboard.js.map +1 -1
- package/dist/src/integrations/agents/subagent-output-store.d.ts.map +1 -1
- package/dist/src/integrations/agents/subagent-output-store.js +3 -4
- package/dist/src/integrations/agents/subagent-output-store.js.map +1 -1
- package/dist/src/integrations/budget/budget-pool.d.ts.map +1 -1
- package/dist/src/integrations/budget/budget-pool.js +4 -8
- package/dist/src/integrations/budget/budget-pool.js.map +1 -1
- package/dist/src/integrations/budget/cancellation.d.ts.map +1 -1
- package/dist/src/integrations/budget/cancellation.js +16 -2
- package/dist/src/integrations/budget/cancellation.js.map +1 -1
- package/dist/src/integrations/budget/dynamic-budget.d.ts.map +1 -1
- package/dist/src/integrations/budget/dynamic-budget.js +4 -6
- package/dist/src/integrations/budget/dynamic-budget.js.map +1 -1
- package/dist/src/integrations/budget/economics.d.ts.map +1 -1
- package/dist/src/integrations/budget/economics.js +51 -19
- package/dist/src/integrations/budget/economics.js.map +1 -1
- package/dist/src/integrations/budget/injection-budget.js +1 -1
- package/dist/src/integrations/budget/injection-budget.js.map +1 -1
- package/dist/src/integrations/budget/loop-detector.d.ts.map +1 -1
- package/dist/src/integrations/budget/loop-detector.js +23 -6
- package/dist/src/integrations/budget/loop-detector.js.map +1 -1
- package/dist/src/integrations/budget/phase-tracker.d.ts.map +1 -1
- package/dist/src/integrations/budget/phase-tracker.js +4 -1
- package/dist/src/integrations/budget/phase-tracker.js.map +1 -1
- package/dist/src/integrations/budget/resources.d.ts.map +1 -1
- package/dist/src/integrations/budget/resources.js +54 -10
- package/dist/src/integrations/budget/resources.js.map +1 -1
- package/dist/src/integrations/context/auto-compaction.d.ts.map +1 -1
- package/dist/src/integrations/context/auto-compaction.js +16 -8
- package/dist/src/integrations/context/auto-compaction.js.map +1 -1
- package/dist/src/integrations/context/code-analyzer.d.ts.map +1 -1
- package/dist/src/integrations/context/code-analyzer.js +17 -20
- package/dist/src/integrations/context/code-analyzer.js.map +1 -1
- package/dist/src/integrations/context/code-selector.d.ts.map +1 -1
- package/dist/src/integrations/context/code-selector.js +42 -23
- package/dist/src/integrations/context/code-selector.js.map +1 -1
- package/dist/src/integrations/context/codebase-ast.d.ts.map +1 -1
- package/dist/src/integrations/context/codebase-ast.js +121 -58
- package/dist/src/integrations/context/codebase-ast.js.map +1 -1
- package/dist/src/integrations/context/codebase-context.d.ts.map +1 -1
- package/dist/src/integrations/context/codebase-context.js +26 -17
- package/dist/src/integrations/context/codebase-context.js.map +1 -1
- package/dist/src/integrations/context/compaction.d.ts.map +1 -1
- package/dist/src/integrations/context/compaction.js +27 -20
- package/dist/src/integrations/context/compaction.js.map +1 -1
- package/dist/src/integrations/context/context-engineering.d.ts.map +1 -1
- package/dist/src/integrations/context/context-engineering.js.map +1 -1
- package/dist/src/integrations/context/semantic-cache.d.ts.map +1 -1
- package/dist/src/integrations/context/semantic-cache.js +6 -1
- package/dist/src/integrations/context/semantic-cache.js.map +1 -1
- package/dist/src/integrations/index.d.ts +2 -2
- package/dist/src/integrations/index.d.ts.map +1 -1
- package/dist/src/integrations/index.js +2 -2
- package/dist/src/integrations/index.js.map +1 -1
- package/dist/src/integrations/mcp/mcp-client.d.ts.map +1 -1
- package/dist/src/integrations/mcp/mcp-client.js +48 -27
- package/dist/src/integrations/mcp/mcp-client.js.map +1 -1
- package/dist/src/integrations/mcp/mcp-custom-tools.d.ts.map +1 -1
- package/dist/src/integrations/mcp/mcp-custom-tools.js +2 -2
- package/dist/src/integrations/mcp/mcp-custom-tools.js.map +1 -1
- package/dist/src/integrations/mcp/mcp-tool-search.d.ts.map +1 -1
- package/dist/src/integrations/mcp/mcp-tool-search.js +8 -8
- package/dist/src/integrations/mcp/mcp-tool-search.js.map +1 -1
- package/dist/src/integrations/mcp/mcp-tool-validator.d.ts.map +1 -1
- package/dist/src/integrations/mcp/mcp-tool-validator.js +5 -7
- package/dist/src/integrations/mcp/mcp-tool-validator.js.map +1 -1
- package/dist/src/integrations/persistence/codebase-repository.d.ts.map +1 -1
- package/dist/src/integrations/persistence/codebase-repository.js +6 -2
- package/dist/src/integrations/persistence/codebase-repository.js.map +1 -1
- package/dist/src/integrations/persistence/goal-repository.d.ts.map +1 -1
- package/dist/src/integrations/persistence/goal-repository.js +8 -5
- package/dist/src/integrations/persistence/goal-repository.js.map +1 -1
- package/dist/src/integrations/persistence/history.d.ts.map +1 -1
- package/dist/src/integrations/persistence/history.js +2 -4
- package/dist/src/integrations/persistence/history.js.map +1 -1
- package/dist/src/integrations/persistence/persistence.d.ts.map +1 -1
- package/dist/src/integrations/persistence/persistence.js +6 -3
- package/dist/src/integrations/persistence/persistence.js.map +1 -1
- package/dist/src/integrations/persistence/session-repository.d.ts.map +1 -1
- package/dist/src/integrations/persistence/session-repository.js +39 -28
- package/dist/src/integrations/persistence/session-repository.js.map +1 -1
- package/dist/src/integrations/persistence/session-store.d.ts.map +1 -1
- package/dist/src/integrations/persistence/session-store.js +4 -4
- package/dist/src/integrations/persistence/session-store.js.map +1 -1
- package/dist/src/integrations/persistence/sqlite-store.d.ts.map +1 -1
- package/dist/src/integrations/persistence/sqlite-store.js +6 -2
- package/dist/src/integrations/persistence/sqlite-store.js.map +1 -1
- package/dist/src/integrations/persistence/worker-repository.d.ts.map +1 -1
- package/dist/src/integrations/persistence/worker-repository.js +1 -3
- package/dist/src/integrations/persistence/worker-repository.js.map +1 -1
- package/dist/src/integrations/quality/auto-checkpoint.d.ts.map +1 -1
- package/dist/src/integrations/quality/auto-checkpoint.js +3 -5
- package/dist/src/integrations/quality/auto-checkpoint.js.map +1 -1
- package/dist/src/integrations/quality/dead-letter-queue.d.ts.map +1 -1
- package/dist/src/integrations/quality/dead-letter-queue.js +14 -8
- package/dist/src/integrations/quality/dead-letter-queue.js.map +1 -1
- package/dist/src/integrations/quality/health-check.d.ts.map +1 -1
- package/dist/src/integrations/quality/health-check.js +14 -11
- package/dist/src/integrations/quality/health-check.js.map +1 -1
- package/dist/src/integrations/quality/learning-store.d.ts.map +1 -1
- package/dist/src/integrations/quality/learning-store.js +108 -31
- package/dist/src/integrations/quality/learning-store.js.map +1 -1
- package/dist/src/integrations/quality/self-improvement.d.ts.map +1 -1
- package/dist/src/integrations/quality/self-improvement.js +1 -1
- package/dist/src/integrations/quality/self-improvement.js.map +1 -1
- package/dist/src/integrations/quality/tool-recommendation.d.ts.map +1 -1
- package/dist/src/integrations/quality/tool-recommendation.js +40 -10
- package/dist/src/integrations/quality/tool-recommendation.js.map +1 -1
- package/dist/src/integrations/safety/bash-policy.d.ts.map +1 -1
- package/dist/src/integrations/safety/bash-policy.js +8 -5
- package/dist/src/integrations/safety/bash-policy.js.map +1 -1
- package/dist/src/integrations/safety/execution-policy.d.ts.map +1 -1
- package/dist/src/integrations/safety/execution-policy.js +15 -5
- package/dist/src/integrations/safety/execution-policy.js.map +1 -1
- package/dist/src/integrations/safety/policy-engine.d.ts.map +1 -1
- package/dist/src/integrations/safety/policy-engine.js +51 -11
- package/dist/src/integrations/safety/policy-engine.js.map +1 -1
- package/dist/src/integrations/safety/safety.d.ts.map +1 -1
- package/dist/src/integrations/safety/safety.js +18 -15
- package/dist/src/integrations/safety/safety.js.map +1 -1
- package/dist/src/integrations/safety/sandbox/basic.d.ts.map +1 -1
- package/dist/src/integrations/safety/sandbox/basic.js +1 -3
- package/dist/src/integrations/safety/sandbox/basic.js.map +1 -1
- package/dist/src/integrations/safety/sandbox/docker.d.ts.map +1 -1
- package/dist/src/integrations/safety/sandbox/docker.js.map +1 -1
- package/dist/src/integrations/safety/sandbox/index.d.ts.map +1 -1
- package/dist/src/integrations/safety/sandbox/index.js +28 -4
- package/dist/src/integrations/safety/sandbox/index.js.map +1 -1
- package/dist/src/integrations/safety/sandbox/landlock.d.ts.map +1 -1
- package/dist/src/integrations/safety/sandbox/landlock.js +7 -3
- package/dist/src/integrations/safety/sandbox/landlock.js.map +1 -1
- package/dist/src/integrations/safety/sandbox/seatbelt.d.ts.map +1 -1
- package/dist/src/integrations/safety/sandbox/seatbelt.js +4 -11
- package/dist/src/integrations/safety/sandbox/seatbelt.js.map +1 -1
- package/dist/src/integrations/safety/type-checker.d.ts.map +1 -1
- package/dist/src/integrations/safety/type-checker.js +6 -2
- package/dist/src/integrations/safety/type-checker.js.map +1 -1
- package/dist/src/integrations/skills/skill-executor.d.ts.map +1 -1
- package/dist/src/integrations/skills/skill-executor.js +3 -7
- package/dist/src/integrations/skills/skill-executor.js.map +1 -1
- package/dist/src/integrations/skills/skills.d.ts.map +1 -1
- package/dist/src/integrations/skills/skills.js +24 -15
- package/dist/src/integrations/skills/skills.js.map +1 -1
- package/dist/src/integrations/streaming/pty-shell.d.ts.map +1 -1
- package/dist/src/integrations/streaming/pty-shell.js +5 -1
- package/dist/src/integrations/streaming/pty-shell.js.map +1 -1
- package/dist/src/integrations/streaming/streaming.d.ts.map +1 -1
- package/dist/src/integrations/streaming/streaming.js +7 -5
- package/dist/src/integrations/streaming/streaming.js.map +1 -1
- package/dist/src/integrations/swarm/failure-classifier.d.ts.map +1 -1
- package/dist/src/integrations/swarm/failure-classifier.js +18 -3
- package/dist/src/integrations/swarm/failure-classifier.js.map +1 -1
- package/dist/src/integrations/swarm/index.d.ts +5 -5
- package/dist/src/integrations/swarm/index.d.ts.map +1 -1
- package/dist/src/integrations/swarm/index.js +4 -4
- package/dist/src/integrations/swarm/index.js.map +1 -1
- package/dist/src/integrations/swarm/model-selector.d.ts.map +1 -1
- package/dist/src/integrations/swarm/model-selector.js +20 -23
- package/dist/src/integrations/swarm/model-selector.js.map +1 -1
- package/dist/src/integrations/swarm/request-throttle.d.ts.map +1 -1
- package/dist/src/integrations/swarm/request-throttle.js +7 -4
- package/dist/src/integrations/swarm/request-throttle.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-budget.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-budget.js +1 -1
- package/dist/src/integrations/swarm/swarm-budget.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-config-loader.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-config-loader.js +46 -17
- package/dist/src/integrations/swarm/swarm-config-loader.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-event-bridge.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-event-bridge.js +69 -23
- package/dist/src/integrations/swarm/swarm-event-bridge.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-events.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-events.js +1 -1
- package/dist/src/integrations/swarm/swarm-events.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-execution.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-execution.js +96 -46
- package/dist/src/integrations/swarm/swarm-execution.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-helpers.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-helpers.js +25 -12
- package/dist/src/integrations/swarm/swarm-helpers.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-lifecycle.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-lifecycle.js +102 -47
- package/dist/src/integrations/swarm/swarm-lifecycle.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-orchestrator.d.ts +1 -1
- package/dist/src/integrations/swarm/swarm-orchestrator.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-orchestrator.js +97 -39
- package/dist/src/integrations/swarm/swarm-orchestrator.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-quality-gate.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-quality-gate.js +18 -14
- package/dist/src/integrations/swarm/swarm-quality-gate.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-recovery.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-recovery.js +42 -29
- package/dist/src/integrations/swarm/swarm-recovery.js.map +1 -1
- package/dist/src/integrations/swarm/swarm-state-store.d.ts.map +1 -1
- package/dist/src/integrations/swarm/swarm-state-store.js +4 -2
- package/dist/src/integrations/swarm/swarm-state-store.js.map +1 -1
- package/dist/src/integrations/swarm/task-queue.d.ts +7 -1
- package/dist/src/integrations/swarm/task-queue.d.ts.map +1 -1
- package/dist/src/integrations/swarm/task-queue.js +32 -25
- package/dist/src/integrations/swarm/task-queue.js.map +1 -1
- package/dist/src/integrations/swarm/types.d.ts.map +1 -1
- package/dist/src/integrations/swarm/types.js +89 -12
- package/dist/src/integrations/swarm/types.js.map +1 -1
- package/dist/src/integrations/swarm/worker-pool.d.ts.map +1 -1
- package/dist/src/integrations/swarm/worker-pool.js +32 -24
- package/dist/src/integrations/swarm/worker-pool.js.map +1 -1
- package/dist/src/integrations/tasks/dependency-analyzer.d.ts.map +1 -1
- package/dist/src/integrations/tasks/dependency-analyzer.js +1 -2
- package/dist/src/integrations/tasks/dependency-analyzer.js.map +1 -1
- package/dist/src/integrations/tasks/interactive-planning.d.ts.map +1 -1
- package/dist/src/integrations/tasks/interactive-planning.js +2 -9
- package/dist/src/integrations/tasks/interactive-planning.js.map +1 -1
- package/dist/src/integrations/tasks/pending-plan.d.ts.map +1 -1
- package/dist/src/integrations/tasks/pending-plan.js +16 -16
- package/dist/src/integrations/tasks/pending-plan.js.map +1 -1
- package/dist/src/integrations/tasks/planning.d.ts.map +1 -1
- package/dist/src/integrations/tasks/planning.js +42 -23
- package/dist/src/integrations/tasks/planning.js.map +1 -1
- package/dist/src/integrations/tasks/smart-decomposer.d.ts.map +1 -1
- package/dist/src/integrations/tasks/smart-decomposer.js +17 -10
- package/dist/src/integrations/tasks/smart-decomposer.js.map +1 -1
- package/dist/src/integrations/tasks/task-manager.d.ts.map +1 -1
- package/dist/src/integrations/tasks/task-manager.js +25 -18
- package/dist/src/integrations/tasks/task-manager.js.map +1 -1
- package/dist/src/integrations/tasks/task-splitter.d.ts.map +1 -1
- package/dist/src/integrations/tasks/task-splitter.js +21 -16
- package/dist/src/integrations/tasks/task-splitter.js.map +1 -1
- package/dist/src/integrations/tasks/verification-gate.d.ts.map +1 -1
- package/dist/src/integrations/tasks/verification-gate.js +4 -2
- package/dist/src/integrations/tasks/verification-gate.js.map +1 -1
- package/dist/src/integrations/tasks/work-log.d.ts.map +1 -1
- package/dist/src/integrations/tasks/work-log.js +22 -10
- package/dist/src/integrations/tasks/work-log.js.map +1 -1
- package/dist/src/integrations/utilities/capabilities.d.ts.map +1 -1
- package/dist/src/integrations/utilities/capabilities.js +46 -8
- package/dist/src/integrations/utilities/capabilities.js.map +1 -1
- package/dist/src/integrations/utilities/diff-utils.d.ts.map +1 -1
- package/dist/src/integrations/utilities/diff-utils.js +6 -7
- package/dist/src/integrations/utilities/diff-utils.js.map +1 -1
- package/dist/src/integrations/utilities/environment-facts.d.ts.map +1 -1
- package/dist/src/integrations/utilities/environment-facts.js +12 -2
- package/dist/src/integrations/utilities/environment-facts.js.map +1 -1
- package/dist/src/integrations/utilities/file-change-tracker.d.ts.map +1 -1
- package/dist/src/integrations/utilities/file-change-tracker.js +7 -8
- package/dist/src/integrations/utilities/file-change-tracker.js.map +1 -1
- package/dist/src/integrations/utilities/graph-visualization.d.ts.map +1 -1
- package/dist/src/integrations/utilities/graph-visualization.js +8 -6
- package/dist/src/integrations/utilities/graph-visualization.js.map +1 -1
- package/dist/src/integrations/utilities/hierarchical-config.d.ts.map +1 -1
- package/dist/src/integrations/utilities/hierarchical-config.js +5 -1
- package/dist/src/integrations/utilities/hierarchical-config.js.map +1 -1
- package/dist/src/integrations/utilities/hooks.d.ts.map +1 -1
- package/dist/src/integrations/utilities/hooks.js +3 -3
- package/dist/src/integrations/utilities/hooks.js.map +1 -1
- package/dist/src/integrations/utilities/ignore.js +1 -1
- package/dist/src/integrations/utilities/ignore.js.map +1 -1
- package/dist/src/integrations/utilities/image-renderer.d.ts.map +1 -1
- package/dist/src/integrations/utilities/image-renderer.js +4 -9
- package/dist/src/integrations/utilities/image-renderer.js.map +1 -1
- package/dist/src/integrations/utilities/logger.d.ts.map +1 -1
- package/dist/src/integrations/utilities/logger.js +1 -3
- package/dist/src/integrations/utilities/logger.js.map +1 -1
- package/dist/src/integrations/utilities/memory.d.ts.map +1 -1
- package/dist/src/integrations/utilities/memory.js +1 -3
- package/dist/src/integrations/utilities/memory.js.map +1 -1
- package/dist/src/integrations/utilities/observability.d.ts.map +1 -1
- package/dist/src/integrations/utilities/observability.js +2 -1
- package/dist/src/integrations/utilities/observability.js.map +1 -1
- package/dist/src/integrations/utilities/openrouter-pricing.d.ts.map +1 -1
- package/dist/src/integrations/utilities/openrouter-pricing.js +3 -3
- package/dist/src/integrations/utilities/openrouter-pricing.js.map +1 -1
- package/dist/src/integrations/utilities/react.d.ts.map +1 -1
- package/dist/src/integrations/utilities/react.js +5 -9
- package/dist/src/integrations/utilities/react.js.map +1 -1
- package/dist/src/integrations/utilities/retry.d.ts.map +1 -1
- package/dist/src/integrations/utilities/retry.js +1 -1
- package/dist/src/integrations/utilities/retry.js.map +1 -1
- package/dist/src/integrations/utilities/routing.d.ts.map +1 -1
- package/dist/src/integrations/utilities/routing.js +16 -4
- package/dist/src/integrations/utilities/routing.js.map +1 -1
- package/dist/src/integrations/utilities/rules.d.ts.map +1 -1
- package/dist/src/integrations/utilities/rules.js +4 -6
- package/dist/src/integrations/utilities/rules.js.map +1 -1
- package/dist/src/integrations/utilities/sourcegraph.d.ts.map +1 -1
- package/dist/src/integrations/utilities/sourcegraph.js +3 -5
- package/dist/src/integrations/utilities/sourcegraph.js.map +1 -1
- package/dist/src/integrations/utilities/thinking-strategy.d.ts.map +1 -1
- package/dist/src/integrations/utilities/thinking-strategy.js.map +1 -1
- package/dist/src/integrations/utilities/thread-manager.d.ts.map +1 -1
- package/dist/src/integrations/utilities/thread-manager.js +8 -6
- package/dist/src/integrations/utilities/thread-manager.js.map +1 -1
- package/dist/src/integrations/utilities/token-estimate.d.ts +5 -0
- package/dist/src/integrations/utilities/token-estimate.d.ts.map +1 -1
- package/dist/src/integrations/utilities/token-estimate.js +7 -1
- package/dist/src/integrations/utilities/token-estimate.js.map +1 -1
- package/dist/src/main.js +41 -24
- package/dist/src/main.js.map +1 -1
- package/dist/src/modes/repl.d.ts.map +1 -1
- package/dist/src/modes/repl.js +51 -17
- package/dist/src/modes/repl.js.map +1 -1
- package/dist/src/modes/tui.d.ts.map +1 -1
- package/dist/src/modes/tui.js +70 -10
- package/dist/src/modes/tui.js.map +1 -1
- package/dist/src/modes.d.ts.map +1 -1
- package/dist/src/modes.js +13 -13
- package/dist/src/modes.js.map +1 -1
- package/dist/src/observability/tracer.d.ts.map +1 -1
- package/dist/src/observability/tracer.js +7 -3
- package/dist/src/observability/tracer.js.map +1 -1
- package/dist/src/observability/types.d.ts.map +1 -1
- package/dist/src/observability/types.js.map +1 -1
- package/dist/src/paths.d.ts.map +1 -1
- package/dist/src/paths.js +2 -6
- package/dist/src/paths.js.map +1 -1
- package/dist/src/persistence/migrator.d.ts.map +1 -1
- package/dist/src/persistence/migrator.js +7 -7
- package/dist/src/persistence/migrator.js.map +1 -1
- package/dist/src/providers/adapters/anthropic.d.ts.map +1 -1
- package/dist/src/providers/adapters/anthropic.js +50 -38
- package/dist/src/providers/adapters/anthropic.js.map +1 -1
- package/dist/src/providers/adapters/azure.d.ts.map +1 -1
- package/dist/src/providers/adapters/azure.js +31 -16
- package/dist/src/providers/adapters/azure.js.map +1 -1
- package/dist/src/providers/adapters/mock.d.ts.map +1 -1
- package/dist/src/providers/adapters/mock.js +9 -9
- package/dist/src/providers/adapters/mock.js.map +1 -1
- package/dist/src/providers/adapters/openai.d.ts.map +1 -1
- package/dist/src/providers/adapters/openai.js +22 -15
- package/dist/src/providers/adapters/openai.js.map +1 -1
- package/dist/src/providers/adapters/openrouter.d.ts.map +1 -1
- package/dist/src/providers/adapters/openrouter.js +60 -33
- package/dist/src/providers/adapters/openrouter.js.map +1 -1
- package/dist/src/providers/circuit-breaker.d.ts.map +1 -1
- package/dist/src/providers/circuit-breaker.js +4 -3
- package/dist/src/providers/circuit-breaker.js.map +1 -1
- package/dist/src/providers/fallback-chain.d.ts.map +1 -1
- package/dist/src/providers/fallback-chain.js +3 -3
- package/dist/src/providers/fallback-chain.js.map +1 -1
- package/dist/src/providers/llm-resilience.d.ts.map +1 -1
- package/dist/src/providers/llm-resilience.js +2 -2
- package/dist/src/providers/llm-resilience.js.map +1 -1
- package/dist/src/providers/provider.d.ts.map +1 -1
- package/dist/src/providers/provider.js +1 -2
- package/dist/src/providers/provider.js.map +1 -1
- package/dist/src/providers/resilient-fetch.d.ts.map +1 -1
- package/dist/src/providers/resilient-fetch.js +3 -4
- package/dist/src/providers/resilient-fetch.js.map +1 -1
- package/dist/src/providers/resilient-provider.d.ts.map +1 -1
- package/dist/src/providers/resilient-provider.js +8 -5
- package/dist/src/providers/resilient-provider.js.map +1 -1
- package/dist/src/session-picker.d.ts.map +1 -1
- package/dist/src/session-picker.js +9 -5
- package/dist/src/session-picker.js.map +1 -1
- package/dist/src/shared/budget-tracker.d.ts.map +1 -1
- package/dist/src/shared/budget-tracker.js +1 -1
- package/dist/src/shared/budget-tracker.js.map +1 -1
- package/dist/src/shared/context-engine.d.ts.map +1 -1
- package/dist/src/shared/context-engine.js +1 -1
- package/dist/src/shared/context-engine.js.map +1 -1
- package/dist/src/shared/persistence.d.ts.map +1 -1
- package/dist/src/shared/persistence.js +2 -6
- package/dist/src/shared/persistence.js.map +1 -1
- package/dist/src/shared/shared-context-state.d.ts.map +1 -1
- package/dist/src/shared/shared-context-state.js.map +1 -1
- package/dist/src/shared/shared-economics-state.d.ts.map +1 -1
- package/dist/src/shared/shared-economics-state.js.map +1 -1
- package/dist/src/tools/agent.d.ts +1 -1
- package/dist/src/tools/agent.d.ts.map +1 -1
- package/dist/src/tools/agent.js +10 -7
- package/dist/src/tools/agent.js.map +1 -1
- package/dist/src/tools/bash.d.ts.map +1 -1
- package/dist/src/tools/bash.js.map +1 -1
- package/dist/src/tools/coercion.js +1 -1
- package/dist/src/tools/coercion.js.map +1 -1
- package/dist/src/tools/file.d.ts.map +1 -1
- package/dist/src/tools/file.js +1 -1
- package/dist/src/tools/file.js.map +1 -1
- package/dist/src/tools/permission.js +5 -6
- package/dist/src/tools/permission.js.map +1 -1
- package/dist/src/tools/registry.d.ts.map +1 -1
- package/dist/src/tools/registry.js +3 -5
- package/dist/src/tools/registry.js.map +1 -1
- package/dist/src/tools/standard.d.ts.map +1 -1
- package/dist/src/tools/standard.js +1 -3
- package/dist/src/tools/standard.js.map +1 -1
- package/dist/src/tools/tasks.d.ts.map +1 -1
- package/dist/src/tools/tasks.js +4 -4
- package/dist/src/tools/tasks.js.map +1 -1
- package/dist/src/tools/types.d.ts.map +1 -1
- package/dist/src/tools/types.js +5 -1
- package/dist/src/tools/types.js.map +1 -1
- package/dist/src/tools/undo.d.ts.map +1 -1
- package/dist/src/tools/undo.js +4 -2
- package/dist/src/tools/undo.js.map +1 -1
- package/dist/src/tracing/cache-boundary-tracker.d.ts.map +1 -1
- package/dist/src/tracing/cache-boundary-tracker.js +7 -11
- package/dist/src/tracing/cache-boundary-tracker.js.map +1 -1
- package/dist/src/tracing/trace-collector.d.ts.map +1 -1
- package/dist/src/tracing/trace-collector.js +28 -28
- package/dist/src/tracing/trace-collector.js.map +1 -1
- package/dist/src/tracing/types.d.ts.map +1 -1
- package/dist/src/tracing/types.js.map +1 -1
- package/dist/src/tricks/failure-evidence.d.ts.map +1 -1
- package/dist/src/tricks/failure-evidence.js +16 -26
- package/dist/src/tricks/failure-evidence.js.map +1 -1
- package/dist/src/tricks/json-utils.d.ts.map +1 -1
- package/dist/src/tricks/json-utils.js +1 -4
- package/dist/src/tricks/json-utils.js.map +1 -1
- package/dist/src/tricks/kv-cache-context.d.ts.map +1 -1
- package/dist/src/tricks/kv-cache-context.js +2 -3
- package/dist/src/tricks/kv-cache-context.js.map +1 -1
- package/dist/src/tricks/recitation.d.ts.map +1 -1
- package/dist/src/tricks/recitation.js +22 -18
- package/dist/src/tricks/recitation.js.map +1 -1
- package/dist/src/tricks/recursive-context.d.ts.map +1 -1
- package/dist/src/tricks/recursive-context.js +8 -5
- package/dist/src/tricks/recursive-context.js.map +1 -1
- package/dist/src/tricks/reversible-compaction.d.ts.map +1 -1
- package/dist/src/tricks/reversible-compaction.js +11 -7
- package/dist/src/tricks/reversible-compaction.js.map +1 -1
- package/dist/src/tricks/serialization-diversity.d.ts.map +1 -1
- package/dist/src/tricks/serialization-diversity.js +12 -12
- package/dist/src/tricks/serialization-diversity.js.map +1 -1
- package/dist/src/tui/app.d.ts +6 -2
- package/dist/src/tui/app.d.ts.map +1 -1
- package/dist/src/tui/app.js +636 -583
- package/dist/src/tui/app.js.map +1 -1
- package/dist/src/tui/components/ActiveAgentsPanel.d.ts +2 -0
- package/dist/src/tui/components/ActiveAgentsPanel.d.ts.map +1 -1
- package/dist/src/tui/components/ActiveAgentsPanel.js +5 -5
- package/dist/src/tui/components/ActiveAgentsPanel.js.map +1 -1
- package/dist/src/tui/components/ApprovalDialog.d.ts.map +1 -1
- package/dist/src/tui/components/ApprovalDialog.js +14 -0
- package/dist/src/tui/components/ApprovalDialog.js.map +1 -1
- package/dist/src/tui/components/BudgetExtensionDialog.d.ts +18 -0
- package/dist/src/tui/components/BudgetExtensionDialog.d.ts.map +1 -0
- package/dist/src/tui/components/BudgetExtensionDialog.js +40 -0
- package/dist/src/tui/components/BudgetExtensionDialog.js.map +1 -0
- package/dist/src/tui/components/CollapsibleDiffView.d.ts.map +1 -1
- package/dist/src/tui/components/CollapsibleDiffView.js +18 -13
- package/dist/src/tui/components/CollapsibleDiffView.js.map +1 -1
- package/dist/src/tui/components/DebugPanel.d.ts.map +1 -1
- package/dist/src/tui/components/DebugPanel.js +46 -26
- package/dist/src/tui/components/DebugPanel.js.map +1 -1
- package/dist/src/tui/components/DiagnosticsPanel.d.ts.map +1 -1
- package/dist/src/tui/components/DiagnosticsPanel.js +18 -2
- package/dist/src/tui/components/DiagnosticsPanel.js.map +1 -1
- package/dist/src/tui/components/DiffView.d.ts.map +1 -1
- package/dist/src/tui/components/DiffView.js +21 -14
- package/dist/src/tui/components/DiffView.js.map +1 -1
- package/dist/src/tui/components/ErrorBoundary.d.ts.map +1 -1
- package/dist/src/tui/components/ErrorBoundary.js +7 -2
- package/dist/src/tui/components/ErrorBoundary.js.map +1 -1
- package/dist/src/tui/components/ErrorDetailPanel.d.ts.map +1 -1
- package/dist/src/tui/components/ErrorDetailPanel.js +4 -4
- package/dist/src/tui/components/ErrorDetailPanel.js.map +1 -1
- package/dist/src/tui/components/FileChangeSummary.d.ts.map +1 -1
- package/dist/src/tui/components/FileChangeSummary.js +3 -3
- package/dist/src/tui/components/FileChangeSummary.js.map +1 -1
- package/dist/src/tui/components/InputArea.d.ts.map +1 -1
- package/dist/src/tui/components/InputArea.js +32 -15
- package/dist/src/tui/components/InputArea.js.map +1 -1
- package/dist/src/tui/components/LearningValidationDialog.d.ts +25 -0
- package/dist/src/tui/components/LearningValidationDialog.d.ts.map +1 -0
- package/dist/src/tui/components/LearningValidationDialog.js +35 -0
- package/dist/src/tui/components/LearningValidationDialog.js.map +1 -0
- package/dist/src/tui/components/MessageItem.d.ts.map +1 -1
- package/dist/src/tui/components/MessageItem.js.map +1 -1
- package/dist/src/tui/components/PlanPanel.d.ts +27 -0
- package/dist/src/tui/components/PlanPanel.d.ts.map +1 -0
- package/dist/src/tui/components/PlanPanel.js +45 -0
- package/dist/src/tui/components/PlanPanel.js.map +1 -0
- package/dist/src/tui/components/ScrollableBox.d.ts.map +1 -1
- package/dist/src/tui/components/ScrollableBox.js +2 -2
- package/dist/src/tui/components/ScrollableBox.js.map +1 -1
- package/dist/src/tui/components/SideBySideDiff.d.ts.map +1 -1
- package/dist/src/tui/components/SideBySideDiff.js +20 -18
- package/dist/src/tui/components/SideBySideDiff.js.map +1 -1
- package/dist/src/tui/components/StatusBar.d.ts +41 -0
- package/dist/src/tui/components/StatusBar.d.ts.map +1 -0
- package/dist/src/tui/components/StatusBar.js +114 -0
- package/dist/src/tui/components/StatusBar.js.map +1 -0
- package/dist/src/tui/components/SwarmStatusPanel.d.ts.map +1 -1
- package/dist/src/tui/components/SwarmStatusPanel.js +25 -17
- package/dist/src/tui/components/SwarmStatusPanel.js.map +1 -1
- package/dist/src/tui/components/TasksPanel.d.ts.map +1 -1
- package/dist/src/tui/components/TasksPanel.js +12 -11
- package/dist/src/tui/components/TasksPanel.js.map +1 -1
- package/dist/src/tui/components/ToolCallItem.d.ts.map +1 -1
- package/dist/src/tui/components/ToolCallItem.js +19 -6
- package/dist/src/tui/components/ToolCallItem.js.map +1 -1
- package/dist/src/tui/components/ToolCallsPanel.d.ts +15 -0
- package/dist/src/tui/components/ToolCallsPanel.d.ts.map +1 -0
- package/dist/src/tui/components/ToolCallsPanel.js +34 -0
- package/dist/src/tui/components/ToolCallsPanel.js.map +1 -0
- package/dist/src/tui/components/TransparencyPanel.d.ts +15 -0
- package/dist/src/tui/components/TransparencyPanel.d.ts.map +1 -0
- package/dist/src/tui/components/TransparencyPanel.js +46 -0
- package/dist/src/tui/components/TransparencyPanel.js.map +1 -0
- package/dist/src/tui/components/index.d.ts +8 -2
- package/dist/src/tui/components/index.d.ts.map +1 -1
- package/dist/src/tui/components/index.js +14 -2
- package/dist/src/tui/components/index.js.map +1 -1
- package/dist/src/tui/event-display.d.ts.map +1 -1
- package/dist/src/tui/event-display.js +12 -3
- package/dist/src/tui/event-display.js.map +1 -1
- package/dist/src/tui/hooks/index.d.ts +1 -0
- package/dist/src/tui/hooks/index.d.ts.map +1 -1
- package/dist/src/tui/hooks/index.js +1 -0
- package/dist/src/tui/hooks/index.js.map +1 -1
- package/dist/src/tui/hooks/use-agent-events.d.ts +53 -0
- package/dist/src/tui/hooks/use-agent-events.d.ts.map +1 -0
- package/dist/src/tui/hooks/use-agent-events.js +444 -0
- package/dist/src/tui/hooks/use-agent-events.js.map +1 -0
- package/dist/src/tui/hooks/use-throttled-state.d.ts +18 -0
- package/dist/src/tui/hooks/use-throttled-state.d.ts.map +1 -0
- package/dist/src/tui/hooks/use-throttled-state.js +93 -0
- package/dist/src/tui/hooks/use-throttled-state.js.map +1 -0
- package/dist/src/tui/hooks/useMessagePruning.d.ts.map +1 -1
- package/dist/src/tui/hooks/useMessagePruning.js.map +1 -1
- package/dist/src/tui/index.d.ts +2 -2
- package/dist/src/tui/index.d.ts.map +1 -1
- package/dist/src/tui/index.js +101 -6
- package/dist/src/tui/index.js.map +1 -1
- package/dist/src/tui/input/CommandPalette.d.ts.map +1 -1
- package/dist/src/tui/input/CommandPalette.js +2 -2
- package/dist/src/tui/input/CommandPalette.js.map +1 -1
- package/dist/src/tui/input/index.d.ts +1 -1
- package/dist/src/tui/input/index.d.ts.map +1 -1
- package/dist/src/tui/input/index.js +1 -1
- package/dist/src/tui/input/index.js.map +1 -1
- package/dist/src/tui/syntax/languages/bash.js +94 -16
- package/dist/src/tui/syntax/languages/bash.js.map +1 -1
- package/dist/src/tui/syntax/languages/javascript.js +65 -12
- package/dist/src/tui/syntax/languages/javascript.js.map +1 -1
- package/dist/src/tui/syntax/languages/json.js.map +1 -1
- package/dist/src/tui/syntax/languages/python.js +81 -15
- package/dist/src/tui/syntax/languages/python.js.map +1 -1
- package/dist/src/tui/theme/index.js.map +1 -1
- package/dist/src/tui/transparency-aggregator.d.ts.map +1 -1
- package/dist/src/tui/transparency-aggregator.js +18 -4
- package/dist/src/tui/transparency-aggregator.js.map +1 -1
- package/dist/src/tui/types.d.ts.map +1 -1
- package/dist/src/tui/types.js.map +1 -1
- package/dist/src/tui/utils/keyboard.d.ts.map +1 -1
- package/dist/src/tui/utils/keyboard.js.map +1 -1
- package/dist/src/types.d.ts +12 -0
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* resilience handling, tool execution, and compaction.
|
|
9
9
|
*/
|
|
10
10
|
import { isFeatureEnabled } from '../defaults.js';
|
|
11
|
-
import { estimateTokenCount } from '../integrations/utilities/token-estimate.js';
|
|
11
|
+
import { estimateTokenCount, estimateTokensFromCharCount } from '../integrations/utilities/token-estimate.js';
|
|
12
12
|
import { callLLM } from './response-handler.js';
|
|
13
13
|
import { executeToolCalls } from './tool-executor.js';
|
|
14
14
|
import { TIMEOUT_WRAPUP_PROMPT, stableStringify, } from '../integrations/index.js';
|
|
@@ -21,11 +21,30 @@ import { invalidateAST } from '../integrations/context/codebase-ast.js';
|
|
|
21
21
|
import * as fs from 'node:fs';
|
|
22
22
|
const log = createComponentLogger('ExecutionLoop');
|
|
23
23
|
// =============================================================================
|
|
24
|
+
// EXECUTION LOOP DEFAULTS
|
|
25
|
+
// =============================================================================
|
|
26
|
+
export const EXECUTION_LOOP_DEFAULTS = {
|
|
27
|
+
/** Preview length when compacting long tool outputs */
|
|
28
|
+
COMPACT_PREVIEW_LENGTH: 200,
|
|
29
|
+
/** Max expensive results preserved from compaction */
|
|
30
|
+
MAX_PRESERVED_EXPENSIVE_RESULTS: 6,
|
|
31
|
+
/** Messages to keep during emergency truncation */
|
|
32
|
+
PRESERVE_RECENT: 10,
|
|
33
|
+
/** Max chars per tool output before truncation */
|
|
34
|
+
MAX_TOOL_OUTPUT_CHARS: 8000,
|
|
35
|
+
/** Number of TS edits before triggering a type check */
|
|
36
|
+
TYPE_CHECK_EDIT_THRESHOLD: 5,
|
|
37
|
+
/** Safety margin ratio for context overflow guard */
|
|
38
|
+
CONTEXT_SAFETY_RATIO: 0.9,
|
|
39
|
+
/** Per-result budget safety margin */
|
|
40
|
+
PER_RESULT_BUDGET_RATIO: 0.95,
|
|
41
|
+
};
|
|
42
|
+
// =============================================================================
|
|
24
43
|
// HELPER FUNCTIONS (extracted from ProductionAgent private methods)
|
|
25
44
|
// =============================================================================
|
|
26
45
|
/**
|
|
27
46
|
* Estimate total tokens in a message array.
|
|
28
|
-
*
|
|
47
|
+
* Delegates to the shared token estimation utility (~3.5 chars/token).
|
|
29
48
|
*/
|
|
30
49
|
export function estimateContextTokens(messages) {
|
|
31
50
|
let totalChars = 0;
|
|
@@ -40,14 +59,13 @@ export function estimateContextTokens(messages) {
|
|
|
40
59
|
}
|
|
41
60
|
}
|
|
42
61
|
}
|
|
43
|
-
return
|
|
62
|
+
return estimateTokensFromCharCount(totalChars);
|
|
44
63
|
}
|
|
45
64
|
/**
|
|
46
65
|
* Compact tool outputs to save context.
|
|
47
66
|
*/
|
|
48
67
|
export function compactToolOutputs(messages) {
|
|
49
|
-
const COMPACT_PREVIEW_LENGTH =
|
|
50
|
-
const MAX_PRESERVED_EXPENSIVE_RESULTS = 6;
|
|
68
|
+
const { COMPACT_PREVIEW_LENGTH, MAX_PRESERVED_EXPENSIVE_RESULTS } = EXECUTION_LOOP_DEFAULTS;
|
|
51
69
|
let compactedCount = 0;
|
|
52
70
|
let savedChars = 0;
|
|
53
71
|
const preservedExpensiveIndexes = messages
|
|
@@ -69,7 +87,10 @@ export function compactToolOutputs(messages) {
|
|
|
69
87
|
}
|
|
70
88
|
}
|
|
71
89
|
if (compactedCount > 0 && process.env.DEBUG) {
|
|
72
|
-
log.debug('Compacted tool outputs', {
|
|
90
|
+
log.debug('Compacted tool outputs', {
|
|
91
|
+
compactedCount,
|
|
92
|
+
savedTokens: estimateTokensFromCharCount(savedChars),
|
|
93
|
+
});
|
|
73
94
|
}
|
|
74
95
|
}
|
|
75
96
|
/**
|
|
@@ -86,21 +107,303 @@ export function isRequestedArtifactMissing(requestedArtifact, executedToolNames)
|
|
|
86
107
|
if (!requestedArtifact)
|
|
87
108
|
return false;
|
|
88
109
|
const artifactWriteTools = ['write_file', 'edit_file', 'apply_patch', 'append_file'];
|
|
89
|
-
return !artifactWriteTools.some(toolName => executedToolNames.has(toolName));
|
|
110
|
+
return !artifactWriteTools.some((toolName) => executedToolNames.has(toolName));
|
|
90
111
|
}
|
|
91
112
|
function getOpenTaskSummary(ctx) {
|
|
92
113
|
if (!ctx.taskManager)
|
|
93
114
|
return undefined;
|
|
94
115
|
const tasks = ctx.taskManager.list();
|
|
95
|
-
const pending = tasks.filter(t => t.status === 'pending').length;
|
|
96
|
-
const inProgress = tasks.filter(t => t.status === 'in_progress').length;
|
|
97
|
-
const blocked = tasks.filter(t => t.status === 'pending' && ctx.taskManager?.isBlocked(t.id)).length;
|
|
116
|
+
const pending = tasks.filter((t) => t.status === 'pending').length;
|
|
117
|
+
const inProgress = tasks.filter((t) => t.status === 'in_progress').length;
|
|
118
|
+
const blocked = tasks.filter((t) => t.status === 'pending' && ctx.taskManager?.isBlocked(t.id)).length;
|
|
98
119
|
return { pending, inProgress, blocked };
|
|
99
120
|
}
|
|
100
121
|
function getPendingWithOwnerCount(ctx) {
|
|
101
122
|
if (!ctx.taskManager)
|
|
102
123
|
return 0;
|
|
103
|
-
return ctx.taskManager.list().filter(t => t.status === 'pending' && !!t.owner).length;
|
|
124
|
+
return ctx.taskManager.list().filter((t) => t.status === 'pending' && !!t.owner).length;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Check economics/iteration budget before an iteration.
|
|
128
|
+
* Returns whether to continue, stop, or whether recovery succeeded.
|
|
129
|
+
*/
|
|
130
|
+
export function checkIterationBudget(deps, messages) {
|
|
131
|
+
if (deps.economics) {
|
|
132
|
+
const budgetCheck = deps.economics.checkBudget();
|
|
133
|
+
const forceTextOnly = budgetCheck.forceTextOnly ?? false;
|
|
134
|
+
const budgetInjectedPrompt = budgetCheck.injectedPrompt;
|
|
135
|
+
const budgetAllowsTaskContinuation = budgetCheck.allowTaskContinuation ?? true;
|
|
136
|
+
deps.traceCollector?.record({
|
|
137
|
+
type: 'budget.check',
|
|
138
|
+
data: {
|
|
139
|
+
iteration: deps.state.iteration,
|
|
140
|
+
canContinue: budgetCheck.canContinue,
|
|
141
|
+
percentUsed: budgetCheck.percentUsed,
|
|
142
|
+
budgetType: budgetCheck.budgetType,
|
|
143
|
+
budgetMode: budgetCheck.budgetMode,
|
|
144
|
+
forceTextOnly,
|
|
145
|
+
allowTaskContinuation: budgetAllowsTaskContinuation,
|
|
146
|
+
enforcementMode: deps.economics.getBudget().enforcementMode ?? 'strict',
|
|
147
|
+
tokenUsage: deps.economics.getUsage().tokens,
|
|
148
|
+
maxTokens: deps.economics.getBudget().maxTokens,
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
if (!budgetCheck.canContinue) {
|
|
152
|
+
// RECOVERY ATTEMPT: Try emergency context reduction
|
|
153
|
+
const isTokenLimit = budgetCheck.budgetType === 'tokens' || budgetCheck.budgetType === 'cost';
|
|
154
|
+
const alreadyTriedRecovery = deps.state._recoveryAttempted === true;
|
|
155
|
+
if (isTokenLimit && !alreadyTriedRecovery) {
|
|
156
|
+
deps.observability?.logger?.info('Budget limit reached, attempting recovery via context reduction', { reason: budgetCheck.reason, percentUsed: budgetCheck.percentUsed });
|
|
157
|
+
deps.emit({
|
|
158
|
+
type: 'resilience.retry',
|
|
159
|
+
reason: 'budget_limit_compaction',
|
|
160
|
+
attempt: 1,
|
|
161
|
+
maxAttempts: 1,
|
|
162
|
+
});
|
|
163
|
+
deps.state.metrics.retryCount = (deps.state.metrics.retryCount ?? 0) + 1;
|
|
164
|
+
deps.state._recoveryAttempted = true;
|
|
165
|
+
const tokensBefore = estimateContextTokens(messages);
|
|
166
|
+
// Step 1: Compact tool outputs aggressively
|
|
167
|
+
compactToolOutputs(deps.state.messages);
|
|
168
|
+
// Step 2: Emergency truncation - keep system + last N messages
|
|
169
|
+
const PRESERVE_RECENT = EXECUTION_LOOP_DEFAULTS.PRESERVE_RECENT;
|
|
170
|
+
if (messages.length > PRESERVE_RECENT + 2) {
|
|
171
|
+
const systemMessage = messages.find((m) => m.role === 'system');
|
|
172
|
+
const recentMessages = messages.slice(-PRESERVE_RECENT);
|
|
173
|
+
messages.length = 0;
|
|
174
|
+
if (systemMessage) {
|
|
175
|
+
messages.push(systemMessage);
|
|
176
|
+
}
|
|
177
|
+
messages.push({
|
|
178
|
+
role: 'system',
|
|
179
|
+
content: `[CONTEXT REDUCED: Earlier messages were removed to stay within budget. Conversation continues from recent context.]`,
|
|
180
|
+
});
|
|
181
|
+
messages.push(...recentMessages);
|
|
182
|
+
// Inject work log after emergency truncation
|
|
183
|
+
if (deps.workLog?.hasContent()) {
|
|
184
|
+
messages.push({ role: 'user', content: deps.workLog.toCompactString() });
|
|
185
|
+
}
|
|
186
|
+
// Update state messages too
|
|
187
|
+
deps.state.messages.length = 0;
|
|
188
|
+
deps.state.messages.push(...messages);
|
|
189
|
+
}
|
|
190
|
+
const tokensAfter = estimateContextTokens(messages);
|
|
191
|
+
const reduction = Math.round((1 - tokensAfter / tokensBefore) * 100);
|
|
192
|
+
if (tokensAfter < tokensBefore * 0.8) {
|
|
193
|
+
deps.observability?.logger?.info('Context reduction successful, continuing execution', { tokensBefore, tokensAfter, reduction });
|
|
194
|
+
deps.emit({ type: 'resilience.recovered', reason: 'budget_limit_compaction', attempts: 1 });
|
|
195
|
+
deps.emit({ type: 'compaction.auto', tokensBefore, tokensAfter, messagesCompacted: tokensBefore - tokensAfter });
|
|
196
|
+
deps.economics?.updateBaseline(tokensAfter);
|
|
197
|
+
return { action: 'recovery_success' };
|
|
198
|
+
}
|
|
199
|
+
deps.observability?.logger?.warn('Context reduction insufficient', {
|
|
200
|
+
tokensBefore, tokensAfter, reduction,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
// Hard limit reached and recovery failed
|
|
204
|
+
deps.observability?.logger?.warn('Budget limit reached', {
|
|
205
|
+
reason: budgetCheck.reason,
|
|
206
|
+
budgetType: budgetCheck.budgetType,
|
|
207
|
+
});
|
|
208
|
+
if (budgetCheck.budgetType === 'iterations') {
|
|
209
|
+
const totalIter = deps.getTotalIterations();
|
|
210
|
+
const iterMsg = deps.parentIterations > 0
|
|
211
|
+
? `${deps.state.iteration} + ${deps.parentIterations} parent = ${totalIter}`
|
|
212
|
+
: `${deps.state.iteration}`;
|
|
213
|
+
const reason = `Max iterations reached (${iterMsg})`;
|
|
214
|
+
deps.emit({ type: 'error', error: reason });
|
|
215
|
+
return { action: 'stop', result: { success: false, terminationReason: 'max_iterations', failureReason: reason } };
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
const reason = budgetCheck.reason || 'Budget exceeded';
|
|
219
|
+
deps.emit({ type: 'error', error: reason });
|
|
220
|
+
return { action: 'stop', result: { success: false, terminationReason: 'budget_limit', failureReason: reason } };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// Check for soft limits
|
|
224
|
+
if (budgetCheck.isSoftLimit && budgetCheck.suggestedAction === 'request_extension') {
|
|
225
|
+
deps.observability?.logger?.info('Approaching budget limit', {
|
|
226
|
+
reason: budgetCheck.reason,
|
|
227
|
+
percentUsed: budgetCheck.percentUsed,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return { action: 'continue', forceTextOnly, budgetInjectedPrompt, budgetAllowsTaskContinuation };
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
// Fallback to simple iteration check
|
|
234
|
+
if (deps.getTotalIterations() >= deps.maxIterations) {
|
|
235
|
+
const totalIter = deps.getTotalIterations();
|
|
236
|
+
const reason = `Max iterations reached (${totalIter})`;
|
|
237
|
+
deps.observability?.logger?.warn('Max iterations reached', {
|
|
238
|
+
iteration: deps.state.iteration,
|
|
239
|
+
parentIterations: deps.parentIterations,
|
|
240
|
+
total: totalIter,
|
|
241
|
+
});
|
|
242
|
+
deps.emit({ type: 'error', error: reason });
|
|
243
|
+
return { action: 'stop', result: { success: false, terminationReason: 'max_iterations', failureReason: reason } };
|
|
244
|
+
}
|
|
245
|
+
return { action: 'continue', forceTextOnly: false, budgetAllowsTaskContinuation: true };
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Handle auto-compaction of context when approaching token limits.
|
|
250
|
+
* Returns the compaction status and whether messages were modified.
|
|
251
|
+
*/
|
|
252
|
+
export async function handleAutoCompaction(deps, messages, stateMessages, setCompactionPending) {
|
|
253
|
+
const currentContextTokens = estimateContextTokens(messages);
|
|
254
|
+
if (deps.autoCompactionManager) {
|
|
255
|
+
const compactionResult = await deps.autoCompactionManager.checkAndMaybeCompact({
|
|
256
|
+
currentTokens: currentContextTokens,
|
|
257
|
+
messages: messages,
|
|
258
|
+
});
|
|
259
|
+
if (compactionResult.status === 'compacted' && compactionResult.compactedMessages) {
|
|
260
|
+
if (!deps.compactionPending) {
|
|
261
|
+
setCompactionPending(true);
|
|
262
|
+
const preCompactionMsg = {
|
|
263
|
+
role: 'user',
|
|
264
|
+
content: '[SYSTEM] Context compaction is imminent. Summarize your current progress, key findings, and next steps into a single concise message. This will be preserved after compaction.',
|
|
265
|
+
};
|
|
266
|
+
messages.push(preCompactionMsg);
|
|
267
|
+
stateMessages.push(preCompactionMsg);
|
|
268
|
+
deps.observability?.logger?.info('Pre-compaction agentic turn: injected summary request');
|
|
269
|
+
return { status: 'compaction_prompt_injected' };
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
setCompactionPending(false);
|
|
273
|
+
// Replace messages with compacted version
|
|
274
|
+
messages.length = 0;
|
|
275
|
+
messages.push(...compactionResult.compactedMessages);
|
|
276
|
+
stateMessages.length = 0;
|
|
277
|
+
stateMessages.push(...compactionResult.compactedMessages);
|
|
278
|
+
// Inject work log after compaction
|
|
279
|
+
if (deps.workLog?.hasContent()) {
|
|
280
|
+
const workLogMessage = { role: 'user', content: deps.workLog.toCompactString() };
|
|
281
|
+
messages.push(workLogMessage);
|
|
282
|
+
stateMessages.push(workLogMessage);
|
|
283
|
+
}
|
|
284
|
+
// Context recovery
|
|
285
|
+
const recoveryParts = [];
|
|
286
|
+
if (deps.store) {
|
|
287
|
+
const goalsSummary = deps.store.getGoalsSummary();
|
|
288
|
+
if (goalsSummary && goalsSummary !== 'No active goals.' && goalsSummary !== 'Goals feature not available.') {
|
|
289
|
+
recoveryParts.push(goalsSummary);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (deps.store) {
|
|
293
|
+
const juncturesSummary = deps.store.getJuncturesSummary(undefined, 5);
|
|
294
|
+
if (juncturesSummary) {
|
|
295
|
+
recoveryParts.push(juncturesSummary);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (deps.learningStore) {
|
|
299
|
+
const learnings = deps.learningStore.getLearningContext({ maxLearnings: 3 });
|
|
300
|
+
if (learnings) {
|
|
301
|
+
recoveryParts.push(learnings);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (recoveryParts.length > 0) {
|
|
305
|
+
const recoveryMessage = {
|
|
306
|
+
role: 'user',
|
|
307
|
+
content: `[CONTEXT RECOVERY — Re-injected after compaction]\n\n${recoveryParts.join('\n\n')}`,
|
|
308
|
+
};
|
|
309
|
+
messages.push(recoveryMessage);
|
|
310
|
+
stateMessages.push(recoveryMessage);
|
|
311
|
+
}
|
|
312
|
+
const compactionTokensAfter = estimateContextTokens(messages);
|
|
313
|
+
deps.economics?.updateBaseline(compactionTokensAfter);
|
|
314
|
+
const compactionEvent = {
|
|
315
|
+
type: 'context.compacted',
|
|
316
|
+
tokensBefore: currentContextTokens,
|
|
317
|
+
tokensAfter: compactionTokensAfter,
|
|
318
|
+
recoveryInjected: recoveryParts.length > 0,
|
|
319
|
+
};
|
|
320
|
+
deps.emit(compactionEvent);
|
|
321
|
+
deps.traceCollector?.record({
|
|
322
|
+
type: 'context.compacted',
|
|
323
|
+
data: {
|
|
324
|
+
tokensBefore: currentContextTokens,
|
|
325
|
+
tokensAfter: compactionTokensAfter,
|
|
326
|
+
recoveryInjected: recoveryParts.length > 0,
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
return { status: 'compacted', tokensBefore: currentContextTokens, tokensAfter: compactionTokensAfter };
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
else if (compactionResult.status === 'hard_limit') {
|
|
333
|
+
const reason = `Context hard limit reached (${Math.round(compactionResult.ratio * 100)}% of max tokens)`;
|
|
334
|
+
deps.emit({ type: 'error', error: reason });
|
|
335
|
+
return {
|
|
336
|
+
status: 'hard_limit',
|
|
337
|
+
result: { success: false, terminationReason: 'hard_context_limit', failureReason: reason },
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
else if (deps.economics) {
|
|
342
|
+
// Fallback to simple compaction
|
|
343
|
+
const currentUsage = deps.economics.getUsage();
|
|
344
|
+
const budget = deps.economics.getBudget();
|
|
345
|
+
const percentUsed = (currentUsage.tokens / budget.maxTokens) * 100;
|
|
346
|
+
if (percentUsed >= 70) {
|
|
347
|
+
deps.observability?.logger?.info('Proactive compaction triggered', {
|
|
348
|
+
percentUsed: Math.round(percentUsed),
|
|
349
|
+
currentTokens: currentUsage.tokens,
|
|
350
|
+
maxTokens: budget.maxTokens,
|
|
351
|
+
});
|
|
352
|
+
compactToolOutputs(stateMessages);
|
|
353
|
+
return { status: 'simple_compaction_triggered' };
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return { status: 'ok' };
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Guard against mass tool results overflowing the context window.
|
|
360
|
+
* Truncates tool results that would push total context beyond budget.
|
|
361
|
+
* Mutates toolResults in-place.
|
|
362
|
+
*/
|
|
363
|
+
export function applyContextOverflowGuard(deps, messages, toolResults) {
|
|
364
|
+
if (!deps.economics || toolResults.length <= 10)
|
|
365
|
+
return 0;
|
|
366
|
+
const preAccumTokens = estimateContextTokens(messages);
|
|
367
|
+
const budget = deps.economics.getBudget();
|
|
368
|
+
const availableTokens = budget.maxTokens * EXECUTION_LOOP_DEFAULTS.CONTEXT_SAFETY_RATIO - preAccumTokens;
|
|
369
|
+
const MAX_TOOL_OUTPUT_CHARS = EXECUTION_LOOP_DEFAULTS.MAX_TOOL_OUTPUT_CHARS;
|
|
370
|
+
let totalResultTokens = 0;
|
|
371
|
+
for (const r of toolResults) {
|
|
372
|
+
const c = typeof r.result === 'string' ? r.result : stableStringify(r.result);
|
|
373
|
+
totalResultTokens += estimateTokensFromCharCount(Math.min(c.length, MAX_TOOL_OUTPUT_CHARS));
|
|
374
|
+
}
|
|
375
|
+
if (totalResultTokens > availableTokens && availableTokens > 0) {
|
|
376
|
+
log.warn('Tool results would exceed context budget — truncating batch', {
|
|
377
|
+
resultCount: toolResults.length,
|
|
378
|
+
estimatedTokens: totalResultTokens,
|
|
379
|
+
availableTokens: Math.round(availableTokens),
|
|
380
|
+
});
|
|
381
|
+
let tokenBudget = availableTokens;
|
|
382
|
+
for (let i = 0; i < toolResults.length; i++) {
|
|
383
|
+
const c = typeof toolResults[i].result === 'string'
|
|
384
|
+
? toolResults[i].result
|
|
385
|
+
: stableStringify(toolResults[i].result);
|
|
386
|
+
const tokens = estimateTokensFromCharCount(Math.min(c.length, MAX_TOOL_OUTPUT_CHARS));
|
|
387
|
+
if (tokens > tokenBudget) {
|
|
388
|
+
const skipped = toolResults.length - i;
|
|
389
|
+
for (let j = i; j < toolResults.length; j++) {
|
|
390
|
+
toolResults[j] = {
|
|
391
|
+
callId: toolResults[j].callId,
|
|
392
|
+
result: `[Result omitted: context overflow guard — ${skipped} of ${toolResults.length} results skipped]`,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
deps.emit({
|
|
396
|
+
type: 'safeguard.context_overflow_guard',
|
|
397
|
+
estimatedTokens: totalResultTokens,
|
|
398
|
+
maxTokens: budget.maxTokens,
|
|
399
|
+
toolResultsSkipped: skipped,
|
|
400
|
+
});
|
|
401
|
+
return skipped;
|
|
402
|
+
}
|
|
403
|
+
tokenBudget -= tokens;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return 0;
|
|
104
407
|
}
|
|
105
408
|
// =============================================================================
|
|
106
409
|
// MAIN EXECUTION LOOP
|
|
@@ -135,12 +438,8 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
135
438
|
const reflectionConfig = ctx.config.reflection;
|
|
136
439
|
const reflectionEnabled = isFeatureEnabled(reflectionConfig);
|
|
137
440
|
const autoReflect = reflectionEnabled && reflectionConfig.autoReflect;
|
|
138
|
-
const maxReflectionAttempts = reflectionEnabled
|
|
139
|
-
|
|
140
|
-
: 1;
|
|
141
|
-
const confidenceThreshold = reflectionEnabled
|
|
142
|
-
? (reflectionConfig.confidenceThreshold || 0.8)
|
|
143
|
-
: 0.8;
|
|
441
|
+
const maxReflectionAttempts = reflectionEnabled ? reflectionConfig.maxAttempts || 3 : 1;
|
|
442
|
+
const confidenceThreshold = reflectionEnabled ? reflectionConfig.confidenceThreshold || 0.8 : 0.8;
|
|
144
443
|
let reflectionAttempt = 0;
|
|
145
444
|
let lastResponse = '';
|
|
146
445
|
let incompleteActionRetries = 0;
|
|
@@ -194,163 +493,33 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
194
493
|
}
|
|
195
494
|
}
|
|
196
495
|
// =======================================================================
|
|
197
|
-
// ECONOMICS CHECK (Token Budget)
|
|
496
|
+
// ECONOMICS CHECK (Token Budget) — delegated to checkIterationBudget()
|
|
198
497
|
// =======================================================================
|
|
199
498
|
let forceTextOnly = false;
|
|
200
499
|
let budgetInjectedPrompt;
|
|
201
500
|
let budgetAllowsTaskContinuation = true;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
ctx.
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
tokenUsage: ctx.economics.getUsage().tokens,
|
|
220
|
-
maxTokens: ctx.economics.getBudget().maxTokens,
|
|
221
|
-
},
|
|
222
|
-
});
|
|
223
|
-
if (!budgetCheck.canContinue) {
|
|
224
|
-
// RECOVERY ATTEMPT: Try emergency context reduction
|
|
225
|
-
const isTokenLimit = budgetCheck.budgetType === 'tokens' || budgetCheck.budgetType === 'cost';
|
|
226
|
-
const alreadyTriedRecovery = ctx.state._recoveryAttempted === true;
|
|
227
|
-
if (isTokenLimit && !alreadyTriedRecovery) {
|
|
228
|
-
ctx.observability?.logger?.info('Budget limit reached, attempting recovery via context reduction', {
|
|
229
|
-
reason: budgetCheck.reason,
|
|
230
|
-
percentUsed: budgetCheck.percentUsed,
|
|
231
|
-
});
|
|
232
|
-
ctx.emit({
|
|
233
|
-
type: 'resilience.retry',
|
|
234
|
-
reason: 'budget_limit_compaction',
|
|
235
|
-
attempt: 1,
|
|
236
|
-
maxAttempts: 1,
|
|
237
|
-
});
|
|
238
|
-
ctx.state.metrics.retryCount = (ctx.state.metrics.retryCount ?? 0) + 1;
|
|
239
|
-
ctx.state._recoveryAttempted = true;
|
|
240
|
-
const tokensBefore = estimateContextTokens(messages);
|
|
241
|
-
// Step 1: Compact tool outputs aggressively
|
|
242
|
-
compactToolOutputs(ctx.state.messages);
|
|
243
|
-
// Step 2: Emergency truncation - keep system + last N messages
|
|
244
|
-
const PRESERVE_RECENT = 10;
|
|
245
|
-
if (messages.length > PRESERVE_RECENT + 2) {
|
|
246
|
-
const systemMessage = messages.find(m => m.role === 'system');
|
|
247
|
-
const recentMessages = messages.slice(-(PRESERVE_RECENT));
|
|
248
|
-
messages.length = 0;
|
|
249
|
-
if (systemMessage) {
|
|
250
|
-
messages.push(systemMessage);
|
|
251
|
-
}
|
|
252
|
-
messages.push({
|
|
253
|
-
role: 'system',
|
|
254
|
-
content: `[CONTEXT REDUCED: Earlier messages were removed to stay within budget. Conversation continues from recent context.]`,
|
|
255
|
-
});
|
|
256
|
-
messages.push(...recentMessages);
|
|
257
|
-
// Inject work log after emergency truncation
|
|
258
|
-
if (ctx.workLog?.hasContent()) {
|
|
259
|
-
const workLogMessage = {
|
|
260
|
-
role: 'user',
|
|
261
|
-
content: ctx.workLog.toCompactString(),
|
|
262
|
-
};
|
|
263
|
-
messages.push(workLogMessage);
|
|
264
|
-
}
|
|
265
|
-
// Update state messages too
|
|
266
|
-
ctx.state.messages.length = 0;
|
|
267
|
-
ctx.state.messages.push(...messages);
|
|
268
|
-
}
|
|
269
|
-
const tokensAfter = estimateContextTokens(messages);
|
|
270
|
-
const reduction = Math.round((1 - tokensAfter / tokensBefore) * 100);
|
|
271
|
-
if (tokensAfter < tokensBefore * 0.8) {
|
|
272
|
-
ctx.observability?.logger?.info('Context reduction successful, continuing execution', {
|
|
273
|
-
tokensBefore,
|
|
274
|
-
tokensAfter,
|
|
275
|
-
reduction,
|
|
276
|
-
});
|
|
277
|
-
ctx.emit({
|
|
278
|
-
type: 'resilience.recovered',
|
|
279
|
-
reason: 'budget_limit_compaction',
|
|
280
|
-
attempts: 1,
|
|
281
|
-
});
|
|
282
|
-
ctx.emit({
|
|
283
|
-
type: 'compaction.auto',
|
|
284
|
-
tokensBefore,
|
|
285
|
-
tokensAfter,
|
|
286
|
-
messagesCompacted: tokensBefore - tokensAfter,
|
|
287
|
-
});
|
|
288
|
-
// Update baseline after emergency context reduction so
|
|
289
|
-
// incremental token accounting reflects the new context size
|
|
290
|
-
ctx.economics?.updateBaseline(tokensAfter);
|
|
291
|
-
continue;
|
|
292
|
-
}
|
|
293
|
-
ctx.observability?.logger?.warn('Context reduction insufficient', {
|
|
294
|
-
tokensBefore,
|
|
295
|
-
tokensAfter,
|
|
296
|
-
reduction,
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
// Hard limit reached and recovery failed
|
|
300
|
-
ctx.observability?.logger?.warn('Budget limit reached', {
|
|
301
|
-
reason: budgetCheck.reason,
|
|
302
|
-
budgetType: budgetCheck.budgetType,
|
|
303
|
-
});
|
|
304
|
-
if (budgetCheck.budgetType === 'iterations') {
|
|
305
|
-
const totalIter = ctx.getTotalIterations();
|
|
306
|
-
const iterMsg = ctx.parentIterations > 0
|
|
307
|
-
? `${ctx.state.iteration} + ${ctx.parentIterations} parent = ${totalIter}`
|
|
308
|
-
: `${ctx.state.iteration}`;
|
|
309
|
-
const reason = `Max iterations reached (${iterMsg})`;
|
|
310
|
-
ctx.emit({ type: 'error', error: reason });
|
|
311
|
-
result = {
|
|
312
|
-
success: false,
|
|
313
|
-
terminationReason: 'max_iterations',
|
|
314
|
-
failureReason: reason,
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
const reason = budgetCheck.reason || 'Budget exceeded';
|
|
319
|
-
ctx.emit({ type: 'error', error: reason });
|
|
320
|
-
result = {
|
|
321
|
-
success: false,
|
|
322
|
-
terminationReason: 'budget_limit',
|
|
323
|
-
failureReason: reason,
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
break;
|
|
327
|
-
}
|
|
328
|
-
// Check for soft limits and potential extension
|
|
329
|
-
if (budgetCheck.isSoftLimit && budgetCheck.suggestedAction === 'request_extension') {
|
|
330
|
-
ctx.observability?.logger?.info('Approaching budget limit', {
|
|
331
|
-
reason: budgetCheck.reason,
|
|
332
|
-
percentUsed: budgetCheck.percentUsed,
|
|
333
|
-
});
|
|
334
|
-
}
|
|
501
|
+
const budgetResult = checkIterationBudget({
|
|
502
|
+
economics: ctx.economics,
|
|
503
|
+
getTotalIterations: () => ctx.getTotalIterations(),
|
|
504
|
+
maxIterations: ctx.config.maxIterations,
|
|
505
|
+
parentIterations: ctx.parentIterations,
|
|
506
|
+
state: ctx.state,
|
|
507
|
+
workLog: ctx.workLog,
|
|
508
|
+
observability: ctx.observability,
|
|
509
|
+
traceCollector: ctx.traceCollector,
|
|
510
|
+
emit: (event) => ctx.emit(event),
|
|
511
|
+
}, messages);
|
|
512
|
+
if (budgetResult.action === 'recovery_success') {
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
else if (budgetResult.action === 'stop') {
|
|
516
|
+
result = budgetResult.result;
|
|
517
|
+
break;
|
|
335
518
|
}
|
|
336
519
|
else {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const reason = `Max iterations reached (${totalIter})`;
|
|
341
|
-
ctx.observability?.logger?.warn('Max iterations reached', {
|
|
342
|
-
iteration: ctx.state.iteration,
|
|
343
|
-
parentIterations: ctx.parentIterations,
|
|
344
|
-
total: totalIter,
|
|
345
|
-
});
|
|
346
|
-
ctx.emit({ type: 'error', error: reason });
|
|
347
|
-
result = {
|
|
348
|
-
success: false,
|
|
349
|
-
terminationReason: 'max_iterations',
|
|
350
|
-
failureReason: reason,
|
|
351
|
-
};
|
|
352
|
-
break;
|
|
353
|
-
}
|
|
520
|
+
forceTextOnly = budgetResult.forceTextOnly;
|
|
521
|
+
budgetInjectedPrompt = budgetResult.budgetInjectedPrompt;
|
|
522
|
+
budgetAllowsTaskContinuation = budgetResult.budgetAllowsTaskContinuation;
|
|
354
523
|
}
|
|
355
524
|
// =======================================================================
|
|
356
525
|
// GRACEFUL WRAPUP CHECK
|
|
@@ -396,15 +565,17 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
396
565
|
}
|
|
397
566
|
const enrichedMessages = ctx.contextEngineering.injectRecitation(messages, {
|
|
398
567
|
goal: task,
|
|
399
|
-
plan: ctx.state.plan
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
568
|
+
plan: ctx.state.plan
|
|
569
|
+
? {
|
|
570
|
+
description: ctx.state.plan.goal || task,
|
|
571
|
+
tasks: ctx.state.plan.tasks.map((t) => ({
|
|
572
|
+
id: t.id,
|
|
573
|
+
description: t.description,
|
|
574
|
+
status: t.status,
|
|
575
|
+
})),
|
|
576
|
+
currentTaskIndex: ctx.state.plan.tasks.findIndex((t) => t.status === 'in_progress'),
|
|
577
|
+
}
|
|
578
|
+
: undefined,
|
|
408
579
|
activeFiles: ctx.economics?.getProgress().filesModified
|
|
409
580
|
? [`${ctx.economics.getProgress().filesModified} files modified`]
|
|
410
581
|
: undefined,
|
|
@@ -412,7 +583,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
412
583
|
});
|
|
413
584
|
if (process.env.DEBUG_LLM) {
|
|
414
585
|
if (process.env.DEBUG)
|
|
415
|
-
log.debug('Recitation after', {
|
|
586
|
+
log.debug('Recitation after', {
|
|
587
|
+
messageCount: enrichedMessages?.length ?? 'null/undefined',
|
|
588
|
+
});
|
|
416
589
|
}
|
|
417
590
|
if (enrichedMessages && enrichedMessages !== messages && enrichedMessages.length > 0) {
|
|
418
591
|
messages.length = 0;
|
|
@@ -421,7 +594,7 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
421
594
|
else if (!enrichedMessages || enrichedMessages.length === 0) {
|
|
422
595
|
log.warn('Recitation returned empty/null messages, keeping original');
|
|
423
596
|
}
|
|
424
|
-
const contextTokens = messages
|
|
597
|
+
const contextTokens = estimateContextTokens(messages);
|
|
425
598
|
ctx.contextEngineering.updateRecitationFrequency(contextTokens);
|
|
426
599
|
}
|
|
427
600
|
// =======================================================================
|
|
@@ -448,7 +621,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
448
621
|
// =======================================================================
|
|
449
622
|
// RESUME ORIENTATION — after compaction, nudge the agent to act, not re-summarize
|
|
450
623
|
// =======================================================================
|
|
451
|
-
const hasCompactionSummary = messages.some(m => m.role === 'system' &&
|
|
624
|
+
const hasCompactionSummary = messages.some((m) => m.role === 'system' &&
|
|
625
|
+
typeof m.content === 'string' &&
|
|
626
|
+
m.content.includes('[Conversation Summary'));
|
|
452
627
|
if (hasCompactionSummary && ctx.state.iteration <= 2) {
|
|
453
628
|
messages.push({
|
|
454
629
|
role: 'user',
|
|
@@ -461,31 +636,48 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
461
636
|
if (ctx.injectionBudget) {
|
|
462
637
|
const proposals = [];
|
|
463
638
|
if (budgetInjectedPrompt) {
|
|
464
|
-
proposals.push({
|
|
639
|
+
proposals.push({
|
|
640
|
+
name: 'budget_warning',
|
|
641
|
+
priority: 0,
|
|
642
|
+
maxTokens: 500,
|
|
643
|
+
content: budgetInjectedPrompt,
|
|
644
|
+
});
|
|
465
645
|
}
|
|
466
646
|
if (ctx.contextEngineering) {
|
|
467
647
|
const failureCtx = ctx.contextEngineering.getFailureContext(5);
|
|
468
648
|
if (failureCtx) {
|
|
469
|
-
proposals.push({
|
|
649
|
+
proposals.push({
|
|
650
|
+
name: 'failure_context',
|
|
651
|
+
priority: 2,
|
|
652
|
+
maxTokens: 300,
|
|
653
|
+
content: failureCtx,
|
|
654
|
+
});
|
|
470
655
|
}
|
|
471
656
|
}
|
|
472
657
|
if (proposals.length > 0) {
|
|
473
658
|
const accepted = ctx.injectionBudget.allocate(proposals);
|
|
474
659
|
const stats = ctx.injectionBudget.getLastStats();
|
|
475
660
|
if (stats && stats.droppedNames.length > 0 && process.env.DEBUG) {
|
|
476
|
-
log.debug('Injection budget dropped items', {
|
|
661
|
+
log.debug('Injection budget dropped items', {
|
|
662
|
+
droppedNames: stats.droppedNames.join(', '),
|
|
663
|
+
proposedTokens: stats.proposedTokens,
|
|
664
|
+
acceptedTokens: stats.acceptedTokens,
|
|
665
|
+
});
|
|
477
666
|
}
|
|
478
667
|
if (stats && process.env.DEBUG_LLM) {
|
|
479
|
-
log.debug('Injection budget summary', {
|
|
668
|
+
log.debug('Injection budget summary', {
|
|
669
|
+
iteration: ctx.state.iteration,
|
|
670
|
+
accepted: accepted.length,
|
|
671
|
+
total: proposals.length,
|
|
672
|
+
tokens: stats.acceptedTokens,
|
|
673
|
+
});
|
|
480
674
|
}
|
|
481
675
|
}
|
|
482
676
|
}
|
|
483
677
|
// =======================================================================
|
|
484
678
|
// RESILIENT LLM CALL
|
|
485
679
|
// =======================================================================
|
|
486
|
-
const resilienceConfig = typeof ctx.config.resilience === 'object'
|
|
487
|
-
? ctx.config.resilience
|
|
488
|
-
: {};
|
|
680
|
+
const resilienceConfig = typeof ctx.config.resilience === 'object' ? ctx.config.resilience : {};
|
|
489
681
|
const resilienceEnabled = isFeatureEnabled(ctx.config.resilience);
|
|
490
682
|
const MAX_EMPTY_RETRIES = resilienceConfig.maxEmptyRetries ?? 2;
|
|
491
683
|
const MAX_CONTINUATIONS = resilienceConfig.maxContinuations ?? 3;
|
|
@@ -537,8 +729,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
537
729
|
// skip the expensive LLM call (whose tool calls would be discarded) and
|
|
538
730
|
// go directly to the task continuation gate. Only allowed once per
|
|
539
731
|
// forceTextOnly episode to prevent tight loops.
|
|
540
|
-
if (forceTextOnly &&
|
|
541
|
-
&&
|
|
732
|
+
if (forceTextOnly &&
|
|
733
|
+
budgetAllowsTaskContinuation &&
|
|
734
|
+
ctx.taskManager &&
|
|
735
|
+
!ctx.state._lastSkippedLLMIteration) {
|
|
542
736
|
const availableTasks = ctx.taskManager.getAvailableTasks();
|
|
543
737
|
if (availableTasks.length > 0) {
|
|
544
738
|
log.info('Skipping LLM call — forceTextOnly with tasks available, going to task continuation', {
|
|
@@ -546,7 +740,8 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
546
740
|
iteration: ctx.state.iteration,
|
|
547
741
|
});
|
|
548
742
|
// Mark that we skipped so we don't skip again on the next iteration
|
|
549
|
-
ctx.state._lastSkippedLLMIteration =
|
|
743
|
+
ctx.state._lastSkippedLLMIteration =
|
|
744
|
+
ctx.state.iteration;
|
|
550
745
|
// Reset forceTextOnly for the next iteration so the task can run normally
|
|
551
746
|
forceTextOnly = false;
|
|
552
747
|
const nextTask = availableTasks[0];
|
|
@@ -638,7 +833,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
638
833
|
response = await callLLM(messages, ctx);
|
|
639
834
|
}
|
|
640
835
|
// Phase 2: Handle max_tokens truncation with continuation
|
|
641
|
-
if (resilienceEnabled &&
|
|
836
|
+
if (resilienceEnabled &&
|
|
837
|
+
AUTO_CONTINUE &&
|
|
838
|
+
response.stopReason === 'max_tokens' &&
|
|
839
|
+
!response.toolCalls?.length) {
|
|
642
840
|
let accumulatedContent = response.content || '';
|
|
643
841
|
while (continuations < MAX_CONTINUATIONS && response.stopReason === 'max_tokens') {
|
|
644
842
|
continuations++;
|
|
@@ -682,10 +880,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
682
880
|
if (resilienceEnabled && response.stopReason === 'max_tokens' && response.toolCalls?.length) {
|
|
683
881
|
ctx.emit({
|
|
684
882
|
type: 'resilience.truncated_tool_call',
|
|
685
|
-
toolNames: response.toolCalls.map(tc => tc.name),
|
|
883
|
+
toolNames: response.toolCalls.map((tc) => tc.name),
|
|
686
884
|
});
|
|
687
885
|
ctx.observability?.logger?.warn('Tool call truncated at max_tokens', {
|
|
688
|
-
toolNames: response.toolCalls.map(tc => tc.name),
|
|
886
|
+
toolNames: response.toolCalls.map((tc) => tc.name),
|
|
689
887
|
outputTokens: response.usage?.outputTokens,
|
|
690
888
|
});
|
|
691
889
|
const truncatedResponse = response;
|
|
@@ -728,9 +926,12 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
728
926
|
ctx.state.messages.push(assistantMessage);
|
|
729
927
|
lastResponse = response.content || (response.thinking ? response.thinking : '');
|
|
730
928
|
// Plan mode: capture exploration findings
|
|
731
|
-
if (ctx.modeManager.getMode() === 'plan' &&
|
|
732
|
-
|
|
733
|
-
|
|
929
|
+
if (ctx.modeManager.getMode() === 'plan' &&
|
|
930
|
+
response.content &&
|
|
931
|
+
response.content.length > 50) {
|
|
932
|
+
const hasReadOnlyTools = response.toolCalls?.every((tc) => ['read_file', 'list_files', 'glob', 'grep', 'search', 'mcp_'].some((prefix) => tc.name.startsWith(prefix) || tc.name === prefix));
|
|
933
|
+
if (hasReadOnlyTools &&
|
|
934
|
+
!response.content.match(/^(Let me|I'll|I will|I need to|First,)/i)) {
|
|
734
935
|
ctx.pendingPlanManager.appendExplorationFinding(response.content.slice(0, 1000));
|
|
735
936
|
}
|
|
736
937
|
}
|
|
@@ -751,10 +952,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
751
952
|
const missingRequiredArtifact = ENFORCE_REQUESTED_ARTIFACTS
|
|
752
953
|
? isRequestedArtifactMissing(requestedArtifact, executedToolNames)
|
|
753
954
|
: false;
|
|
754
|
-
const shouldRecoverIncompleteAction = resilienceEnabled
|
|
755
|
-
&&
|
|
756
|
-
|
|
757
|
-
|
|
955
|
+
const shouldRecoverIncompleteAction = resilienceEnabled &&
|
|
956
|
+
INCOMPLETE_ACTION_RECOVERY &&
|
|
957
|
+
!forceTextOnly &&
|
|
958
|
+
(incompleteAction || missingRequiredArtifact);
|
|
758
959
|
if (shouldRecoverIncompleteAction) {
|
|
759
960
|
ctx.emit({
|
|
760
961
|
type: 'completion.before',
|
|
@@ -847,15 +1048,20 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
847
1048
|
incompleteActionRetries = 0;
|
|
848
1049
|
}
|
|
849
1050
|
// TypeScript compilation gate — block completion if TS files edited and errors exist
|
|
850
|
-
if (ctx.typeCheckerState?.tsconfigDir
|
|
851
|
-
|
|
852
|
-
|
|
1051
|
+
if (ctx.typeCheckerState?.tsconfigDir &&
|
|
1052
|
+
!forceTextOnly &&
|
|
1053
|
+
(ctx.typeCheckerState.tsEditsSinceLastCheck > 0 || !ctx.typeCheckerState.hasRunOnce)) {
|
|
853
1054
|
const tscResult = await runTypeCheck(ctx.typeCheckerState.tsconfigDir);
|
|
854
1055
|
ctx.typeCheckerState.tsEditsSinceLastCheck = 0;
|
|
855
1056
|
ctx.typeCheckerState.lastResult = tscResult;
|
|
856
1057
|
ctx.typeCheckerState.hasRunOnce = true;
|
|
857
1058
|
ctx.verificationGate?.recordCompilationResult(tscResult.success, tscResult.errorCount);
|
|
858
|
-
ctx.emit({
|
|
1059
|
+
ctx.emit({
|
|
1060
|
+
type: 'diagnostics.tsc-check',
|
|
1061
|
+
errorCount: tscResult.errorCount,
|
|
1062
|
+
duration: tscResult.duration,
|
|
1063
|
+
trigger: 'completion',
|
|
1064
|
+
});
|
|
859
1065
|
if (!tscResult.success) {
|
|
860
1066
|
const vState = ctx.verificationGate?.getState();
|
|
861
1067
|
const maxCompNudges = 8;
|
|
@@ -865,7 +1071,10 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
865
1071
|
messages.push(nudgeMessage);
|
|
866
1072
|
ctx.state.messages.push(nudgeMessage);
|
|
867
1073
|
ctx.verificationGate?.incrementCompilationNudge();
|
|
868
|
-
log.info('Compilation gate blocked completion', {
|
|
1074
|
+
log.info('Compilation gate blocked completion', {
|
|
1075
|
+
count: tscResult.errorCount,
|
|
1076
|
+
nudgeCount: ctx.verificationGate?.getState().compilationNudgeCount,
|
|
1077
|
+
});
|
|
869
1078
|
ctx.emit({
|
|
870
1079
|
type: 'iteration.after',
|
|
871
1080
|
iteration: ctx.state.iteration,
|
|
@@ -995,7 +1204,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
995
1204
|
}
|
|
996
1205
|
const reasons = [
|
|
997
1206
|
`Open tasks remain: ${openTasks.pending} pending, ${openTasks.inProgress} in_progress`,
|
|
998
|
-
openTasks.blocked > 0
|
|
1207
|
+
openTasks.blocked > 0
|
|
1208
|
+
? `${openTasks.blocked} pending tasks are currently blocked`
|
|
1209
|
+
: '',
|
|
999
1210
|
].filter(Boolean);
|
|
1000
1211
|
ctx.emit({
|
|
1001
1212
|
type: 'completion.blocked',
|
|
@@ -1025,7 +1236,7 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
1025
1236
|
log.warn('Tool call explosion detected — capping', {
|
|
1026
1237
|
requested: toolCalls.length,
|
|
1027
1238
|
cap: maxToolCallsPerResponse,
|
|
1028
|
-
toolNames: [...new Set(toolCalls.map(tc => tc.name))],
|
|
1239
|
+
toolNames: [...new Set(toolCalls.map((tc) => tc.name))],
|
|
1029
1240
|
});
|
|
1030
1241
|
ctx.emit({
|
|
1031
1242
|
type: 'safeguard.tool_call_cap',
|
|
@@ -1052,7 +1263,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
1052
1263
|
// Record in work log
|
|
1053
1264
|
const toolOutput = result?.result && typeof result.result === 'object' && 'output' in result.result
|
|
1054
1265
|
? String(result.result.output)
|
|
1055
|
-
: typeof result?.result === 'string'
|
|
1266
|
+
: typeof result?.result === 'string'
|
|
1267
|
+
? result.result
|
|
1268
|
+
: undefined;
|
|
1056
1269
|
ctx.workLog?.recordToolExecution(toolCall.name, toolCall.arguments, toolOutput);
|
|
1057
1270
|
// Record in verification gate
|
|
1058
1271
|
if (ctx.verificationGate) {
|
|
@@ -1060,9 +1273,11 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
1060
1273
|
const toolRes = result?.result;
|
|
1061
1274
|
const output = toolRes && typeof toolRes === 'object' && 'output' in toolRes
|
|
1062
1275
|
? String(toolRes.output)
|
|
1063
|
-
: typeof toolRes === 'string'
|
|
1276
|
+
: typeof toolRes === 'string'
|
|
1277
|
+
? toolRes
|
|
1278
|
+
: '';
|
|
1064
1279
|
const exitCode = toolRes && typeof toolRes === 'object' && toolRes.metadata
|
|
1065
|
-
? toolRes.metadata.exitCode ?? null
|
|
1280
|
+
? (toolRes.metadata.exitCode ?? null)
|
|
1066
1281
|
: null;
|
|
1067
1282
|
ctx.verificationGate.recordBashExecution(String(toolCall.arguments.command || ''), output, exitCode);
|
|
1068
1283
|
}
|
|
@@ -1071,7 +1286,9 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
1071
1286
|
}
|
|
1072
1287
|
}
|
|
1073
1288
|
// Phase 5.1: Post-edit syntax validation + AST cache invalidation
|
|
1074
|
-
if (['write_file', 'edit_file'].includes(toolCall.name) &&
|
|
1289
|
+
if (['write_file', 'edit_file'].includes(toolCall.name) &&
|
|
1290
|
+
result?.result &&
|
|
1291
|
+
result.result.success) {
|
|
1075
1292
|
const filePath = String(toolCall.arguments.path || '');
|
|
1076
1293
|
if (filePath) {
|
|
1077
1294
|
// Invalidate stale AST cache entry so next analysis/validation reparses
|
|
@@ -1086,18 +1303,26 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
1086
1303
|
try {
|
|
1087
1304
|
await ctx.codebaseContext.updateFile(filePath, content);
|
|
1088
1305
|
}
|
|
1089
|
-
catch {
|
|
1306
|
+
catch {
|
|
1307
|
+
/* non-blocking */
|
|
1308
|
+
}
|
|
1090
1309
|
}
|
|
1091
1310
|
const validation = validateSyntax(content, filePath);
|
|
1092
1311
|
if (!validation.valid && result.result && typeof result.result === 'object') {
|
|
1093
1312
|
const errorSummary = validation.errors
|
|
1094
1313
|
.slice(0, 3)
|
|
1095
|
-
.map(e => ` L${e.line}:${e.column}: ${e.message}`)
|
|
1314
|
+
.map((e) => ` L${e.line}:${e.column}: ${e.message}`)
|
|
1096
1315
|
.join('\n');
|
|
1097
|
-
result.result.output +=
|
|
1316
|
+
result.result.output +=
|
|
1317
|
+
`\n\n⚠ Syntax validation warning:\n${errorSummary}`;
|
|
1098
1318
|
// Emit diagnostic events for each syntax error
|
|
1099
1319
|
for (const err of validation.errors.slice(0, 5)) {
|
|
1100
|
-
ctx.emit({
|
|
1320
|
+
ctx.emit({
|
|
1321
|
+
type: 'diagnostics.syntax-error',
|
|
1322
|
+
file: filePath,
|
|
1323
|
+
line: err.line,
|
|
1324
|
+
message: err.message,
|
|
1325
|
+
});
|
|
1101
1326
|
}
|
|
1102
1327
|
}
|
|
1103
1328
|
}
|
|
@@ -1112,180 +1337,48 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
1112
1337
|
}
|
|
1113
1338
|
}
|
|
1114
1339
|
// Add tool results to messages (with truncation and proactive budget management)
|
|
1115
|
-
const MAX_TOOL_OUTPUT_CHARS =
|
|
1116
|
-
// PROACTIVE BUDGET CHECK
|
|
1117
|
-
const
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
ctx.state.messages.push(preCompactionMsg);
|
|
1132
|
-
ctx.observability?.logger?.info('Pre-compaction agentic turn: injected summary request');
|
|
1133
|
-
}
|
|
1134
|
-
else {
|
|
1135
|
-
mutators.setCompactionPending(false);
|
|
1136
|
-
// Pre-compaction checkpoint
|
|
1137
|
-
// NOTE: autoCheckpoint is called via the agent's method, not directly here
|
|
1138
|
-
// The agent wires this through the mutators pattern
|
|
1139
|
-
// Replace messages with compacted version
|
|
1140
|
-
messages.length = 0;
|
|
1141
|
-
messages.push(...compactionResult.compactedMessages);
|
|
1142
|
-
ctx.state.messages.length = 0;
|
|
1143
|
-
ctx.state.messages.push(...compactionResult.compactedMessages);
|
|
1144
|
-
// Inject work log after compaction
|
|
1145
|
-
if (ctx.workLog?.hasContent()) {
|
|
1146
|
-
const workLogMessage = {
|
|
1147
|
-
role: 'user',
|
|
1148
|
-
content: ctx.workLog.toCompactString(),
|
|
1149
|
-
};
|
|
1150
|
-
messages.push(workLogMessage);
|
|
1151
|
-
ctx.state.messages.push(workLogMessage);
|
|
1152
|
-
}
|
|
1153
|
-
// Context recovery
|
|
1154
|
-
const recoveryParts = [];
|
|
1155
|
-
if (ctx.store) {
|
|
1156
|
-
const goalsSummary = ctx.store.getGoalsSummary();
|
|
1157
|
-
if (goalsSummary && goalsSummary !== 'No active goals.' && goalsSummary !== 'Goals feature not available.') {
|
|
1158
|
-
recoveryParts.push(goalsSummary);
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
if (ctx.store) {
|
|
1162
|
-
const juncturesSummary = ctx.store.getJuncturesSummary(undefined, 5);
|
|
1163
|
-
if (juncturesSummary) {
|
|
1164
|
-
recoveryParts.push(juncturesSummary);
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
if (ctx.learningStore) {
|
|
1168
|
-
const learnings = ctx.learningStore.getLearningContext({ maxLearnings: 3 });
|
|
1169
|
-
if (learnings) {
|
|
1170
|
-
recoveryParts.push(learnings);
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
if (recoveryParts.length > 0) {
|
|
1174
|
-
const recoveryMessage = {
|
|
1175
|
-
role: 'user',
|
|
1176
|
-
content: `[CONTEXT RECOVERY — Re-injected after compaction]\n\n${recoveryParts.join('\n\n')}`,
|
|
1177
|
-
};
|
|
1178
|
-
messages.push(recoveryMessage);
|
|
1179
|
-
ctx.state.messages.push(recoveryMessage);
|
|
1180
|
-
}
|
|
1181
|
-
// Emit compaction event
|
|
1182
|
-
const compactionTokensAfter = estimateContextTokens(messages);
|
|
1183
|
-
const compactionRecoveryInjected = recoveryParts.length > 0;
|
|
1184
|
-
// Update baseline after compaction so incremental token
|
|
1185
|
-
// accounting reflects the reduced context size
|
|
1186
|
-
ctx.economics?.updateBaseline(compactionTokensAfter);
|
|
1187
|
-
const compactionEvent = {
|
|
1188
|
-
type: 'context.compacted',
|
|
1189
|
-
tokensBefore: currentContextTokens,
|
|
1190
|
-
tokensAfter: compactionTokensAfter,
|
|
1191
|
-
recoveryInjected: compactionRecoveryInjected,
|
|
1192
|
-
};
|
|
1193
|
-
ctx.emit(compactionEvent);
|
|
1194
|
-
if (ctx.traceCollector) {
|
|
1195
|
-
ctx.traceCollector.record({
|
|
1196
|
-
type: 'context.compacted',
|
|
1197
|
-
data: {
|
|
1198
|
-
tokensBefore: currentContextTokens,
|
|
1199
|
-
tokensAfter: compactionTokensAfter,
|
|
1200
|
-
recoveryInjected: compactionRecoveryInjected,
|
|
1201
|
-
},
|
|
1202
|
-
});
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
else if (compactionResult.status === 'hard_limit') {
|
|
1207
|
-
const reason = `Context hard limit reached (${Math.round(compactionResult.ratio * 100)}% of max tokens)`;
|
|
1208
|
-
ctx.emit({ type: 'error', error: reason });
|
|
1209
|
-
result = {
|
|
1210
|
-
success: false,
|
|
1211
|
-
terminationReason: 'hard_context_limit',
|
|
1212
|
-
failureReason: reason,
|
|
1213
|
-
};
|
|
1214
|
-
break;
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
else if (ctx.economics) {
|
|
1218
|
-
// Fallback to simple compaction
|
|
1219
|
-
const currentUsage = ctx.economics.getUsage();
|
|
1220
|
-
const budget = ctx.economics.getBudget();
|
|
1221
|
-
const percentUsed = (currentUsage.tokens / budget.maxTokens) * 100;
|
|
1222
|
-
if (percentUsed >= 70) {
|
|
1223
|
-
ctx.observability?.logger?.info('Proactive compaction triggered', {
|
|
1224
|
-
percentUsed: Math.round(percentUsed),
|
|
1225
|
-
currentTokens: currentUsage.tokens,
|
|
1226
|
-
maxTokens: budget.maxTokens,
|
|
1227
|
-
});
|
|
1228
|
-
compactToolOutputs(ctx.state.messages);
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
// SAFEGUARD: Aggregate context guard — prevent mass small results from overflowing
|
|
1232
|
-
if (ctx.economics && toolResults.length > 10) {
|
|
1233
|
-
const preAccumTokens = estimateContextTokens(messages);
|
|
1234
|
-
const budget = ctx.economics.getBudget();
|
|
1235
|
-
const availableTokens = budget.maxTokens * 0.90 - preAccumTokens;
|
|
1236
|
-
// Estimate total result tokens
|
|
1237
|
-
let totalResultTokens = 0;
|
|
1238
|
-
for (const r of toolResults) {
|
|
1239
|
-
const c = typeof r.result === 'string' ? r.result : stableStringify(r.result);
|
|
1240
|
-
totalResultTokens += Math.ceil(Math.min(c.length, MAX_TOOL_OUTPUT_CHARS) / 4);
|
|
1241
|
-
}
|
|
1242
|
-
if (totalResultTokens > availableTokens && availableTokens > 0) {
|
|
1243
|
-
log.warn('Tool results would exceed context budget — truncating batch', {
|
|
1244
|
-
resultCount: toolResults.length,
|
|
1245
|
-
estimatedTokens: totalResultTokens,
|
|
1246
|
-
availableTokens: Math.round(availableTokens),
|
|
1247
|
-
});
|
|
1248
|
-
let tokenBudget = availableTokens;
|
|
1249
|
-
for (let i = 0; i < toolResults.length; i++) {
|
|
1250
|
-
const c = typeof toolResults[i].result === 'string'
|
|
1251
|
-
? toolResults[i].result
|
|
1252
|
-
: stableStringify(toolResults[i].result);
|
|
1253
|
-
const tokens = Math.ceil(Math.min(c.length, MAX_TOOL_OUTPUT_CHARS) / 4);
|
|
1254
|
-
if (tokens > tokenBudget) {
|
|
1255
|
-
const skipped = toolResults.length - i;
|
|
1256
|
-
for (let j = i; j < toolResults.length; j++) {
|
|
1257
|
-
toolResults[j] = {
|
|
1258
|
-
callId: toolResults[j].callId,
|
|
1259
|
-
result: `[Result omitted: context overflow guard — ${skipped} of ${toolResults.length} results skipped]`,
|
|
1260
|
-
};
|
|
1261
|
-
}
|
|
1262
|
-
ctx.emit({
|
|
1263
|
-
type: 'safeguard.context_overflow_guard',
|
|
1264
|
-
estimatedTokens: totalResultTokens,
|
|
1265
|
-
maxTokens: budget.maxTokens,
|
|
1266
|
-
toolResultsSkipped: skipped,
|
|
1267
|
-
});
|
|
1268
|
-
break;
|
|
1269
|
-
}
|
|
1270
|
-
tokenBudget -= tokens;
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1340
|
+
const MAX_TOOL_OUTPUT_CHARS = EXECUTION_LOOP_DEFAULTS.MAX_TOOL_OUTPUT_CHARS;
|
|
1341
|
+
// PROACTIVE BUDGET CHECK — delegate to extracted function
|
|
1342
|
+
const compactionStatus = await handleAutoCompaction({
|
|
1343
|
+
autoCompactionManager: ctx.autoCompactionManager ?? null,
|
|
1344
|
+
compactionPending: ctx.compactionPending,
|
|
1345
|
+
economics: ctx.economics,
|
|
1346
|
+
workLog: ctx.workLog,
|
|
1347
|
+
store: ctx.store,
|
|
1348
|
+
learningStore: ctx.learningStore,
|
|
1349
|
+
observability: ctx.observability,
|
|
1350
|
+
traceCollector: ctx.traceCollector,
|
|
1351
|
+
emit: (event) => ctx.emit(event),
|
|
1352
|
+
}, messages, ctx.state.messages, (v) => mutators.setCompactionPending(v));
|
|
1353
|
+
if (compactionStatus.status === 'hard_limit') {
|
|
1354
|
+
result = compactionStatus.result;
|
|
1355
|
+
break;
|
|
1273
1356
|
}
|
|
1274
|
-
|
|
1357
|
+
// SAFEGUARD: Aggregate context guard — delegate to extracted function
|
|
1358
|
+
applyContextOverflowGuard({ economics: ctx.economics, emit: (event) => ctx.emit(event) }, messages, toolResults);
|
|
1359
|
+
const toolCallNameById = new Map(toolCalls.map((tc) => [tc.id, tc.name]));
|
|
1275
1360
|
for (const result of toolResults) {
|
|
1276
|
-
let content = typeof result.result === 'string'
|
|
1361
|
+
let content = typeof result.result === 'string'
|
|
1362
|
+
? result.result
|
|
1363
|
+
: ctx.contextEngineering
|
|
1364
|
+
? ctx.contextEngineering.serialize(result.result)
|
|
1365
|
+
: stableStringify(result.result);
|
|
1277
1366
|
const sourceToolName = toolCallNameById.get(result.callId);
|
|
1278
1367
|
const isExpensiveResult = sourceToolName === 'spawn_agent' || sourceToolName === 'spawn_agents_parallel';
|
|
1279
|
-
const effectiveMaxChars = isExpensiveResult
|
|
1368
|
+
const effectiveMaxChars = isExpensiveResult
|
|
1369
|
+
? MAX_TOOL_OUTPUT_CHARS * 2
|
|
1370
|
+
: MAX_TOOL_OUTPUT_CHARS;
|
|
1280
1371
|
if (content.length > effectiveMaxChars) {
|
|
1281
|
-
content =
|
|
1372
|
+
content =
|
|
1373
|
+
content.slice(0, effectiveMaxChars) +
|
|
1374
|
+
`\n\n... [truncated ${content.length - effectiveMaxChars} chars]`;
|
|
1282
1375
|
}
|
|
1283
1376
|
// Check if adding this result would exceed budget
|
|
1284
1377
|
if (ctx.economics) {
|
|
1285
1378
|
const estimatedNewTokens = estimateTokenCount(content);
|
|
1286
1379
|
const currentCtxTokens = estimateContextTokens(messages);
|
|
1287
1380
|
const budget = ctx.economics.getBudget();
|
|
1288
|
-
if (currentCtxTokens + estimatedNewTokens > budget.maxTokens *
|
|
1381
|
+
if (currentCtxTokens + estimatedNewTokens > budget.maxTokens * EXECUTION_LOOP_DEFAULTS.PER_RESULT_BUDGET_RATIO) {
|
|
1289
1382
|
ctx.observability?.logger?.warn('Skipping tool result to stay within budget', {
|
|
1290
1383
|
toolCallId: result.callId,
|
|
1291
1384
|
estimatedTokens: estimatedNewTokens,
|
|
@@ -1320,16 +1413,21 @@ export async function executeDirectly(task, messages, ctx, mutators) {
|
|
|
1320
1413
|
ctx.state.messages.push(toolMessage);
|
|
1321
1414
|
}
|
|
1322
1415
|
// Periodic TypeScript compilation check (every 5 TS edits)
|
|
1323
|
-
const TYPE_CHECK_EDIT_THRESHOLD =
|
|
1324
|
-
if (ctx.typeCheckerState?.tsconfigDir
|
|
1325
|
-
|
|
1326
|
-
|
|
1416
|
+
const TYPE_CHECK_EDIT_THRESHOLD = EXECUTION_LOOP_DEFAULTS.TYPE_CHECK_EDIT_THRESHOLD;
|
|
1417
|
+
if (ctx.typeCheckerState?.tsconfigDir &&
|
|
1418
|
+
ctx.typeCheckerState.tsEditsSinceLastCheck >= TYPE_CHECK_EDIT_THRESHOLD &&
|
|
1419
|
+
!forceTextOnly) {
|
|
1327
1420
|
const tscResult = await runTypeCheck(ctx.typeCheckerState.tsconfigDir);
|
|
1328
1421
|
ctx.typeCheckerState.tsEditsSinceLastCheck = 0;
|
|
1329
1422
|
ctx.typeCheckerState.lastResult = tscResult;
|
|
1330
1423
|
ctx.typeCheckerState.hasRunOnce = true;
|
|
1331
1424
|
ctx.verificationGate?.recordCompilationResult(tscResult.success, tscResult.errorCount);
|
|
1332
|
-
ctx.emit({
|
|
1425
|
+
ctx.emit({
|
|
1426
|
+
type: 'diagnostics.tsc-check',
|
|
1427
|
+
errorCount: tscResult.errorCount,
|
|
1428
|
+
duration: tscResult.duration,
|
|
1429
|
+
trigger: 'periodic',
|
|
1430
|
+
});
|
|
1333
1431
|
if (!tscResult.success) {
|
|
1334
1432
|
const nudge = formatTypeCheckNudge(tscResult);
|
|
1335
1433
|
const infoMsg = { role: 'user', content: nudge };
|