@warlock.js/ai 4.2.11 → 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
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ToolContract } from "../tool/tool.mjs";
|
|
2
|
+
import { OrchestratorAsToolOptions, OrchestratorContract } from "../contracts/orchestrator/orchestrator.contract.mjs";
|
|
3
|
+
|
|
4
|
+
//#region ../@warlock.js/ai/src/orchestrator/as-tool.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Wrap an {@link OrchestratorContract} as a {@link ToolContract} so an
|
|
7
|
+
* outer agent can invoke it from its tool-call loop (design §13).
|
|
8
|
+
* Mirrors `supervisor.asTool()` — same `compositeAsTool` composition and
|
|
9
|
+
* error normalization — and adds `sessionScope`.
|
|
10
|
+
*
|
|
11
|
+
* The boundary is OPAQUE (§13, §18.6): the parent's `signal` / `context`
|
|
12
|
+
* / events do NOT auto-forward. Anything the wrapped orchestrator needs
|
|
13
|
+
* per call must ride on the tool's `inputSchema` payload.
|
|
14
|
+
*
|
|
15
|
+
* Session continuity:
|
|
16
|
+
* - `"fresh"` (default) — each invocation gets a brand-new `sessionId`
|
|
17
|
+
* (a generated id) and empty history; the session lives only for this
|
|
18
|
+
* tool call. The whole validated payload is forwarded as the
|
|
19
|
+
* orchestrator's `execute(input)` argument.
|
|
20
|
+
* - `"shared"` — the parent supplies `sessionId` (and optionally
|
|
21
|
+
* `history`) inside the validated payload; the orchestrator
|
|
22
|
+
* participates in that session. The remaining payload fields are
|
|
23
|
+
* forwarded as `execute(input)`. A missing/blank `sessionId` throws
|
|
24
|
+
* {@link SupervisorFailedError}.
|
|
25
|
+
*
|
|
26
|
+
* On `result.error`, the typed orchestrator error is thrown so the tool
|
|
27
|
+
* wrapper produces a `ToolExecutionError` with `cause` preserved — the
|
|
28
|
+
* outer agent sees one uniform error class.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const support = ai.orchestrator({ name: "refund-support", intents });
|
|
32
|
+
* const supportTool = support.asTool({
|
|
33
|
+
* name: "handle_refund",
|
|
34
|
+
* description: "Handle a refund conversation end-to-end.",
|
|
35
|
+
* inputSchema: v.object({ message: v.string() }),
|
|
36
|
+
* });
|
|
37
|
+
* const concierge = ai.agent({ model, tools: [supportTool] });
|
|
38
|
+
*/
|
|
39
|
+
declare function asTool<TOutput, TState, TToolInput>(orchestrator: OrchestratorContract<TOutput, TState>, options: OrchestratorAsToolOptions<TToolInput>): ToolContract<TToolInput, TOutput>;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { asTool };
|
|
42
|
+
//# sourceMappingURL=as-tool.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"as-tool.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/as-tool.ts"],"mappings":";;;;;;AAyDA;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGmC;;;;;iBAHnB,MAAA,8BACd,YAAA,EAAc,oBAAA,CAAqB,OAAA,EAAS,MAAA,GAC5C,OAAA,EAAS,yBAAA,CAA0B,UAAA,IAClC,YAAA,CAAa,UAAA,EAAY,OAAA"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { SupervisorFailedError } from "../errors/supervisor-failed-error.mjs";
|
|
2
|
+
import "../errors/index.mjs";
|
|
3
|
+
import { generateRunId } from "../utils/generate-run-id.mjs";
|
|
4
|
+
import { compositeAsTool } from "../tool/tool.mjs";
|
|
5
|
+
|
|
6
|
+
//#region ../@warlock.js/ai/src/orchestrator/as-tool.ts
|
|
7
|
+
/**
|
|
8
|
+
* Wrap an {@link OrchestratorContract} as a {@link ToolContract} so an
|
|
9
|
+
* outer agent can invoke it from its tool-call loop (design §13).
|
|
10
|
+
* Mirrors `supervisor.asTool()` — same `compositeAsTool` composition and
|
|
11
|
+
* error normalization — and adds `sessionScope`.
|
|
12
|
+
*
|
|
13
|
+
* The boundary is OPAQUE (§13, §18.6): the parent's `signal` / `context`
|
|
14
|
+
* / events do NOT auto-forward. Anything the wrapped orchestrator needs
|
|
15
|
+
* per call must ride on the tool's `inputSchema` payload.
|
|
16
|
+
*
|
|
17
|
+
* Session continuity:
|
|
18
|
+
* - `"fresh"` (default) — each invocation gets a brand-new `sessionId`
|
|
19
|
+
* (a generated id) and empty history; the session lives only for this
|
|
20
|
+
* tool call. The whole validated payload is forwarded as the
|
|
21
|
+
* orchestrator's `execute(input)` argument.
|
|
22
|
+
* - `"shared"` — the parent supplies `sessionId` (and optionally
|
|
23
|
+
* `history`) inside the validated payload; the orchestrator
|
|
24
|
+
* participates in that session. The remaining payload fields are
|
|
25
|
+
* forwarded as `execute(input)`. A missing/blank `sessionId` throws
|
|
26
|
+
* {@link SupervisorFailedError}.
|
|
27
|
+
*
|
|
28
|
+
* On `result.error`, the typed orchestrator error is thrown so the tool
|
|
29
|
+
* wrapper produces a `ToolExecutionError` with `cause` preserved — the
|
|
30
|
+
* outer agent sees one uniform error class.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const support = ai.orchestrator({ name: "refund-support", intents });
|
|
34
|
+
* const supportTool = support.asTool({
|
|
35
|
+
* name: "handle_refund",
|
|
36
|
+
* description: "Handle a refund conversation end-to-end.",
|
|
37
|
+
* inputSchema: v.object({ message: v.string() }),
|
|
38
|
+
* });
|
|
39
|
+
* const concierge = ai.agent({ model, tools: [supportTool] });
|
|
40
|
+
*/
|
|
41
|
+
function asTool(orchestrator, options) {
|
|
42
|
+
if (!orchestrator.name || typeof orchestrator.name !== "string") throw new SupervisorFailedError("orchestrator.asTool(): orchestrator must have a `name` to be wrapped as a tool");
|
|
43
|
+
const sessionScope = options.sessionScope ?? "fresh";
|
|
44
|
+
return compositeAsTool({
|
|
45
|
+
name: options.name ?? orchestrator.name,
|
|
46
|
+
description: options.description ?? `Invoke orchestrator "${orchestrator.name}" as a tool.`,
|
|
47
|
+
input: options.inputSchema,
|
|
48
|
+
execute: async (input) => {
|
|
49
|
+
const { sessionId, history, executeInput } = resolveSession(sessionScope, input);
|
|
50
|
+
const result = await orchestrator.execute(executeInput, {
|
|
51
|
+
sessionId,
|
|
52
|
+
history
|
|
53
|
+
});
|
|
54
|
+
if (result.error) throw result.error;
|
|
55
|
+
return {
|
|
56
|
+
data: result.data,
|
|
57
|
+
usage: result.usage,
|
|
58
|
+
report: result.report
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Resolve the per-call `sessionId`, `history`, and the `execute(input)`
|
|
65
|
+
* argument from the validated tool payload, according to `sessionScope`.
|
|
66
|
+
*/
|
|
67
|
+
function resolveSession(sessionScope, input) {
|
|
68
|
+
if (sessionScope === "fresh") return {
|
|
69
|
+
sessionId: generateRunId("session"),
|
|
70
|
+
history: [],
|
|
71
|
+
executeInput: coerceInput(input)
|
|
72
|
+
};
|
|
73
|
+
const payload = typeof input === "object" && input !== null ? input : {};
|
|
74
|
+
if (typeof payload.sessionId !== "string" || payload.sessionId.length === 0) throw new SupervisorFailedError("orchestrator.asTool(): sessionScope \"shared\" requires a `sessionId` string in the tool input payload");
|
|
75
|
+
const { sessionId, history, ...rest } = payload;
|
|
76
|
+
return {
|
|
77
|
+
sessionId,
|
|
78
|
+
history: Array.isArray(history) ? history : [],
|
|
79
|
+
executeInput: coerceInput(rest)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Coerce a tool-input value into the `SupervisorInput` shape the
|
|
84
|
+
* orchestrator's `execute()` accepts (`string | Record<string,
|
|
85
|
+
* unknown>`). Strings and plain objects pass through; everything else
|
|
86
|
+
* is JSON-stringified so the orchestrator receives a predictable input
|
|
87
|
+
* regardless of how the outer agent shaped its call.
|
|
88
|
+
*/
|
|
89
|
+
function coerceInput(value) {
|
|
90
|
+
if (typeof value === "string") return value;
|
|
91
|
+
if (typeof value === "object" && value !== null) return value;
|
|
92
|
+
if (value === void 0 || value === null) return "";
|
|
93
|
+
return String(value);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
//#endregion
|
|
97
|
+
export { asTool };
|
|
98
|
+
//# sourceMappingURL=as-tool.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"as-tool.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/as-tool.ts"],"sourcesContent":["import type { Message } from \"../contracts/conversation-message.type\";\nimport type {\n OrchestratorAsToolOptions,\n OrchestratorContract,\n} from \"../contracts/orchestrator/orchestrator.contract\";\nimport type { SupervisorInput } from \"../contracts/supervisor/supervisor-input.type\";\nimport { SupervisorFailedError } from \"../errors\";\nimport { compositeAsTool, type ToolContract } from \"../tool/tool\";\nimport { generateRunId } from \"../utils/generate-run-id\";\n\n/**\n * Shape the orchestrator looks for inside the validated tool input when\n * `sessionScope: \"shared\"` — the parent must thread the session id (and\n * optionally the prior history) through the tool's `inputSchema`\n * payload, since the boundary is opaque (§13). Everything else on the\n * payload becomes the orchestrator's `execute(input)` argument.\n */\ntype SharedScopePayload = {\n sessionId?: unknown;\n history?: unknown;\n [key: string]: unknown;\n};\n\n/**\n * Wrap an {@link OrchestratorContract} as a {@link ToolContract} so an\n * outer agent can invoke it from its tool-call loop (design §13).\n * Mirrors `supervisor.asTool()` — same `compositeAsTool` composition and\n * error normalization — and adds `sessionScope`.\n *\n * The boundary is OPAQUE (§13, §18.6): the parent's `signal` / `context`\n * / events do NOT auto-forward. Anything the wrapped orchestrator needs\n * per call must ride on the tool's `inputSchema` payload.\n *\n * Session continuity:\n * - `\"fresh\"` (default) — each invocation gets a brand-new `sessionId`\n * (a generated id) and empty history; the session lives only for this\n * tool call. The whole validated payload is forwarded as the\n * orchestrator's `execute(input)` argument.\n * - `\"shared\"` — the parent supplies `sessionId` (and optionally\n * `history`) inside the validated payload; the orchestrator\n * participates in that session. The remaining payload fields are\n * forwarded as `execute(input)`. A missing/blank `sessionId` throws\n * {@link SupervisorFailedError}.\n *\n * On `result.error`, the typed orchestrator error is thrown so the tool\n * wrapper produces a `ToolExecutionError` with `cause` preserved — the\n * outer agent sees one uniform error class.\n *\n * @example\n * const support = ai.orchestrator({ name: \"refund-support\", intents });\n * const supportTool = support.asTool({\n * name: \"handle_refund\",\n * description: \"Handle a refund conversation end-to-end.\",\n * inputSchema: v.object({ message: v.string() }),\n * });\n * const concierge = ai.agent({ model, tools: [supportTool] });\n */\nexport function asTool<TOutput, TState, TToolInput>(\n orchestrator: OrchestratorContract<TOutput, TState>,\n options: OrchestratorAsToolOptions<TToolInput>,\n): ToolContract<TToolInput, TOutput> {\n if (!orchestrator.name || typeof orchestrator.name !== \"string\") {\n throw new SupervisorFailedError(\n \"orchestrator.asTool(): orchestrator must have a `name` to be wrapped as a tool\",\n );\n }\n\n const sessionScope = options.sessionScope ?? \"fresh\";\n\n return compositeAsTool<TToolInput, TOutput>({\n name: options.name ?? orchestrator.name,\n description:\n options.description ??\n `Invoke orchestrator \"${orchestrator.name}\" as a tool.`,\n input: options.inputSchema,\n execute: async (input) => {\n const { sessionId, history, executeInput } = resolveSession(\n sessionScope,\n input,\n );\n\n const result = await orchestrator.execute(executeInput, {\n sessionId,\n history,\n });\n\n if (result.error) {\n // Surface the typed orchestrator error — the outer ToolContract\n // wraps it as a ToolExecutionError with `cause` preserved.\n throw result.error;\n }\n\n return {\n data: result.data as TOutput,\n usage: result.usage,\n report: result.report,\n };\n },\n });\n}\n\n/**\n * Resolve the per-call `sessionId`, `history`, and the `execute(input)`\n * argument from the validated tool payload, according to `sessionScope`.\n */\nfunction resolveSession(\n sessionScope: \"fresh\" | \"shared\",\n input: unknown,\n): { sessionId: string; history: Message[]; executeInput: SupervisorInput } {\n if (sessionScope === \"fresh\") {\n return {\n sessionId: generateRunId(\"session\"),\n history: [],\n executeInput: coerceInput(input),\n };\n }\n\n const payload = (\n typeof input === \"object\" && input !== null ? input : {}\n ) as SharedScopePayload;\n\n if (typeof payload.sessionId !== \"string\" || payload.sessionId.length === 0) {\n throw new SupervisorFailedError(\n 'orchestrator.asTool(): sessionScope \"shared\" requires a `sessionId` string in the tool input payload',\n );\n }\n\n const { sessionId, history, ...rest } = payload;\n\n return {\n sessionId,\n history: Array.isArray(history) ? (history as Message[]) : [],\n executeInput: coerceInput(rest),\n };\n}\n\n/**\n * Coerce a tool-input value into the `SupervisorInput` shape the\n * orchestrator's `execute()` accepts (`string | Record<string,\n * unknown>`). Strings and plain objects pass through; everything else\n * is JSON-stringified so the orchestrator receives a predictable input\n * regardless of how the outer agent shaped its call.\n */\nfunction coerceInput(value: unknown): SupervisorInput {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (typeof value === \"object\" && value !== null) {\n return value as Record<string, unknown>;\n }\n\n if (value === undefined || value === null) {\n return \"\";\n }\n\n return String(value);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,SAAgB,OACd,cACA,SACmC;CACnC,IAAI,CAAC,aAAa,QAAQ,OAAO,aAAa,SAAS,UACrD,MAAM,IAAI,sBACR,gFACF;CAGF,MAAM,eAAe,QAAQ,gBAAgB;CAE7C,OAAO,gBAAqC;EAC1C,MAAM,QAAQ,QAAQ,aAAa;EACnC,aACE,QAAQ,eACR,wBAAwB,aAAa,KAAK;EAC5C,OAAO,QAAQ;EACf,SAAS,OAAO,UAAU;GACxB,MAAM,EAAE,WAAW,SAAS,iBAAiB,eAC3C,cACA,KACF;GAEA,MAAM,SAAS,MAAM,aAAa,QAAQ,cAAc;IACtD;IACA;GACF,CAAC;GAED,IAAI,OAAO,OAGT,MAAM,OAAO;GAGf,OAAO;IACL,MAAM,OAAO;IACb,OAAO,OAAO;IACd,QAAQ,OAAO;GACjB;EACF;CACF,CAAC;AACH;;;;;AAMA,SAAS,eACP,cACA,OAC0E;CAC1E,IAAI,iBAAiB,SACnB,OAAO;EACL,WAAW,cAAc,SAAS;EAClC,SAAS,CAAC;EACV,cAAc,YAAY,KAAK;CACjC;CAGF,MAAM,UACJ,OAAO,UAAU,YAAY,UAAU,OAAO,QAAQ,CAAC;CAGzD,IAAI,OAAO,QAAQ,cAAc,YAAY,QAAQ,UAAU,WAAW,GACxE,MAAM,IAAI,sBACR,wGACF;CAGF,MAAM,EAAE,WAAW,SAAS,GAAG,SAAS;CAExC,OAAO;EACL;EACA,SAAS,MAAM,QAAQ,OAAO,IAAK,UAAwB,CAAC;EAC5D,cAAc,YAAY,IAAI;CAChC;AACF;;;;;;;;AASA,SAAS,YAAY,OAAiC;CACpD,IAAI,OAAO,UAAU,UACnB,OAAO;CAGT,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAGT,IAAI,UAAU,UAAa,UAAU,MACnC,OAAO;CAGT,OAAO,OAAO,KAAK;AACrB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//#region ../@warlock.js/ai/src/orchestrator/checkpoint.ts
|
|
2
|
+
/** Framework default for snapshot retention per session (§4 Phase 6). */
|
|
3
|
+
const DEFAULT_KEEP_SNAPSHOTS = 100;
|
|
4
|
+
/**
|
|
5
|
+
* Summarize a supervisor dispatch decision into the `last_route`
|
|
6
|
+
* checkpoint column (§4 Phase 6). A bare string passes through; a
|
|
7
|
+
* fan-out array passes through; the `END` sentinel and anything else
|
|
8
|
+
* collapse to `null` (the turn routed nowhere worth recording).
|
|
9
|
+
*/
|
|
10
|
+
function summarizeRoute(next) {
|
|
11
|
+
if (typeof next === "string") return next === "__warlock:end__" ? null : next;
|
|
12
|
+
if (Array.isArray(next)) return next;
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Phase 6 — persist checkpoint (orchestrator.md §3 / §4 Phase 6).
|
|
17
|
+
* Writes a fresh append-only row at `turn_index = N` carrying the
|
|
18
|
+
* post-merge `state`, the current `signature` (read by the next call's
|
|
19
|
+
* Phase 2), the informational `version`, the dispatch `last_route`, and
|
|
20
|
+
* the carried-forward `summarized_through`. Lock columns are written
|
|
21
|
+
* `null` here — they are populated only by an in-flight Phase 7
|
|
22
|
+
* compaction.
|
|
23
|
+
*
|
|
24
|
+
* Emits `orchestrator.checkpoint.persisted` after the row lands, then
|
|
25
|
+
* prunes to `keepSnapshots` (default 100; `"all"` opts out) — §4 Phase
|
|
26
|
+
* 6 pruning (Q20). Pruning runs only when the store exposes the
|
|
27
|
+
* optional `prune` hook (memory/pg/redis own their own pruning); when
|
|
28
|
+
* absent the write still succeeds.
|
|
29
|
+
*
|
|
30
|
+
* Returns the persisted record so the engine can fold it into the
|
|
31
|
+
* turn's report.
|
|
32
|
+
*/
|
|
33
|
+
async function persistCheckpoint(params) {
|
|
34
|
+
const { ctx, sessionId, turnIndex, state, lastRoute, summarizedThrough } = params;
|
|
35
|
+
const record = {
|
|
36
|
+
orchestrator_name: ctx.config.name,
|
|
37
|
+
session_id: sessionId,
|
|
38
|
+
turn_index: turnIndex,
|
|
39
|
+
state,
|
|
40
|
+
last_route: lastRoute,
|
|
41
|
+
signature: ctx.signature,
|
|
42
|
+
version: ctx.config.version ?? null,
|
|
43
|
+
summarized_through: summarizedThrough,
|
|
44
|
+
lock_acquired_at: null,
|
|
45
|
+
lock_expires_at: null,
|
|
46
|
+
saved_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
47
|
+
};
|
|
48
|
+
await ctx.checkpointStore.save(record);
|
|
49
|
+
ctx.emitter.emit("orchestrator.checkpoint.persisted", {
|
|
50
|
+
sessionId,
|
|
51
|
+
turnIndex
|
|
52
|
+
});
|
|
53
|
+
await prune(ctx, sessionId, turnIndex);
|
|
54
|
+
return record;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Prune session rows older than `max_turn_index - keepSnapshots` (§4
|
|
58
|
+
* Phase 6). Synchronous-after-save; opted out with
|
|
59
|
+
* `keepSnapshots: "all"`. Delegated to an optional store-side `prune`
|
|
60
|
+
* hook so each driver implements deletion in its own dialect — the
|
|
61
|
+
* engine never reaches into store internals.
|
|
62
|
+
*/
|
|
63
|
+
async function prune(ctx, sessionId, latestTurnIndex) {
|
|
64
|
+
const keep = ctx.config.keepSnapshots ?? 100;
|
|
65
|
+
if (keep === "all") return;
|
|
66
|
+
const store = ctx.checkpointStore;
|
|
67
|
+
if (typeof store.prune !== "function") return;
|
|
68
|
+
const keepBeforeTurnIndex = latestTurnIndex - keep + 1;
|
|
69
|
+
if (keepBeforeTurnIndex <= 0) return;
|
|
70
|
+
await store.prune(ctx.config.name, sessionId, keepBeforeTurnIndex);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
export { persistCheckpoint, summarizeRoute };
|
|
75
|
+
//# sourceMappingURL=checkpoint.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/checkpoint.ts"],"sourcesContent":["import type { CheckpointRecord } from \"../contracts/orchestrator/checkpoint-store.contract\";\nimport type { Next } from \"../contracts/supervisor/next.type\";\nimport type { OrchestratorEngineContext } from \"./engine-context.type\";\n\n/** Framework default for snapshot retention per session (§4 Phase 6). */\nexport const DEFAULT_KEEP_SNAPSHOTS = 100;\n\n/** Fields the engine supplies to build a fresh checkpoint row. */\nexport type PersistParams<TState> = {\n ctx: OrchestratorEngineContext<unknown, TState>;\n sessionId: string;\n turnIndex: number;\n state: unknown;\n /** Dispatch decision summary — a single intent, fan-out list, or null. */\n lastRoute: string | string[] | null;\n /** Carried forward from the loaded checkpoint (compaction progress). */\n summarizedThrough: number | null;\n};\n\n/**\n * Summarize a supervisor dispatch decision into the `last_route`\n * checkpoint column (§4 Phase 6). A bare string passes through; a\n * fan-out array passes through; the `END` sentinel and anything else\n * collapse to `null` (the turn routed nowhere worth recording).\n */\nexport function summarizeRoute(next: Next | undefined): string | string[] | null {\n if (typeof next === \"string\") {\n return next === \"__warlock:end__\" ? null : next;\n }\n\n if (Array.isArray(next)) {\n return next;\n }\n\n return null;\n}\n\n/**\n * Phase 6 — persist checkpoint (orchestrator.md §3 / §4 Phase 6).\n * Writes a fresh append-only row at `turn_index = N` carrying the\n * post-merge `state`, the current `signature` (read by the next call's\n * Phase 2), the informational `version`, the dispatch `last_route`, and\n * the carried-forward `summarized_through`. Lock columns are written\n * `null` here — they are populated only by an in-flight Phase 7\n * compaction.\n *\n * Emits `orchestrator.checkpoint.persisted` after the row lands, then\n * prunes to `keepSnapshots` (default 100; `\"all\"` opts out) — §4 Phase\n * 6 pruning (Q20). Pruning runs only when the store exposes the\n * optional `prune` hook (memory/pg/redis own their own pruning); when\n * absent the write still succeeds.\n *\n * Returns the persisted record so the engine can fold it into the\n * turn's report.\n */\nexport async function persistCheckpoint<TState>(\n params: PersistParams<TState>,\n): Promise<CheckpointRecord> {\n const { ctx, sessionId, turnIndex, state, lastRoute, summarizedThrough } = params;\n\n const record: CheckpointRecord = {\n orchestrator_name: ctx.config.name,\n session_id: sessionId,\n turn_index: turnIndex,\n state,\n last_route: lastRoute,\n signature: ctx.signature,\n version: ctx.config.version ?? null,\n summarized_through: summarizedThrough,\n lock_acquired_at: null,\n lock_expires_at: null,\n saved_at: new Date().toISOString(),\n };\n\n await ctx.checkpointStore.save(record);\n\n ctx.emitter.emit(\"orchestrator.checkpoint.persisted\", {\n sessionId,\n turnIndex,\n });\n\n await prune(ctx, sessionId, turnIndex);\n\n return record;\n}\n\n/**\n * Prune session rows older than `max_turn_index - keepSnapshots` (§4\n * Phase 6). Synchronous-after-save; opted out with\n * `keepSnapshots: \"all\"`. Delegated to an optional store-side `prune`\n * hook so each driver implements deletion in its own dialect — the\n * engine never reaches into store internals.\n */\nasync function prune<TState>(\n ctx: OrchestratorEngineContext<unknown, TState>,\n sessionId: string,\n latestTurnIndex: number,\n): Promise<void> {\n const keep = ctx.config.keepSnapshots ?? DEFAULT_KEEP_SNAPSHOTS;\n\n if (keep === \"all\") {\n return;\n }\n\n const store = ctx.checkpointStore as {\n prune?: (\n orchestratorName: string,\n sessionId: string,\n keepBeforeTurnIndex: number,\n ) => Promise<void>;\n };\n\n if (typeof store.prune !== \"function\") {\n return;\n }\n\n const keepBeforeTurnIndex = latestTurnIndex - keep + 1;\n\n if (keepBeforeTurnIndex <= 0) {\n return;\n }\n\n await store.prune(ctx.config.name, sessionId, keepBeforeTurnIndex);\n}\n"],"mappings":";;AAKA,MAAa,yBAAyB;;;;;;;AAoBtC,SAAgB,eAAe,MAAkD;CAC/E,IAAI,OAAO,SAAS,UAClB,OAAO,SAAS,oBAAoB,OAAO;CAG7C,IAAI,MAAM,QAAQ,IAAI,GACpB,OAAO;CAGT,OAAO;AACT;;;;;;;;;;;;;;;;;;;AAoBA,eAAsB,kBACpB,QAC2B;CAC3B,MAAM,EAAE,KAAK,WAAW,WAAW,OAAO,WAAW,sBAAsB;CAE3E,MAAM,SAA2B;EAC/B,mBAAmB,IAAI,OAAO;EAC9B,YAAY;EACZ,YAAY;EACZ;EACA,YAAY;EACZ,WAAW,IAAI;EACf,SAAS,IAAI,OAAO,WAAW;EAC/B,oBAAoB;EACpB,kBAAkB;EAClB,iBAAiB;EACjB,2BAAU,IAAI,KAAK,EAAC,CAAC,YAAY;CACnC;CAEA,MAAM,IAAI,gBAAgB,KAAK,MAAM;CAErC,IAAI,QAAQ,KAAK,qCAAqC;EACpD;EACA;CACF,CAAC;CAED,MAAM,MAAM,KAAK,WAAW,SAAS;CAErC,OAAO;AACT;;;;;;;;AASA,eAAe,MACb,KACA,WACA,iBACe;CACf,MAAM,OAAO,IAAI,OAAO;CAExB,IAAI,SAAS,OACX;CAGF,MAAM,QAAQ,IAAI;CAQlB,IAAI,OAAO,MAAM,UAAU,YACzB;CAGF,MAAM,sBAAsB,kBAAkB,OAAO;CAErD,IAAI,uBAAuB,GACzB;CAGF,MAAM,MAAM,MAAM,IAAI,OAAO,MAAM,WAAW,mBAAmB;AACnE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { OrchestratorCommands } from "../contracts/orchestrator/orchestrator-commands.type.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../@warlock.js/ai/src/orchestrator/commands.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Per-command handler bag — one async runner per key of
|
|
6
|
+
* {@link OrchestratorCommands}. The orchestrator factory supplies the
|
|
7
|
+
* `compact` runner (which delegates to the shared compaction code path,
|
|
8
|
+
* §11) so this module owns command ROUTING only, never the compaction
|
|
9
|
+
* logic itself.
|
|
10
|
+
*
|
|
11
|
+
* Typed against the same discriminated map the public `command<K>`
|
|
12
|
+
* method uses, so a registered handler's `args` / result line up with
|
|
13
|
+
* the contract with no casting at the call site.
|
|
14
|
+
*/
|
|
15
|
+
type OrchestratorCommandHandlers = { [K in keyof OrchestratorCommands]: (args: OrchestratorCommands[K]["args"]) => Promise<OrchestratorCommands[K]["result"]> };
|
|
16
|
+
/**
|
|
17
|
+
* Build the typed `command(name, args)` dispatcher backing
|
|
18
|
+
* {@link import("../contracts/orchestrator/orchestrator.contract").OrchestratorContract.command}
|
|
19
|
+
* (design §11). Looks the command up in the supplied handler bag and
|
|
20
|
+
* forwards `args`, preserving the discriminated `OrchestratorCommands`
|
|
21
|
+
* typing end to end.
|
|
22
|
+
*
|
|
23
|
+
* v1 ships exactly one built-in command, `compact`. v2 user commands
|
|
24
|
+
* attach via module augmentation of `OrchestratorCommands`; the
|
|
25
|
+
* dispatcher widens with the map automatically, and an unregistered
|
|
26
|
+
* command throws {@link SupervisorFailedError} rather than silently
|
|
27
|
+
* resolving `undefined`.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const command = createCommandDispatcher({
|
|
31
|
+
* compact: (args) => runCompaction(args),
|
|
32
|
+
* });
|
|
33
|
+
* const result = await command("compact", { sessionId, history });
|
|
34
|
+
*/
|
|
35
|
+
declare function createCommandDispatcher(handlers: OrchestratorCommandHandlers): <K extends keyof OrchestratorCommands>(name: K, args: OrchestratorCommands[K]["args"]) => Promise<OrchestratorCommands[K]["result"]>;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { OrchestratorCommandHandlers, createCommandDispatcher };
|
|
38
|
+
//# sourceMappingURL=commands.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/commands.ts"],"mappings":";;;;;AAcA;;;;;;;;;KAAY,2BAAA,iBACE,oBAAA,IACV,IAAA,EAAM,oBAAA,CAAqB,CAAA,cACxB,OAAA,CAAQ,oBAAA,CAAqB,CAAA;;;;;;;;;AAAC;AAsBrC;;;;;;;;;;iBAAgB,uBAAA,CAAwB,QAAA,EAAU,2BAAA,oBACR,oBAAA,EACtC,IAAA,EAAM,CAAA,EACN,IAAA,EAAM,oBAAA,CAAqB,CAAA,cAC1B,OAAA,CAAQ,oBAAA,CAAqB,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { SupervisorFailedError } from "../errors/supervisor-failed-error.mjs";
|
|
2
|
+
import "../errors/index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region ../@warlock.js/ai/src/orchestrator/commands.ts
|
|
5
|
+
/**
|
|
6
|
+
* Build the typed `command(name, args)` dispatcher backing
|
|
7
|
+
* {@link import("../contracts/orchestrator/orchestrator.contract").OrchestratorContract.command}
|
|
8
|
+
* (design §11). Looks the command up in the supplied handler bag and
|
|
9
|
+
* forwards `args`, preserving the discriminated `OrchestratorCommands`
|
|
10
|
+
* typing end to end.
|
|
11
|
+
*
|
|
12
|
+
* v1 ships exactly one built-in command, `compact`. v2 user commands
|
|
13
|
+
* attach via module augmentation of `OrchestratorCommands`; the
|
|
14
|
+
* dispatcher widens with the map automatically, and an unregistered
|
|
15
|
+
* command throws {@link SupervisorFailedError} rather than silently
|
|
16
|
+
* resolving `undefined`.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* const command = createCommandDispatcher({
|
|
20
|
+
* compact: (args) => runCompaction(args),
|
|
21
|
+
* });
|
|
22
|
+
* const result = await command("compact", { sessionId, history });
|
|
23
|
+
*/
|
|
24
|
+
function createCommandDispatcher(handlers) {
|
|
25
|
+
return function command(name, args) {
|
|
26
|
+
const handler = handlers[name];
|
|
27
|
+
if (typeof handler !== "function") throw new SupervisorFailedError(`orchestrator.command(): unknown command "${String(name)}"`);
|
|
28
|
+
return handler(args);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
export { createCommandDispatcher };
|
|
34
|
+
//# sourceMappingURL=commands.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/commands.ts"],"sourcesContent":["import type { OrchestratorCommands } from \"../contracts/orchestrator/orchestrator-commands.type\";\nimport { SupervisorFailedError } from \"../errors\";\n\n/**\n * Per-command handler bag — one async runner per key of\n * {@link OrchestratorCommands}. The orchestrator factory supplies the\n * `compact` runner (which delegates to the shared compaction code path,\n * §11) so this module owns command ROUTING only, never the compaction\n * logic itself.\n *\n * Typed against the same discriminated map the public `command<K>`\n * method uses, so a registered handler's `args` / result line up with\n * the contract with no casting at the call site.\n */\nexport type OrchestratorCommandHandlers = {\n [K in keyof OrchestratorCommands]: (\n args: OrchestratorCommands[K][\"args\"],\n ) => Promise<OrchestratorCommands[K][\"result\"]>;\n};\n\n/**\n * Build the typed `command(name, args)` dispatcher backing\n * {@link import(\"../contracts/orchestrator/orchestrator.contract\").OrchestratorContract.command}\n * (design §11). Looks the command up in the supplied handler bag and\n * forwards `args`, preserving the discriminated `OrchestratorCommands`\n * typing end to end.\n *\n * v1 ships exactly one built-in command, `compact`. v2 user commands\n * attach via module augmentation of `OrchestratorCommands`; the\n * dispatcher widens with the map automatically, and an unregistered\n * command throws {@link SupervisorFailedError} rather than silently\n * resolving `undefined`.\n *\n * @example\n * const command = createCommandDispatcher({\n * compact: (args) => runCompaction(args),\n * });\n * const result = await command(\"compact\", { sessionId, history });\n */\nexport function createCommandDispatcher(handlers: OrchestratorCommandHandlers) {\n return function command<K extends keyof OrchestratorCommands>(\n name: K,\n args: OrchestratorCommands[K][\"args\"],\n ): Promise<OrchestratorCommands[K][\"result\"]> {\n const handler = handlers[name];\n\n if (typeof handler !== \"function\") {\n throw new SupervisorFailedError(\n `orchestrator.command(): unknown command \"${String(name)}\"`,\n );\n }\n\n return handler(args);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuCA,SAAgB,wBAAwB,UAAuC;CAC7E,OAAO,SAAS,QACd,MACA,MAC4C;EAC5C,MAAM,UAAU,SAAS;EAEzB,IAAI,OAAO,YAAY,YACrB,MAAM,IAAI,sBACR,4CAA4C,OAAO,IAAI,EAAE,EAC3D;EAGF,OAAO,QAAQ,IAAI;CACrB;AACF"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { DEFAULT_LOCK_MAX_WAIT } from "./lock.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../@warlock.js/ai/src/orchestrator/compaction.ts
|
|
4
|
+
/**
|
|
5
|
+
* Most-recent messages kept verbatim when `summarize.keep` is omitted.
|
|
6
|
+
* Defaulting to 0 would compact the entire history into one memo (losing
|
|
7
|
+
* the live tail every turn), so the object form keeps a small recent
|
|
8
|
+
* window by default — matching the canonical doc examples (`keep: 8`).
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_COMPACTION_KEEP = 8;
|
|
11
|
+
/** Whether the configured `summarize` is the fully-pluggable callback form. */
|
|
12
|
+
function isCallbackForm(summarize) {
|
|
13
|
+
return typeof summarize === "function";
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Decide whether Phase 7 compaction should fire this turn (orchestrator
|
|
17
|
+
* .md §4 Phase 7 / §12.1). v1 trigger is count-based:
|
|
18
|
+
* `summarize.afterTurns` fires once `turnIndex >= afterTurns`. The
|
|
19
|
+
* callback form has no threshold and never auto-fires — it is driven
|
|
20
|
+
* exclusively by `command("compact")` (the manual path). Returns false
|
|
21
|
+
* when `summarize` is unset.
|
|
22
|
+
*/
|
|
23
|
+
function shouldCompact(ctx, turnIndex) {
|
|
24
|
+
const summarize = ctx.config.summarize;
|
|
25
|
+
if (summarize === void 0 || isCallbackForm(summarize)) return false;
|
|
26
|
+
const afterTurns = summarize.afterTurns;
|
|
27
|
+
return afterTurns !== void 0 && turnIndex >= afterTurns;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Run the configured summarizer against the session history and build
|
|
31
|
+
* a {@link CompactionResult} (§12.2 step 2–3). Three resolution paths:
|
|
32
|
+
*
|
|
33
|
+
* - callback form — `summarize(history)` returns the result directly.
|
|
34
|
+
* - config + `summarizer` model — summarize the slice (history minus
|
|
35
|
+
* the most-recent `keep`) into one synthetic memo turn.
|
|
36
|
+
* - config without a `summarizer` — produce a trivial degenerate memo
|
|
37
|
+
* (no model available); the dev is expected to supply a summarizer
|
|
38
|
+
* for real compaction. The range still reflects the kept tail.
|
|
39
|
+
*/
|
|
40
|
+
async function produceCompaction(summarize, history) {
|
|
41
|
+
if (isCallbackForm(summarize)) return summarize(history);
|
|
42
|
+
const keep = summarize.keep ?? 8;
|
|
43
|
+
const replacesFromIndex = 0;
|
|
44
|
+
const replacesToIndex = Math.max(-1, history.length - keep - 1);
|
|
45
|
+
return {
|
|
46
|
+
summary: {
|
|
47
|
+
role: "system",
|
|
48
|
+
content: await summarizeSlice(summarize, history.slice(0, replacesToIndex + 1))
|
|
49
|
+
},
|
|
50
|
+
replacesFromIndex,
|
|
51
|
+
replacesToIndex
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Summarize a slice of history into text. Uses the configured
|
|
56
|
+
* `summarizer` model when present (a single non-streaming completion);
|
|
57
|
+
* otherwise returns a placeholder memo. The summarizer is intentionally
|
|
58
|
+
* the cheap model — never the specialists (§12.4).
|
|
59
|
+
*/
|
|
60
|
+
async function summarizeSlice(summarize, slice) {
|
|
61
|
+
if (slice.length === 0) return "";
|
|
62
|
+
if (!summarize.summarizer) return `Summary of ${slice.length} prior message(s).`;
|
|
63
|
+
const transcript = slice.map((message) => `${message.role}: ${stringifyContent(message.content)}`).join("\n");
|
|
64
|
+
return (await summarize.summarizer.complete([{
|
|
65
|
+
role: "system",
|
|
66
|
+
content: "Summarize the following conversation slice into a concise memo that preserves the facts, decisions, and open threads a later turn would need. Reply with the memo only."
|
|
67
|
+
}, {
|
|
68
|
+
role: "user",
|
|
69
|
+
content: transcript
|
|
70
|
+
}])).content;
|
|
71
|
+
}
|
|
72
|
+
/** Coerce a message's content into a flat string for the summarizer prompt. */
|
|
73
|
+
function stringifyContent(content) {
|
|
74
|
+
if (typeof content === "string") return content;
|
|
75
|
+
return JSON.stringify(content);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Phase 7 — post-turn compaction (orchestrator.md §3 / §4 Phase 7 /
|
|
79
|
+
* §12.2). Runs AFTER the turn settles; never blocks the caller's
|
|
80
|
+
* resolution path beyond this phase.
|
|
81
|
+
*
|
|
82
|
+
* Acquires the cooperative session lock (writes `lock_acquired_at` /
|
|
83
|
+
* `lock_expires_at` onto a fresh row), runs the summarizer, builds the
|
|
84
|
+
* compaction, then either invokes `summarize.onCompact` (framework-
|
|
85
|
+
* driven apply) or surfaces the compaction on the result for the dev to
|
|
86
|
+
* apply. Releases the lock on settle. Emits
|
|
87
|
+
* `orchestrator.compaction.suggested` always,
|
|
88
|
+
* `orchestrator.compaction.applied` only when `onCompact` succeeded, and
|
|
89
|
+
* `orchestrator.compaction.failed` (carrying the thrown `error` and the
|
|
90
|
+
* `phase` that failed) when the summarizer or `onCompact` throws.
|
|
91
|
+
*
|
|
92
|
+
* Retry policy is skip-and-log (§4 Phase 7): a summarizer failure
|
|
93
|
+
* leaves the session running with unchanged history — the engine
|
|
94
|
+
* treats a thrown summarizer / `onCompact` as "no compaction this
|
|
95
|
+
* turn", emits `orchestrator.compaction.failed`, and returns `undefined`
|
|
96
|
+
* (summarizer) or surfaces the unapplied compaction (`onCompact`).
|
|
97
|
+
*/
|
|
98
|
+
async function runCompaction(ctx, sessionId, history) {
|
|
99
|
+
const summarize = ctx.config.summarize;
|
|
100
|
+
if (summarize === void 0) return;
|
|
101
|
+
await acquireCompactionLock(ctx, sessionId);
|
|
102
|
+
try {
|
|
103
|
+
const compaction = await produceCompaction(summarize, history);
|
|
104
|
+
ctx.emitter.emit("orchestrator.compaction.suggested", {
|
|
105
|
+
sessionId,
|
|
106
|
+
compaction
|
|
107
|
+
});
|
|
108
|
+
const onCompact = isCallbackForm(summarize) ? void 0 : summarize.onCompact;
|
|
109
|
+
if (!onCompact) return {
|
|
110
|
+
compaction,
|
|
111
|
+
applied: false
|
|
112
|
+
};
|
|
113
|
+
try {
|
|
114
|
+
await onCompact(compaction, { sessionId });
|
|
115
|
+
ctx.emitter.emit("orchestrator.compaction.applied", {
|
|
116
|
+
sessionId,
|
|
117
|
+
compaction
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
compaction,
|
|
121
|
+
applied: true
|
|
122
|
+
};
|
|
123
|
+
} catch (error) {
|
|
124
|
+
ctx.emitter.emit("orchestrator.compaction.failed", {
|
|
125
|
+
sessionId,
|
|
126
|
+
phase: "onCompact",
|
|
127
|
+
error
|
|
128
|
+
});
|
|
129
|
+
return {
|
|
130
|
+
compaction,
|
|
131
|
+
applied: false
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
} catch (error) {
|
|
135
|
+
ctx.emitter.emit("orchestrator.compaction.failed", {
|
|
136
|
+
sessionId,
|
|
137
|
+
phase: "summarize",
|
|
138
|
+
error
|
|
139
|
+
});
|
|
140
|
+
return;
|
|
141
|
+
} finally {
|
|
142
|
+
await releaseCompactionLock(ctx, sessionId);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Run a manual compaction for `command("compact", ...)` (§11 / §12.1).
|
|
147
|
+
* Same code path as the post-turn trigger but driven on demand against
|
|
148
|
+
* the supplied history, returning the raw {@link CompactionResult}. The
|
|
149
|
+
* callback form is honored; the config form without a `summarizer`
|
|
150
|
+
* produces the degenerate memo. Does not apply `onCompact` — the
|
|
151
|
+
* command surface returns the compaction for the caller to handle.
|
|
152
|
+
*/
|
|
153
|
+
async function runManualCompaction(ctx, history) {
|
|
154
|
+
const summarize = ctx.config.summarize;
|
|
155
|
+
if (summarize === void 0) return {
|
|
156
|
+
summary: {
|
|
157
|
+
role: "system",
|
|
158
|
+
content: `Summary of ${history.length} message(s).`
|
|
159
|
+
},
|
|
160
|
+
replacesFromIndex: 0,
|
|
161
|
+
replacesToIndex: Math.max(-1, history.length - 1)
|
|
162
|
+
};
|
|
163
|
+
return produceCompaction(summarize, history);
|
|
164
|
+
}
|
|
165
|
+
/** Resolve the lock TTL from the summarize config (config form only). */
|
|
166
|
+
function resolveLockMaxWait(ctx) {
|
|
167
|
+
const summarize = ctx.config.summarize;
|
|
168
|
+
if (summarize === void 0 || isCallbackForm(summarize)) return DEFAULT_LOCK_MAX_WAIT;
|
|
169
|
+
return summarize.lock?.maxWait ?? 3e4;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Write the cooperative compaction lock onto a fresh checkpoint row
|
|
173
|
+
* (§12.2 step 1). The lock lives on the latest persisted row; we load
|
|
174
|
+
* it, stamp the lock columns, and re-save (append-only) so the next
|
|
175
|
+
* turn's Phase 3 observes it.
|
|
176
|
+
*/
|
|
177
|
+
async function acquireCompactionLock(ctx, sessionId) {
|
|
178
|
+
const latest = await ctx.checkpointStore.load(ctx.config.name, sessionId);
|
|
179
|
+
if (!latest) return;
|
|
180
|
+
const now = Date.now();
|
|
181
|
+
const maxWait = resolveLockMaxWait(ctx);
|
|
182
|
+
await ctx.checkpointStore.save({
|
|
183
|
+
...latest,
|
|
184
|
+
lock_acquired_at: new Date(now).toISOString(),
|
|
185
|
+
lock_expires_at: new Date(now + maxWait).toISOString(),
|
|
186
|
+
saved_at: new Date(now).toISOString()
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Clear the compaction lock columns (§12.2 step 6) by re-saving the
|
|
191
|
+
* latest row with the lock fields nulled.
|
|
192
|
+
*/
|
|
193
|
+
async function releaseCompactionLock(ctx, sessionId) {
|
|
194
|
+
const latest = await ctx.checkpointStore.load(ctx.config.name, sessionId);
|
|
195
|
+
if (!latest) return;
|
|
196
|
+
await ctx.checkpointStore.save({
|
|
197
|
+
...latest,
|
|
198
|
+
lock_acquired_at: null,
|
|
199
|
+
lock_expires_at: null,
|
|
200
|
+
saved_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
//#endregion
|
|
205
|
+
export { runCompaction, runManualCompaction, shouldCompact };
|
|
206
|
+
//# sourceMappingURL=compaction.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/compaction.ts"],"sourcesContent":["import type { Message } from \"../contracts/conversation-message.type\";\nimport type {\n SummarizeCallback,\n SummarizeConfig,\n} from \"../contracts/orchestrator/orchestrator-config.type\";\nimport type { CompactionResult } from \"../contracts/result/orchestrator-result.type\";\nimport type { OrchestratorEngineContext } from \"./engine-context.type\";\nimport { DEFAULT_LOCK_MAX_WAIT } from \"./lock\";\n\n/**\n * Most-recent messages kept verbatim when `summarize.keep` is omitted.\n * Defaulting to 0 would compact the entire history into one memo (losing\n * the live tail every turn), so the object form keeps a small recent\n * window by default — matching the canonical doc examples (`keep: 8`).\n */\nexport const DEFAULT_COMPACTION_KEEP = 8;\n\n/** Whether the configured `summarize` is the fully-pluggable callback form. */\nfunction isCallbackForm(\n summarize: SummarizeConfig | SummarizeCallback | undefined,\n): summarize is SummarizeCallback {\n return typeof summarize === \"function\";\n}\n\n/**\n * Decide whether Phase 7 compaction should fire this turn (orchestrator\n * .md §4 Phase 7 / §12.1). v1 trigger is count-based:\n * `summarize.afterTurns` fires once `turnIndex >= afterTurns`. The\n * callback form has no threshold and never auto-fires — it is driven\n * exclusively by `command(\"compact\")` (the manual path). Returns false\n * when `summarize` is unset.\n */\nexport function shouldCompact(\n ctx: OrchestratorEngineContext,\n turnIndex: number,\n): boolean {\n const summarize = ctx.config.summarize;\n\n if (summarize === undefined || isCallbackForm(summarize)) {\n return false;\n }\n\n const afterTurns = summarize.afterTurns;\n\n return afterTurns !== undefined && turnIndex >= afterTurns;\n}\n\n/** Result of a Phase-7 run — what the engine folds into the turn. */\nexport type CompactionOutcome = {\n /** The produced compaction, surfaced on `result.compaction`. */\n compaction: CompactionResult;\n /**\n * Whether `summarize.onCompact` ran AND succeeded — when true the\n * engine advances `summarized_through` to `replacesToIndex` (§12.2\n * step 4); when false it leaves it unchanged (§12.2 step 5).\n */\n applied: boolean;\n};\n\n/**\n * Run the configured summarizer against the session history and build\n * a {@link CompactionResult} (§12.2 step 2–3). Three resolution paths:\n *\n * - callback form — `summarize(history)` returns the result directly.\n * - config + `summarizer` model — summarize the slice (history minus\n * the most-recent `keep`) into one synthetic memo turn.\n * - config without a `summarizer` — produce a trivial degenerate memo\n * (no model available); the dev is expected to supply a summarizer\n * for real compaction. The range still reflects the kept tail.\n */\nasync function produceCompaction(\n summarize: SummarizeConfig | SummarizeCallback,\n history: Message[],\n): Promise<CompactionResult> {\n if (isCallbackForm(summarize)) {\n return summarize(history);\n }\n\n const keep = summarize.keep ?? DEFAULT_COMPACTION_KEEP;\n const replacesFromIndex = 0;\n const replacesToIndex = Math.max(-1, history.length - keep - 1);\n const slice = history.slice(0, replacesToIndex + 1);\n\n const summaryText = await summarizeSlice(summarize, slice);\n\n return {\n summary: { role: \"system\", content: summaryText },\n replacesFromIndex,\n replacesToIndex,\n };\n}\n\n/**\n * Summarize a slice of history into text. Uses the configured\n * `summarizer` model when present (a single non-streaming completion);\n * otherwise returns a placeholder memo. The summarizer is intentionally\n * the cheap model — never the specialists (§12.4).\n */\nasync function summarizeSlice(\n summarize: SummarizeConfig,\n slice: Message[],\n): Promise<string> {\n if (slice.length === 0) {\n return \"\";\n }\n\n if (!summarize.summarizer) {\n return `Summary of ${slice.length} prior message(s).`;\n }\n\n const transcript = slice\n .map((message) => `${message.role}: ${stringifyContent(message.content)}`)\n .join(\"\\n\");\n\n const response = await summarize.summarizer.complete([\n {\n role: \"system\",\n content:\n \"Summarize the following conversation slice into a concise memo \" +\n \"that preserves the facts, decisions, and open threads a later \" +\n \"turn would need. Reply with the memo only.\",\n },\n { role: \"user\", content: transcript },\n ]);\n\n return response.content;\n}\n\n/** Coerce a message's content into a flat string for the summarizer prompt. */\nfunction stringifyContent(content: Message[\"content\"]): string {\n if (typeof content === \"string\") {\n return content;\n }\n\n return JSON.stringify(content);\n}\n\n/**\n * Phase 7 — post-turn compaction (orchestrator.md §3 / §4 Phase 7 /\n * §12.2). Runs AFTER the turn settles; never blocks the caller's\n * resolution path beyond this phase.\n *\n * Acquires the cooperative session lock (writes `lock_acquired_at` /\n * `lock_expires_at` onto a fresh row), runs the summarizer, builds the\n * compaction, then either invokes `summarize.onCompact` (framework-\n * driven apply) or surfaces the compaction on the result for the dev to\n * apply. Releases the lock on settle. Emits\n * `orchestrator.compaction.suggested` always,\n * `orchestrator.compaction.applied` only when `onCompact` succeeded, and\n * `orchestrator.compaction.failed` (carrying the thrown `error` and the\n * `phase` that failed) when the summarizer or `onCompact` throws.\n *\n * Retry policy is skip-and-log (§4 Phase 7): a summarizer failure\n * leaves the session running with unchanged history — the engine\n * treats a thrown summarizer / `onCompact` as \"no compaction this\n * turn\", emits `orchestrator.compaction.failed`, and returns `undefined`\n * (summarizer) or surfaces the unapplied compaction (`onCompact`).\n */\nexport async function runCompaction<TState>(\n ctx: OrchestratorEngineContext<unknown, TState>,\n sessionId: string,\n history: Message[],\n): Promise<CompactionOutcome | undefined> {\n const summarize = ctx.config.summarize;\n\n if (summarize === undefined) {\n return undefined;\n }\n\n await acquireCompactionLock(ctx, sessionId);\n\n try {\n const compaction = await produceCompaction(summarize, history);\n\n ctx.emitter.emit(\"orchestrator.compaction.suggested\", {\n sessionId,\n compaction,\n });\n\n const onCompact = isCallbackForm(summarize) ? undefined : summarize.onCompact;\n\n if (!onCompact) {\n return { compaction, applied: false };\n }\n\n try {\n await onCompact(compaction, { sessionId });\n\n ctx.emitter.emit(\"orchestrator.compaction.applied\", {\n sessionId,\n compaction,\n });\n\n return { compaction, applied: true };\n } catch (error) {\n // onCompact threw — surface the compaction for the dev to apply,\n // leave summarized_through unchanged (§12.2 step 4 failure path).\n ctx.emitter.emit(\"orchestrator.compaction.failed\", {\n sessionId,\n phase: \"onCompact\",\n error,\n });\n\n return { compaction, applied: false };\n }\n } catch (error) {\n // Summarizer failed — skip-and-log; session keeps running unchanged.\n ctx.emitter.emit(\"orchestrator.compaction.failed\", {\n sessionId,\n phase: \"summarize\",\n error,\n });\n\n return undefined;\n } finally {\n await releaseCompactionLock(ctx, sessionId);\n }\n}\n\n/**\n * Run a manual compaction for `command(\"compact\", ...)` (§11 / §12.1).\n * Same code path as the post-turn trigger but driven on demand against\n * the supplied history, returning the raw {@link CompactionResult}. The\n * callback form is honored; the config form without a `summarizer`\n * produces the degenerate memo. Does not apply `onCompact` — the\n * command surface returns the compaction for the caller to handle.\n */\nexport async function runManualCompaction<TState>(\n ctx: OrchestratorEngineContext<unknown, TState>,\n history: Message[],\n): Promise<CompactionResult> {\n const summarize = ctx.config.summarize;\n\n if (summarize === undefined) {\n // No summarize policy configured — produce a degenerate memo over\n // the full supplied history so the command always resolves.\n return {\n summary: { role: \"system\", content: `Summary of ${history.length} message(s).` },\n replacesFromIndex: 0,\n replacesToIndex: Math.max(-1, history.length - 1),\n };\n }\n\n return produceCompaction(summarize, history);\n}\n\n/** Resolve the lock TTL from the summarize config (config form only). */\nfunction resolveLockMaxWait(ctx: OrchestratorEngineContext): number {\n const summarize = ctx.config.summarize;\n\n if (summarize === undefined || isCallbackForm(summarize)) {\n return DEFAULT_LOCK_MAX_WAIT;\n }\n\n return summarize.lock?.maxWait ?? DEFAULT_LOCK_MAX_WAIT;\n}\n\n/**\n * Write the cooperative compaction lock onto a fresh checkpoint row\n * (§12.2 step 1). The lock lives on the latest persisted row; we load\n * it, stamp the lock columns, and re-save (append-only) so the next\n * turn's Phase 3 observes it.\n */\nasync function acquireCompactionLock<TState>(\n ctx: OrchestratorEngineContext<unknown, TState>,\n sessionId: string,\n): Promise<void> {\n const latest = await ctx.checkpointStore.load(ctx.config.name, sessionId);\n\n if (!latest) {\n return;\n }\n\n const now = Date.now();\n const maxWait = resolveLockMaxWait(ctx as OrchestratorEngineContext);\n\n await ctx.checkpointStore.save({\n ...latest,\n lock_acquired_at: new Date(now).toISOString(),\n lock_expires_at: new Date(now + maxWait).toISOString(),\n saved_at: new Date(now).toISOString(),\n });\n}\n\n/**\n * Clear the compaction lock columns (§12.2 step 6) by re-saving the\n * latest row with the lock fields nulled.\n */\nasync function releaseCompactionLock<TState>(\n ctx: OrchestratorEngineContext<unknown, TState>,\n sessionId: string,\n): Promise<void> {\n const latest = await ctx.checkpointStore.load(ctx.config.name, sessionId);\n\n if (!latest) {\n return;\n }\n\n await ctx.checkpointStore.save({\n ...latest,\n lock_acquired_at: null,\n lock_expires_at: null,\n saved_at: new Date().toISOString(),\n });\n}\n"],"mappings":";;;;;;;;;AAeA,MAAa,0BAA0B;;AAGvC,SAAS,eACP,WACgC;CAChC,OAAO,OAAO,cAAc;AAC9B;;;;;;;;;AAUA,SAAgB,cACd,KACA,WACS;CACT,MAAM,YAAY,IAAI,OAAO;CAE7B,IAAI,cAAc,UAAa,eAAe,SAAS,GACrD,OAAO;CAGT,MAAM,aAAa,UAAU;CAE7B,OAAO,eAAe,UAAa,aAAa;AAClD;;;;;;;;;;;;AAyBA,eAAe,kBACb,WACA,SAC2B;CAC3B,IAAI,eAAe,SAAS,GAC1B,OAAO,UAAU,OAAO;CAG1B,MAAM,OAAO,UAAU;CACvB,MAAM,oBAAoB;CAC1B,MAAM,kBAAkB,KAAK,IAAI,IAAI,QAAQ,SAAS,OAAO,CAAC;CAK9D,OAAO;EACL,SAAS;GAAE,MAAM;GAAU,SAAS,MAHZ,eAAe,WAF3B,QAAQ,MAAM,GAAG,kBAAkB,CAEO,CAAC;EAGP;EAChD;EACA;CACF;AACF;;;;;;;AAQA,eAAe,eACb,WACA,OACiB;CACjB,IAAI,MAAM,WAAW,GACnB,OAAO;CAGT,IAAI,CAAC,UAAU,YACb,OAAO,cAAc,MAAM,OAAO;CAGpC,MAAM,aAAa,MAChB,KAAK,YAAY,GAAG,QAAQ,KAAK,IAAI,iBAAiB,QAAQ,OAAO,GAAG,CAAC,CACzE,KAAK,IAAI;CAaZ,QAAO,MAXgB,UAAU,WAAW,SAAS,CACnD;EACE,MAAM;EACN,SACE;CAGJ,GACA;EAAE,MAAM;EAAQ,SAAS;CAAW,CACtC,CAAC,EAEc,CAAC;AAClB;;AAGA,SAAS,iBAAiB,SAAqC;CAC7D,IAAI,OAAO,YAAY,UACrB,OAAO;CAGT,OAAO,KAAK,UAAU,OAAO;AAC/B;;;;;;;;;;;;;;;;;;;;;;AAuBA,eAAsB,cACpB,KACA,WACA,SACwC;CACxC,MAAM,YAAY,IAAI,OAAO;CAE7B,IAAI,cAAc,QAChB;CAGF,MAAM,sBAAsB,KAAK,SAAS;CAE1C,IAAI;EACF,MAAM,aAAa,MAAM,kBAAkB,WAAW,OAAO;EAE7D,IAAI,QAAQ,KAAK,qCAAqC;GACpD;GACA;EACF,CAAC;EAED,MAAM,YAAY,eAAe,SAAS,IAAI,SAAY,UAAU;EAEpE,IAAI,CAAC,WACH,OAAO;GAAE;GAAY,SAAS;EAAM;EAGtC,IAAI;GACF,MAAM,UAAU,YAAY,EAAE,UAAU,CAAC;GAEzC,IAAI,QAAQ,KAAK,mCAAmC;IAClD;IACA;GACF,CAAC;GAED,OAAO;IAAE;IAAY,SAAS;GAAK;EACrC,SAAS,OAAO;GAGd,IAAI,QAAQ,KAAK,kCAAkC;IACjD;IACA,OAAO;IACP;GACF,CAAC;GAED,OAAO;IAAE;IAAY,SAAS;GAAM;EACtC;CACF,SAAS,OAAO;EAEd,IAAI,QAAQ,KAAK,kCAAkC;GACjD;GACA,OAAO;GACP;EACF,CAAC;EAED;CACF,UAAU;EACR,MAAM,sBAAsB,KAAK,SAAS;CAC5C;AACF;;;;;;;;;AAUA,eAAsB,oBACpB,KACA,SAC2B;CAC3B,MAAM,YAAY,IAAI,OAAO;CAE7B,IAAI,cAAc,QAGhB,OAAO;EACL,SAAS;GAAE,MAAM;GAAU,SAAS,cAAc,QAAQ,OAAO;EAAc;EAC/E,mBAAmB;EACnB,iBAAiB,KAAK,IAAI,IAAI,QAAQ,SAAS,CAAC;CAClD;CAGF,OAAO,kBAAkB,WAAW,OAAO;AAC7C;;AAGA,SAAS,mBAAmB,KAAwC;CAClE,MAAM,YAAY,IAAI,OAAO;CAE7B,IAAI,cAAc,UAAa,eAAe,SAAS,GACrD,OAAO;CAGT,OAAO,UAAU,MAAM;AACzB;;;;;;;AAQA,eAAe,sBACb,KACA,WACe;CACf,MAAM,SAAS,MAAM,IAAI,gBAAgB,KAAK,IAAI,OAAO,MAAM,SAAS;CAExE,IAAI,CAAC,QACH;CAGF,MAAM,MAAM,KAAK,IAAI;CACrB,MAAM,UAAU,mBAAmB,GAAgC;CAEnE,MAAM,IAAI,gBAAgB,KAAK;EAC7B,GAAG;EACH,kBAAkB,IAAI,KAAK,GAAG,CAAC,CAAC,YAAY;EAC5C,iBAAiB,IAAI,KAAK,MAAM,OAAO,CAAC,CAAC,YAAY;EACrD,UAAU,IAAI,KAAK,GAAG,CAAC,CAAC,YAAY;CACtC,CAAC;AACH;;;;;AAMA,eAAe,sBACb,KACA,WACe;CACf,MAAM,SAAS,MAAM,IAAI,gBAAgB,KAAK,IAAI,OAAO,MAAM,SAAS;CAExE,IAAI,CAAC,QACH;CAGF,MAAM,IAAI,gBAAgB,KAAK;EAC7B,GAAG;EACH,kBAAkB;EAClB,iBAAiB;EACjB,2BAAU,IAAI,KAAK,EAAC,CAAC,YAAY;CACnC,CAAC;AACH"}
|