agent-nuvira 3.3.1 → 3.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -13
- package/dist/agent-sdk/src/agent.d.ts +2 -0
- package/dist/agent-sdk/src/agent.d.ts.map +1 -1
- package/dist/agent-sdk/src/define.d.ts +64 -0
- package/dist/agent-sdk/src/define.d.ts.map +1 -0
- package/dist/agent-sdk/src/define.js +76 -0
- package/dist/agent-sdk/src/define.js.map +1 -0
- package/dist/agent-sdk/src/index.d.ts +9 -0
- package/dist/agent-sdk/src/index.d.ts.map +1 -1
- package/dist/agent-sdk/src/index.js +9 -0
- package/dist/agent-sdk/src/index.js.map +1 -1
- package/dist/agent-sdk/src/scaffold.d.ts +11 -0
- package/dist/agent-sdk/src/scaffold.d.ts.map +1 -1
- package/dist/agent-sdk/src/scaffold.js +16 -6
- package/dist/agent-sdk/src/scaffold.js.map +1 -1
- package/dist/agents/agents/runner.d.ts +9 -0
- package/dist/agents/agents/runner.d.ts.map +1 -1
- package/dist/agents/agents/runner.js +34 -12
- package/dist/agents/agents/runner.js.map +1 -1
- package/dist/agents/agents/writer-tool-calling.d.ts.map +1 -1
- package/dist/agents/agents/writer-tool-calling.js +7 -2
- package/dist/agents/agents/writer-tool-calling.js.map +1 -1
- package/dist/agents/agents/writer.d.ts.map +1 -1
- package/dist/agents/agents/writer.js +7 -1
- package/dist/agents/agents/writer.js.map +1 -1
- package/dist/agents/artifact-verification.d.ts +102 -0
- package/dist/agents/artifact-verification.d.ts.map +1 -0
- package/dist/agents/artifact-verification.js +216 -0
- package/dist/agents/artifact-verification.js.map +1 -0
- package/dist/agents/checkpoint-store.d.ts +73 -0
- package/dist/agents/checkpoint-store.d.ts.map +1 -1
- package/dist/agents/checkpoint-store.js +161 -0
- package/dist/agents/checkpoint-store.js.map +1 -1
- package/dist/agents/credential-store.d.ts +120 -0
- package/dist/agents/credential-store.d.ts.map +1 -1
- package/dist/agents/credential-store.js +358 -19
- package/dist/agents/credential-store.js.map +1 -1
- package/dist/agents/long-form-plan.d.ts.map +1 -1
- package/dist/agents/long-form-plan.js +2 -1
- package/dist/agents/long-form-plan.js.map +1 -1
- package/dist/agents/orchestrator.d.ts +10 -1
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +239 -79
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/agents/phase-engine.d.ts +61 -0
- package/dist/agents/phase-engine.d.ts.map +1 -1
- package/dist/agents/phase-engine.js +68 -2
- package/dist/agents/phase-engine.js.map +1 -1
- package/dist/agents/prompt-assembly.d.ts +11 -0
- package/dist/agents/prompt-assembly.d.ts.map +1 -1
- package/dist/agents/prompt-assembly.js +17 -0
- package/dist/agents/prompt-assembly.js.map +1 -1
- package/dist/agents/release-preflight.d.ts +121 -0
- package/dist/agents/release-preflight.d.ts.map +1 -0
- package/dist/agents/release-preflight.js +259 -0
- package/dist/agents/release-preflight.js.map +1 -0
- package/dist/agents/release-runner.d.ts +157 -0
- package/dist/agents/release-runner.d.ts.map +1 -0
- package/dist/agents/release-runner.js +719 -0
- package/dist/agents/release-runner.js.map +1 -0
- package/dist/agents/step-handoff.d.ts +190 -0
- package/dist/agents/step-handoff.d.ts.map +1 -0
- package/dist/agents/step-handoff.js +443 -0
- package/dist/agents/step-handoff.js.map +1 -0
- package/dist/cli/agent.d.ts +2 -2
- package/dist/cli/agent.js +10 -10
- package/dist/cli/benchmark.d.ts.map +1 -1
- package/dist/cli/benchmark.js +11 -4
- package/dist/cli/benchmark.js.map +1 -1
- package/dist/cli/chat.d.ts +94 -0
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +379 -24
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +8 -0
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +9 -1
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/credentials.d.ts +28 -0
- package/dist/cli/credentials.d.ts.map +1 -0
- package/dist/cli/credentials.js +213 -0
- package/dist/cli/credentials.js.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +3 -2
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/edit.js +2 -2
- package/dist/cli/eval.d.ts +17 -0
- package/dist/cli/eval.d.ts.map +1 -1
- package/dist/cli/eval.js +105 -2
- package/dist/cli/eval.js.map +1 -1
- package/dist/cli/execute.d.ts +16 -1
- package/dist/cli/execute.d.ts.map +1 -1
- package/dist/cli/execute.js +192 -22
- package/dist/cli/execute.js.map +1 -1
- package/dist/cli/failover-runner.d.ts.map +1 -1
- package/dist/cli/failover-runner.js +9 -3
- package/dist/cli/failover-runner.js.map +1 -1
- package/dist/cli/loop-executor.d.ts +55 -0
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +285 -19
- package/dist/cli/loop-executor.js.map +1 -1
- package/dist/cli/model.d.ts.map +1 -1
- package/dist/cli/model.js +9 -8
- package/dist/cli/model.js.map +1 -1
- package/dist/cli/models.d.ts +1 -1
- package/dist/cli/models.js +4 -4
- package/dist/cli/nlu.d.ts.map +1 -1
- package/dist/cli/nlu.js +8 -2
- package/dist/cli/nlu.js.map +1 -1
- package/dist/cli/parity.d.ts +85 -0
- package/dist/cli/parity.d.ts.map +1 -0
- package/dist/cli/parity.js +506 -0
- package/dist/cli/parity.js.map +1 -0
- package/dist/cli/plan.d.ts.map +1 -1
- package/dist/cli/plan.js +2 -1
- package/dist/cli/plan.js.map +1 -1
- package/dist/cli/publish.d.ts +22 -0
- package/dist/cli/publish.d.ts.map +1 -1
- package/dist/cli/publish.js +109 -13
- package/dist/cli/publish.js.map +1 -1
- package/dist/cli/retrieval.d.ts.map +1 -1
- package/dist/cli/retrieval.js +5 -4
- package/dist/cli/retrieval.js.map +1 -1
- package/dist/cli/sdk.js +4 -4
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli/trace.d.ts.map +1 -1
- package/dist/cli/trace.js +2 -1
- package/dist/cli/trace.js.map +1 -1
- package/dist/cli/workflow.js +2 -2
- package/dist/cli/workflow.js.map +1 -1
- package/dist/config/live-credentials.d.ts +57 -0
- package/dist/config/live-credentials.d.ts.map +1 -0
- package/dist/config/live-credentials.js +126 -0
- package/dist/config/live-credentials.js.map +1 -0
- package/dist/config/paths.d.ts +18 -0
- package/dist/config/paths.d.ts.map +1 -1
- package/dist/config/paths.js +25 -0
- package/dist/config/paths.js.map +1 -1
- package/dist/config/types.d.ts +44 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/federation/a2a-types.js +1 -1
- package/dist/federation/a2a-types.js.map +1 -1
- package/dist/findings/verdicts.d.ts +241 -0
- package/dist/findings/verdicts.d.ts.map +1 -0
- package/dist/findings/verdicts.js +284 -0
- package/dist/findings/verdicts.js.map +1 -0
- package/dist/gateway/adapters.d.ts +65 -0
- package/dist/gateway/adapters.d.ts.map +1 -1
- package/dist/gateway/adapters.js +216 -10
- package/dist/gateway/adapters.js.map +1 -1
- package/dist/gateway/channel-directory.d.ts +31 -0
- package/dist/gateway/channel-directory.d.ts.map +1 -1
- package/dist/gateway/channel-directory.js +40 -0
- package/dist/gateway/channel-directory.js.map +1 -1
- package/dist/gateway/gateway-log.d.ts +1 -1
- package/dist/gateway/gateway-log.d.ts.map +1 -1
- package/dist/gateway/gateway-log.js.map +1 -1
- package/dist/gateway/hooks.d.ts +87 -19
- package/dist/gateway/hooks.d.ts.map +1 -1
- package/dist/gateway/hooks.js +62 -23
- package/dist/gateway/hooks.js.map +1 -1
- package/dist/gateway/inbound-media.d.ts +147 -0
- package/dist/gateway/inbound-media.d.ts.map +1 -0
- package/dist/gateway/inbound-media.js +317 -0
- package/dist/gateway/inbound-media.js.map +1 -0
- package/dist/gateway/inbox.d.ts +8 -1
- package/dist/gateway/inbox.d.ts.map +1 -1
- package/dist/gateway/inbox.js.map +1 -1
- package/dist/gateway/platform-config.d.ts +14 -0
- package/dist/gateway/platform-config.d.ts.map +1 -1
- package/dist/gateway/platform-config.js +26 -8
- package/dist/gateway/platform-config.js.map +1 -1
- package/dist/gateway/realtime.d.ts +114 -0
- package/dist/gateway/realtime.d.ts.map +1 -0
- package/dist/gateway/realtime.js +402 -0
- package/dist/gateway/realtime.js.map +1 -0
- package/dist/gateway/registry.d.ts +31 -0
- package/dist/gateway/registry.d.ts.map +1 -1
- package/dist/gateway/registry.js +224 -4
- package/dist/gateway/registry.js.map +1 -1
- package/dist/gateway/whatsapp/baileys-bridge.d.ts +11 -1
- package/dist/gateway/whatsapp/baileys-bridge.d.ts.map +1 -1
- package/dist/gateway/whatsapp/baileys-bridge.js +123 -4
- package/dist/gateway/whatsapp/baileys-bridge.js.map +1 -1
- package/dist/gateway/whatsapp/bridge.d.ts +6 -2
- package/dist/gateway/whatsapp/bridge.d.ts.map +1 -1
- package/dist/gateway/whatsapp/bridge.js.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/inference/factory.d.ts +14 -0
- package/dist/inference/factory.d.ts.map +1 -1
- package/dist/inference/factory.js +17 -0
- package/dist/inference/factory.js.map +1 -1
- package/dist/inference/groq-adapter.d.ts +2 -0
- package/dist/inference/groq-adapter.d.ts.map +1 -1
- package/dist/inference/groq-adapter.js +16 -6
- package/dist/inference/groq-adapter.js.map +1 -1
- package/dist/inference/model-validator.d.ts +6 -1
- package/dist/inference/model-validator.d.ts.map +1 -1
- package/dist/inference/model-validator.js +7 -2
- package/dist/inference/model-validator.js.map +1 -1
- package/dist/inference/route-resolver.d.ts +116 -0
- package/dist/inference/route-resolver.d.ts.map +1 -0
- package/dist/inference/route-resolver.js +159 -0
- package/dist/inference/route-resolver.js.map +1 -0
- package/dist/inference/tools.d.ts.map +1 -1
- package/dist/inference/tools.js +29 -0
- package/dist/inference/tools.js.map +1 -1
- package/dist/learning/autonomy-policy.d.ts +18 -0
- package/dist/learning/autonomy-policy.d.ts.map +1 -1
- package/dist/learning/autonomy-policy.js +35 -0
- package/dist/learning/autonomy-policy.js.map +1 -1
- package/dist/learning/benchmark.d.ts.map +1 -1
- package/dist/learning/benchmark.js +3 -2
- package/dist/learning/benchmark.js.map +1 -1
- package/dist/learning/continuation.d.ts.map +1 -1
- package/dist/learning/continuation.js +2 -1
- package/dist/learning/continuation.js.map +1 -1
- package/dist/learning/cost-tracker.d.ts.map +1 -1
- package/dist/learning/cost-tracker.js +2 -1
- package/dist/learning/cost-tracker.js.map +1 -1
- package/dist/learning/deferred-task.d.ts.map +1 -1
- package/dist/learning/deferred-task.js +13 -4
- package/dist/learning/deferred-task.js.map +1 -1
- package/dist/learning/eval-framework.d.ts.map +1 -1
- package/dist/learning/eval-framework.js +2 -1
- package/dist/learning/eval-framework.js.map +1 -1
- package/dist/learning/long-form.d.ts.map +1 -1
- package/dist/learning/long-form.js +2 -1
- package/dist/learning/long-form.js.map +1 -1
- package/dist/learning/model-registry.d.ts.map +1 -1
- package/dist/learning/model-registry.js +2 -1
- package/dist/learning/model-registry.js.map +1 -1
- package/dist/learning/reasoning-cache.d.ts.map +1 -1
- package/dist/learning/reasoning-cache.js +2 -1
- package/dist/learning/reasoning-cache.js.map +1 -1
- package/dist/learning/reasoning-trace.d.ts +38 -2
- package/dist/learning/reasoning-trace.d.ts.map +1 -1
- package/dist/learning/reasoning-trace.js +91 -1
- package/dist/learning/reasoning-trace.js.map +1 -1
- package/dist/learning/resilient-call.d.ts.map +1 -1
- package/dist/learning/resilient-call.js +31 -18
- package/dist/learning/resilient-call.js.map +1 -1
- package/dist/learning/retrieval.d.ts.map +1 -1
- package/dist/learning/retrieval.js +2 -1
- package/dist/learning/retrieval.js.map +1 -1
- package/dist/learning/seeded-benchmark.d.ts +160 -0
- package/dist/learning/seeded-benchmark.d.ts.map +1 -0
- package/dist/learning/seeded-benchmark.js +321 -0
- package/dist/learning/seeded-benchmark.js.map +1 -0
- package/dist/learning/seeded-bugs.d.ts +142 -0
- package/dist/learning/seeded-bugs.d.ts.map +1 -0
- package/dist/learning/seeded-bugs.js +535 -0
- package/dist/learning/seeded-bugs.js.map +1 -0
- package/dist/learning/skill-store.d.ts.map +1 -1
- package/dist/learning/skill-store.js +30 -9
- package/dist/learning/skill-store.js.map +1 -1
- package/dist/learning/step-checkpoint.d.ts +127 -0
- package/dist/learning/step-checkpoint.d.ts.map +1 -0
- package/dist/learning/step-checkpoint.js +244 -0
- package/dist/learning/step-checkpoint.js.map +1 -0
- package/dist/mcp/catalog.js +2 -3
- package/dist/mcp/catalog.js.map +1 -1
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +5 -3
- package/dist/mcp/manager.js.map +1 -1
- package/dist/nlu/intent-confirm.d.ts +23 -1
- package/dist/nlu/intent-confirm.d.ts.map +1 -1
- package/dist/nlu/intent-confirm.js +85 -2
- package/dist/nlu/intent-confirm.js.map +1 -1
- package/dist/nlu/learnings.d.ts +7 -0
- package/dist/nlu/learnings.d.ts.map +1 -1
- package/dist/nlu/learnings.js +7 -0
- package/dist/nlu/learnings.js.map +1 -1
- package/dist/observability/debug-log.d.ts +250 -0
- package/dist/observability/debug-log.d.ts.map +1 -0
- package/dist/observability/debug-log.js +500 -0
- package/dist/observability/debug-log.js.map +1 -0
- package/dist/observability/event-bus.d.ts.map +1 -1
- package/dist/observability/event-bus.js +4 -1
- package/dist/observability/event-bus.js.map +1 -1
- package/dist/observability/otel.d.ts +278 -0
- package/dist/observability/otel.d.ts.map +1 -0
- package/dist/observability/otel.js +590 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/parity/drivers.d.ts +99 -0
- package/dist/parity/drivers.d.ts.map +1 -0
- package/dist/parity/drivers.js +1362 -0
- package/dist/parity/drivers.js.map +1 -0
- package/dist/parity/graph.d.ts +73 -0
- package/dist/parity/graph.d.ts.map +1 -0
- package/dist/parity/graph.js +162 -0
- package/dist/parity/graph.js.map +1 -0
- package/dist/parity/matrix.d.ts +105 -0
- package/dist/parity/matrix.d.ts.map +1 -0
- package/dist/parity/matrix.js +352 -0
- package/dist/parity/matrix.js.map +1 -0
- package/dist/parity/observation.d.ts +444 -0
- package/dist/parity/observation.d.ts.map +1 -0
- package/dist/parity/observation.js +333 -0
- package/dist/parity/observation.js.map +1 -0
- package/dist/parity/scenarios.d.ts +229 -0
- package/dist/parity/scenarios.d.ts.map +1 -0
- package/dist/parity/scenarios.js +175 -0
- package/dist/parity/scenarios.js.map +1 -0
- package/dist/parity/surfaces.d.ts +122 -0
- package/dist/parity/surfaces.d.ts.map +1 -0
- package/dist/parity/surfaces.js +190 -0
- package/dist/parity/surfaces.js.map +1 -0
- package/dist/runtime/fault-injection.d.ts +173 -0
- package/dist/runtime/fault-injection.d.ts.map +1 -0
- package/dist/runtime/fault-injection.js +281 -0
- package/dist/runtime/fault-injection.js.map +1 -0
- package/dist/skills/secret-capture.d.ts.map +1 -1
- package/dist/skills/secret-capture.js +9 -4
- package/dist/skills/secret-capture.js.map +1 -1
- package/dist/tools/child-agent-entry.d.ts +23 -0
- package/dist/tools/child-agent-entry.d.ts.map +1 -0
- package/dist/tools/child-agent-entry.js +129 -0
- package/dist/tools/child-agent-entry.js.map +1 -0
- package/dist/tools/child-agent-runtime.d.ts +124 -0
- package/dist/tools/child-agent-runtime.d.ts.map +1 -0
- package/dist/tools/child-agent-runtime.js +704 -0
- package/dist/tools/child-agent-runtime.js.map +1 -0
- package/dist/tools/coding-tools.d.ts.map +1 -1
- package/dist/tools/coding-tools.js +82 -10
- package/dist/tools/coding-tools.js.map +1 -1
- package/dist/tools/credentials-tool.d.ts +24 -0
- package/dist/tools/credentials-tool.d.ts.map +1 -0
- package/dist/tools/credentials-tool.js +125 -0
- package/dist/tools/credentials-tool.js.map +1 -0
- package/dist/tools/delegation-system.d.ts +31 -0
- package/dist/tools/delegation-system.d.ts.map +1 -1
- package/dist/tools/delegation-system.js +70 -9
- package/dist/tools/delegation-system.js.map +1 -1
- package/dist/tools/extract/docx.d.ts +27 -0
- package/dist/tools/extract/docx.d.ts.map +1 -0
- package/dist/tools/extract/docx.js +48 -0
- package/dist/tools/extract/docx.js.map +1 -0
- package/dist/tools/extract/html-text.d.ts +27 -0
- package/dist/tools/extract/html-text.d.ts.map +1 -0
- package/dist/tools/extract/html-text.js +86 -0
- package/dist/tools/extract/html-text.js.map +1 -0
- package/dist/tools/extract/pdf-ocr.d.ts +58 -0
- package/dist/tools/extract/pdf-ocr.d.ts.map +1 -0
- package/dist/tools/extract/pdf-ocr.js +116 -0
- package/dist/tools/extract/pdf-ocr.js.map +1 -0
- package/dist/tools/extract/pdf.d.ts +65 -0
- package/dist/tools/extract/pdf.d.ts.map +1 -0
- package/dist/tools/extract/pdf.js +197 -0
- package/dist/tools/extract/pdf.js.map +1 -0
- package/dist/tools/extract/pptx.d.ts +32 -0
- package/dist/tools/extract/pptx.d.ts.map +1 -0
- package/dist/tools/extract/pptx.js +77 -0
- package/dist/tools/extract/pptx.js.map +1 -0
- package/dist/tools/extract/xlsx.d.ts +47 -0
- package/dist/tools/extract/xlsx.d.ts.map +1 -0
- package/dist/tools/extract/xlsx.js +111 -0
- package/dist/tools/extract/xlsx.js.map +1 -0
- package/dist/tools/finding-tool.d.ts +76 -0
- package/dist/tools/finding-tool.d.ts.map +1 -0
- package/dist/tools/finding-tool.js +125 -0
- package/dist/tools/finding-tool.js.map +1 -0
- package/dist/tools/git-tool.d.ts +25 -7
- package/dist/tools/git-tool.d.ts.map +1 -1
- package/dist/tools/git-tool.js +155 -15
- package/dist/tools/git-tool.js.map +1 -1
- package/dist/tools/loop-project-context.d.ts.map +1 -1
- package/dist/tools/loop-project-context.js +16 -0
- package/dist/tools/loop-project-context.js.map +1 -1
- package/dist/tools/loop-route-feed.d.ts +57 -0
- package/dist/tools/loop-route-feed.d.ts.map +1 -0
- package/dist/tools/loop-route-feed.js +101 -0
- package/dist/tools/loop-route-feed.js.map +1 -0
- package/dist/tools/messaging-tools.d.ts +41 -11
- package/dist/tools/messaging-tools.d.ts.map +1 -1
- package/dist/tools/messaging-tools.js +104 -55
- package/dist/tools/messaging-tools.js.map +1 -1
- package/dist/tools/neutts-synth.d.ts +27 -3
- package/dist/tools/neutts-synth.d.ts.map +1 -1
- package/dist/tools/neutts-synth.js +57 -13
- package/dist/tools/neutts-synth.js.map +1 -1
- package/dist/tools/pipeline-tool.d.ts +43 -1
- package/dist/tools/pipeline-tool.d.ts.map +1 -1
- package/dist/tools/pipeline-tool.js +21 -4
- package/dist/tools/pipeline-tool.js.map +1 -1
- package/dist/tools/publish-tool.d.ts.map +1 -1
- package/dist/tools/publish-tool.js +76 -10
- package/dist/tools/publish-tool.js.map +1 -1
- package/dist/tools/read-extract.d.ts +116 -45
- package/dist/tools/read-extract.d.ts.map +1 -1
- package/dist/tools/read-extract.js +494 -158
- package/dist/tools/read-extract.js.map +1 -1
- package/dist/tools/registry.d.ts +23 -3
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +196 -29
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/run-terminal.d.ts +9 -0
- package/dist/tools/run-terminal.d.ts.map +1 -1
- package/dist/tools/run-terminal.js +80 -2
- package/dist/tools/run-terminal.js.map +1 -1
- package/dist/tools/subagent-refusal.d.ts +15 -0
- package/dist/tools/subagent-refusal.d.ts.map +1 -0
- package/dist/tools/subagent-refusal.js +18 -0
- package/dist/tools/subagent-refusal.js.map +1 -0
- package/dist/tools/subagent-spawner.d.ts +122 -0
- package/dist/tools/subagent-spawner.d.ts.map +1 -1
- package/dist/tools/subagent-spawner.js +249 -28
- package/dist/tools/subagent-spawner.js.map +1 -1
- package/dist/tools/tool-hooks.d.ts +177 -0
- package/dist/tools/tool-hooks.d.ts.map +1 -0
- package/dist/tools/tool-hooks.js +427 -0
- package/dist/tools/tool-hooks.js.map +1 -0
- package/dist/tools/tool-loop.d.ts +94 -5
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +315 -9
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/tools/tool-refusal.d.ts +68 -0
- package/dist/tools/tool-refusal.d.ts.map +1 -0
- package/dist/tools/tool-refusal.js +78 -0
- package/dist/tools/tool-refusal.js.map +1 -0
- package/dist/tools/toolsets.d.ts +8 -0
- package/dist/tools/toolsets.d.ts.map +1 -1
- package/dist/tools/toolsets.js +14 -4
- package/dist/tools/toolsets.js.map +1 -1
- package/dist/tools/vision-tools.d.ts +88 -83
- package/dist/tools/vision-tools.d.ts.map +1 -1
- package/dist/tools/vision-tools.js +134 -103
- package/dist/tools/vision-tools.js.map +1 -1
- package/dist/tools/worktree.d.ts +210 -0
- package/dist/tools/worktree.d.ts.map +1 -0
- package/dist/tools/worktree.js +374 -0
- package/dist/tools/worktree.js.map +1 -0
- package/dist/utils/format.d.ts +3 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +32 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/web-dashboard/attachment-extract.d.ts +64 -0
- package/dist/web-dashboard/attachment-extract.d.ts.map +1 -0
- package/dist/web-dashboard/attachment-extract.js +154 -0
- package/dist/web-dashboard/attachment-extract.js.map +1 -0
- package/dist/web-dashboard/chat-console.d.ts +108 -1
- package/dist/web-dashboard/chat-console.d.ts.map +1 -1
- package/dist/web-dashboard/chat-console.js +36 -0
- package/dist/web-dashboard/chat-console.js.map +1 -1
- package/dist/web-dashboard/hub-data.d.ts +37 -0
- package/dist/web-dashboard/hub-data.d.ts.map +1 -1
- package/dist/web-dashboard/hub-data.js +61 -1
- package/dist/web-dashboard/hub-data.js.map +1 -1
- package/dist/web-dashboard/server.d.ts +14 -0
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +247 -13
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +196 -48
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/dist/workflow/registry.js +1 -1
- package/dist/workflow/registry.js.map +1 -1
- package/package.json +22 -6
- package/src/web-dashboard/public/assets/{index-Cyd6tIew.css → index-XJjj2cBX.css} +1 -1
- package/src/web-dashboard/public/assets/index-YWF9FpwQ.js +207 -0
- package/src/web-dashboard/public/assets/index-YWF9FpwQ.js.map +1 -0
- package/src/web-dashboard/public/index.html +2 -2
- package/dist/tools/child-agent-worker.js +0 -212
- package/src/web-dashboard/public/assets/index-CjvoBhlz.js +0 -207
- package/src/web-dashboard/public/assets/index-CjvoBhlz.js.map +0 -1
package/dist/tools/tool-loop.js
CHANGED
|
@@ -16,6 +16,20 @@
|
|
|
16
16
|
* blocks after its response text (contract in TOOL_CONTRACT_JSON).
|
|
17
17
|
*/
|
|
18
18
|
import { getTool, toolJsonSchemas } from './registry.js';
|
|
19
|
+
// WS3 (#25) — the turn's span tree. Null-safe throughout: with export off every
|
|
20
|
+
// helper below is a no-op and no span object is ever built.
|
|
21
|
+
import { TOOL_SPAN_PREFIX, withSpanActive } from '../observability/otel.js';
|
|
22
|
+
// WS4 (#26) — the operator's tool lifecycle hooks. Never able to break a call:
|
|
23
|
+
// `runBeforeToolHooks` always resolves, and a broken hook never vetoes.
|
|
24
|
+
import { runBeforeToolHooks, runToolOutcomeHooks, toolHookRefusalText, } from './tool-hooks.js';
|
|
25
|
+
// WS5 (#27) — the resume ledger. A `StepReplay` is threaded through the turn
|
|
26
|
+
// when the run is a resume; `stepDigest` is over the whole input, so a step whose
|
|
27
|
+
// thread or tool schema changed MISSES and is paid for again (see the module).
|
|
28
|
+
import { stepDigest } from '../learning/step-checkpoint.js';
|
|
29
|
+
// WS6 (#28) — the declared fault seam. `faultAt` is a null check when this
|
|
30
|
+
// process declared no fault (`NUVIRA_INJECT_FAULT`), so an ordinary turn is
|
|
31
|
+
// unaffected.
|
|
32
|
+
import { faultAt } from '../runtime/fault-injection.js';
|
|
19
33
|
import { detectPermissionSeeking, isAffirmativeReply, replyAsksTheReader, requestAuthorizesWrites, stripTrailingPermissionSeek, } from '../learning/autonomy-policy.js';
|
|
20
34
|
import { envelopeFromPlan, envelopeFromRequest, getEnvelope, grantEnvelope, isEnvelopeKey, } from '../learning/intent-envelope.js';
|
|
21
35
|
import { detectProcessComplaint, isTraceKey, repeatNudge, runTraceFor, RunTrace, } from '../learning/run-trace.js';
|
|
@@ -23,7 +37,50 @@ import { wantsAuthoredArtifact } from '../learning/deliverable-class.js';
|
|
|
23
37
|
import { normalizeFollowups } from './followup-utils.js';
|
|
24
38
|
import { assessEditActivity, detectUnverifiedEditClaim, isVerificationTool, verificationNudgeFor, THINK_ONLY_ESCALATION, AUTHORIZED_WORK_NUDGE, deliverableNudge, } from './edit-verification.js';
|
|
25
39
|
import { effectiveToolJsonSchemas, coreToolJsonSchemas, isToolEnabled, toolsetForTool } from './toolsets.js';
|
|
40
|
+
import { deliverablesNamedIn, recordStepHandoff } from '../agents/step-handoff.js';
|
|
41
|
+
/**
|
|
42
|
+
* Tools that MUTATE the workspace. A refusal of one of these is the only
|
|
43
|
+
* refusal that leaves work undone — a declined `read_file` costs a step, a
|
|
44
|
+
* declined `write_file` means the deliverable was never produced.
|
|
45
|
+
*/
|
|
46
|
+
const MUTATING_TOOL_NAMES = new Set([
|
|
47
|
+
'write_file',
|
|
48
|
+
'edit_file',
|
|
49
|
+
'propose_change',
|
|
50
|
+
'run_terminal',
|
|
51
|
+
'run_cli',
|
|
52
|
+
]);
|
|
53
|
+
/** The path a mutating call was aimed at, when it named one. */
|
|
54
|
+
function mutatedPathOf(args) {
|
|
55
|
+
const a = args;
|
|
56
|
+
const p = a?.path ?? a?.file_path ?? a?.file;
|
|
57
|
+
return typeof p === 'string' && p.trim() ? p.trim() : undefined;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The ask this turn is answering — the text a hand-off is keyed against.
|
|
61
|
+
* `authorizationRequest` is the loop's own record of the last user message;
|
|
62
|
+
* the thread scan is the fallback for callers that do not set it (tests, direct
|
|
63
|
+
* invocations). Injected blocks (`[Project context]`, the route feed) are
|
|
64
|
+
* skipped: they are the loop's own additions, not the user's words.
|
|
65
|
+
*/
|
|
66
|
+
function currentAsk(opts) {
|
|
67
|
+
const recorded = opts.context?.authorizationRequest?.trim();
|
|
68
|
+
if (recorded)
|
|
69
|
+
return recorded.slice(0, 600);
|
|
70
|
+
const messages = opts.messages ?? [];
|
|
71
|
+
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
72
|
+
const m = messages[i];
|
|
73
|
+
if (m.role !== 'user')
|
|
74
|
+
continue;
|
|
75
|
+
const text = (m.content ?? '').trim();
|
|
76
|
+
if (!text || text.startsWith('['))
|
|
77
|
+
continue;
|
|
78
|
+
return text.slice(0, 600);
|
|
79
|
+
}
|
|
80
|
+
return '';
|
|
81
|
+
}
|
|
26
82
|
import { appendToolArtifact } from './artifact-append.js';
|
|
83
|
+
import { ROUTE_FEED_MARKER, isUnresolvedModel, routeFeedFingerprint, routeFeedText } from './loop-route-feed.js';
|
|
27
84
|
import { logger } from '../utils/logger.js';
|
|
28
85
|
import { toUserFacingGenerationError, TEXTUAL_TOOL_CALL_HINT, isTextualFollowupsPayload, followupEntriesFromPayload, stripTrailingFollowupsHeader, } from '../inference/tool-call-utils.js';
|
|
29
86
|
// ─── P3c — tool-fallback hints (switch tools when one fails) ────────────────
|
|
@@ -519,6 +576,8 @@ async function runToolLoopInner(opts, progress) {
|
|
|
519
576
|
return added;
|
|
520
577
|
};
|
|
521
578
|
const thread = [...messages];
|
|
579
|
+
/** Serving pairs the loop has already told the model about, oldest first. */
|
|
580
|
+
const routeFeedState = { pairs: [] };
|
|
522
581
|
// ── Stage 2: answer a question ABOUT the run from the run ────────────────
|
|
523
582
|
// The live audit's worst moment was the user asking "why are you asking me
|
|
524
583
|
// this again and again?" and the turn replying with an edit plan — not through
|
|
@@ -546,6 +605,13 @@ async function runToolLoopInner(opts, progress) {
|
|
|
546
605
|
// steps, one advisory delegate suggestion fires (bounded, deterministic).
|
|
547
606
|
const parallel = makeParallelSuggester();
|
|
548
607
|
let steps = 0;
|
|
608
|
+
/**
|
|
609
|
+
* WS5 (#27) — model calls this run did NOT make because the checkpoint had a
|
|
610
|
+
* recorded answer for the exact same input. Zero on an ordinary run, and
|
|
611
|
+
* reported rather than merely logged: "this turn cost one model call instead of
|
|
612
|
+
* three" is the whole claim of a partial resume.
|
|
613
|
+
*/
|
|
614
|
+
let replayedSteps = 0;
|
|
549
615
|
// The last SUBSTANTIVE answer text. JSON-only steps (a `{"tool":...}` block
|
|
550
616
|
// with no visible text, common after the model already answered) must NOT
|
|
551
617
|
// clobber it — otherwise the delivered answer is lost and the turn ends
|
|
@@ -570,7 +636,7 @@ async function runToolLoopInner(opts, progress) {
|
|
|
570
636
|
// P4 — check cancellation BEFORE each step (a pre-aborted signal never
|
|
571
637
|
// spends a model call) and after tool executions (below).
|
|
572
638
|
if (opts.signal?.aborted) {
|
|
573
|
-
return { content: '', followups, toolCalls: toolCallsRun, steps, bounded: false, cancelled: true };
|
|
639
|
+
return { content: '', followups, toolCalls: toolCallsRun, steps, ...(opts.resume ? { replayedSteps } : {}), bounded: false, cancelled: true };
|
|
574
640
|
}
|
|
575
641
|
steps += 1;
|
|
576
642
|
// Mechanical thread budget: trim BEFORE the model call so a provider
|
|
@@ -584,9 +650,35 @@ async function runToolLoopInner(opts, progress) {
|
|
|
584
650
|
deps.onEvent?.(` ✂️ ${trimmedResult.trimmed} old tool result(s) trimmed to fit the ${Math.round(budgetChars / 1000)}K-char context budget.`);
|
|
585
651
|
}
|
|
586
652
|
}
|
|
653
|
+
// ── The route feed, re-synced before every call ────────────────────────
|
|
654
|
+
// Placed here rather than at thread construction because THIS is the last
|
|
655
|
+
// point before the call: a failover during step N must be visible at step
|
|
656
|
+
// N+1, and a single up-front line would have the model answering about a
|
|
657
|
+
// model that has since stopped serving it.
|
|
658
|
+
syncRouteFeed(thread, opts.servedRoute, routeFeedState);
|
|
587
659
|
let response;
|
|
588
660
|
try {
|
|
589
|
-
|
|
661
|
+
// WS5 (#27) — a resumed run replays this step when its input is unchanged.
|
|
662
|
+
// The key is the step's POSITION and the digest is its whole input, so both
|
|
663
|
+
// have to line up: a plan that shifted by one step replays nothing (the
|
|
664
|
+
// positions hold different inputs), while a re-run of the same plan replays
|
|
665
|
+
// every step whose thread and schema are byte-identical.
|
|
666
|
+
const resumeKey = `model:${steps}`;
|
|
667
|
+
const resumeDigest = opts.resume ? stepDigest(thread, schemas) : '';
|
|
668
|
+
const replayed = opts.resume?.replay(resumeKey, resumeDigest) ?? null;
|
|
669
|
+
if (replayed) {
|
|
670
|
+
response = replayed;
|
|
671
|
+
replayedSteps += 1;
|
|
672
|
+
deps.onEvent?.(` ↩️ step ${steps} replayed from the checkpoint — no model call`);
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
response = await deps.callModel(thread, schemas, opts.onToken, opts.signal);
|
|
676
|
+
// Recorded AFTER the call, and only what the model actually returned: a
|
|
677
|
+
// failed call records nothing, so a resume cannot inherit a failure as an
|
|
678
|
+
// answer.
|
|
679
|
+
if (opts.resume)
|
|
680
|
+
opts.resume.record(resumeKey, resumeDigest, response);
|
|
681
|
+
}
|
|
590
682
|
// A provider/adapter that resolves with nothing usable (undefined, a
|
|
591
683
|
// missing content field) must not crash the turn — treat it as this
|
|
592
684
|
// step's generation failure so the bounded continuation logic below can
|
|
@@ -595,13 +687,18 @@ async function runToolLoopInner(opts, progress) {
|
|
|
595
687
|
if (!response || typeof response.content !== 'string' || !Array.isArray(response.toolCalls)) {
|
|
596
688
|
throw new Error('model returned a malformed step response (no content/toolCalls)');
|
|
597
689
|
}
|
|
690
|
+
// R2 — the transport the caller reported for THIS step. Recorded before
|
|
691
|
+
// anything can return, so a turn that dies mid-way still attributes the
|
|
692
|
+
// transport that served the steps it did complete.
|
|
693
|
+
if (response.transport)
|
|
694
|
+
progress.transport = response.transport;
|
|
598
695
|
}
|
|
599
696
|
catch (err) {
|
|
600
697
|
// P4 — an abort (the dashboard Cancel button) is a clean stop, NOT a
|
|
601
698
|
// generation failure: the caller discards the turn. No error text, no
|
|
602
699
|
// fallback — the fetch itself aborted on the caller's signal.
|
|
603
700
|
if (opts.signal?.aborted) {
|
|
604
|
-
return { content: '', followups, toolCalls: toolCallsRun, steps, bounded: false, cancelled: true };
|
|
701
|
+
return { content: '', followups, toolCalls: toolCallsRun, steps, ...(opts.resume ? { replayedSteps } : {}), bounded: false, cancelled: true };
|
|
605
702
|
}
|
|
606
703
|
// Generation failure — surface what we have rather than crash the turn.
|
|
607
704
|
// generationFailed is TRUE only when NOTHING happened yet (no content, no
|
|
@@ -663,6 +760,7 @@ async function runToolLoopInner(opts, progress) {
|
|
|
663
760
|
followups,
|
|
664
761
|
toolCalls: toolCallsRun,
|
|
665
762
|
steps,
|
|
763
|
+
...(opts.resume ? { replayedSteps } : {}),
|
|
666
764
|
bounded: false,
|
|
667
765
|
continuations,
|
|
668
766
|
generationFailed: delivered === '' || !madeProgress,
|
|
@@ -934,6 +1032,7 @@ async function runToolLoopInner(opts, progress) {
|
|
|
934
1032
|
followups,
|
|
935
1033
|
toolCalls: toolCallsRun,
|
|
936
1034
|
steps,
|
|
1035
|
+
...(opts.resume ? { replayedSteps } : {}),
|
|
937
1036
|
bounded: false,
|
|
938
1037
|
continuations,
|
|
939
1038
|
};
|
|
@@ -1016,31 +1115,117 @@ async function runToolLoopInner(opts, progress) {
|
|
|
1016
1115
|
followups.length = 0;
|
|
1017
1116
|
}
|
|
1018
1117
|
// I2: emit `tool:started` (before execution) + `tool:called` (after)
|
|
1019
|
-
// on the observability bus — drives the
|
|
1020
|
-
// the `post_tool_call` hook AND the dashboard's
|
|
1118
|
+
// on the observability bus — drives the dashboard's
|
|
1021
1119
|
// step cards (P0.6: the GUI renders each call as a live card —
|
|
1022
1120
|
// running → ok/error with duration + collapsible result). Timing is
|
|
1023
1121
|
// wall-clock; `ok` mirrors the tool-result convention (Error: prefix).
|
|
1024
1122
|
const startedAt = Date.now();
|
|
1123
|
+
// WS4 (#26) — the `before` hooks, and the ONE place an operator's veto can
|
|
1124
|
+
// stop a call. It happens before `tool:started` is announced and before a
|
|
1125
|
+
// span is created, so a vetoed call leaves no evidence of having run — and
|
|
1126
|
+
// it is reported as a `called` call with an `Error:` result, so every
|
|
1127
|
+
// surface's tool lifecycle shows the attempt and its outcome rather than an
|
|
1128
|
+
// unexplained gap.
|
|
1129
|
+
const beforeHooks = await runBeforeToolHooks({
|
|
1130
|
+
tool: call.name,
|
|
1131
|
+
args: call.arguments,
|
|
1132
|
+
callId: call.id,
|
|
1133
|
+
...(opts.surface ? { surface: opts.surface } : {}),
|
|
1134
|
+
...(ctx.cwd ? { cwd: ctx.cwd } : {}),
|
|
1135
|
+
...(ctx.configManager ? { configManager: ctx.configManager } : {}),
|
|
1136
|
+
});
|
|
1137
|
+
for (const problem of beforeHooks.problems) {
|
|
1138
|
+
// A hook that failed to run is REPORTED rather than swallowed: the seam
|
|
1139
|
+
// fails open, so without this a broken policy looks exactly like one that
|
|
1140
|
+
// allowed everything.
|
|
1141
|
+
traceEvent({ kind: 'gate', gate: 'tool-hook', tool: call.name, ok: false, summary: problem });
|
|
1142
|
+
}
|
|
1143
|
+
if (beforeHooks.denied) {
|
|
1144
|
+
const refusal = toolHookRefusalText(beforeHooks);
|
|
1145
|
+
traceEvent({
|
|
1146
|
+
kind: 'gate',
|
|
1147
|
+
gate: 'tool-hook',
|
|
1148
|
+
tool: call.name,
|
|
1149
|
+
ok: false,
|
|
1150
|
+
summary: `${beforeHooks.by ?? 'a tool hook'} refused ${call.name}` +
|
|
1151
|
+
(beforeHooks.reason ? `: ${beforeHooks.reason}` : ''),
|
|
1152
|
+
});
|
|
1153
|
+
deps.onEvent?.(` ⛔ ${call.name} — refused by a tool hook`);
|
|
1154
|
+
ctx.emit?.('tool:called', {
|
|
1155
|
+
id: call.id,
|
|
1156
|
+
tool: call.name,
|
|
1157
|
+
ok: false,
|
|
1158
|
+
result: refusal,
|
|
1159
|
+
durationMs: Date.now() - startedAt,
|
|
1160
|
+
});
|
|
1161
|
+
return refusal;
|
|
1162
|
+
}
|
|
1163
|
+
/**
|
|
1164
|
+
* Tell the `after` / `failed` hooks what happened to this call.
|
|
1165
|
+
*
|
|
1166
|
+
* Observe-only by construction: the outcome has already been decided and
|
|
1167
|
+
* reported by the time this runs, so a hook here cannot rewrite history —
|
|
1168
|
+
* the phase it is named for is the fact it receives.
|
|
1169
|
+
*/
|
|
1170
|
+
const reportToolOutcome = async (outcome) => {
|
|
1171
|
+
const report = await runToolOutcomeHooks({
|
|
1172
|
+
tool: call.name,
|
|
1173
|
+
args: call.arguments,
|
|
1174
|
+
callId: call.id,
|
|
1175
|
+
...(opts.surface ? { surface: opts.surface } : {}),
|
|
1176
|
+
...(ctx.cwd ? { cwd: ctx.cwd } : {}),
|
|
1177
|
+
...(ctx.configManager ? { configManager: ctx.configManager } : {}),
|
|
1178
|
+
durationMs: Date.now() - startedAt,
|
|
1179
|
+
...outcome,
|
|
1180
|
+
});
|
|
1181
|
+
for (const problem of report.problems) {
|
|
1182
|
+
traceEvent({ kind: 'gate', gate: 'tool-hook', tool: call.name, ok: false, summary: problem });
|
|
1183
|
+
}
|
|
1184
|
+
};
|
|
1025
1185
|
ctx.emit?.('tool:started', {
|
|
1026
1186
|
id: call.id,
|
|
1027
1187
|
tool: call.name,
|
|
1028
1188
|
args: call.arguments,
|
|
1029
1189
|
});
|
|
1190
|
+
// WS3 (#25) — the call as a child span of the turn. Created where the call
|
|
1191
|
+
// actually runs (not where it is announced), so a call that was REFUSED by
|
|
1192
|
+
// a gate above never gets a span claiming it happened.
|
|
1193
|
+
const toolSpan = opts.otel?.child(`${TOOL_SPAN_PREFIX}${call.name}`, { 'nuvira.tool': call.name }) ?? null;
|
|
1030
1194
|
try {
|
|
1031
1195
|
deps.onEvent?.(` ⚙ ${call.name}(${summarizeArgs(call.arguments)})`);
|
|
1032
|
-
|
|
1196
|
+
// The span is ACTIVE for the whole execution: that is what lets a tool
|
|
1197
|
+
// which spawns a subagent propagate the trace instead of starting a
|
|
1198
|
+
// second, unrelated one in the child.
|
|
1199
|
+
let resultText = await withSpanActive(toolSpan, async () => {
|
|
1200
|
+
// WS6 (#28) — a DECLARED fault, injected at the one place this loop runs
|
|
1201
|
+
// a tool, so every in-process surface (CLI chat, dashboard, gateway,
|
|
1202
|
+
// execute) is affected by the same declaration and none of them needs to
|
|
1203
|
+
// know the seam exists. The result is an `Error:` string rather than a
|
|
1204
|
+
// throw, which is exactly what a tool that really failed returns — so the
|
|
1205
|
+
// call is reported as FAILED, the `failed` hook fires, and the model is
|
|
1206
|
+
// handed the fault's own words. With no declaration this is a null check.
|
|
1207
|
+
const injected = faultAt('tool', call.name);
|
|
1208
|
+
if (injected)
|
|
1209
|
+
return `Error: ${injected.message}`;
|
|
1210
|
+
return deps.executeTool(call.name, call.arguments, ctx);
|
|
1211
|
+
});
|
|
1033
1212
|
// I3: a tool that returns {artifact, result} gets its deliverable
|
|
1034
1213
|
// recorded on the session and only `result`
|
|
1035
1214
|
// is fed back to the model — the JSON payload is runtime metadata.
|
|
1036
1215
|
resultText = appendToolArtifact(resultText, ctx.artifacts);
|
|
1216
|
+
// The SAME outcome convention the loop uses everywhere else (`Error:`
|
|
1217
|
+
// prefix), so the span cannot report a success the result did not have.
|
|
1218
|
+
const toolOk = !resultText.startsWith('Error:');
|
|
1037
1219
|
ctx.emit?.('tool:called', {
|
|
1038
1220
|
id: call.id,
|
|
1039
1221
|
tool: call.name,
|
|
1040
|
-
ok:
|
|
1222
|
+
ok: toolOk,
|
|
1041
1223
|
result: resultText,
|
|
1042
1224
|
durationMs: Date.now() - startedAt,
|
|
1043
1225
|
});
|
|
1226
|
+
toolSpan?.attr('nuvira.ok', toolOk);
|
|
1227
|
+
toolSpan?.end({ ok: toolOk });
|
|
1228
|
+
await reportToolOutcome({ ok: toolOk, result: resultText });
|
|
1044
1229
|
if (call.name === 'suggest_followups')
|
|
1045
1230
|
endedAfterConcluding = true;
|
|
1046
1231
|
return resultText;
|
|
@@ -1054,10 +1239,16 @@ async function runToolLoopInner(opts, progress) {
|
|
|
1054
1239
|
error: message,
|
|
1055
1240
|
durationMs: Date.now() - startedAt,
|
|
1056
1241
|
});
|
|
1242
|
+
toolSpan?.end({ ok: false, message });
|
|
1243
|
+
await reportToolOutcome({ ok: false, error: message });
|
|
1057
1244
|
return `Error: ${message}`;
|
|
1058
1245
|
}
|
|
1059
1246
|
finally {
|
|
1060
1247
|
toolDurations.set(call.id, Date.now() - startedAt);
|
|
1248
|
+
// A safety net, not a second report: `end()` is idempotent, so a call
|
|
1249
|
+
// that already ended its span is untouched, and one that reached here
|
|
1250
|
+
// without reporting says so rather than defaulting to success.
|
|
1251
|
+
toolSpan?.end({ ok: false, message: 'tool outcome was never reported' });
|
|
1061
1252
|
}
|
|
1062
1253
|
};
|
|
1063
1254
|
const executed = new Array(plans.length).fill('');
|
|
@@ -1146,6 +1337,40 @@ async function runToolLoopInner(opts, progress) {
|
|
|
1146
1337
|
// can see "blocked twice, identically" instead of rediscovering it — and
|
|
1147
1338
|
// so the repetition gate has a refusal signal as well as an ask signal.
|
|
1148
1339
|
runTrace.recordRefusal(call.name, refusal?.gate ?? 'error', rawResult);
|
|
1340
|
+
// ── DURABLE HAND-OFF ────────────────────────────────────────────────
|
|
1341
|
+
// A refused MUTATION is the one failure that must outlive the turn.
|
|
1342
|
+
// The live NVDA-addon failure is exactly this: `write_file` was refused
|
|
1343
|
+
// on every attempt because the target was outside the workspace, and
|
|
1344
|
+
// each of the 18 following attempts rediscovered it from zero — same
|
|
1345
|
+
// plan, same refusal, same empty package. Recording it here means the
|
|
1346
|
+
// next candidate, the next turn and the next RUN are told which path
|
|
1347
|
+
// could not be written and WHY, so they change approach instead of
|
|
1348
|
+
// repeating the identical call (see step-handoff.ts).
|
|
1349
|
+
//
|
|
1350
|
+
// Best-effort: a hand-off write must never break the loop.
|
|
1351
|
+
if (refusal !== null && MUTATING_TOOL_NAMES.has(call.name)) {
|
|
1352
|
+
try {
|
|
1353
|
+
const ask = currentAsk(opts);
|
|
1354
|
+
const aimedAt = mutatedPathOf(call.arguments);
|
|
1355
|
+
// Key on the deliverable the ASK names when there is one, so the
|
|
1356
|
+
// same work asked for in different words resumes the same hand-off.
|
|
1357
|
+
const named = deliverablesNamedIn(ask);
|
|
1358
|
+
recordStepHandoff({
|
|
1359
|
+
projectPath: opts.context?.cwd || process.cwd(),
|
|
1360
|
+
goal: ask,
|
|
1361
|
+
stepDescription: aimedAt
|
|
1362
|
+
? `${call.name} → ${aimedAt} (refused: ${refusal.gate ?? 'gate'})`
|
|
1363
|
+
: `${call.name} (refused: ${refusal.gate ?? 'gate'})`,
|
|
1364
|
+
declared: named.length > 0 ? named : aimedAt ? [aimedAt] : [],
|
|
1365
|
+
route: 'loop',
|
|
1366
|
+
kind: 'refused',
|
|
1367
|
+
reason: `${refusal.summary}${aimedAt ? ` — path: ${aimedAt}` : ''}`,
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
catch {
|
|
1371
|
+
// Best-effort — a hand-off write must never break the loop.
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1149
1374
|
}
|
|
1150
1375
|
let resultText = executed[i];
|
|
1151
1376
|
// P3c — on error/denial, append the deterministic fallback hint for
|
|
@@ -1186,7 +1411,7 @@ async function runToolLoopInner(opts, progress) {
|
|
|
1186
1411
|
// P4 — cancellation during/after tool execution: do NOT request another
|
|
1187
1412
|
// model step on a cancelled turn (the user already walked away).
|
|
1188
1413
|
if (opts.signal?.aborted) {
|
|
1189
|
-
return { content: '', followups, toolCalls: toolCallsRun, steps, bounded: false, cancelled: true };
|
|
1414
|
+
return { content: '', followups, toolCalls: toolCallsRun, steps, ...(opts.resume ? { replayedSteps } : {}), bounded: false, cancelled: true };
|
|
1190
1415
|
}
|
|
1191
1416
|
// ── endsAgentStep — a successful dispenser's RESULT is the answer ────────
|
|
1192
1417
|
// `build`/`resume`/`repair`/`document`/`website`/`analyze`/`test`/`publish`
|
|
@@ -1213,6 +1438,7 @@ async function runToolLoopInner(opts, progress) {
|
|
|
1213
1438
|
followups,
|
|
1214
1439
|
toolCalls: toolCallsRun,
|
|
1215
1440
|
steps,
|
|
1441
|
+
...(opts.resume ? { replayedSteps } : {}),
|
|
1216
1442
|
bounded: false,
|
|
1217
1443
|
continuations,
|
|
1218
1444
|
};
|
|
@@ -1291,6 +1517,7 @@ async function runToolLoopInner(opts, progress) {
|
|
|
1291
1517
|
followups,
|
|
1292
1518
|
toolCalls: toolCallsRun,
|
|
1293
1519
|
steps,
|
|
1520
|
+
...(opts.resume ? { replayedSteps } : {}),
|
|
1294
1521
|
bounded: false,
|
|
1295
1522
|
continuations,
|
|
1296
1523
|
};
|
|
@@ -1310,6 +1537,7 @@ async function runToolLoopInner(opts, progress) {
|
|
|
1310
1537
|
followups,
|
|
1311
1538
|
toolCalls: toolCallsRun,
|
|
1312
1539
|
steps,
|
|
1540
|
+
...(opts.resume ? { replayedSteps } : {}),
|
|
1313
1541
|
bounded: true,
|
|
1314
1542
|
continuations,
|
|
1315
1543
|
};
|
|
@@ -1444,6 +1672,69 @@ export function detectUnfulfilledIntentPromise(content) {
|
|
|
1444
1672
|
* honest-answer flags so every surface (CLI, dashboard, gateway, trace) can
|
|
1445
1673
|
* distinguish "generated a reply" from "actually performed the action".
|
|
1446
1674
|
*/
|
|
1675
|
+
/**
|
|
1676
|
+
* Keep ONE route frame in the thread, current with what is serving the turn.
|
|
1677
|
+
*
|
|
1678
|
+
* Insert/replace is deliberate: appending a frame per step would pile up stale
|
|
1679
|
+
* route claims the model can quote back ("I am gemini-2.5-flash" — from step 1,
|
|
1680
|
+
* after a failover), and rewriting unconditionally would churn the thread (and
|
|
1681
|
+
* the thread budget) on every step for no change in content.
|
|
1682
|
+
*
|
|
1683
|
+
* A caller with no route supplies nothing; a caller whose route resolves to the
|
|
1684
|
+
* same fact as last step gets no write.
|
|
1685
|
+
*/
|
|
1686
|
+
function syncRouteFeed(thread, read, observed) {
|
|
1687
|
+
if (!read)
|
|
1688
|
+
return;
|
|
1689
|
+
let route = null;
|
|
1690
|
+
try {
|
|
1691
|
+
route = read();
|
|
1692
|
+
}
|
|
1693
|
+
catch {
|
|
1694
|
+
// A route read must never break the turn; an unknown route is a fact too.
|
|
1695
|
+
return;
|
|
1696
|
+
}
|
|
1697
|
+
if (!route)
|
|
1698
|
+
return;
|
|
1699
|
+
// The loop OWNS the failover history, because the loop is the only thing that
|
|
1700
|
+
// sees the sequence of routes it told the model about. Requiring each caller
|
|
1701
|
+
// to track it means every future caller can silently forget, and a model told
|
|
1702
|
+
// only the current pair describes the whole turn as having been run by it —
|
|
1703
|
+
// the same fabricated answer, one layer down.
|
|
1704
|
+
const currentPair = isUnresolvedModel(route.model) ? '' : `${route.providerType}/${route.model}`;
|
|
1705
|
+
const previous = [...(route.previous ?? [])];
|
|
1706
|
+
for (const pair of observed.pairs) {
|
|
1707
|
+
if (pair !== currentPair && !previous.includes(pair))
|
|
1708
|
+
previous.push(pair);
|
|
1709
|
+
}
|
|
1710
|
+
const rendered = previous.length > 0 ? { ...route, previous } : route;
|
|
1711
|
+
const fingerprint = routeFeedFingerprint(rendered);
|
|
1712
|
+
const index = thread.findIndex((m) => m.role === 'system' && typeof m.content === 'string' && m.content.startsWith(ROUTE_FEED_MARKER));
|
|
1713
|
+
if (currentPair && !observed.pairs.includes(currentPair))
|
|
1714
|
+
observed.pairs.push(currentPair);
|
|
1715
|
+
if (index === -1) {
|
|
1716
|
+
const frame = { role: 'system', content: routeFeedText(rendered) };
|
|
1717
|
+
// Immediately after the leading system prompt when there is one — the route
|
|
1718
|
+
// belongs with the run's own framing, not buried under tool output.
|
|
1719
|
+
const insertAt = thread.length > 0 && thread[0].role === 'system' ? 1 : 0;
|
|
1720
|
+
thread.splice(insertAt, 0, frame);
|
|
1721
|
+
routeFeedFingerprints.set(frame, fingerprint);
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
const existing = thread[index];
|
|
1725
|
+
if (routeFeedFingerprints.get(existing) === fingerprint)
|
|
1726
|
+
return;
|
|
1727
|
+
const updated = { role: 'system', content: routeFeedText(rendered) };
|
|
1728
|
+
thread[index] = updated;
|
|
1729
|
+
routeFeedFingerprints.delete(existing);
|
|
1730
|
+
routeFeedFingerprints.set(updated, fingerprint);
|
|
1731
|
+
}
|
|
1732
|
+
/**
|
|
1733
|
+
* Fingerprint per frame object, so a thread that was trimmed and re-built does
|
|
1734
|
+
* not re-write identical content. A WeakMap: a frame the loop drops is garbage
|
|
1735
|
+
* the moment nothing references it.
|
|
1736
|
+
*/
|
|
1737
|
+
const routeFeedFingerprints = new WeakMap();
|
|
1447
1738
|
export async function runToolLoop(opts) {
|
|
1448
1739
|
const progress = {
|
|
1449
1740
|
successfulToolCalls: [],
|
|
@@ -1452,6 +1743,11 @@ export async function runToolLoop(opts) {
|
|
|
1452
1743
|
verificationEvidence: [],
|
|
1453
1744
|
};
|
|
1454
1745
|
const result = await runToolLoopInner(opts, progress);
|
|
1746
|
+
// R2 — relay the transport the caller's seam reported. Attached on EVERY
|
|
1747
|
+
// exit path, including a cancelled/failed turn: if a model call happened over
|
|
1748
|
+
// the JSON fallback before the turn died, that is a fact about the run.
|
|
1749
|
+
if (progress.transport)
|
|
1750
|
+
result.transport = progress.transport;
|
|
1455
1751
|
if (!result.cancelled && !result.generationFailed) {
|
|
1456
1752
|
result.successfulToolCalls = [...progress.successfulToolCalls];
|
|
1457
1753
|
result.deliveryConfirmed = progress.deliveryConfirmed;
|
|
@@ -1579,7 +1875,17 @@ function previewToolResult(result, max = 200) {
|
|
|
1579
1875
|
*/
|
|
1580
1876
|
export function classifyToolRefusal(result) {
|
|
1581
1877
|
const text = result || '';
|
|
1582
|
-
if (/needs explicit confirmation|requires confirmation|retry with confirm|call ask_user/i.test(text)
|
|
1878
|
+
if (/needs explicit confirmation|requires confirmation|retry with confirm|call ask_user/i.test(text) ||
|
|
1879
|
+
// The REAL `confirmFirst` wording (coding-tools.ts: "write_file: state-changing
|
|
1880
|
+
// — NOT applied. Ask the user first via ask_user (…), then retry write_file with
|
|
1881
|
+
// confirm:true once they approve.") matched NONE of the patterns above: the
|
|
1882
|
+
// words are the same but the phrasing is "retry write_file with confirm", not
|
|
1883
|
+
// "retry with confirm". A write that was NOT applied therefore counted as a call
|
|
1884
|
+
// that ran — so the path it named counted as a MUTATION, the run trace recorded
|
|
1885
|
+
// a change that never happened, and the verification gate asked the model to
|
|
1886
|
+
// check a file nothing had written. Found by the child's gate, where the same
|
|
1887
|
+
// miscount reported `unverifiedEdit` for an empty diff.
|
|
1888
|
+
/\bstate-changing\b[^.]*\bNOT applied\b|\bretry\s+\w+\s+with\s+confirm/i.test(text)) {
|
|
1583
1889
|
return { gate: 'confirmation', summary: 'declined until the user approves — the gate asked before acting' };
|
|
1584
1890
|
}
|
|
1585
1891
|
// A BOUNDARY denial is the other refusal that did not read as one. The
|