@warlock.js/ai 4.2.10 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -1
- package/cjs/index.cjs +10151 -4625
- package/cjs/index.cjs.map +1 -1
- package/cjs/magic-string.es-BtxW4VqG.cjs +1015 -0
- package/cjs/magic-string.es-BtxW4VqG.cjs.map +1 -0
- package/cjs/matcher-logic-SBnzYohQ.cjs +217 -0
- package/cjs/matcher-logic-SBnzYohQ.cjs.map +1 -0
- package/cjs/matchers-BBh3gyB-.cjs +13739 -0
- package/cjs/matchers-BBh3gyB-.cjs.map +1 -0
- package/esm/agent/agent-config.type.d.mts +19 -6
- package/esm/agent/agent-config.type.d.mts.map +1 -1
- package/esm/agent/agent.d.mts.map +1 -1
- package/esm/agent/agent.mjs +17 -6
- package/esm/agent/agent.mjs.map +1 -1
- package/esm/agent/index.d.mts +2 -1
- package/esm/agent/index.mjs +1 -0
- package/esm/agent/spawn-sub-agent.d.mts +87 -0
- package/esm/agent/spawn-sub-agent.d.mts.map +1 -0
- package/esm/agent/spawn-sub-agent.mjs +68 -0
- package/esm/agent/spawn-sub-agent.mjs.map +1 -0
- package/esm/ai.d.mts +58 -3
- package/esm/ai.d.mts.map +1 -1
- package/esm/ai.mjs +58 -3
- package/esm/ai.mjs.map +1 -1
- package/esm/batch/batch.d.mts +43 -0
- package/esm/batch/batch.d.mts.map +1 -0
- package/esm/batch/batch.mjs +179 -0
- package/esm/batch/batch.mjs.map +1 -0
- package/esm/batch/batch.type.d.mts +144 -0
- package/esm/batch/batch.type.d.mts.map +1 -0
- package/esm/batch/index.mjs +3 -0
- package/esm/batch/run-batch-item.mjs +100 -0
- package/esm/batch/run-batch-item.mjs.map +1 -0
- package/esm/batch/run-with-concurrency.mjs +39 -0
- package/esm/batch/run-with-concurrency.mjs.map +1 -0
- package/esm/checkpoint/index.d.mts +3 -0
- package/esm/checkpoint/memory.d.mts +21 -0
- package/esm/checkpoint/memory.d.mts.map +1 -0
- package/esm/checkpoint/memory.mjs +0 -0
- package/esm/checkpoint/memory.mjs.map +1 -0
- package/esm/checkpoint/pg.d.mts +37 -0
- package/esm/checkpoint/pg.d.mts.map +1 -0
- package/esm/checkpoint/pg.mjs +265 -0
- package/esm/checkpoint/pg.mjs.map +1 -0
- package/esm/checkpoint/redis.d.mts +39 -0
- package/esm/checkpoint/redis.d.mts.map +1 -0
- package/esm/checkpoint/redis.mjs +200 -0
- package/esm/checkpoint/redis.mjs.map +1 -0
- package/esm/config.d.mts +61 -14
- package/esm/config.d.mts.map +1 -1
- package/esm/config.mjs +25 -6
- package/esm/config.mjs.map +1 -1
- package/esm/contracts/agent/agent.contract.d.mts +43 -0
- package/esm/contracts/agent/agent.contract.d.mts.map +1 -1
- package/esm/contracts/agent/eval.type.d.mts +143 -0
- package/esm/contracts/agent/eval.type.d.mts.map +1 -0
- package/esm/contracts/agent/index.d.mts +1 -0
- package/esm/contracts/events/supervisor-events.type.d.mts +3 -3
- package/esm/contracts/fallback-model.contract.d.mts +65 -0
- package/esm/contracts/fallback-model.contract.d.mts.map +1 -0
- package/esm/contracts/index.d.mts +32 -12
- package/esm/contracts/memory/index.d.mts +4 -0
- package/esm/contracts/memory/memory-config.type.d.mts +150 -0
- package/esm/contracts/memory/memory-config.type.d.mts.map +1 -0
- package/esm/contracts/memory/memory-item.type.d.mts +64 -0
- package/esm/contracts/memory/memory-item.type.d.mts.map +1 -0
- package/esm/contracts/memory/memory.contract.d.mts +87 -0
- package/esm/contracts/memory/memory.contract.d.mts.map +1 -0
- package/esm/contracts/memory/recall-options.type.d.mts +33 -0
- package/esm/contracts/memory/recall-options.type.d.mts.map +1 -0
- package/esm/contracts/middleware/index.d.mts +2 -2
- package/esm/contracts/middleware/middleware-context.type.d.mts +42 -2
- package/esm/contracts/middleware/middleware-context.type.d.mts.map +1 -1
- package/esm/contracts/middleware/middleware.contract.d.mts +46 -2
- package/esm/contracts/middleware/middleware.contract.d.mts.map +1 -1
- package/esm/contracts/model.contract.d.mts +63 -2
- package/esm/contracts/model.contract.d.mts.map +1 -1
- package/esm/contracts/orchestrator/checkpoint-store.contract.d.mts +91 -0
- package/esm/contracts/orchestrator/checkpoint-store.contract.d.mts.map +1 -0
- package/esm/contracts/orchestrator/index.d.mts +8 -0
- package/esm/contracts/orchestrator/orchestrator-commands.type.d.mts +43 -0
- package/esm/contracts/orchestrator/orchestrator-commands.type.d.mts.map +1 -0
- package/esm/contracts/orchestrator/orchestrator-config.type.d.mts +170 -0
- package/esm/contracts/orchestrator/orchestrator-config.type.d.mts.map +1 -0
- package/esm/contracts/orchestrator/orchestrator-event.type.d.mts +118 -0
- package/esm/contracts/orchestrator/orchestrator-event.type.d.mts.map +1 -0
- package/esm/contracts/orchestrator/orchestrator-execute-options.type.d.mts +44 -0
- package/esm/contracts/orchestrator/orchestrator-execute-options.type.d.mts.map +1 -0
- package/esm/contracts/orchestrator/orchestrator.contract.d.mts +129 -0
- package/esm/contracts/orchestrator/orchestrator.contract.d.mts.map +1 -0
- package/esm/contracts/orchestrator/session.contract.d.mts +26 -0
- package/esm/contracts/orchestrator/session.contract.d.mts.map +1 -0
- package/esm/contracts/orchestrator/snapshot-store.contract.d.mts +89 -0
- package/esm/contracts/orchestrator/snapshot-store.contract.d.mts.map +1 -0
- package/esm/contracts/planner/index.d.mts +6 -0
- package/esm/contracts/planner/planner-capability.type.d.mts +39 -0
- package/esm/contracts/planner/planner-capability.type.d.mts.map +1 -0
- package/esm/contracts/planner/planner-config.type.d.mts +78 -0
- package/esm/contracts/planner/planner-config.type.d.mts.map +1 -0
- package/esm/contracts/planner/planner-execute-options.type.d.mts +43 -0
- package/esm/contracts/planner/planner-execute-options.type.d.mts.map +1 -0
- package/esm/contracts/planner/planner-plan.type.d.mts +48 -0
- package/esm/contracts/planner/planner-plan.type.d.mts.map +1 -0
- package/esm/contracts/planner/planner-result.type.d.mts +82 -0
- package/esm/contracts/planner/planner-result.type.d.mts.map +1 -0
- package/esm/contracts/planner/planner.contract.d.mts +60 -0
- package/esm/contracts/planner/planner.contract.d.mts.map +1 -0
- package/esm/contracts/result/base-report.type.d.mts +7 -2
- package/esm/contracts/result/base-report.type.d.mts.map +1 -1
- package/esm/contracts/result/base-report.type.mjs.map +1 -1
- package/esm/contracts/result/index.d.mts +2 -1
- package/esm/contracts/result/model-pricing.type.d.mts +10 -0
- package/esm/contracts/result/model-pricing.type.d.mts.map +1 -1
- package/esm/contracts/result/orchestrator-result.type.d.mts +139 -0
- package/esm/contracts/result/orchestrator-result.type.d.mts.map +1 -0
- package/esm/contracts/result/session-send-result.type.d.mts +12 -3
- package/esm/contracts/result/session-send-result.type.d.mts.map +1 -1
- package/esm/contracts/result/supervisor-result.type.d.mts +1 -1
- package/esm/contracts/result/usage.type.d.mts +24 -0
- package/esm/contracts/result/usage.type.d.mts.map +1 -1
- package/esm/contracts/sdk-adapter.contract.d.mts +1 -1
- package/esm/contracts/supervisor/dispatch-context.type.d.mts +3 -3
- package/esm/contracts/supervisor/evaluate-context.type.d.mts +1 -1
- package/esm/contracts/supervisor/index.d.mts +5 -5
- package/esm/contracts/supervisor/route-context.type.d.mts +2 -2
- package/esm/contracts/supervisor/supervisor-config.type.d.mts +55 -13
- package/esm/contracts/supervisor/supervisor-config.type.d.mts.map +1 -1
- package/esm/contracts/supervisor/supervisor-snapshot.type.d.mts +1 -1
- package/esm/contracts/supervisor/supervisor.contract.d.mts +9 -2
- package/esm/contracts/supervisor/supervisor.contract.d.mts.map +1 -1
- package/esm/contracts/workflow/index.d.mts +2 -2
- package/esm/contracts/workflow/workflow.contract.d.mts +28 -7
- package/esm/contracts/workflow/workflow.contract.d.mts.map +1 -1
- package/esm/errors/error-code.type.d.mts +1 -1
- package/esm/errors/index.d.mts +7 -0
- package/esm/errors/index.mjs +7 -0
- package/esm/errors/orchestrator-cancelled-error.d.mts +32 -0
- package/esm/errors/orchestrator-cancelled-error.d.mts.map +1 -0
- package/esm/errors/orchestrator-cancelled-error.mjs +31 -0
- package/esm/errors/orchestrator-cancelled-error.mjs.map +1 -0
- package/esm/errors/orchestrator-config-error.d.mts +26 -0
- package/esm/errors/orchestrator-config-error.d.mts.map +1 -0
- package/esm/errors/orchestrator-config-error.mjs +30 -0
- package/esm/errors/orchestrator-config-error.mjs.map +1 -0
- package/esm/errors/orchestrator-drift-error.d.mts +38 -0
- package/esm/errors/orchestrator-drift-error.d.mts.map +1 -0
- package/esm/errors/orchestrator-drift-error.mjs +37 -0
- package/esm/errors/orchestrator-drift-error.mjs.map +1 -0
- package/esm/errors/orchestrator-failed-error.d.mts +33 -0
- package/esm/errors/orchestrator-failed-error.d.mts.map +1 -0
- package/esm/errors/orchestrator-failed-error.mjs +36 -0
- package/esm/errors/orchestrator-failed-error.mjs.map +1 -0
- package/esm/errors/planner-cancelled-error.d.mts +33 -0
- package/esm/errors/planner-cancelled-error.d.mts.map +1 -0
- package/esm/errors/planner-cancelled-error.mjs +29 -0
- package/esm/errors/planner-cancelled-error.mjs.map +1 -0
- package/esm/errors/planner-failed-error.d.mts +40 -0
- package/esm/errors/planner-failed-error.d.mts.map +1 -0
- package/esm/errors/planner-failed-error.mjs +37 -0
- package/esm/errors/planner-failed-error.mjs.map +1 -0
- package/esm/errors/planner-plan-invalid-error.d.mts +21 -0
- package/esm/errors/planner-plan-invalid-error.d.mts.map +1 -0
- package/esm/errors/planner-plan-invalid-error.mjs +25 -0
- package/esm/errors/planner-plan-invalid-error.mjs.map +1 -0
- package/esm/eval/eval-runner.d.mts +17 -0
- package/esm/eval/eval-runner.d.mts.map +1 -0
- package/esm/eval/eval-runner.mjs +121 -0
- package/esm/eval/eval-runner.mjs.map +1 -0
- package/esm/eval/index.d.mts +29 -0
- package/esm/eval/index.d.mts.map +1 -0
- package/esm/eval/index.mjs +30 -0
- package/esm/eval/index.mjs.map +1 -0
- package/esm/eval/judge-scorer.d.mts +21 -0
- package/esm/eval/judge-scorer.d.mts.map +1 -0
- package/esm/eval/judge-scorer.mjs +87 -0
- package/esm/eval/judge-scorer.mjs.map +1 -0
- package/esm/eval/scorers.d.mts +50 -0
- package/esm/eval/scorers.d.mts.map +1 -0
- package/esm/eval/scorers.mjs +101 -0
- package/esm/eval/scorers.mjs.map +1 -0
- package/esm/index.d.mts +95 -30
- package/esm/index.mjs +66 -22
- package/esm/memory/derive-id.mjs +24 -0
- package/esm/memory/derive-id.mjs.map +1 -0
- package/esm/memory/episodic-memory.mjs +106 -0
- package/esm/memory/episodic-memory.mjs.map +1 -0
- package/esm/memory/index.d.mts +5 -0
- package/esm/memory/memory.d.mts +42 -0
- package/esm/memory/memory.d.mts.map +1 -0
- package/esm/memory/memory.mjs +166 -0
- package/esm/memory/memory.mjs.map +1 -0
- package/esm/memory/procedural-memory.mjs +103 -0
- package/esm/memory/procedural-memory.mjs.map +1 -0
- package/esm/memory/semantic-memory.mjs +80 -0
- package/esm/memory/semantic-memory.mjs.map +1 -0
- package/esm/memory/working-memory.mjs +62 -0
- package/esm/memory/working-memory.mjs.map +1 -0
- package/esm/middleware/builtins/budget-contract.type.d.mts +126 -0
- package/esm/middleware/builtins/budget-contract.type.d.mts.map +1 -0
- package/esm/middleware/builtins/budget.d.mts +71 -1
- package/esm/middleware/builtins/budget.d.mts.map +1 -1
- package/esm/middleware/builtins/budget.mjs +119 -4
- package/esm/middleware/builtins/budget.mjs.map +1 -1
- package/esm/middleware/builtins/semantic-cache.d.mts +1 -1
- package/esm/middleware/index.d.mts +2 -1
- package/esm/middleware/index.mjs +1 -1
- package/esm/middleware/pipeline.d.mts +9 -6
- package/esm/middleware/pipeline.d.mts.map +1 -1
- package/esm/middleware/pipeline.mjs.map +1 -1
- package/esm/mock/index.d.mts +1 -0
- package/esm/mock/index.mjs +1 -0
- package/esm/mock/mock-router.d.mts +63 -0
- package/esm/mock/mock-router.d.mts.map +1 -0
- package/esm/mock/mock-router.mjs +58 -0
- package/esm/mock/mock-router.mjs.map +1 -0
- package/esm/model/fallback-model.d.mts +45 -0
- package/esm/model/fallback-model.d.mts.map +1 -0
- package/esm/model/fallback-model.mjs +218 -0
- package/esm/model/fallback-model.mjs.map +1 -0
- package/esm/model/index.d.mts +2 -0
- package/esm/model/index.mjs +3 -0
- package/esm/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs +78 -0
- package/esm/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs.map +1 -0
- package/esm/node_modules/@vitest/expect/dist/index.mjs +1473 -0
- package/esm/node_modules/@vitest/expect/dist/index.mjs.map +1 -0
- package/esm/node_modules/@vitest/pretty-format/dist/index.mjs +888 -0
- package/esm/node_modules/@vitest/pretty-format/dist/index.mjs.map +1 -0
- package/esm/node_modules/@vitest/runner/dist/chunk-artifact.mjs +1533 -0
- package/esm/node_modules/@vitest/runner/dist/chunk-artifact.mjs.map +1 -0
- package/esm/node_modules/@vitest/runner/dist/index.mjs +3 -0
- package/esm/node_modules/@vitest/runner/dist/utils.mjs +3 -0
- package/esm/node_modules/@vitest/snapshot/dist/index.mjs +922 -0
- package/esm/node_modules/@vitest/snapshot/dist/index.mjs.map +1 -0
- package/esm/node_modules/@vitest/spy/dist/index.mjs +386 -0
- package/esm/node_modules/@vitest/spy/dist/index.mjs.map +1 -0
- package/esm/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.mjs +82 -0
- package/esm/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.mjs.map +1 -0
- package/esm/node_modules/@vitest/utils/dist/diff.mjs +1357 -0
- package/esm/node_modules/@vitest/utils/dist/diff.mjs.map +1 -0
- package/esm/node_modules/@vitest/utils/dist/display.mjs +559 -0
- package/esm/node_modules/@vitest/utils/dist/display.mjs.map +1 -0
- package/esm/node_modules/@vitest/utils/dist/error.mjs +38 -0
- package/esm/node_modules/@vitest/utils/dist/error.mjs.map +1 -0
- package/esm/node_modules/@vitest/utils/dist/helpers.mjs +181 -0
- package/esm/node_modules/@vitest/utils/dist/helpers.mjs.map +1 -0
- package/esm/node_modules/@vitest/utils/dist/offset.mjs +27 -0
- package/esm/node_modules/@vitest/utils/dist/offset.mjs.map +1 -0
- package/esm/node_modules/@vitest/utils/dist/serialize.mjs +77 -0
- package/esm/node_modules/@vitest/utils/dist/serialize.mjs.map +1 -0
- package/esm/node_modules/@vitest/utils/dist/source-map.mjs +374 -0
- package/esm/node_modules/@vitest/utils/dist/source-map.mjs.map +1 -0
- package/esm/node_modules/@vitest/utils/dist/timers.mjs +37 -0
- package/esm/node_modules/@vitest/utils/dist/timers.mjs.map +1 -0
- package/esm/node_modules/chai/index.mjs +2973 -0
- package/esm/node_modules/chai/index.mjs.map +1 -0
- package/esm/node_modules/magic-string/dist/magic-string.es.mjs +940 -0
- package/esm/node_modules/magic-string/dist/magic-string.es.mjs.map +1 -0
- package/esm/node_modules/tinyrainbow/dist/index.mjs +87 -0
- package/esm/node_modules/tinyrainbow/dist/index.mjs.map +1 -0
- package/esm/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.mjs +6 -0
- package/esm/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.mjs.map +1 -0
- package/esm/node_modules/vitest/dist/chunks/rpc.MzXet3jl.mjs +52 -0
- package/esm/node_modules/vitest/dist/chunks/rpc.MzXet3jl.mjs.map +1 -0
- package/esm/node_modules/vitest/dist/chunks/test.DNmyFkvJ.mjs +2697 -0
- package/esm/node_modules/vitest/dist/chunks/test.DNmyFkvJ.mjs.map +1 -0
- package/esm/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.mjs +45 -0
- package/esm/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.mjs.map +1 -0
- package/esm/orchestrator/as-tool.d.mts +42 -0
- package/esm/orchestrator/as-tool.d.mts.map +1 -0
- package/esm/orchestrator/as-tool.mjs +98 -0
- package/esm/orchestrator/as-tool.mjs.map +1 -0
- package/esm/orchestrator/checkpoint.mjs +75 -0
- package/esm/orchestrator/checkpoint.mjs.map +1 -0
- package/esm/orchestrator/commands.d.mts +38 -0
- package/esm/orchestrator/commands.d.mts.map +1 -0
- package/esm/orchestrator/commands.mjs +34 -0
- package/esm/orchestrator/commands.mjs.map +1 -0
- package/esm/orchestrator/compaction.mjs +206 -0
- package/esm/orchestrator/compaction.mjs.map +1 -0
- package/esm/orchestrator/dispatch.mjs +171 -0
- package/esm/orchestrator/dispatch.mjs.map +1 -0
- package/esm/orchestrator/emitter-port.type.d.mts +31 -0
- package/esm/orchestrator/emitter-port.type.d.mts.map +1 -0
- package/esm/orchestrator/emitter.d.mts +56 -0
- package/esm/orchestrator/emitter.d.mts.map +1 -0
- package/esm/orchestrator/emitter.mjs +85 -0
- package/esm/orchestrator/emitter.mjs.map +1 -0
- package/esm/orchestrator/engine-context.type.d.mts +56 -0
- package/esm/orchestrator/engine-context.type.d.mts.map +1 -0
- package/esm/orchestrator/execution.d.mts +116 -0
- package/esm/orchestrator/execution.d.mts.map +1 -0
- package/esm/orchestrator/execution.mjs +406 -0
- package/esm/orchestrator/execution.mjs.map +1 -0
- package/esm/orchestrator/index.d.mts +8 -0
- package/esm/orchestrator/index.mjs +10 -0
- package/esm/orchestrator/load.mjs +49 -0
- package/esm/orchestrator/load.mjs.map +1 -0
- package/esm/orchestrator/lock.mjs +75 -0
- package/esm/orchestrator/lock.mjs.map +1 -0
- package/esm/orchestrator/memory.d.mts +84 -0
- package/esm/orchestrator/memory.d.mts.map +1 -0
- package/esm/orchestrator/memory.mjs +141 -0
- package/esm/orchestrator/memory.mjs.map +1 -0
- package/esm/orchestrator/orchestrator-stream.d.mts +42 -0
- package/esm/orchestrator/orchestrator-stream.d.mts.map +1 -0
- package/esm/orchestrator/orchestrator-stream.mjs +98 -0
- package/esm/orchestrator/orchestrator-stream.mjs.map +1 -0
- package/esm/orchestrator/orchestrator.d.mts +38 -0
- package/esm/orchestrator/orchestrator.d.mts.map +1 -0
- package/esm/orchestrator/orchestrator.mjs +173 -0
- package/esm/orchestrator/orchestrator.mjs.map +1 -0
- package/esm/orchestrator/resume.mjs +74 -0
- package/esm/orchestrator/resume.mjs.map +1 -0
- package/esm/orchestrator/signature.d.mts +40 -0
- package/esm/orchestrator/signature.d.mts.map +1 -0
- package/esm/orchestrator/signature.mjs +120 -0
- package/esm/orchestrator/signature.mjs.map +1 -0
- package/esm/orchestrator/window.mjs +56 -0
- package/esm/orchestrator/window.mjs.map +1 -0
- package/esm/planner/index.d.mts +5 -0
- package/esm/planner/index.mjs +6 -0
- package/esm/planner/plan-prompt.d.mts +17 -0
- package/esm/planner/plan-prompt.d.mts.map +1 -0
- package/esm/planner/plan-prompt.mjs +30 -0
- package/esm/planner/plan-prompt.mjs.map +1 -0
- package/esm/planner/plan-schema.d.mts +27 -0
- package/esm/planner/plan-schema.d.mts.map +1 -0
- package/esm/planner/plan-schema.mjs +117 -0
- package/esm/planner/plan-schema.mjs.map +1 -0
- package/esm/planner/planner-run.d.mts +23 -0
- package/esm/planner/planner-run.d.mts.map +1 -0
- package/esm/planner/planner-run.mjs +344 -0
- package/esm/planner/planner-run.mjs.map +1 -0
- package/esm/planner/planner.d.mts +37 -0
- package/esm/planner/planner.d.mts.map +1 -0
- package/esm/planner/planner.mjs +120 -0
- package/esm/planner/planner.mjs.map +1 -0
- package/esm/planner/signature.d.mts +18 -0
- package/esm/planner/signature.d.mts.map +1 -0
- package/esm/planner/signature.mjs +27 -0
- package/esm/planner/signature.mjs.map +1 -0
- package/esm/snapshot/index.d.mts +3 -0
- package/esm/snapshot/memory.d.mts +26 -0
- package/esm/snapshot/memory.d.mts.map +1 -0
- package/esm/snapshot/memory.mjs +81 -0
- package/esm/snapshot/memory.mjs.map +1 -0
- package/esm/snapshot/pg.d.mts +41 -0
- package/esm/snapshot/pg.d.mts.map +1 -0
- package/esm/snapshot/pg.mjs +146 -0
- package/esm/snapshot/pg.mjs.map +1 -0
- package/esm/snapshot/redis.d.mts +42 -0
- package/esm/snapshot/redis.d.mts.map +1 -0
- package/esm/snapshot/redis.mjs +101 -0
- package/esm/snapshot/redis.mjs.map +1 -0
- package/esm/supervisor/as-tool.d.mts +0 -6
- package/esm/supervisor/as-tool.d.mts.map +1 -1
- package/esm/supervisor/as-tool.mjs +0 -6
- package/esm/supervisor/as-tool.mjs.map +1 -1
- package/esm/supervisor/execution.d.mts +43 -8
- package/esm/supervisor/execution.d.mts.map +1 -1
- package/esm/supervisor/execution.mjs +66 -16
- package/esm/supervisor/execution.mjs.map +1 -1
- package/esm/supervisor/fan-out.d.mts +65 -0
- package/esm/supervisor/fan-out.d.mts.map +1 -0
- package/esm/supervisor/fan-out.mjs +65 -0
- package/esm/supervisor/fan-out.mjs.map +1 -0
- package/esm/supervisor/index.d.mts +5 -3
- package/esm/supervisor/index.mjs +3 -1
- package/esm/supervisor/router-factory.d.mts +110 -0
- package/esm/supervisor/router-factory.d.mts.map +1 -0
- package/esm/supervisor/router-factory.mjs +141 -0
- package/esm/supervisor/router-factory.mjs.map +1 -0
- package/esm/supervisor/router-prompt.d.mts +1 -1
- package/esm/supervisor/snapshot.d.mts +4 -10
- package/esm/supervisor/snapshot.d.mts.map +1 -1
- package/esm/supervisor/snapshot.mjs +8 -16
- package/esm/supervisor/snapshot.mjs.map +1 -1
- package/esm/supervisor/supervisor.mjs +1 -0
- package/esm/supervisor/supervisor.mjs.map +1 -1
- package/esm/system-prompt/index.mjs +6 -0
- package/esm/system-prompt/system-prompt.d.mts +51 -3
- package/esm/system-prompt/system-prompt.d.mts.map +1 -1
- package/esm/system-prompt/system-prompt.mjs +52 -6
- package/esm/system-prompt/system-prompt.mjs.map +1 -1
- package/esm/testing/matcher-logic.d.mts +76 -0
- package/esm/testing/matcher-logic.d.mts.map +1 -0
- package/esm/testing/matcher-logic.mjs +144 -0
- package/esm/testing/matcher-logic.mjs.map +1 -0
- package/esm/testing/matchers.d.mts +48 -0
- package/esm/testing/matchers.d.mts.map +1 -0
- package/esm/testing/matchers.mjs +37 -0
- package/esm/testing/matchers.mjs.map +1 -0
- package/esm/testing/register-lazy.d.mts +20 -0
- package/esm/testing/register-lazy.d.mts.map +1 -0
- package/esm/testing/register-lazy.mjs +24 -0
- package/esm/testing/register-lazy.mjs.map +1 -0
- package/esm/tool/executable-as-tool.d.mts +87 -0
- package/esm/tool/executable-as-tool.d.mts.map +1 -0
- package/esm/tool/executable-as-tool.mjs +81 -0
- package/esm/tool/executable-as-tool.mjs.map +1 -0
- package/esm/tool/index.d.mts +2 -1
- package/esm/tool/index.mjs +1 -0
- package/esm/workflow/as-tool.mjs +0 -6
- package/esm/workflow/as-tool.mjs.map +1 -1
- package/esm/workflow/engine.mjs +2 -2
- package/esm/workflow/snapshot.mjs +13 -7
- package/esm/workflow/snapshot.mjs.map +1 -1
- package/esm/workflow/step-runner.mjs +1 -1
- package/esm/workflow/workflow.mjs +1 -0
- package/esm/workflow/workflow.mjs.map +1 -1
- package/llms-full.txt +947 -42
- package/llms.txt +13 -8
- package/package.json +3 -3
- package/skills/README.md +25 -5
- package/skills/ai-basics/SKILL.md +18 -7
- package/skills/ai-dx-helpers/SKILL.md +180 -0
- package/skills/attach-ai-middleware/SKILL.md +32 -3
- package/skills/handle-ai-errors/SKILL.md +20 -6
- package/skills/manage-ai-stores/SKILL.md +127 -0
- package/skills/persist-ai-data/SKILL.md +21 -10
- package/skills/pick-ai-provider/SKILL.md +46 -12
- package/skills/run-ai-agent/SKILL.md +51 -2
- package/skills/run-orchestrator/SKILL.md +198 -0
- package/skills/run-planner/SKILL.md +68 -0
- package/skills/run-supervisor/SKILL.md +47 -2
- package/skills/use-ai-memory/SKILL.md +124 -0
- package/skills/write-system-prompt/SKILL.md +14 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AgentToolEntry } from "../tool/executable-as-tool.mjs";
|
|
2
|
+
import { ModelCallOptions, ModelContract } from "../contracts/model.contract.mjs";
|
|
3
|
+
import { AgentMiddleware } from "../contracts/middleware/middleware.contract.mjs";
|
|
2
4
|
import { Placeholders } from "../contracts/placeholders.type.mjs";
|
|
3
5
|
import { SystemPromptContract } from "../contracts/system-prompt.contract.mjs";
|
|
4
6
|
import { AgentEventMap } from "../contracts/events/event-map.type.mjs";
|
|
5
7
|
import { StreamingToolGuardConfig } from "../contracts/streaming-tool-guard-config.type.mjs";
|
|
6
|
-
import { ModelCallOptions, ModelContract } from "../contracts/model.contract.mjs";
|
|
7
|
-
import { AgentMiddleware } from "../contracts/middleware/middleware.contract.mjs";
|
|
8
8
|
import { CompleteEvent } from "../contracts/events/complete-event.type.mjs";
|
|
9
9
|
import { UsageEvent } from "../contracts/events/usage-event.type.mjs";
|
|
10
10
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
@@ -79,8 +79,21 @@ type AgentConfig<TOutput = unknown> = {
|
|
|
79
79
|
* System prompt for the agent. A plain string is treated as a single instruction.
|
|
80
80
|
* A SystemPromptContract gives full builder control with placeholder support.
|
|
81
81
|
*/
|
|
82
|
-
systemPrompt?: SystemPromptContract | string;
|
|
83
|
-
|
|
82
|
+
systemPrompt?: SystemPromptContract | string;
|
|
83
|
+
/**
|
|
84
|
+
* Tools exposed to the LLM during execution.
|
|
85
|
+
*
|
|
86
|
+
* Accepts both shapes interchangeably:
|
|
87
|
+
* - A built `ToolContract` — from `ai.tool(...)` or an explicit
|
|
88
|
+
* `.asTool(...)` wrapper on an executable.
|
|
89
|
+
* - A raw executable primitive (`AgentContract` / `WorkflowInstance`
|
|
90
|
+
* / `SupervisorContract`) — auto-adapted into a `ToolContract` at
|
|
91
|
+
* factory time. The tool manifest is derived from the executable's
|
|
92
|
+
* `name` + `description` + (optional) `inputSchema`; dispatch flows
|
|
93
|
+
* through its `execute()`. `.asTool()` remains fully supported and
|
|
94
|
+
* takes precedence when you need a custom name / schema per use.
|
|
95
|
+
*/
|
|
96
|
+
tools?: AgentToolEntry<any, any>[]; /** Placeholder values merged into system prompt templates */
|
|
84
97
|
placeholders?: Placeholders;
|
|
85
98
|
/**
|
|
86
99
|
* Maximum number of LLM trips before aborting with an error.
|
|
@@ -156,5 +169,5 @@ type AgentConfig<TOutput = unknown> = {
|
|
|
156
169
|
onComplete?: (event: CompleteEvent<TOutput>) => void | Promise<void>;
|
|
157
170
|
};
|
|
158
171
|
//#endregion
|
|
159
|
-
export { AgentConfig };
|
|
172
|
+
export { AgentConfig, AgentEventHandlers };
|
|
160
173
|
//# sourceMappingURL=agent-config.type.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-config.type.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/agent/agent-config.type.ts"],"mappings":";;;;;;;;;;;;;;;AAgBA;;KAAY,kBAAA,GAAqB,OAAA,eACnB,aAAA,IAAiB,OAAA,EAAS,aAAA,CAAc,CAAA;;;;;;;;;;;;AAAE;AA0BxD;;;;;;;;;;;KAAY,WAAA;
|
|
1
|
+
{"version":3,"file":"agent-config.type.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/agent/agent-config.type.ts"],"mappings":";;;;;;;;;;;;;;;AAgBA;;KAAY,kBAAA,GAAqB,OAAA,eACnB,aAAA,IAAiB,OAAA,EAAS,aAAA,CAAc,CAAA;;;;;;;;;;;;AAAE;AA0BxD;;;;;;;;;;;KAAY,WAAA;EAsGW;;;;;;;;;;;;EAzFrB,IAAA;EAuBO;;;;;;;EAfP,WAAA;EA2CA;;;;;;;;;;;;EA9BA,OAAA,WAmFW;EAjFX,KAAA,EAAO,aAAA;EA8FP;;;;EAzFA,YAAA,GAAe,oBAAA;EAyF+C;AAAA;;;;;;;;;;;;EA3E9D,KAAA,GAAQ,cAAA;EAER,YAAA,GAAe,YAAA;;;;;EAKf,QAAA;EAEA,YAAA,GAAe,gBAAA;;;;;;;;;EASf,MAAA,GAAS,gBAAA,CAAiB,OAAA;;;;;;EAM1B,EAAA,GAAK,kBAAA;;;;;;;;;;;;EAYL,UAAA,GAAa,eAAA;;;;;;;;;;;EAWb,kBAAA,GAAqB,wBAAA;;;;;;;;;;;;;;;EAerB,OAAA,IAAW,KAAA,EAAO,UAAA,YAAsB,OAAA;;;;;;;;;;;;;EAaxC,UAAA,IAAc,KAAA,EAAO,aAAA,CAAc,OAAA,aAAoB,OAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/agent/agent.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"agent.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/agent/agent.ts"],"mappings":";;;;;;;AA+LA;;;;;;;;;;;;;;;;AAA6F;;;;;;;;;;;iBAA7E,KAAA,oBAAyB,MAAA,EAAQ,WAAA,CAAY,OAAA,IAAW,aAAA,CAAc,OAAA"}
|
package/esm/agent/agent.mjs
CHANGED
|
@@ -4,14 +4,16 @@ import { AgentCancelledError } from "../errors/agent-cancelled-error.mjs";
|
|
|
4
4
|
import { AgentMaxTripsError } from "../errors/agent-max-trips-error.mjs";
|
|
5
5
|
import { SchemaValidationError } from "../errors/schema-validation-error.mjs";
|
|
6
6
|
import "../errors/index.mjs";
|
|
7
|
-
import { runPipeline } from "../middleware/pipeline.mjs";
|
|
8
|
-
import "../middleware/index.mjs";
|
|
9
7
|
import { accumulateCost, computeCost } from "../utils/compute-cost.mjs";
|
|
10
8
|
import { extractJsonPayload } from "../utils/extract-json-payload.mjs";
|
|
11
9
|
import { generateRunId } from "../utils/generate-run-id.mjs";
|
|
12
10
|
import { safeJsonParse } from "../utils/safe-json-parse.mjs";
|
|
13
11
|
import { stampReportLineage } from "../utils/stamp-report-lineage.mjs";
|
|
14
12
|
import "../utils/index.mjs";
|
|
13
|
+
import { runEval } from "../eval/eval-runner.mjs";
|
|
14
|
+
import { runPipeline } from "../middleware/pipeline.mjs";
|
|
15
|
+
import "../middleware/index.mjs";
|
|
16
|
+
import { normalizeAgentTools } from "../tool/executable-as-tool.mjs";
|
|
15
17
|
import { buildAgentInputMessages } from "./agent-input-builder.mjs";
|
|
16
18
|
import { logAgentEvent } from "./agent-log-event.mjs";
|
|
17
19
|
import { createAgentStream } from "./agent-stream.mjs";
|
|
@@ -123,10 +125,15 @@ function validateMiddleware(middleware) {
|
|
|
123
125
|
function agent(config) {
|
|
124
126
|
validateMiddleware(config.middleware);
|
|
125
127
|
const isAnonymous = !config.name || typeof config.name !== "string";
|
|
126
|
-
const
|
|
128
|
+
const tools = normalizeAgentTools(config.tools);
|
|
129
|
+
const name = isAnonymous ? synthesizeAgentName({
|
|
130
|
+
...config,
|
|
131
|
+
tools
|
|
132
|
+
}) : config.name;
|
|
127
133
|
const resolvedConfig = {
|
|
128
134
|
...config,
|
|
129
|
-
name
|
|
135
|
+
name,
|
|
136
|
+
tools
|
|
130
137
|
};
|
|
131
138
|
const instanceHandlers = /* @__PURE__ */ new Map();
|
|
132
139
|
function on(event, handler) {
|
|
@@ -142,7 +149,7 @@ function agent(config) {
|
|
|
142
149
|
bucket.delete(handler);
|
|
143
150
|
if (bucket.size === 0) instanceHandlers.delete(event);
|
|
144
151
|
}
|
|
145
|
-
|
|
152
|
+
const agentContract = {
|
|
146
153
|
name,
|
|
147
154
|
isAnonymous,
|
|
148
155
|
description: config.description,
|
|
@@ -155,8 +162,12 @@ function agent(config) {
|
|
|
155
162
|
return stream;
|
|
156
163
|
},
|
|
157
164
|
on,
|
|
158
|
-
off
|
|
165
|
+
off,
|
|
166
|
+
eval(options) {
|
|
167
|
+
return runEval(agentContract, options);
|
|
168
|
+
}
|
|
159
169
|
};
|
|
170
|
+
return agentContract;
|
|
160
171
|
}
|
|
161
172
|
/**
|
|
162
173
|
* Per-call driver that owns the full lifecycle of a single
|
package/esm/agent/agent.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/agent/agent.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { log, type Logger } from \"@warlock.js/logger\";\nimport type {\n AgentContract,\n AgentEventHandler,\n AgentEventMap,\n AgentExecuteOptions,\n AgentResult,\n BaseReport,\n CompleteEvent,\n FinishReason,\n LLMTrip,\n Message,\n MiddlewareExecuteContext,\n MiddlewareState,\n MiddlewareToolContext,\n MiddlewareTripContext,\n ModelResponse,\n ModelToolCallRequest,\n StreamContract,\n StreamEventBody,\n StreamingToolGuardConfig,\n ToolCall,\n ToolEventMeta,\n Usage,\n UsageEvent,\n WithoutIdentity,\n} from \"../contracts\";\nimport {\n AgentCancelledError,\n AgentExecutionError,\n AgentMaxTripsError,\n AIError,\n SchemaValidationError,\n} from \"../errors\";\nimport { runPipeline } from \"../middleware\";\nimport type { ToolContract, ToolInvokeResult } from \"../tool/tool\";\nimport {\n accumulateCost,\n computeCost,\n extractJsonPayload,\n generateRunId,\n safeJsonParse,\n stampReportLineage,\n} from \"../utils\";\nimport type { AgentConfig } from \"./agent-config.type\";\nimport { buildAgentInputMessages } from \"./agent-input-builder\";\nimport { logAgentEvent } from \"./agent-log-event\";\nimport { createAgentStream, type StreamController } from \"./agent-stream\";\nimport { agentEventToStreamEvent } from \"./agent-to-stream-event\";\nimport { JsonStreamGuard } from \"./json-stream-guard\";\n\nconst LOG_MODULE = \"ai.agent\";\n\n/**\n * Detect abort-flavored errors surfaced by SDK HTTP layers — the\n * DOM `AbortError`, axios `ERR_CANCELED`, node-fetch's own\n * `AbortError`. Used to classify them as cancellation rather than\n * generic agent-execution failures.\n */\nfunction isAbortLike(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n\n const e = err as { name?: unknown; code?: unknown };\n\n return e.name === \"AbortError\" || e.code === \"ERR_CANCELED\" || e.code === \"ABORT_ERR\";\n}\n\n/**\n * Readable synthetic name for agents constructed without an explicit\n * `name`. Format: `anon_<provider>_<model>[_<tool1>+<tool2>+...]` —\n * deterministic (same config → same name across restarts) and\n * human-readable in logs / workflow snapshots.\n *\n * Keeps drift detection honest for the `ai.agent({ model })`\n * one-liner without punishing it with a hashed id nobody can read.\n */\nfunction synthesizeAgentName<T>(config: AgentConfig<T>): string {\n const provider = (config.model as unknown as { provider?: string })?.provider ?? \"unknown\";\n const model = config.model?.name ?? \"unknown\";\n const tools = (config.tools ?? [])\n .map((tool) => tool.name)\n .sort()\n .join(\"+\");\n\n const base = `anon_${sanitize(provider)}_${sanitize(model)}`;\n return tools ? `${base}_${sanitize(tools, { keepPlus: true })}` : base;\n}\n\nfunction sanitize(value: string, opts: { keepPlus?: boolean } = {}): string {\n const allowed = opts.keepPlus ? /[^a-zA-Z0-9._+-]/g : /[^a-zA-Z0-9._-]/g;\n return value.replace(allowed, \"-\");\n}\n\n/**\n * Authoring-time check on the middleware array. Throws an\n * `AgentExecutionError` with `context: { authoring: true }` the\n * moment an invalid entry is found — the agent factory surface is\n * where config bugs should surface, not ten trips into a run.\n *\n * Validates:\n * - Every entry is a non-null object with a non-empty string `name`.\n * - No two entries share the same `name` (would silently collide on\n * `ctx.state` keys and produce impossible-to-debug behavior).\n *\n * Does NOT validate that hook maps contain callable functions —\n * that would catch late-binding bugs but also reject legitimate\n * patterns like `before` being conditionally `undefined`. Runtime\n * dispatch handles missing hooks safely.\n */\nfunction validateMiddleware(middleware: ReadonlyArray<unknown> | undefined): void {\n if (!middleware || middleware.length === 0) {\n return;\n }\n\n const seen = new Set<string>();\n\n for (let index = 0; index < middleware.length; index++) {\n const entry = middleware[index];\n\n if (!entry || typeof entry !== \"object\") {\n throw new AgentExecutionError(\n `middleware[${index}] must be an object; received ${entry === null ? \"null\" : typeof entry}`,\n { context: { authoring: true, index } },\n );\n }\n\n const name = (entry as { name?: unknown }).name;\n\n if (typeof name !== \"string\" || name.length === 0) {\n throw new AgentExecutionError(`middleware[${index}] must have a non-empty string \"name\"`, {\n context: { authoring: true, index },\n });\n }\n\n if (seen.has(name)) {\n throw new AgentExecutionError(\n `duplicate middleware name \"${name}\" — each middleware needs a unique name so ctx.state keys do not collide`,\n { context: { authoring: true, index, name } },\n );\n }\n\n seen.add(name);\n }\n}\n\n/**\n * Creates an executable AI agent from the given configuration.\n *\n * The agent runs a bounded trip loop: each trip calls the model, dispatches\n * any requested tool calls, then loops until the model stops or `maxTrips`\n * is reached. Each `execute()` / `stream()` call spawns a fresh internal\n * `Execution` instance — the factory itself holds no state across calls.\n *\n * `execute()` never throws — any error is attached to the returned result\n * under `result.error`. `stream()` surfaces errors both on the terminal\n * `error` stream event and via the `stream.result` promise.\n *\n * @example\n * const myAgent = agent({\n * model: openai.model({ name: \"gpt-4o\" }),\n * systemPrompt: \"You are a helpful assistant.\",\n * tools: [searchTool],\n * });\n *\n * const result = await myAgent.execute(\"What is the capital of Egypt?\");\n *\n * @example\n * const stream = myAgent.stream(\"Write a haiku about Cairo.\");\n *\n * for await (const event of stream) {\n * if (event.type === \"streaming\") process.stdout.write(event.delta);\n * }\n *\n * const result = await stream.result;\n */\nexport function agent<TOutput = unknown>(config: AgentConfig<TOutput>): AgentContract<TOutput> {\n // Authoring-time validation of the middleware array. Rejects two\n // classes of bug that would otherwise surface as opaque failures\n // mid-execution: (a) entries that aren't proper middleware\n // objects (null, undefined, missing `name`), and (b) two\n // middlewares sharing the same `name`, which would silently\n // collide on `ctx.state` keys. Fail fast, fail loud — per the\n // authoring-time rules in `domains/ai/conventions/errors.md`.\n validateMiddleware(config.middleware);\n\n // Resolve the agent's identity. Explicit `name` wins; otherwise we\n // synthesize a DETERMINISTIC fingerprint from the config's\n // identity-defining fields (model + provider + tool names). Same\n // config across process restarts produces the same synthetic name,\n // so workflow signature drift detection stays honest for agents\n // composed into workflows without explicit names.\n const isAnonymous = !config.name || typeof config.name !== \"string\";\n const name = isAnonymous ? synthesizeAgentName(config) : (config.name as string);\n const resolvedConfig: AgentConfig<TOutput> = { ...config, name };\n\n // Instance-level handlers registered via `.on()`. Stored here\n // (factory-scope) so every `execute()` / `stream()` call on this\n // agent sees the same set. Each event name gets its own Set so\n // `off()` can remove a specific handler without disturbing others.\n const instanceHandlers = new Map<\n keyof AgentEventMap,\n Set<AgentEventHandler<keyof AgentEventMap>>\n >();\n\n function on<K extends keyof AgentEventMap>(event: K, handler: AgentEventHandler<K>): () => void {\n const existing = instanceHandlers.get(event);\n const bucket = existing ?? new Set<AgentEventHandler<keyof AgentEventMap>>();\n\n if (!existing) {\n instanceHandlers.set(event, bucket);\n }\n\n bucket.add(handler as AgentEventHandler<keyof AgentEventMap>);\n\n return () => off(event, handler);\n }\n\n function off<K extends keyof AgentEventMap>(event: K, handler: AgentEventHandler<K>): void {\n const bucket = instanceHandlers.get(event);\n\n if (!bucket) {\n return;\n }\n\n bucket.delete(handler as AgentEventHandler<keyof AgentEventMap>);\n\n if (bucket.size === 0) {\n instanceHandlers.delete(event);\n }\n }\n\n return {\n name,\n isAnonymous,\n description: config.description,\n async execute(\n input: string,\n options?: AgentExecuteOptions<TOutput>,\n ): Promise<AgentResult<TOutput>> {\n return new Execution<TOutput>(\n resolvedConfig,\n input,\n options,\n undefined,\n instanceHandlers,\n ).run();\n },\n\n stream(\n input: string,\n options?: AgentExecuteOptions<TOutput>,\n ): StreamContract<AgentResult<TOutput>> {\n const { controller, stream } = createAgentStream<AgentResult<TOutput>>();\n\n const execution = new Execution<TOutput>(\n resolvedConfig,\n input,\n options,\n controller,\n instanceHandlers,\n );\n\n void execution.run();\n\n return stream;\n },\n\n on,\n off,\n };\n}\n\n/**\n * Name → handler-set map shared between the `agent()` factory and its\n * per-call `Execution`. Each `.on()` registration mutates this map;\n * every `Execution` reads from the same reference so additions and\n * removals take effect mid-flight.\n */\ntype InstanceHandlerMap = Map<keyof AgentEventMap, Set<AgentEventHandler<keyof AgentEventMap>>>;\n\n/**\n * Per-call driver that owns the full lifecycle of a single\n * `agent.execute()` or `agent.stream()` invocation.\n *\n * **Role.** An `Execution` is the short-lived state container and phase\n * orchestrator for one agent run. The public `agent()` factory stays purely\n * functional — all mutable bookkeeping (trips, tool calls, usage totals,\n * message history, terminal error, parsed output) lives here so each call\n * gets a fresh, isolated instance.\n *\n * **Responsibility.**\n * - Owns: building the initial message list, driving the bounded trip loop,\n * dispatching tool calls safely, parsing the final output against the\n * caller's schema, emitting lifecycle events (to both the user handler\n * and, in stream mode, the `StreamController`), and producing the\n * `AgentResult`.\n * - Does NOT own: how the model produces responses (delegated to\n * `ModelContract.complete` / `ModelContract.stream`), how tools execute\n * (delegated to `ToolContract.invoke`), the async-queue plumbing for\n * streaming (delegated to `createAgentStream`), or any cross-call state\n * (factory-level concerns live in `agent()`).\n *\n * Streaming mode is opt-in via the fourth constructor argument: pass a\n * `StreamController` and every event is mirrored into it while model calls\n * are driven via `model.stream()` instead of `model.complete()`. The public\n * contract of `execute()` says it never throws — `Execution` enforces that\n * by funneling every unexpected error into `this.error` and returning a\n * well-formed result regardless of what went wrong.\n *\n * Not exported — consumers interact only with the `agent()` factory (see\n * §4.2 of code-style.md — \"per-call execution state across phases\").\n *\n * @example\n * // Non-streaming — inside agent.execute():\n * const result = await new Execution(config, input, options).run();\n *\n * @example\n * // Streaming — inside agent.stream():\n * const { controller, stream } = createAgentStream();\n * void new Execution(config, input, options, controller).run();\n * return stream;\n */\nclass Execution<TOutput> {\n private readonly trips: LLMTrip[] = [];\n private readonly toolCalls: ToolCall[] = [];\n private readonly usage: Usage = { input: 0, output: 0, total: 0 };\n private readonly messages: Message[] = [];\n private readonly maxTrips: number;\n private readonly startedAt = new Date();\n private readonly start = performance.now();\n private readonly runId = generateRunId(\"agent\");\n private readonly logger: Logger = log;\n private readonly middleware: ReadonlyArray<\n NonNullable<AgentConfig<TOutput>[\"middleware\"]>[number]\n >;\n private readonly middlewareState: MiddlewareState = new Map();\n\n private error?: AIError;\n private data?: TOutput;\n private responseSchema?: Record<string, unknown>;\n\n public constructor(\n private readonly config: AgentConfig<TOutput>,\n private readonly input: string,\n private readonly options?: AgentExecuteOptions<TOutput>,\n private readonly streamController?: StreamController<AgentResult<TOutput>>,\n private readonly instanceHandlers?: InstanceHandlerMap,\n ) {\n this.maxTrips = config.maxTrips ?? 10;\n this.middleware = config.middleware ?? [];\n }\n\n /**\n * Base middleware context shared by every level. `state` is the\n * single mutable bag threaded through `execute`, `trip`, and `tool`\n * hooks for the lifetime of this execution — fresh per `execute()`\n * call, never reused across runs.\n */\n private buildExecuteContext(): MiddlewareExecuteContext {\n return {\n agent: {\n name: this.config.name ?? this.config.model.name,\n isAnonymous: !this.config.name,\n },\n model: {\n name: this.config.model.name,\n provider: this.config.model.provider,\n },\n input: this.input,\n options: this.options as AgentExecuteOptions<unknown> | undefined,\n state: this.middlewareState,\n signal: this.options?.signal,\n };\n }\n\n /**\n * Entry point for a single agent execution. Wraps the real work\n * (`runCore`) in the `execute`-level middleware pipeline, then\n * emits the terminal `agent.completed` / `agent.error` events and\n * closes the stream (if any) with the post-pipeline result — so\n * middleware that short-circuits or transforms the final result\n * still produces a well-formed public outcome.\n *\n * Must never throw: any error that escapes the pipeline is\n * converted into an `AgentResult` with `error` populated before\n * returning, preserving the `agent.execute()` public contract.\n */\n public async run(): Promise<AgentResult<TOutput>> {\n const context = this.buildExecuteContext();\n\n let result: AgentResult<TOutput>;\n\n try {\n result = (await runPipeline(\n this.middleware,\n \"execute\",\n context,\n () => this.runCore(),\n this.logger,\n )) as AgentResult<TOutput>;\n } catch (thrown) {\n this.error = this.toAIError(thrown);\n result = this.buildResult();\n }\n\n if (result.error) {\n this.emit(\"agent.error\", { error: result.error });\n }\n\n this.emit(\"agent.completed\", { result });\n\n // Fire the `onComplete` hook with a flat payload (runId +\n // durationMs pre-extracted) for audit-log consumers. Awaited but\n // errors swallowed so consumer bugs cannot crash the agent or\n // interfere with the result returned to the caller.\n await this.fireCompleteHook(result);\n\n this.streamController?.end(result);\n\n return result;\n }\n\n /**\n * Inner body wrapped by the `execute`-level pipeline. Drives the\n * full lifecycle — build messages → emit starting → run trip loop\n * → parse output → build result. Catches any unexpected throw and\n * funnels it into `this.error` so the returned result is always\n * well-formed; `execute`-level `after` hooks receive the result,\n * with `error` populated when things went wrong.\n */\n private async runCore(): Promise<AgentResult<TOutput>> {\n try {\n await this.buildInitialMessages();\n\n this.emit(\"agent.starting\", { input: this.input });\n\n await this.runTripLoop();\n\n const parseOutcome = await this.parseOutput();\n\n if (parseOutcome === \"failed\" && this.options?.repair) {\n await this.runRepairLoop();\n }\n } catch (thrown) {\n this.error = this.toAIError(thrown);\n }\n\n return this.buildResult();\n }\n\n /**\n * Resolve the system prompt (string or `SystemPromptContract`), merge\n * placeholders from config + execute options, inject a structured-output\n * instruction when the caller wants typed output but the model can't\n * enforce it natively, prepend any conversation history, and append the\n * user input. Produces the initial `messages` array the first trip sends\n * to the model. Runs exactly once per execution.\n */\n private async buildInitialMessages(): Promise<void> {\n const { messages, responseSchema } = await buildAgentInputMessages({\n config: this.config,\n input: this.input,\n options: this.options,\n });\n this.messages.push(...messages);\n this.responseSchema = responseSchema;\n }\n\n /**\n * Drive sequential trips up to `maxTrips`. Each trip may stop the loop\n * naturally (model returned a non-tool-call finish), abort it (model\n * threw), or continue it (model requested tools). When the loop exits\n * after the cap without a natural stop, records a \"Max trips exceeded\"\n * error so the caller can distinguish runaway tool loops from a real result.\n */\n private async runTripLoop(): Promise<void> {\n for (let tripIndex = 0; tripIndex < this.maxTrips; tripIndex++) {\n if (this.options?.signal?.aborted) {\n this.error = this.makeCancelledError();\n return;\n }\n\n const tripInput = tripIndex === 0 ? this.input : \"[tool results]\";\n const outcome = await this.runTrip(tripIndex, tripInput);\n\n if (outcome === \"error\" || outcome === \"stop\") {\n return;\n }\n }\n\n const lastTrip = this.trips[this.trips.length - 1];\n\n if (lastTrip?.finishReason === \"tool_calls\") {\n this.error = new AgentMaxTripsError(\"Max trips exceeded\", {\n maxTrips: this.maxTrips,\n });\n }\n }\n\n /**\n * Execute one round-trip to the model. Aggregates usage into the running\n * total, dispatches any requested tool calls, appends the assistant +\n * tool-result messages for the next trip, and records an `LLMTrip`.\n * Returns an outcome that tells `runTripLoop` whether to continue, stop,\n * or abort.\n */\n private async runTrip(\n tripIndex: number,\n tripInput: string,\n ): Promise<\"continue\" | \"stop\" | \"error\"> {\n this.emit(\"agent.trip.started\", { tripIndex, input: tripInput });\n\n const tripStartedAt = new Date();\n const tripStart = performance.now();\n\n let response: ModelResponse;\n\n try {\n response = await this.runTripThroughPipeline(tripIndex);\n } catch (thrown) {\n this.error = this.toAIError(thrown);\n\n const failedTrip: LLMTrip = {\n index: tripIndex,\n input: tripInput,\n output: \"\",\n finishReason: \"error\",\n startedAt: tripStartedAt.toISOString(),\n endedAt: new Date().toISOString(),\n duration: performance.now() - tripStart,\n usage: { input: 0, output: 0, total: 0 },\n error: this.error,\n };\n\n this.trips.push(failedTrip);\n\n this.emit(\"agent.trip.completed\", { trip: failedTrip });\n this.emit(\"agent.error\", { error: this.error });\n\n return \"error\";\n }\n\n // Attach per-trip cost breakdown using the model's pricing table\n // (when configured). Done at the framework boundary so stored trip\n // records carry historical cost — Panoptic and other archive\n // consumers never re-derive against today's pricing, and the\n // input/output/cached split stays queryable without joining to a\n // pricing table at all.\n if (response.usage.cost === undefined) {\n response.usage.cost = computeCost(response.usage, this.config.model.pricing);\n }\n\n this.usage.input += response.usage.input;\n this.usage.output += response.usage.output;\n this.usage.total += response.usage.total;\n if (response.usage.cachedTokens !== undefined) {\n this.usage.cachedTokens = (this.usage.cachedTokens ?? 0) + response.usage.cachedTokens;\n }\n this.usage.cost = accumulateCost(this.usage.cost, response.usage.cost);\n\n // Fire the `onUsage` hook with a flat, pre-packaged payload so\n // cost-ledger code receives stable identity (runId, model+provider)\n // without joining from elsewhere. Awaited but errors swallowed.\n await this.fireUsageHook(tripIndex, response.usage);\n\n const isToolCallTrip =\n response.finishReason === \"tool_calls\" &&\n response.toolCalls !== undefined &&\n response.toolCalls.length > 0;\n\n const tripToolCalls: ToolCall[] = [];\n\n if (isToolCallTrip) {\n this.messages.push({\n role: \"assistant\",\n content: response.content,\n toolCalls: response.toolCalls,\n });\n\n for (const toolCallRequest of response.toolCalls!) {\n const record = await this.dispatchToolCall(toolCallRequest, tripIndex);\n\n tripToolCalls.push(record);\n }\n }\n\n const trip: LLMTrip = {\n index: tripIndex,\n input: tripInput,\n output: response.content,\n finishReason: response.finishReason,\n startedAt: tripStartedAt.toISOString(),\n endedAt: new Date().toISOString(),\n duration: performance.now() - tripStart,\n usage: response.usage,\n toolCalls: tripToolCalls.length > 0 ? tripToolCalls : undefined,\n };\n\n this.trips.push(trip);\n\n this.emit(\"agent.trip.completed\", { trip });\n\n if (!isToolCallTrip) {\n return \"stop\";\n }\n\n // Terminate the trip loop when EVERY tool call this trip is\n // `mode: \"silent\"`. Silent tools don't feed their result back\n // to the model — the prose the model streamed alongside the\n // tool call IS the final reply. The \"all\" rule is load-bearing:\n // if any feedback tool was called too, its result still needs\n // to round-trip, so we must continue.\n //\n // Composite (`asTool`-wrapped) tools never set `mode: \"silent\"`\n // in v1 — silent-composite mechanics are deferred per plan\n // 2026-05-07-silent-tools.md (Q4). They behave as feedback.\n const allSilent = response.toolCalls!.every((request) => {\n const registered = this.config.tools?.find((tool) => tool.name === request.name);\n return registered?.mode === \"silent\";\n });\n\n return allSilent ? \"stop\" : \"continue\";\n }\n\n /**\n * Route `getModelResponse` through the `trip`-level middleware\n * pipeline. `trip.before` hooks can short-circuit the trip by\n * returning a synthetic `ModelResponse` (semantic cache hit).\n * `trip.after` hooks can transform the response before the trip\n * record is built or any tool calls are dispatched. `trip.onError`\n * hooks can recover from provider failures (fallback chain).\n */\n private async runTripThroughPipeline(tripIndex: number): Promise<ModelResponse> {\n const context: MiddlewareTripContext = {\n ...this.buildExecuteContext(),\n tripIndex,\n messages: this.messages,\n };\n\n return (await runPipeline(\n this.middleware,\n \"trip\",\n context,\n () => this.getModelResponse(tripIndex),\n this.logger,\n )) as ModelResponse;\n }\n\n /**\n * Produce the `ModelResponse` for the current trip. In non-streaming\n * mode, delegates straight to `model.complete()`. In streaming mode,\n * drains `model.stream()` while emitting `streaming` events per delta\n * and accumulates the chunks into the same `ModelResponse` shape, so the\n * rest of the trip pipeline (tool dispatch, trip record, usage\n * aggregation) stays identical between the two modes.\n */\n private async getModelResponse(tripIndex: number): Promise<ModelResponse> {\n const callOptions = {\n ...this.config.modelOptions,\n tools: this.config.tools ?? [],\n ...(this.responseSchema ? { responseSchema: this.responseSchema } : {}),\n ...(this.options?.signal ? { signal: this.options.signal } : {}),\n };\n\n if (!this.streamController) {\n return this.config.model.complete(this.messages, callOptions);\n }\n\n let content = \"\";\n let finishReason: FinishReason = \"stop\";\n let usage: Usage = { input: 0, output: 0, total: 0 };\n const toolCalls: ModelToolCallRequest[] = [];\n const recoveredCalls: ModelToolCallRequest[] = [];\n\n const guardConfig = this.resolveStreamingToolGuard();\n const guard = guardConfig\n ? new JsonStreamGuard({\n tools: (this.config.tools ?? []) as ReadonlyArray<ToolContract<unknown, unknown>>,\n maxBufferBytes: guardConfig.maxBufferBytes,\n onSafeDelta: (delta) => {\n content += delta;\n\n this.emit(\"agent.trip.streaming\", { delta, tripIndex });\n },\n onRecoveredCall: (request) => {\n recoveredCalls.push(request);\n },\n })\n : undefined;\n\n for await (const chunk of this.config.model.stream(this.messages, callOptions)) {\n // Mid-stream abort — break out cleanly instead of continuing to\n // consume the iterator. The underlying fetch is already\n // cancelled via `signal` forwarded in callOptions; this covers\n // adapters that don't honor signal natively and keeps mock\n // models consistent under cancellation tests.\n if (this.options?.signal?.aborted) {\n throw this.makeCancelledError();\n }\n\n if (chunk.type === \"delta\") {\n if (guard) {\n await guard.feed(chunk.content);\n } else {\n content += chunk.content;\n\n this.emit(\"agent.trip.streaming\", { delta: chunk.content, tripIndex });\n }\n\n continue;\n }\n\n if (chunk.type === \"tool-call\") {\n toolCalls.push({\n id: chunk.id,\n name: chunk.name,\n input: chunk.input,\n ...(chunk.providerMetadata ? { providerMetadata: chunk.providerMetadata } : {}),\n });\n\n continue;\n }\n\n finishReason = chunk.finishReason;\n usage = chunk.usage;\n }\n\n if (guard) {\n await guard.finalize();\n }\n\n // Dedupe synthesized calls against real ones the provider streamed\n // structurally — the model occasionally emits BOTH channels for\n // the same call (real tool-call chunk + narrated JSON envelope).\n // Real wins; the synthesized duplicate is dropped so dispatch\n // doesn't run twice. See plan 2026-05-22 §Q5.\n const dedupedRecovered = recoveredCalls.filter(\n (recovered) => !isDuplicateToolCall(recovered, toolCalls),\n );\n\n const mergedToolCalls = [...toolCalls, ...dedupedRecovered];\n\n // When the guard recovered any calls but the model reported a\n // natural `\"stop\"`, override to `\"tool_calls\"` so the agent's\n // dispatch loop (`runTrip` → `isToolCallTrip`) actually fires.\n // Without this the guard silently suppresses the leaked JSON but\n // never dispatches the real action — chips never render.\n const resolvedFinishReason: FinishReason =\n dedupedRecovered.length > 0 && finishReason === \"stop\" ? \"tool_calls\" : finishReason;\n\n return {\n content,\n finishReason: resolvedFinishReason,\n usage,\n toolCalls: mergedToolCalls.length > 0 ? mergedToolCalls : undefined,\n };\n }\n\n /**\n * Resolve the effective `streamingToolGuard` for this trip.\n * Per-call options win over the agent-level config when the key is\n * explicitly present on options (including the explicit `undefined`\n * \"disable for this call\" form). Returns `undefined` when no guard\n * should run.\n */\n private resolveStreamingToolGuard(): StreamingToolGuardConfig | undefined {\n if (\n this.options !== undefined &&\n Object.prototype.hasOwnProperty.call(this.options, \"streamingToolGuard\")\n ) {\n return this.options.streamingToolGuard;\n }\n\n return this.config.streamingToolGuard;\n }\n\n /**\n * Dispatch a single tool call requested by the model. Looks up the tool\n * by name, invokes it via the safe `ToolContract.invoke` entry, pushes a\n * matching tool-result message into `this.messages` so the next trip can\n * see it, and emits the right lifecycle event (`tool-called` on success,\n * `tool-calling-failed` when the tool is unregistered or invoke returned\n * an error). Never throws — always returns a `ToolCall` record.\n */\n private async dispatchToolCall(\n toolCallRequest: ModelToolCallRequest,\n tripIndex: number,\n ): Promise<ToolCall> {\n const registeredTool = this.config.tools?.find((tool) => tool.name === toolCallRequest.name);\n\n if (!registeredTool) {\n const error = new AgentExecutionError(`Tool not registered: ${toolCallRequest.name}`, {\n context: { toolName: toolCallRequest.name, tripIndex },\n });\n\n const nowIso = new Date().toISOString();\n\n const record: ToolCall = {\n runId: generateRunId(\"tool\"),\n rootRunId: this.runId,\n name: toolCallRequest.name,\n type: \"tool\",\n status: \"failed\",\n startedAt: nowIso,\n endedAt: nowIso,\n duration: 0,\n usage: { input: 0, output: 0, total: 0 },\n children: [],\n tripIndex,\n input: toolCallRequest.input,\n error,\n ...(toolCallRequest.recoveredFrom ? { recoveredFrom: toolCallRequest.recoveredFrom } : {}),\n };\n\n this.toolCalls.push(record);\n\n this.messages.push({\n role: \"tool\",\n toolCallId: toolCallRequest.id,\n content: JSON.stringify({ error: error.message }),\n });\n\n // Stub meta — there's no real tool to describe. Carries the\n // requested name for log correlation and an explanatory\n // description so consumers don't see an empty string.\n this.emit(\"agent.tool.failed\", {\n tool: {\n name: toolCallRequest.name,\n description: \"(unregistered tool — no description available)\",\n },\n input: toolCallRequest.input,\n error,\n tripIndex,\n });\n\n return record;\n }\n\n // Build the lightweight event meta once. Resolves `action` to a\n // string here so consumers receive plain data rather than having\n // to re-evaluate a callback on every event.\n const toolMeta: ToolEventMeta = {\n name: registeredTool.name,\n description: registeredTool.description,\n action: resolveToolAction(registeredTool, toolCallRequest.input),\n };\n\n this.emit(\"agent.tool.calling\", {\n tool: toolMeta,\n input: toolCallRequest.input,\n tripIndex,\n });\n\n const toolContext: MiddlewareToolContext = {\n ...this.buildExecuteContext(),\n tripIndex,\n messages: this.messages,\n tool: {\n name: registeredTool.name,\n description: registeredTool.description,\n mode: registeredTool.mode,\n },\n request: toolCallRequest,\n };\n\n let invokeResult: ToolInvokeResult<unknown>;\n\n try {\n invokeResult = (await runPipeline(\n this.middleware,\n \"tool\",\n toolContext,\n () => registeredTool.invoke(toolCallRequest.input, this.options?.toolCtx),\n this.logger,\n )) as ToolInvokeResult<unknown>;\n } catch (thrown) {\n // A `tool`-level middleware hook threw. The real invoke never\n // throws (it funnels errors into `result.error`), so only a\n // middleware abort or a bug reaches this branch. Synthesize a\n // failed-invoke record so the tool-call trace stays consistent.\n const error = this.toAIError(thrown);\n const nowIso = new Date().toISOString();\n const emptyUsage: Usage = { input: 0, output: 0, total: 0 };\n\n const failedRunId = generateRunId(\"tool\");\n invokeResult = {\n error,\n usage: emptyUsage,\n report: {\n runId: failedRunId,\n rootRunId: failedRunId,\n name: registeredTool.name,\n version: registeredTool.version,\n type: \"tool\",\n status: \"failed\",\n startedAt: nowIso,\n endedAt: nowIso,\n duration: 0,\n usage: emptyUsage,\n children: [],\n },\n };\n }\n\n // The agent-level ToolCall record merges the tool's own invocation\n // report with agent-side enrichments (tripIndex, input, output,\n // error). When the underlying tool was an `asTool`-wrapped\n // composite, its inner report becomes the sole child of this\n // ToolCall — preserving the full nested tree while keeping this\n // node's own `type` as `\"tool\"` (from the agent's POV it *was* a\n // tool dispatch).\n const innerReport = invokeResult.report;\n const isComposite = innerReport.type !== \"tool\";\n\n const record: ToolCall = {\n runId: innerReport.runId,\n rootRunId: this.runId,\n name: toolCallRequest.name,\n version: registeredTool.version,\n type: \"tool\",\n status: innerReport.status,\n startedAt: innerReport.startedAt,\n endedAt: innerReport.endedAt,\n duration: innerReport.duration,\n usage: invokeResult.usage,\n children: isComposite ? [innerReport] : innerReport.children,\n tripIndex,\n input: toolCallRequest.input,\n output: invokeResult.data,\n error: invokeResult.error,\n ...(toolCallRequest.recoveredFrom ? { recoveredFrom: toolCallRequest.recoveredFrom } : {}),\n };\n\n this.toolCalls.push(record);\n\n // Roll child usage into the agent's accumulator. Leaf tools\n // contribute zero; `asTool`-wrapped composites contribute the\n // full cost of the inner agent/workflow/supervisor run.\n this.usage.input += invokeResult.usage.input;\n this.usage.output += invokeResult.usage.output;\n this.usage.total += invokeResult.usage.total;\n this.usage.cost = accumulateCost(this.usage.cost, invokeResult.usage.cost);\n\n this.messages.push({\n role: \"tool\",\n toolCallId: toolCallRequest.id,\n content: invokeResult.error\n ? JSON.stringify({ error: invokeResult.error.message })\n : JSON.stringify(invokeResult.data ?? null),\n });\n\n if (invokeResult.error) {\n this.emit(\"agent.tool.failed\", {\n tool: toolMeta,\n input: toolCallRequest.input,\n error: invokeResult.error,\n tripIndex,\n });\n } else {\n this.emit(\"agent.tool.called\", { ...record, tool: toolMeta });\n }\n\n return record;\n }\n\n /**\n * Parse the final trip output against the user-supplied schema (if any).\n * Failures populate `this.error` but never throw. Returns an outcome the\n * caller uses to decide whether self-repair is worth attempting:\n *\n * - `\"skipped\"` — no schema, or a prior trip-level error already set\n * `this.error` (model crash, max trips). Not repairable; the failure\n * isn't a parse problem the model can fix by re-asking.\n * - `\"failed\"` — schema present, output text either failed JSON.parse\n * or failed `~standard.validate`. Repairable via `runRepairLoop`.\n * - `\"success\"` — parsed and validated; `this.data` populated.\n */\n private async parseOutput(): Promise<\"success\" | \"failed\" | \"skipped\"> {\n const schema = this.options?.output ?? this.config.output;\n\n if (!schema || this.error) {\n return \"skipped\";\n }\n\n const finalTrip = this.trips[this.trips.length - 1];\n const text = finalTrip?.output ?? \"\";\n\n if (!text) {\n return \"skipped\";\n }\n\n const payload = extractJsonPayload(text);\n const sentinel = Symbol(\"parse-failed\");\n const parsed = safeJsonParse<unknown>(payload, sentinel);\n\n if (parsed === sentinel) {\n this.error = new SchemaValidationError(\"Failed to parse model output as JSON\", {\n context: { text },\n });\n return \"failed\";\n }\n\n const validation = await (schema as StandardSchemaV1<TOutput>)[\"~standard\"].validate(parsed);\n\n if (validation.issues) {\n const summary = validation.issues.map((issue) => issue.message).join(\"; \");\n this.error = new SchemaValidationError(summary, {\n issues: validation.issues,\n });\n return \"failed\";\n }\n\n this.data = validation.value;\n return \"success\";\n }\n\n /**\n * Opt-in self-repair loop for `output` schema failures. Triggered only\n * when `options.repair` is set and `parseOutput()` returned `\"failed\"`.\n *\n * Each attempt:\n * 1. Pushes the bad assistant response into `this.messages` (so the\n * model can see what it just produced).\n * 2. Pushes a corrective user message naming the validation/parse error.\n * 3. Runs another trip — counted against the same `maxTrips` cap as\n * normal trips so a stuck model can't loop forever.\n * 4. Re-parses. Stops on success, on a trip-level error, or when\n * either `maxAttempts` or `maxTrips` is exhausted.\n *\n * Resets `this.error` and `this.data` before each attempt so the final\n * outcome (success or last failure) is what surfaces to the caller.\n */\n private async runRepairLoop(): Promise<void> {\n const maxAttempts = this.options?.repair?.maxAttempts ?? 1;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (this.trips.length >= this.maxTrips) {\n return;\n }\n\n const lastTrip = this.trips[this.trips.length - 1];\n const badResponse = lastTrip?.output ?? \"\";\n const failureReason = this.error?.message ?? \"unknown validation failure\";\n\n this.error = undefined;\n this.data = undefined;\n\n this.messages.push({ role: \"assistant\", content: badResponse });\n\n this.messages.push({\n role: \"user\",\n content: [\n `Your previous response failed validation: ${failureReason}.`,\n \"Respond again with valid JSON only — no prose, no markdown fences, no commentary.\",\n ].join(\" \"),\n });\n\n const tripIndex = this.trips.length;\n\n this.logger.warn(LOG_MODULE, \"repair.attempting\", \"retrying after validation failure\", {\n attempt: attempt + 1,\n maxAttempts,\n reason: failureReason,\n });\n\n const outcome = await this.runTrip(tripIndex, \"[repair attempt]\");\n\n if (outcome === \"error\") {\n return;\n }\n\n const parseOutcome = await this.parseOutput();\n\n if (parseOutcome === \"success\") {\n return;\n }\n }\n }\n\n /**\n * Build the final `AgentResult` snapshot from accumulated state\n * (trips, tool calls, data/error, usage, timing).\n *\n * Pure — no side effects. `run()` owns terminal event emission and\n * stream closure so the post-pipeline result (possibly transformed\n * or short-circuited by an `execute`-level middleware) is what\n * flows out to consumers and listeners.\n *\n * Trips, tool calls, status, and timing live under `report` so the\n * root stays focused on the four things callers reach for most:\n * `data`, `text`, `usage`, `error`.\n */\n private buildResult(): AgentResult<TOutput> {\n const finalTrip = this.trips[this.trips.length - 1];\n const endedAt = new Date();\n\n const agentName = this.config.name ?? this.config.model.name;\n const status: BaseReport[\"status\"] = this.error\n ? this.error instanceof AgentCancelledError\n ? \"cancelled\"\n : \"failed\"\n : \"completed\";\n\n const report = {\n runId: this.runId,\n rootRunId: this.runId,\n name: agentName,\n version: this.config.version,\n type: \"agent\" as const,\n status,\n startedAt: this.startedAt.toISOString(),\n endedAt: endedAt.toISOString(),\n duration: performance.now() - this.start,\n usage: this.usage,\n children: this.toolCalls,\n model: {\n name: this.config.model.name,\n provider: this.config.model.provider,\n },\n trips: this.trips,\n };\n\n // Stamp lineage on the assembled tree exactly once per run.\n // Rewrites any inner self-roots from composite children to this\n // run's id, stamps `reportSchemaVersion` on the root, and\n // propagates `sessionId` to every node.\n stampReportLineage(report, {\n rootRunId: this.runId,\n sessionId: this.options?.sessionId,\n });\n\n return {\n type: \"agent\",\n data: this.data,\n text: finalTrip?.output,\n report,\n usage: this.usage,\n error: this.error,\n };\n }\n\n /**\n * Normalize any thrown value into an `AIError`. `AIError` instances\n * pass through untouched; provider-adapter SDK errors are caught by\n * the adapter and already arrive typed, so this branch mainly\n * handles runtime crashes (TypeError, ReferenceError) inside\n * model.complete / model.stream and non-Error values (`throw \"bad\"`).\n */\n private toAIError(thrown: unknown): AIError {\n if (thrown instanceof AIError) {\n return thrown;\n }\n\n // Classify abort-flavored errors (DOMException \"AbortError\",\n // node-fetch's `FetchError` with name \"AbortError\", `ERR_CANCELED`\n // from the OpenAI SDK's axios-ish layer) as cancelled instead of\n // a generic exec failure so callers can route retries correctly.\n if (isAbortLike(thrown)) {\n return this.makeCancelledError();\n }\n\n const message = thrown instanceof Error ? thrown.message : String(thrown);\n\n return new AgentExecutionError(message, { cause: thrown });\n }\n\n /**\n * Build the typed cancelled error that both the trip-loop guard\n * and the mid-stream guard emit. Captures the abort reason when\n * one was supplied to `controller.abort(reason)` so logs and\n * telemetry can see what cancelled the run.\n */\n private makeCancelledError(): AgentCancelledError {\n const reason = this.options?.signal?.reason;\n const reasonText = reason === undefined ? \"\" : String(reason);\n\n return new AgentCancelledError(\"agent execution cancelled\", {\n cause: reason,\n cancelledAt: new Date().toISOString(),\n reason: reasonText,\n });\n }\n\n /**\n * Fire a single event through all three subscription tiers in order\n * — factory → instance → per-call — and mirror it into the\n * `StreamController` when streaming is active. A throwing user\n * handler must never crash the agent, so every dispatch is wrapped\n * in `safeCall`. Stream events are converted from the internal\n * `AgentEventMap` payload to the public `StreamEvent` shape because\n * some of them differ (e.g. the tool-called payload vs stream\n * event).\n */\n private emit<K extends keyof AgentEventMap>(\n event: K,\n payload: WithoutIdentity<AgentEventMap[K]>,\n ): void {\n // Inject run identity once, here, so every subscription tier and\n // the stream see it. `rootRunId === runId` for a standalone run;\n // nested propagation lands in a follow-up.\n const fullPayload = {\n ...payload,\n runId: this.runId,\n rootRunId: this.runId,\n } as AgentEventMap[K];\n\n this.logEvent(event, fullPayload);\n\n const factoryHandler = this.config.on?.[event] as AgentEventHandler<K> | undefined;\n\n if (factoryHandler) {\n safeCall(factoryHandler, fullPayload);\n }\n\n const bucket = this.instanceHandlers?.get(event);\n\n if (bucket) {\n for (const handler of bucket) {\n safeCall(handler as AgentEventHandler<K>, fullPayload);\n }\n }\n\n const perCallHandler = this.options?.on?.[event] as AgentEventHandler<K> | undefined;\n\n if (perCallHandler) {\n safeCall(perCallHandler, fullPayload);\n }\n\n if (this.streamController) {\n const body = this.toStreamEvent(event, fullPayload);\n\n if (body) {\n this.streamController.push({\n runId: this.runId,\n rootRunId: this.runId,\n ...body,\n });\n }\n }\n }\n\n /**\n * Emit a structured log line for a lifecycle event. The action\n * string mirrors the event name with the `agent.` prefix stripped\n * (`agent.trip.started` → `trip.started`) so log grep filters and\n * event handlers read the same vocabulary. Level mapping follows\n * the convention documented on `@warlock.js/logger`'s `Logger`.\n */\n private logEvent<K extends keyof AgentEventMap>(event: K, payload: AgentEventMap[K]): void {\n const agentName = this.config.name || this.config.model.name;\n logAgentEvent(\n this.logger,\n {\n module: `${LOG_MODULE}.${agentName}`,\n maxTrips: this.maxTrips,\n modelName: this.config.model.name,\n totalUsage: this.usage,\n totalDurationMs: performance.now() - this.start,\n trips: this.trips,\n toolCalls: this.toolCalls,\n },\n event,\n payload,\n );\n }\n\n private toStreamEvent<K extends keyof AgentEventMap>(\n event: K,\n payload: AgentEventMap[K],\n ): StreamEventBody | undefined {\n return agentEventToStreamEvent(event, payload);\n }\n\n /**\n * Invoke the `onUsage` hook (when configured) with a flat payload\n * carrying stable identity. Awaits the handler so async ledger\n * writes complete before the next trip starts; swallows any throw\n * so consumer bugs cannot crash the agent. Sync handlers wrapped\n * via `Promise.resolve()` so the await is safe in either case.\n */\n private async fireUsageHook(tripIndex: number, tripUsage: Usage): Promise<void> {\n const handler = this.config.onUsage;\n if (!handler) return;\n\n const event: UsageEvent = {\n runId: this.runId,\n tripIndex,\n model: {\n name: this.config.model.name,\n provider: this.config.model.provider,\n },\n usage: { ...tripUsage },\n timestamp: new Date().toISOString(),\n };\n\n try {\n await Promise.resolve(handler(event));\n } catch (err) {\n this.logger.warn(LOG_MODULE, \"onUsage.hook.error\", \"onUsage handler threw\", {\n runId: this.runId,\n tripIndex,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n /**\n * Invoke the `onComplete` hook (when configured) once at the end\n * of every run. Receives the full `AgentResult` plus pre-extracted\n * `runId` and `durationMs`. Same swallow-and-log error policy as\n * `fireUsageHook`.\n */\n private async fireCompleteHook(result: AgentResult<TOutput>): Promise<void> {\n const handler = this.config.onComplete;\n if (!handler) return;\n\n const event: CompleteEvent<TOutput> = {\n result,\n runId: this.runId,\n durationMs: performance.now() - this.start,\n };\n\n try {\n await Promise.resolve(handler(event));\n } catch (err) {\n this.logger.warn(LOG_MODULE, \"onComplete.hook.error\", \"onComplete handler threw\", {\n runId: this.runId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n}\n\n/**\n * Decide whether a guard-synthesized tool call duplicates a real one\n * the provider already streamed structurally. Match key is\n * `name + key-sorted JSON of input` so identical calls (regardless of\n * argument key order) collapse, but two legitimate calls to the same\n * tool with different inputs still both dispatch.\n */\nfunction isDuplicateToolCall(\n recovered: ModelToolCallRequest,\n realCalls: ReadonlyArray<ModelToolCallRequest>,\n): boolean {\n const recoveredKey = `${recovered.name}|${stableStringify(recovered.input)}`;\n\n for (const real of realCalls) {\n const realKey = `${real.name}|${stableStringify(real.input)}`;\n\n if (realKey === recoveredKey) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * `JSON.stringify` variant that sorts object keys at every nesting\n * level so structurally-equal inputs serialize to identical strings.\n * Used only for dedupe-key comparison; never surfaces to consumers.\n */\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(value, (_key, val) => {\n if (val !== null && typeof val === \"object\" && !Array.isArray(val)) {\n const source = val as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n\n for (const key of Object.keys(source).sort()) {\n sorted[key] = source[key];\n }\n\n return sorted;\n }\n\n return val;\n });\n}\n\n/**\n * Invoke a user-supplied event handler without letting exceptions\n * escape the agent. Thrown errors are swallowed — structured logging\n * attaches here in Phase 0.5 so operators still see the failure.\n */\nfunction safeCall<T>(handler: (payload: T) => void, payload: T): void {\n try {\n handler(payload);\n } catch {\n // Intentionally swallowed — user handlers never crash the agent.\n }\n}\n\n/**\n * Resolve a tool's `action` declaration into a plain string for\n * inclusion in `ToolEventMeta`. Static strings pass through;\n * function-shaped actions are invoked with the validated input.\n *\n * Defensive: if the user's callback throws, swallow and return\n * `undefined` rather than crashing the agent — UI strings are not\n * worth aborting an LLM dispatch over.\n */\nfunction resolveToolAction(\n tool: ToolContract<unknown, unknown>,\n input: unknown,\n): string | undefined {\n if (tool.action === undefined) return undefined;\n if (typeof tool.action === \"string\") return tool.action;\n try {\n return tool.action(input);\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agent.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/agent/agent.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { log, type Logger } from \"@warlock.js/logger\";\nimport type {\n AgentContract,\n AgentEventHandler,\n AgentEventMap,\n AgentExecuteOptions,\n AgentResult,\n BaseReport,\n CompleteEvent,\n FinishReason,\n LLMTrip,\n Message,\n MiddlewareExecuteContext,\n MiddlewareState,\n MiddlewareToolContext,\n MiddlewareTripContext,\n ModelResponse,\n ModelToolCallRequest,\n StreamContract,\n StreamEventBody,\n StreamingToolGuardConfig,\n ToolCall,\n ToolEventMeta,\n Usage,\n UsageEvent,\n WithoutIdentity,\n} from \"../contracts\";\nimport {\n AgentCancelledError,\n AgentExecutionError,\n AgentMaxTripsError,\n AIError,\n SchemaValidationError,\n} from \"../errors\";\nimport type { AgentContract as AgentContractType } from \"../contracts/agent/agent.contract\";\nimport type { EvalOptions, EvalReport } from \"../contracts/agent/eval.type\";\nimport { runEval } from \"../eval/eval-runner\";\nimport { runPipeline } from \"../middleware\";\nimport { normalizeAgentTools } from \"../tool/executable-as-tool\";\nimport type { ToolContract, ToolInvokeResult } from \"../tool/tool\";\nimport {\n accumulateCost,\n computeCost,\n extractJsonPayload,\n generateRunId,\n safeJsonParse,\n stampReportLineage,\n} from \"../utils\";\nimport type { AgentConfig } from \"./agent-config.type\";\nimport { buildAgentInputMessages } from \"./agent-input-builder\";\nimport { logAgentEvent } from \"./agent-log-event\";\nimport { createAgentStream, type StreamController } from \"./agent-stream\";\nimport { agentEventToStreamEvent } from \"./agent-to-stream-event\";\nimport { JsonStreamGuard } from \"./json-stream-guard\";\n\nconst LOG_MODULE = \"ai.agent\";\n\n/**\n * Internal post-normalization view of an `AgentConfig`. The public\n * `tools` field accepts both built `ToolContract`s and raw executables\n * (`AgentToolEntry[]`); by the time the runtime sees the config every\n * entry has been adapted to a `ToolContract`, so `Execution` works\n * against this narrowed shape and never has to re-discriminate.\n */\ntype ResolvedAgentConfig<TOutput> = Omit<AgentConfig<TOutput>, \"tools\"> & {\n tools?: ToolContract<unknown, unknown>[];\n};\n\n/**\n * Detect abort-flavored errors surfaced by SDK HTTP layers — the\n * DOM `AbortError`, axios `ERR_CANCELED`, node-fetch's own\n * `AbortError`. Used to classify them as cancellation rather than\n * generic agent-execution failures.\n */\nfunction isAbortLike(err: unknown): boolean {\n if (!err || typeof err !== \"object\") return false;\n\n const e = err as { name?: unknown; code?: unknown };\n\n return e.name === \"AbortError\" || e.code === \"ERR_CANCELED\" || e.code === \"ABORT_ERR\";\n}\n\n/**\n * Readable synthetic name for agents constructed without an explicit\n * `name`. Format: `anon_<provider>_<model>[_<tool1>+<tool2>+...]` —\n * deterministic (same config → same name across restarts) and\n * human-readable in logs / workflow snapshots.\n *\n * Keeps drift detection honest for the `ai.agent({ model })`\n * one-liner without punishing it with a hashed id nobody can read.\n */\nfunction synthesizeAgentName<T>(config: AgentConfig<T>): string {\n const provider = (config.model as unknown as { provider?: string })?.provider ?? \"unknown\";\n const model = config.model?.name ?? \"unknown\";\n const tools = (config.tools ?? [])\n .map((tool) => tool.name)\n .sort()\n .join(\"+\");\n\n const base = `anon_${sanitize(provider)}_${sanitize(model)}`;\n return tools ? `${base}_${sanitize(tools, { keepPlus: true })}` : base;\n}\n\nfunction sanitize(value: string, opts: { keepPlus?: boolean } = {}): string {\n const allowed = opts.keepPlus ? /[^a-zA-Z0-9._+-]/g : /[^a-zA-Z0-9._-]/g;\n return value.replace(allowed, \"-\");\n}\n\n/**\n * Authoring-time check on the middleware array. Throws an\n * `AgentExecutionError` with `context: { authoring: true }` the\n * moment an invalid entry is found — the agent factory surface is\n * where config bugs should surface, not ten trips into a run.\n *\n * Validates:\n * - Every entry is a non-null object with a non-empty string `name`.\n * - No two entries share the same `name` (would silently collide on\n * `ctx.state` keys and produce impossible-to-debug behavior).\n *\n * Does NOT validate that hook maps contain callable functions —\n * that would catch late-binding bugs but also reject legitimate\n * patterns like `before` being conditionally `undefined`. Runtime\n * dispatch handles missing hooks safely.\n */\nfunction validateMiddleware(middleware: ReadonlyArray<unknown> | undefined): void {\n if (!middleware || middleware.length === 0) {\n return;\n }\n\n const seen = new Set<string>();\n\n for (let index = 0; index < middleware.length; index++) {\n const entry = middleware[index];\n\n if (!entry || typeof entry !== \"object\") {\n throw new AgentExecutionError(\n `middleware[${index}] must be an object; received ${entry === null ? \"null\" : typeof entry}`,\n { context: { authoring: true, index } },\n );\n }\n\n const name = (entry as { name?: unknown }).name;\n\n if (typeof name !== \"string\" || name.length === 0) {\n throw new AgentExecutionError(`middleware[${index}] must have a non-empty string \"name\"`, {\n context: { authoring: true, index },\n });\n }\n\n if (seen.has(name)) {\n throw new AgentExecutionError(\n `duplicate middleware name \"${name}\" — each middleware needs a unique name so ctx.state keys do not collide`,\n { context: { authoring: true, index, name } },\n );\n }\n\n seen.add(name);\n }\n}\n\n/**\n * Creates an executable AI agent from the given configuration.\n *\n * The agent runs a bounded trip loop: each trip calls the model, dispatches\n * any requested tool calls, then loops until the model stops or `maxTrips`\n * is reached. Each `execute()` / `stream()` call spawns a fresh internal\n * `Execution` instance — the factory itself holds no state across calls.\n *\n * `execute()` never throws — any error is attached to the returned result\n * under `result.error`. `stream()` surfaces errors both on the terminal\n * `error` stream event and via the `stream.result` promise.\n *\n * @example\n * const myAgent = agent({\n * model: openai.model({ name: \"gpt-4o\" }),\n * systemPrompt: \"You are a helpful assistant.\",\n * tools: [searchTool],\n * });\n *\n * const result = await myAgent.execute(\"What is the capital of Egypt?\");\n *\n * @example\n * const stream = myAgent.stream(\"Write a haiku about Cairo.\");\n *\n * for await (const event of stream) {\n * if (event.type === \"streaming\") process.stdout.write(event.delta);\n * }\n *\n * const result = await stream.result;\n */\nexport function agent<TOutput = unknown>(config: AgentConfig<TOutput>): AgentContract<TOutput> {\n // Authoring-time validation of the middleware array. Rejects two\n // classes of bug that would otherwise surface as opaque failures\n // mid-execution: (a) entries that aren't proper middleware\n // objects (null, undefined, missing `name`), and (b) two\n // middlewares sharing the same `name`, which would silently\n // collide on `ctx.state` keys. Fail fast, fail loud — per the\n // authoring-time rules in `domains/ai/conventions/errors.md`.\n validateMiddleware(config.middleware);\n\n // Resolve the agent's identity. Explicit `name` wins; otherwise we\n // synthesize a DETERMINISTIC fingerprint from the config's\n // identity-defining fields (model + provider + tool names). Same\n // config across process restarts produces the same synthetic name,\n // so workflow signature drift detection stays honest for agents\n // composed into workflows without explicit names.\n const isAnonymous = !config.name || typeof config.name !== \"string\";\n\n // Auto-adapt any raw executable (agent/workflow/supervisor) dropped\n // into `tools: []` into a `ToolContract` before the name is\n // synthesized — `synthesizeAgentName` reads `config.tools[].name`,\n // so the fingerprint must see the normalized entries. Built\n // `ToolContract`s (from `.asTool()` / `ai.tool()`) pass through\n // untouched, so this is a no-op for the existing surface.\n const tools = normalizeAgentTools(config.tools);\n const name = isAnonymous\n ? synthesizeAgentName({ ...config, tools })\n : (config.name as string);\n const resolvedConfig: ResolvedAgentConfig<TOutput> = { ...config, name, tools };\n\n // Instance-level handlers registered via `.on()`. Stored here\n // (factory-scope) so every `execute()` / `stream()` call on this\n // agent sees the same set. Each event name gets its own Set so\n // `off()` can remove a specific handler without disturbing others.\n const instanceHandlers = new Map<\n keyof AgentEventMap,\n Set<AgentEventHandler<keyof AgentEventMap>>\n >();\n\n function on<K extends keyof AgentEventMap>(event: K, handler: AgentEventHandler<K>): () => void {\n const existing = instanceHandlers.get(event);\n const bucket = existing ?? new Set<AgentEventHandler<keyof AgentEventMap>>();\n\n if (!existing) {\n instanceHandlers.set(event, bucket);\n }\n\n bucket.add(handler as AgentEventHandler<keyof AgentEventMap>);\n\n return () => off(event, handler);\n }\n\n function off<K extends keyof AgentEventMap>(event: K, handler: AgentEventHandler<K>): void {\n const bucket = instanceHandlers.get(event);\n\n if (!bucket) {\n return;\n }\n\n bucket.delete(handler as AgentEventHandler<keyof AgentEventMap>);\n\n if (bucket.size === 0) {\n instanceHandlers.delete(event);\n }\n }\n\n const agentContract: AgentContractType<TOutput> = {\n name,\n isAnonymous,\n description: config.description,\n async execute(\n input: string,\n options?: AgentExecuteOptions<TOutput>,\n ): Promise<AgentResult<TOutput>> {\n return new Execution<TOutput>(\n resolvedConfig,\n input,\n options,\n undefined,\n instanceHandlers,\n ).run();\n },\n\n stream(\n input: string,\n options?: AgentExecuteOptions<TOutput>,\n ): StreamContract<AgentResult<TOutput>> {\n const { controller, stream } = createAgentStream<AgentResult<TOutput>>();\n\n const execution = new Execution<TOutput>(\n resolvedConfig,\n input,\n options,\n controller,\n instanceHandlers,\n );\n\n void execution.run();\n\n return stream;\n },\n\n on,\n off,\n\n eval<TEval = TOutput>(options: EvalOptions<TEval>): Promise<EvalReport<TEval>> {\n return runEval<TEval>(agentContract as unknown as AgentContract<TEval>, options);\n },\n };\n\n return agentContract;\n}\n\n/**\n * Name → handler-set map shared between the `agent()` factory and its\n * per-call `Execution`. Each `.on()` registration mutates this map;\n * every `Execution` reads from the same reference so additions and\n * removals take effect mid-flight.\n */\ntype InstanceHandlerMap = Map<keyof AgentEventMap, Set<AgentEventHandler<keyof AgentEventMap>>>;\n\n/**\n * Per-call driver that owns the full lifecycle of a single\n * `agent.execute()` or `agent.stream()` invocation.\n *\n * **Role.** An `Execution` is the short-lived state container and phase\n * orchestrator for one agent run. The public `agent()` factory stays purely\n * functional — all mutable bookkeeping (trips, tool calls, usage totals,\n * message history, terminal error, parsed output) lives here so each call\n * gets a fresh, isolated instance.\n *\n * **Responsibility.**\n * - Owns: building the initial message list, driving the bounded trip loop,\n * dispatching tool calls safely, parsing the final output against the\n * caller's schema, emitting lifecycle events (to both the user handler\n * and, in stream mode, the `StreamController`), and producing the\n * `AgentResult`.\n * - Does NOT own: how the model produces responses (delegated to\n * `ModelContract.complete` / `ModelContract.stream`), how tools execute\n * (delegated to `ToolContract.invoke`), the async-queue plumbing for\n * streaming (delegated to `createAgentStream`), or any cross-call state\n * (factory-level concerns live in `agent()`).\n *\n * Streaming mode is opt-in via the fourth constructor argument: pass a\n * `StreamController` and every event is mirrored into it while model calls\n * are driven via `model.stream()` instead of `model.complete()`. The public\n * contract of `execute()` says it never throws — `Execution` enforces that\n * by funneling every unexpected error into `this.error` and returning a\n * well-formed result regardless of what went wrong.\n *\n * Not exported — consumers interact only with the `agent()` factory (see\n * §4.2 of code-style.md — \"per-call execution state across phases\").\n *\n * @example\n * // Non-streaming — inside agent.execute():\n * const result = await new Execution(config, input, options).run();\n *\n * @example\n * // Streaming — inside agent.stream():\n * const { controller, stream } = createAgentStream();\n * void new Execution(config, input, options, controller).run();\n * return stream;\n */\nclass Execution<TOutput> {\n private readonly trips: LLMTrip[] = [];\n private readonly toolCalls: ToolCall[] = [];\n private readonly usage: Usage = { input: 0, output: 0, total: 0 };\n private readonly messages: Message[] = [];\n private readonly maxTrips: number;\n private readonly startedAt = new Date();\n private readonly start = performance.now();\n private readonly runId = generateRunId(\"agent\");\n private readonly logger: Logger = log;\n private readonly middleware: ReadonlyArray<\n NonNullable<AgentConfig<TOutput>[\"middleware\"]>[number]\n >;\n private readonly middlewareState: MiddlewareState = new Map();\n\n private error?: AIError;\n private data?: TOutput;\n private responseSchema?: Record<string, unknown>;\n\n public constructor(\n private readonly config: ResolvedAgentConfig<TOutput>,\n private readonly input: string,\n private readonly options?: AgentExecuteOptions<TOutput>,\n private readonly streamController?: StreamController<AgentResult<TOutput>>,\n private readonly instanceHandlers?: InstanceHandlerMap,\n ) {\n this.maxTrips = config.maxTrips ?? 10;\n this.middleware = config.middleware ?? [];\n }\n\n /**\n * Base middleware context shared by every level. `state` is the\n * single mutable bag threaded through `execute`, `trip`, and `tool`\n * hooks for the lifetime of this execution — fresh per `execute()`\n * call, never reused across runs.\n */\n private buildExecuteContext(): MiddlewareExecuteContext {\n return {\n agent: {\n name: this.config.name ?? this.config.model.name,\n isAnonymous: !this.config.name,\n },\n model: {\n name: this.config.model.name,\n provider: this.config.model.provider,\n },\n input: this.input,\n options: this.options as AgentExecuteOptions<unknown> | undefined,\n state: this.middlewareState,\n signal: this.options?.signal,\n };\n }\n\n /**\n * Entry point for a single agent execution. Wraps the real work\n * (`runCore`) in the `execute`-level middleware pipeline, then\n * emits the terminal `agent.completed` / `agent.error` events and\n * closes the stream (if any) with the post-pipeline result — so\n * middleware that short-circuits or transforms the final result\n * still produces a well-formed public outcome.\n *\n * Must never throw: any error that escapes the pipeline is\n * converted into an `AgentResult` with `error` populated before\n * returning, preserving the `agent.execute()` public contract.\n */\n public async run(): Promise<AgentResult<TOutput>> {\n const context = this.buildExecuteContext();\n\n let result: AgentResult<TOutput>;\n\n try {\n result = (await runPipeline(\n this.middleware,\n \"execute\",\n context,\n () => this.runCore(),\n this.logger,\n )) as AgentResult<TOutput>;\n } catch (thrown) {\n this.error = this.toAIError(thrown);\n result = this.buildResult();\n }\n\n if (result.error) {\n this.emit(\"agent.error\", { error: result.error });\n }\n\n this.emit(\"agent.completed\", { result });\n\n // Fire the `onComplete` hook with a flat payload (runId +\n // durationMs pre-extracted) for audit-log consumers. Awaited but\n // errors swallowed so consumer bugs cannot crash the agent or\n // interfere with the result returned to the caller.\n await this.fireCompleteHook(result);\n\n this.streamController?.end(result);\n\n return result;\n }\n\n /**\n * Inner body wrapped by the `execute`-level pipeline. Drives the\n * full lifecycle — build messages → emit starting → run trip loop\n * → parse output → build result. Catches any unexpected throw and\n * funnels it into `this.error` so the returned result is always\n * well-formed; `execute`-level `after` hooks receive the result,\n * with `error` populated when things went wrong.\n */\n private async runCore(): Promise<AgentResult<TOutput>> {\n try {\n await this.buildInitialMessages();\n\n this.emit(\"agent.starting\", { input: this.input });\n\n await this.runTripLoop();\n\n const parseOutcome = await this.parseOutput();\n\n if (parseOutcome === \"failed\" && this.options?.repair) {\n await this.runRepairLoop();\n }\n } catch (thrown) {\n this.error = this.toAIError(thrown);\n }\n\n return this.buildResult();\n }\n\n /**\n * Resolve the system prompt (string or `SystemPromptContract`), merge\n * placeholders from config + execute options, inject a structured-output\n * instruction when the caller wants typed output but the model can't\n * enforce it natively, prepend any conversation history, and append the\n * user input. Produces the initial `messages` array the first trip sends\n * to the model. Runs exactly once per execution.\n */\n private async buildInitialMessages(): Promise<void> {\n const { messages, responseSchema } = await buildAgentInputMessages({\n config: this.config,\n input: this.input,\n options: this.options,\n });\n this.messages.push(...messages);\n this.responseSchema = responseSchema;\n }\n\n /**\n * Drive sequential trips up to `maxTrips`. Each trip may stop the loop\n * naturally (model returned a non-tool-call finish), abort it (model\n * threw), or continue it (model requested tools). When the loop exits\n * after the cap without a natural stop, records a \"Max trips exceeded\"\n * error so the caller can distinguish runaway tool loops from a real result.\n */\n private async runTripLoop(): Promise<void> {\n for (let tripIndex = 0; tripIndex < this.maxTrips; tripIndex++) {\n if (this.options?.signal?.aborted) {\n this.error = this.makeCancelledError();\n return;\n }\n\n const tripInput = tripIndex === 0 ? this.input : \"[tool results]\";\n const outcome = await this.runTrip(tripIndex, tripInput);\n\n if (outcome === \"error\" || outcome === \"stop\") {\n return;\n }\n }\n\n const lastTrip = this.trips[this.trips.length - 1];\n\n if (lastTrip?.finishReason === \"tool_calls\") {\n this.error = new AgentMaxTripsError(\"Max trips exceeded\", {\n maxTrips: this.maxTrips,\n });\n }\n }\n\n /**\n * Execute one round-trip to the model. Aggregates usage into the running\n * total, dispatches any requested tool calls, appends the assistant +\n * tool-result messages for the next trip, and records an `LLMTrip`.\n * Returns an outcome that tells `runTripLoop` whether to continue, stop,\n * or abort.\n */\n private async runTrip(\n tripIndex: number,\n tripInput: string,\n ): Promise<\"continue\" | \"stop\" | \"error\"> {\n this.emit(\"agent.trip.started\", { tripIndex, input: tripInput });\n\n const tripStartedAt = new Date();\n const tripStart = performance.now();\n\n let response: ModelResponse;\n\n try {\n response = await this.runTripThroughPipeline(tripIndex);\n } catch (thrown) {\n this.error = this.toAIError(thrown);\n\n const failedTrip: LLMTrip = {\n index: tripIndex,\n input: tripInput,\n output: \"\",\n finishReason: \"error\",\n startedAt: tripStartedAt.toISOString(),\n endedAt: new Date().toISOString(),\n duration: performance.now() - tripStart,\n usage: { input: 0, output: 0, total: 0 },\n error: this.error,\n };\n\n this.trips.push(failedTrip);\n\n this.emit(\"agent.trip.completed\", { trip: failedTrip });\n this.emit(\"agent.error\", { error: this.error });\n\n return \"error\";\n }\n\n // Attach per-trip cost breakdown using the model's pricing table\n // (when configured). Done at the framework boundary so stored trip\n // records carry historical cost — Panoptic and other archive\n // consumers never re-derive against today's pricing, and the\n // input/output/cached split stays queryable without joining to a\n // pricing table at all.\n if (response.usage.cost === undefined) {\n response.usage.cost = computeCost(response.usage, this.config.model.pricing);\n }\n\n this.usage.input += response.usage.input;\n this.usage.output += response.usage.output;\n this.usage.total += response.usage.total;\n if (response.usage.cachedTokens !== undefined) {\n this.usage.cachedTokens = (this.usage.cachedTokens ?? 0) + response.usage.cachedTokens;\n }\n this.usage.cost = accumulateCost(this.usage.cost, response.usage.cost);\n\n // Fire the `onUsage` hook with a flat, pre-packaged payload so\n // cost-ledger code receives stable identity (runId, model+provider)\n // without joining from elsewhere. Awaited but errors swallowed.\n await this.fireUsageHook(tripIndex, response.usage);\n\n const isToolCallTrip =\n response.finishReason === \"tool_calls\" &&\n response.toolCalls !== undefined &&\n response.toolCalls.length > 0;\n\n const tripToolCalls: ToolCall[] = [];\n\n if (isToolCallTrip) {\n this.messages.push({\n role: \"assistant\",\n content: response.content,\n toolCalls: response.toolCalls,\n });\n\n for (const toolCallRequest of response.toolCalls!) {\n const record = await this.dispatchToolCall(toolCallRequest, tripIndex);\n\n tripToolCalls.push(record);\n }\n }\n\n const trip: LLMTrip = {\n index: tripIndex,\n input: tripInput,\n output: response.content,\n finishReason: response.finishReason,\n startedAt: tripStartedAt.toISOString(),\n endedAt: new Date().toISOString(),\n duration: performance.now() - tripStart,\n usage: response.usage,\n toolCalls: tripToolCalls.length > 0 ? tripToolCalls : undefined,\n };\n\n this.trips.push(trip);\n\n this.emit(\"agent.trip.completed\", { trip });\n\n if (!isToolCallTrip) {\n return \"stop\";\n }\n\n // Terminate the trip loop when EVERY tool call this trip is\n // `mode: \"silent\"`. Silent tools don't feed their result back\n // to the model — the prose the model streamed alongside the\n // tool call IS the final reply. The \"all\" rule is load-bearing:\n // if any feedback tool was called too, its result still needs\n // to round-trip, so we must continue.\n //\n // Composite (`asTool`-wrapped) tools never set `mode: \"silent\"`\n // in v1 — silent-composite mechanics are deferred per plan\n // 2026-05-07-silent-tools.md (Q4). They behave as feedback.\n const allSilent = response.toolCalls!.every((request) => {\n const registered = this.config.tools?.find((tool) => tool.name === request.name);\n return registered?.mode === \"silent\";\n });\n\n return allSilent ? \"stop\" : \"continue\";\n }\n\n /**\n * Route `getModelResponse` through the `trip`-level middleware\n * pipeline. `trip.before` hooks can short-circuit the trip by\n * returning a synthetic `ModelResponse` (semantic cache hit).\n * `trip.after` hooks can transform the response before the trip\n * record is built or any tool calls are dispatched. `trip.onError`\n * hooks can recover from provider failures (fallback chain).\n */\n private async runTripThroughPipeline(tripIndex: number): Promise<ModelResponse> {\n const context: MiddlewareTripContext = {\n ...this.buildExecuteContext(),\n tripIndex,\n messages: this.messages,\n };\n\n return (await runPipeline(\n this.middleware,\n \"trip\",\n context,\n () => this.getModelResponse(tripIndex),\n this.logger,\n )) as ModelResponse;\n }\n\n /**\n * Produce the `ModelResponse` for the current trip. In non-streaming\n * mode, delegates straight to `model.complete()`. In streaming mode,\n * drains `model.stream()` while emitting `streaming` events per delta\n * and accumulates the chunks into the same `ModelResponse` shape, so the\n * rest of the trip pipeline (tool dispatch, trip record, usage\n * aggregation) stays identical between the two modes.\n */\n private async getModelResponse(tripIndex: number): Promise<ModelResponse> {\n const callOptions = {\n ...this.config.modelOptions,\n tools: this.config.tools ?? [],\n ...(this.responseSchema ? { responseSchema: this.responseSchema } : {}),\n ...(this.options?.signal ? { signal: this.options.signal } : {}),\n };\n\n if (!this.streamController) {\n return this.config.model.complete(this.messages, callOptions);\n }\n\n let content = \"\";\n let finishReason: FinishReason = \"stop\";\n let usage: Usage = { input: 0, output: 0, total: 0 };\n const toolCalls: ModelToolCallRequest[] = [];\n const recoveredCalls: ModelToolCallRequest[] = [];\n\n const guardConfig = this.resolveStreamingToolGuard();\n const guard = guardConfig\n ? new JsonStreamGuard({\n tools: (this.config.tools ?? []) as ReadonlyArray<ToolContract<unknown, unknown>>,\n maxBufferBytes: guardConfig.maxBufferBytes,\n onSafeDelta: (delta) => {\n content += delta;\n\n this.emit(\"agent.trip.streaming\", { delta, tripIndex });\n },\n onRecoveredCall: (request) => {\n recoveredCalls.push(request);\n },\n })\n : undefined;\n\n for await (const chunk of this.config.model.stream(this.messages, callOptions)) {\n // Mid-stream abort — break out cleanly instead of continuing to\n // consume the iterator. The underlying fetch is already\n // cancelled via `signal` forwarded in callOptions; this covers\n // adapters that don't honor signal natively and keeps mock\n // models consistent under cancellation tests.\n if (this.options?.signal?.aborted) {\n throw this.makeCancelledError();\n }\n\n if (chunk.type === \"delta\") {\n if (guard) {\n await guard.feed(chunk.content);\n } else {\n content += chunk.content;\n\n this.emit(\"agent.trip.streaming\", { delta: chunk.content, tripIndex });\n }\n\n continue;\n }\n\n if (chunk.type === \"tool-call\") {\n toolCalls.push({\n id: chunk.id,\n name: chunk.name,\n input: chunk.input,\n ...(chunk.providerMetadata ? { providerMetadata: chunk.providerMetadata } : {}),\n });\n\n continue;\n }\n\n finishReason = chunk.finishReason;\n usage = chunk.usage;\n }\n\n if (guard) {\n await guard.finalize();\n }\n\n // Dedupe synthesized calls against real ones the provider streamed\n // structurally — the model occasionally emits BOTH channels for\n // the same call (real tool-call chunk + narrated JSON envelope).\n // Real wins; the synthesized duplicate is dropped so dispatch\n // doesn't run twice. See plan 2026-05-22 §Q5.\n const dedupedRecovered = recoveredCalls.filter(\n (recovered) => !isDuplicateToolCall(recovered, toolCalls),\n );\n\n const mergedToolCalls = [...toolCalls, ...dedupedRecovered];\n\n // When the guard recovered any calls but the model reported a\n // natural `\"stop\"`, override to `\"tool_calls\"` so the agent's\n // dispatch loop (`runTrip` → `isToolCallTrip`) actually fires.\n // Without this the guard silently suppresses the leaked JSON but\n // never dispatches the real action — chips never render.\n const resolvedFinishReason: FinishReason =\n dedupedRecovered.length > 0 && finishReason === \"stop\" ? \"tool_calls\" : finishReason;\n\n return {\n content,\n finishReason: resolvedFinishReason,\n usage,\n toolCalls: mergedToolCalls.length > 0 ? mergedToolCalls : undefined,\n };\n }\n\n /**\n * Resolve the effective `streamingToolGuard` for this trip.\n * Per-call options win over the agent-level config when the key is\n * explicitly present on options (including the explicit `undefined`\n * \"disable for this call\" form). Returns `undefined` when no guard\n * should run.\n */\n private resolveStreamingToolGuard(): StreamingToolGuardConfig | undefined {\n if (\n this.options !== undefined &&\n Object.prototype.hasOwnProperty.call(this.options, \"streamingToolGuard\")\n ) {\n return this.options.streamingToolGuard;\n }\n\n return this.config.streamingToolGuard;\n }\n\n /**\n * Dispatch a single tool call requested by the model. Looks up the tool\n * by name, invokes it via the safe `ToolContract.invoke` entry, pushes a\n * matching tool-result message into `this.messages` so the next trip can\n * see it, and emits the right lifecycle event (`tool-called` on success,\n * `tool-calling-failed` when the tool is unregistered or invoke returned\n * an error). Never throws — always returns a `ToolCall` record.\n */\n private async dispatchToolCall(\n toolCallRequest: ModelToolCallRequest,\n tripIndex: number,\n ): Promise<ToolCall> {\n const registeredTool = this.config.tools?.find((tool) => tool.name === toolCallRequest.name);\n\n if (!registeredTool) {\n const error = new AgentExecutionError(`Tool not registered: ${toolCallRequest.name}`, {\n context: { toolName: toolCallRequest.name, tripIndex },\n });\n\n const nowIso = new Date().toISOString();\n\n const record: ToolCall = {\n runId: generateRunId(\"tool\"),\n rootRunId: this.runId,\n name: toolCallRequest.name,\n type: \"tool\",\n status: \"failed\",\n startedAt: nowIso,\n endedAt: nowIso,\n duration: 0,\n usage: { input: 0, output: 0, total: 0 },\n children: [],\n tripIndex,\n input: toolCallRequest.input,\n error,\n ...(toolCallRequest.recoveredFrom ? { recoveredFrom: toolCallRequest.recoveredFrom } : {}),\n };\n\n this.toolCalls.push(record);\n\n this.messages.push({\n role: \"tool\",\n toolCallId: toolCallRequest.id,\n content: JSON.stringify({ error: error.message }),\n });\n\n // Stub meta — there's no real tool to describe. Carries the\n // requested name for log correlation and an explanatory\n // description so consumers don't see an empty string.\n this.emit(\"agent.tool.failed\", {\n tool: {\n name: toolCallRequest.name,\n description: \"(unregistered tool — no description available)\",\n },\n input: toolCallRequest.input,\n error,\n tripIndex,\n });\n\n return record;\n }\n\n // Build the lightweight event meta once. Resolves `action` to a\n // string here so consumers receive plain data rather than having\n // to re-evaluate a callback on every event.\n const toolMeta: ToolEventMeta = {\n name: registeredTool.name,\n description: registeredTool.description,\n action: resolveToolAction(registeredTool, toolCallRequest.input),\n };\n\n this.emit(\"agent.tool.calling\", {\n tool: toolMeta,\n input: toolCallRequest.input,\n tripIndex,\n });\n\n const toolContext: MiddlewareToolContext = {\n ...this.buildExecuteContext(),\n tripIndex,\n messages: this.messages,\n tool: {\n name: registeredTool.name,\n description: registeredTool.description,\n mode: registeredTool.mode,\n },\n request: toolCallRequest,\n };\n\n let invokeResult: ToolInvokeResult<unknown>;\n\n try {\n invokeResult = (await runPipeline(\n this.middleware,\n \"tool\",\n toolContext,\n () => registeredTool.invoke(toolCallRequest.input, this.options?.toolCtx),\n this.logger,\n )) as ToolInvokeResult<unknown>;\n } catch (thrown) {\n // A `tool`-level middleware hook threw. The real invoke never\n // throws (it funnels errors into `result.error`), so only a\n // middleware abort or a bug reaches this branch. Synthesize a\n // failed-invoke record so the tool-call trace stays consistent.\n const error = this.toAIError(thrown);\n const nowIso = new Date().toISOString();\n const emptyUsage: Usage = { input: 0, output: 0, total: 0 };\n\n const failedRunId = generateRunId(\"tool\");\n invokeResult = {\n error,\n usage: emptyUsage,\n report: {\n runId: failedRunId,\n rootRunId: failedRunId,\n name: registeredTool.name,\n version: registeredTool.version,\n type: \"tool\",\n status: \"failed\",\n startedAt: nowIso,\n endedAt: nowIso,\n duration: 0,\n usage: emptyUsage,\n children: [],\n },\n };\n }\n\n // The agent-level ToolCall record merges the tool's own invocation\n // report with agent-side enrichments (tripIndex, input, output,\n // error). When the underlying tool was an `asTool`-wrapped\n // composite, its inner report becomes the sole child of this\n // ToolCall — preserving the full nested tree while keeping this\n // node's own `type` as `\"tool\"` (from the agent's POV it *was* a\n // tool dispatch).\n const innerReport = invokeResult.report;\n const isComposite = innerReport.type !== \"tool\";\n\n const record: ToolCall = {\n runId: innerReport.runId,\n rootRunId: this.runId,\n name: toolCallRequest.name,\n version: registeredTool.version,\n type: \"tool\",\n status: innerReport.status,\n startedAt: innerReport.startedAt,\n endedAt: innerReport.endedAt,\n duration: innerReport.duration,\n usage: invokeResult.usage,\n children: isComposite ? [innerReport] : innerReport.children,\n tripIndex,\n input: toolCallRequest.input,\n output: invokeResult.data,\n error: invokeResult.error,\n ...(toolCallRequest.recoveredFrom ? { recoveredFrom: toolCallRequest.recoveredFrom } : {}),\n };\n\n this.toolCalls.push(record);\n\n // Roll child usage into the agent's accumulator. Leaf tools\n // contribute zero; `asTool`-wrapped composites contribute the\n // full cost of the inner agent/workflow/supervisor run.\n this.usage.input += invokeResult.usage.input;\n this.usage.output += invokeResult.usage.output;\n this.usage.total += invokeResult.usage.total;\n this.usage.cost = accumulateCost(this.usage.cost, invokeResult.usage.cost);\n\n this.messages.push({\n role: \"tool\",\n toolCallId: toolCallRequest.id,\n content: invokeResult.error\n ? JSON.stringify({ error: invokeResult.error.message })\n : JSON.stringify(invokeResult.data ?? null),\n });\n\n if (invokeResult.error) {\n this.emit(\"agent.tool.failed\", {\n tool: toolMeta,\n input: toolCallRequest.input,\n error: invokeResult.error,\n tripIndex,\n });\n } else {\n this.emit(\"agent.tool.called\", { ...record, tool: toolMeta });\n }\n\n return record;\n }\n\n /**\n * Parse the final trip output against the user-supplied schema (if any).\n * Failures populate `this.error` but never throw. Returns an outcome the\n * caller uses to decide whether self-repair is worth attempting:\n *\n * - `\"skipped\"` — no schema, or a prior trip-level error already set\n * `this.error` (model crash, max trips). Not repairable; the failure\n * isn't a parse problem the model can fix by re-asking.\n * - `\"failed\"` — schema present, output text either failed JSON.parse\n * or failed `~standard.validate`. Repairable via `runRepairLoop`.\n * - `\"success\"` — parsed and validated; `this.data` populated.\n */\n private async parseOutput(): Promise<\"success\" | \"failed\" | \"skipped\"> {\n const schema = this.options?.output ?? this.config.output;\n\n if (!schema || this.error) {\n return \"skipped\";\n }\n\n const finalTrip = this.trips[this.trips.length - 1];\n const text = finalTrip?.output ?? \"\";\n\n if (!text) {\n return \"skipped\";\n }\n\n const payload = extractJsonPayload(text);\n const sentinel = Symbol(\"parse-failed\");\n const parsed = safeJsonParse<unknown>(payload, sentinel);\n\n if (parsed === sentinel) {\n this.error = new SchemaValidationError(\"Failed to parse model output as JSON\", {\n context: { text },\n });\n return \"failed\";\n }\n\n const validation = await (schema as StandardSchemaV1<TOutput>)[\"~standard\"].validate(parsed);\n\n if (validation.issues) {\n const summary = validation.issues.map((issue) => issue.message).join(\"; \");\n this.error = new SchemaValidationError(summary, {\n issues: validation.issues,\n });\n return \"failed\";\n }\n\n this.data = validation.value;\n return \"success\";\n }\n\n /**\n * Opt-in self-repair loop for `output` schema failures. Triggered only\n * when `options.repair` is set and `parseOutput()` returned `\"failed\"`.\n *\n * Each attempt:\n * 1. Pushes the bad assistant response into `this.messages` (so the\n * model can see what it just produced).\n * 2. Pushes a corrective user message naming the validation/parse error.\n * 3. Runs another trip — counted against the same `maxTrips` cap as\n * normal trips so a stuck model can't loop forever.\n * 4. Re-parses. Stops on success, on a trip-level error, or when\n * either `maxAttempts` or `maxTrips` is exhausted.\n *\n * Resets `this.error` and `this.data` before each attempt so the final\n * outcome (success or last failure) is what surfaces to the caller.\n */\n private async runRepairLoop(): Promise<void> {\n const maxAttempts = this.options?.repair?.maxAttempts ?? 1;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (this.trips.length >= this.maxTrips) {\n return;\n }\n\n const lastTrip = this.trips[this.trips.length - 1];\n const badResponse = lastTrip?.output ?? \"\";\n const failureReason = this.error?.message ?? \"unknown validation failure\";\n\n this.error = undefined;\n this.data = undefined;\n\n this.messages.push({ role: \"assistant\", content: badResponse });\n\n this.messages.push({\n role: \"user\",\n content: [\n `Your previous response failed validation: ${failureReason}.`,\n \"Respond again with valid JSON only — no prose, no markdown fences, no commentary.\",\n ].join(\" \"),\n });\n\n const tripIndex = this.trips.length;\n\n this.logger.warn(LOG_MODULE, \"repair.attempting\", \"retrying after validation failure\", {\n attempt: attempt + 1,\n maxAttempts,\n reason: failureReason,\n });\n\n const outcome = await this.runTrip(tripIndex, \"[repair attempt]\");\n\n if (outcome === \"error\") {\n return;\n }\n\n const parseOutcome = await this.parseOutput();\n\n if (parseOutcome === \"success\") {\n return;\n }\n }\n }\n\n /**\n * Build the final `AgentResult` snapshot from accumulated state\n * (trips, tool calls, data/error, usage, timing).\n *\n * Pure — no side effects. `run()` owns terminal event emission and\n * stream closure so the post-pipeline result (possibly transformed\n * or short-circuited by an `execute`-level middleware) is what\n * flows out to consumers and listeners.\n *\n * Trips, tool calls, status, and timing live under `report` so the\n * root stays focused on the four things callers reach for most:\n * `data`, `text`, `usage`, `error`.\n */\n private buildResult(): AgentResult<TOutput> {\n const finalTrip = this.trips[this.trips.length - 1];\n const endedAt = new Date();\n\n const agentName = this.config.name ?? this.config.model.name;\n const status: BaseReport[\"status\"] = this.error\n ? this.error instanceof AgentCancelledError\n ? \"cancelled\"\n : \"failed\"\n : \"completed\";\n\n const report = {\n runId: this.runId,\n rootRunId: this.runId,\n name: agentName,\n version: this.config.version,\n type: \"agent\" as const,\n status,\n startedAt: this.startedAt.toISOString(),\n endedAt: endedAt.toISOString(),\n duration: performance.now() - this.start,\n usage: this.usage,\n children: this.toolCalls,\n model: {\n name: this.config.model.name,\n provider: this.config.model.provider,\n },\n trips: this.trips,\n };\n\n // Stamp lineage on the assembled tree exactly once per run.\n // Rewrites any inner self-roots from composite children to this\n // run's id, stamps `reportSchemaVersion` on the root, and\n // propagates `sessionId` to every node.\n stampReportLineage(report, {\n rootRunId: this.runId,\n sessionId: this.options?.sessionId,\n });\n\n return {\n type: \"agent\",\n data: this.data,\n text: finalTrip?.output,\n report,\n usage: this.usage,\n error: this.error,\n };\n }\n\n /**\n * Normalize any thrown value into an `AIError`. `AIError` instances\n * pass through untouched; provider-adapter SDK errors are caught by\n * the adapter and already arrive typed, so this branch mainly\n * handles runtime crashes (TypeError, ReferenceError) inside\n * model.complete / model.stream and non-Error values (`throw \"bad\"`).\n */\n private toAIError(thrown: unknown): AIError {\n if (thrown instanceof AIError) {\n return thrown;\n }\n\n // Classify abort-flavored errors (DOMException \"AbortError\",\n // node-fetch's `FetchError` with name \"AbortError\", `ERR_CANCELED`\n // from the OpenAI SDK's axios-ish layer) as cancelled instead of\n // a generic exec failure so callers can route retries correctly.\n if (isAbortLike(thrown)) {\n return this.makeCancelledError();\n }\n\n const message = thrown instanceof Error ? thrown.message : String(thrown);\n\n return new AgentExecutionError(message, { cause: thrown });\n }\n\n /**\n * Build the typed cancelled error that both the trip-loop guard\n * and the mid-stream guard emit. Captures the abort reason when\n * one was supplied to `controller.abort(reason)` so logs and\n * telemetry can see what cancelled the run.\n */\n private makeCancelledError(): AgentCancelledError {\n const reason = this.options?.signal?.reason;\n const reasonText = reason === undefined ? \"\" : String(reason);\n\n return new AgentCancelledError(\"agent execution cancelled\", {\n cause: reason,\n cancelledAt: new Date().toISOString(),\n reason: reasonText,\n });\n }\n\n /**\n * Fire a single event through all three subscription tiers in order\n * — factory → instance → per-call — and mirror it into the\n * `StreamController` when streaming is active. A throwing user\n * handler must never crash the agent, so every dispatch is wrapped\n * in `safeCall`. Stream events are converted from the internal\n * `AgentEventMap` payload to the public `StreamEvent` shape because\n * some of them differ (e.g. the tool-called payload vs stream\n * event).\n */\n private emit<K extends keyof AgentEventMap>(\n event: K,\n payload: WithoutIdentity<AgentEventMap[K]>,\n ): void {\n // Inject run identity once, here, so every subscription tier and\n // the stream see it. `rootRunId === runId` for a standalone run;\n // nested propagation lands in a follow-up.\n const fullPayload = {\n ...payload,\n runId: this.runId,\n rootRunId: this.runId,\n } as AgentEventMap[K];\n\n this.logEvent(event, fullPayload);\n\n const factoryHandler = this.config.on?.[event] as AgentEventHandler<K> | undefined;\n\n if (factoryHandler) {\n safeCall(factoryHandler, fullPayload);\n }\n\n const bucket = this.instanceHandlers?.get(event);\n\n if (bucket) {\n for (const handler of bucket) {\n safeCall(handler as AgentEventHandler<K>, fullPayload);\n }\n }\n\n const perCallHandler = this.options?.on?.[event] as AgentEventHandler<K> | undefined;\n\n if (perCallHandler) {\n safeCall(perCallHandler, fullPayload);\n }\n\n if (this.streamController) {\n const body = this.toStreamEvent(event, fullPayload);\n\n if (body) {\n this.streamController.push({\n runId: this.runId,\n rootRunId: this.runId,\n ...body,\n });\n }\n }\n }\n\n /**\n * Emit a structured log line for a lifecycle event. The action\n * string mirrors the event name with the `agent.` prefix stripped\n * (`agent.trip.started` → `trip.started`) so log grep filters and\n * event handlers read the same vocabulary. Level mapping follows\n * the convention documented on `@warlock.js/logger`'s `Logger`.\n */\n private logEvent<K extends keyof AgentEventMap>(event: K, payload: AgentEventMap[K]): void {\n const agentName = this.config.name || this.config.model.name;\n logAgentEvent(\n this.logger,\n {\n module: `${LOG_MODULE}.${agentName}`,\n maxTrips: this.maxTrips,\n modelName: this.config.model.name,\n totalUsage: this.usage,\n totalDurationMs: performance.now() - this.start,\n trips: this.trips,\n toolCalls: this.toolCalls,\n },\n event,\n payload,\n );\n }\n\n private toStreamEvent<K extends keyof AgentEventMap>(\n event: K,\n payload: AgentEventMap[K],\n ): StreamEventBody | undefined {\n return agentEventToStreamEvent(event, payload);\n }\n\n /**\n * Invoke the `onUsage` hook (when configured) with a flat payload\n * carrying stable identity. Awaits the handler so async ledger\n * writes complete before the next trip starts; swallows any throw\n * so consumer bugs cannot crash the agent. Sync handlers wrapped\n * via `Promise.resolve()` so the await is safe in either case.\n */\n private async fireUsageHook(tripIndex: number, tripUsage: Usage): Promise<void> {\n const handler = this.config.onUsage;\n if (!handler) return;\n\n const event: UsageEvent = {\n runId: this.runId,\n tripIndex,\n model: {\n name: this.config.model.name,\n provider: this.config.model.provider,\n },\n usage: { ...tripUsage },\n timestamp: new Date().toISOString(),\n };\n\n try {\n await Promise.resolve(handler(event));\n } catch (err) {\n this.logger.warn(LOG_MODULE, \"onUsage.hook.error\", \"onUsage handler threw\", {\n runId: this.runId,\n tripIndex,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n /**\n * Invoke the `onComplete` hook (when configured) once at the end\n * of every run. Receives the full `AgentResult` plus pre-extracted\n * `runId` and `durationMs`. Same swallow-and-log error policy as\n * `fireUsageHook`.\n */\n private async fireCompleteHook(result: AgentResult<TOutput>): Promise<void> {\n const handler = this.config.onComplete;\n if (!handler) return;\n\n const event: CompleteEvent<TOutput> = {\n result,\n runId: this.runId,\n durationMs: performance.now() - this.start,\n };\n\n try {\n await Promise.resolve(handler(event));\n } catch (err) {\n this.logger.warn(LOG_MODULE, \"onComplete.hook.error\", \"onComplete handler threw\", {\n runId: this.runId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n}\n\n/**\n * Decide whether a guard-synthesized tool call duplicates a real one\n * the provider already streamed structurally. Match key is\n * `name + key-sorted JSON of input` so identical calls (regardless of\n * argument key order) collapse, but two legitimate calls to the same\n * tool with different inputs still both dispatch.\n */\nfunction isDuplicateToolCall(\n recovered: ModelToolCallRequest,\n realCalls: ReadonlyArray<ModelToolCallRequest>,\n): boolean {\n const recoveredKey = `${recovered.name}|${stableStringify(recovered.input)}`;\n\n for (const real of realCalls) {\n const realKey = `${real.name}|${stableStringify(real.input)}`;\n\n if (realKey === recoveredKey) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * `JSON.stringify` variant that sorts object keys at every nesting\n * level so structurally-equal inputs serialize to identical strings.\n * Used only for dedupe-key comparison; never surfaces to consumers.\n */\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(value, (_key, val) => {\n if (val !== null && typeof val === \"object\" && !Array.isArray(val)) {\n const source = val as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n\n for (const key of Object.keys(source).sort()) {\n sorted[key] = source[key];\n }\n\n return sorted;\n }\n\n return val;\n });\n}\n\n/**\n * Invoke a user-supplied event handler without letting exceptions\n * escape the agent. Thrown errors are swallowed — structured logging\n * attaches here in Phase 0.5 so operators still see the failure.\n */\nfunction safeCall<T>(handler: (payload: T) => void, payload: T): void {\n try {\n handler(payload);\n } catch {\n // Intentionally swallowed — user handlers never crash the agent.\n }\n}\n\n/**\n * Resolve a tool's `action` declaration into a plain string for\n * inclusion in `ToolEventMeta`. Static strings pass through;\n * function-shaped actions are invoked with the validated input.\n *\n * Defensive: if the user's callback throws, swallow and return\n * `undefined` rather than crashing the agent — UI strings are not\n * worth aborting an LLM dispatch over.\n */\nfunction resolveToolAction(\n tool: ToolContract<unknown, unknown>,\n input: unknown,\n): string | undefined {\n if (tool.action === undefined) return undefined;\n if (typeof tool.action === \"string\") return tool.action;\n try {\n return tool.action(input);\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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"}
|
package/esm/agent/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { AgentConfig } from "./agent-config.type.mjs";
|
|
2
2
|
import { agent } from "./agent.mjs";
|
|
3
|
-
import { StreamController, createAgentStream } from "./agent-stream.mjs";
|
|
3
|
+
import { StreamController, createAgentStream } from "./agent-stream.mjs";
|
|
4
|
+
import { SpawnSubAgentSpec, spawnSubAgent } from "./spawn-sub-agent.mjs";
|
package/esm/agent/index.mjs
CHANGED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { AgentResult } from "../contracts/result/agent-result.type.mjs";
|
|
2
|
+
import { AgentToolEntry } from "../tool/executable-as-tool.mjs";
|
|
3
|
+
import { ModelContract } from "../contracts/model.contract.mjs";
|
|
4
|
+
import { SystemPromptContract } from "../contracts/system-prompt.contract.mjs";
|
|
5
|
+
import { BudgetOptions } from "../middleware/builtins/budget.mjs";
|
|
6
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
7
|
+
|
|
8
|
+
//#region ../@warlock.js/ai/src/agent/spawn-sub-agent.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* Spec for `spawnSubAgent` — a one-shot agent invocation. `spawnSubAgent`
|
|
11
|
+
* is a thin convenience wrapper: it builds a fresh `agent()` from this
|
|
12
|
+
* spec, optionally attaches a `budget` middleware, runs the `task` once,
|
|
13
|
+
* and returns the `AgentResult`. There is no separate "sub-agent" runtime
|
|
14
|
+
* — a spawn is an ordinary new `agent()` instance, so it starts from an
|
|
15
|
+
* empty conversation with its own tools/prompt exactly the way every
|
|
16
|
+
* `agent()` does.
|
|
17
|
+
*
|
|
18
|
+
* `budget` is the one field that adds something a bare `agent()` config
|
|
19
|
+
* doesn't already give you ergonomically: a first-class per-task
|
|
20
|
+
* cost/token cap. When set, the spawn runs under a `budget` middleware
|
|
21
|
+
* that aborts the moment a cap is crossed, so a delegated subtask cannot
|
|
22
|
+
* overrun its allowance. (Equivalent to passing
|
|
23
|
+
* `middleware: [budget(...)]` to a plain agent — this just promotes it to
|
|
24
|
+
* a spec field.) Distinct from `maxTrips`, which caps round-trips, not spend.
|
|
25
|
+
*/
|
|
26
|
+
type SpawnSubAgentSpec<TOutput = unknown> = {
|
|
27
|
+
/** Stable identifier for the spawned agent. */name: string; /** The model the sub-agent runs against. */
|
|
28
|
+
model: ModelContract; /** The subtask instruction handed to the sub-agent's `execute()`. */
|
|
29
|
+
task: string; /** Optional system prompt scoping the sub-agent's behavior. */
|
|
30
|
+
systemPrompt?: SystemPromptContract | string; /** Tools the spawned agent may call inside its own loop (a fresh agent, so not shared with the caller). */
|
|
31
|
+
tools?: AgentToolEntry<unknown, unknown>[]; /** Per-spawn round-trip cap. Forwarded to the agent. Defaults to the agent default. */
|
|
32
|
+
maxTrips?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Per-task budget. When set, the spawn runs under a `budget` middleware
|
|
35
|
+
* that aborts once a cap (`maxTokens` / `maxCostUSD`) is crossed — a
|
|
36
|
+
* spend ceiling scoped to this one subtask. Because each spawn is its
|
|
37
|
+
* own `agent()` instance, that ledger starts fresh per spawn.
|
|
38
|
+
*/
|
|
39
|
+
budget?: BudgetOptions; /** Structured-output schema validated into `result.data`. */
|
|
40
|
+
output?: StandardSchemaV1<TOutput>; /** Cancellation handle threaded into the sub-agent run. */
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
/**
|
|
43
|
+
* Session identifier propagated onto the sub-agent's report tree so
|
|
44
|
+
* the spawned run groups under the parent's session in flat trace
|
|
45
|
+
* queries.
|
|
46
|
+
*/
|
|
47
|
+
sessionId?: string;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Build a fresh agent, run a single subtask through it once, and return
|
|
51
|
+
* the unified {@link AgentResult}. Equivalent to
|
|
52
|
+
* `agent({ ...spec, middleware: spec.budget && [budget(spec.budget)] }).execute(spec.task, { output, signal, sessionId })`.
|
|
53
|
+
*
|
|
54
|
+
* **Role.** A general-purpose "build, run, discard" primitive: a caller
|
|
55
|
+
* (an agent tool, a workflow step, a planner step, a route callback, or
|
|
56
|
+
* hand-rolled orchestration) hands a self-contained subtask to a
|
|
57
|
+
* single-use agent created just for it, instead of reusing a long-lived
|
|
58
|
+
* agent. The spawned `report` slots under the caller's
|
|
59
|
+
* `report.children[]` like any executable, so cost and traces roll up
|
|
60
|
+
* uniformly. It is not tied to any one primitive — it depends only on
|
|
61
|
+
* `agent()` and the optional `budget` middleware.
|
|
62
|
+
*
|
|
63
|
+
* **What it is NOT.** Not a sandbox or a separate runtime. Each spawn is
|
|
64
|
+
* a plain new `agent()` — its fresh conversation, own tools, and own
|
|
65
|
+
* middleware state are ordinary new-instance behavior, not special
|
|
66
|
+
* isolation (every `agent()` already has them). It is also a *narrower*
|
|
67
|
+
* surface than `agent.execute`: one-shot, with no `history`,
|
|
68
|
+
* `placeholders`, per-call event handlers, or `repair`. Reach for it when
|
|
69
|
+
* you want a named single-use delegation with a per-task budget cap;
|
|
70
|
+
* otherwise just construct an `agent()` and call it.
|
|
71
|
+
*
|
|
72
|
+
* Never throws on runtime failure — the agent surfaces failures on
|
|
73
|
+
* `result.error` and a `"failed"` / `"cancelled"` report status.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* const result = await spawnSubAgent({
|
|
77
|
+
* name: "extract-entities",
|
|
78
|
+
* model,
|
|
79
|
+
* task: "Pull every company name from this article: ...",
|
|
80
|
+
* budget: { maxCostUSD: 0.05 },
|
|
81
|
+
* output: z.object({ companies: z.array(z.string()) }),
|
|
82
|
+
* });
|
|
83
|
+
*/
|
|
84
|
+
declare function spawnSubAgent<TOutput = unknown>(spec: SpawnSubAgentSpec<TOutput>): Promise<AgentResult<TOutput>>;
|
|
85
|
+
//#endregion
|
|
86
|
+
export { SpawnSubAgentSpec, spawnSubAgent };
|
|
87
|
+
//# sourceMappingURL=spawn-sub-agent.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn-sub-agent.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/agent/spawn-sub-agent.ts"],"mappings":";;;;;;;;;;AA2BA;;;;;;;;;;;;;;;KAAY,iBAAA;EAMV,+CAJA,IAAA,UAMe;EAJf,KAAA,EAAO,aAAA,EAMC;EAJR,IAAA,UAaA;EAXA,YAAA,GAAe,oBAAA,WAaf;EAXA,KAAA,GAAQ,cAAA,sBAWkB;EAT1B,QAAA;EAWS;;;AAMA;AAsCX;;EAhDE,MAAA,GAAS,aAAA,EAiDe;EA/CxB,MAAA,GAAS,gBAAA,CAAiB,OAAA,GAgDL;EA9CrB,MAAA,GAAS,WAAA;EA8CR;;;;;EAxCD,SAAA;AAAA;;;;;AAwC4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAFR,aAAA,oBACpB,IAAA,EAAM,iBAAA,CAAkB,OAAA,IACvB,OAAA,CAAQ,WAAA,CAAY,OAAA"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { budget } from "../middleware/builtins/budget.mjs";
|
|
2
|
+
import { agent } from "./agent.mjs";
|
|
3
|
+
|
|
4
|
+
//#region ../@warlock.js/ai/src/agent/spawn-sub-agent.ts
|
|
5
|
+
/**
|
|
6
|
+
* Build a fresh agent, run a single subtask through it once, and return
|
|
7
|
+
* the unified {@link AgentResult}. Equivalent to
|
|
8
|
+
* `agent({ ...spec, middleware: spec.budget && [budget(spec.budget)] }).execute(spec.task, { output, signal, sessionId })`.
|
|
9
|
+
*
|
|
10
|
+
* **Role.** A general-purpose "build, run, discard" primitive: a caller
|
|
11
|
+
* (an agent tool, a workflow step, a planner step, a route callback, or
|
|
12
|
+
* hand-rolled orchestration) hands a self-contained subtask to a
|
|
13
|
+
* single-use agent created just for it, instead of reusing a long-lived
|
|
14
|
+
* agent. The spawned `report` slots under the caller's
|
|
15
|
+
* `report.children[]` like any executable, so cost and traces roll up
|
|
16
|
+
* uniformly. It is not tied to any one primitive — it depends only on
|
|
17
|
+
* `agent()` and the optional `budget` middleware.
|
|
18
|
+
*
|
|
19
|
+
* **What it is NOT.** Not a sandbox or a separate runtime. Each spawn is
|
|
20
|
+
* a plain new `agent()` — its fresh conversation, own tools, and own
|
|
21
|
+
* middleware state are ordinary new-instance behavior, not special
|
|
22
|
+
* isolation (every `agent()` already has them). It is also a *narrower*
|
|
23
|
+
* surface than `agent.execute`: one-shot, with no `history`,
|
|
24
|
+
* `placeholders`, per-call event handlers, or `repair`. Reach for it when
|
|
25
|
+
* you want a named single-use delegation with a per-task budget cap;
|
|
26
|
+
* otherwise just construct an `agent()` and call it.
|
|
27
|
+
*
|
|
28
|
+
* Never throws on runtime failure — the agent surfaces failures on
|
|
29
|
+
* `result.error` and a `"failed"` / `"cancelled"` report status.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* const result = await spawnSubAgent({
|
|
33
|
+
* name: "extract-entities",
|
|
34
|
+
* model,
|
|
35
|
+
* task: "Pull every company name from this article: ...",
|
|
36
|
+
* budget: { maxCostUSD: 0.05 },
|
|
37
|
+
* output: z.object({ companies: z.array(z.string()) }),
|
|
38
|
+
* });
|
|
39
|
+
*/
|
|
40
|
+
async function spawnSubAgent(spec) {
|
|
41
|
+
const subAgent = buildSubAgent(spec);
|
|
42
|
+
const options = {};
|
|
43
|
+
if (spec.output !== void 0) options.output = spec.output;
|
|
44
|
+
if (spec.signal !== void 0) options.signal = spec.signal;
|
|
45
|
+
if (spec.sessionId !== void 0) options.sessionId = spec.sessionId;
|
|
46
|
+
return subAgent.execute(spec.task, options);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Construct the fresh agent for one spawn. Attaches a `budget`
|
|
50
|
+
* middleware only when a cap was requested, so the common no-budget case
|
|
51
|
+
* is just a plain agent.
|
|
52
|
+
*/
|
|
53
|
+
function buildSubAgent(spec) {
|
|
54
|
+
const middleware = spec.budget !== void 0 ? [budget(spec.budget)] : void 0;
|
|
55
|
+
return agent({
|
|
56
|
+
name: spec.name,
|
|
57
|
+
model: spec.model,
|
|
58
|
+
systemPrompt: spec.systemPrompt,
|
|
59
|
+
tools: spec.tools,
|
|
60
|
+
maxTrips: spec.maxTrips,
|
|
61
|
+
output: spec.output,
|
|
62
|
+
middleware
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
export { spawnSubAgent };
|
|
68
|
+
//# sourceMappingURL=spawn-sub-agent.mjs.map
|