@warlock.js/ai 4.2.11 → 4.4.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 +68 -1
- package/cjs/index.cjs +10155 -4626
- 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 +88 -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 +143 -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 +2 -2
- package/esm/contracts/result/supervisor-result.type.d.mts.map +1 -1
- package/esm/contracts/result/tool-call.type.d.mts +2 -2
- package/esm/contracts/result/tool-call.type.d.mts.map +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/result/workflow-result.type.d.mts +1 -1
- package/esm/contracts/result/workflow-result.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 +120 -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 @@
|
|
|
1
|
+
{"version":3,"file":"signature.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/planner/signature.ts"],"sourcesContent":["import type { PlannerCapability } from \"../contracts/planner/planner-capability.type\";\n\n/**\n * Delimiter between capability names in a planner signature. A NUL\n * control character can never appear in a real capability name, so it\n * keeps name boundaries unambiguous — a single capability literally\n * named `\"a,b\"` can never collide with the two capabilities\n * `[\"a\", \"b\"]` (a comma delimiter would render both as `caps:a,b`).\n */\nconst CAPABILITY_DELIMITER = String.fromCharCode(0);\n\n/**\n * Compute a stable structural fingerprint for a planner definition —\n * the planner name plus its ordered capability names. Stamped on every\n * report node the planner produces so trace consumers can tell runs of\n * structurally-different planners apart even when they share a name.\n *\n * Deliberately coarse: it captures WHICH capabilities the planner can\n * dispatch (and in what registration order), not their descriptions or\n * the underlying executables' internals — those don't change the set of\n * plans the planner can produce.\n */\nexport function computeSignature(name: string, capabilities: PlannerCapability[]): string {\n const capabilityNames = capabilities\n .map((capability) => capability.name)\n .join(CAPABILITY_DELIMITER);\n\n return `planner:${name}|caps:${capabilityNames}`;\n}\n"],"mappings":";;;;;;;;AASA,MAAM,uBAAuB,OAAO,aAAa,CAAC;;;;;;;;;;;;AAalD,SAAgB,iBAAiB,MAAc,cAA2C;CAKxF,OAAO,WAAW,KAAK,QAJC,aACrB,KAAK,eAAe,WAAW,IAAI,CAAC,CACpC,KAAK,oBAEqC;AAC/C"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SupervisorSnapshot } from "../contracts/supervisor/supervisor-snapshot.type.mjs";
|
|
2
|
+
import { SnapshotStore } from "../contracts/orchestrator/snapshot-store.contract.mjs";
|
|
3
|
+
|
|
4
|
+
//#region ../@warlock.js/ai/src/snapshot/memory.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Create an in-memory {@link SnapshotStore}. Zero-config — no client,
|
|
7
|
+
* no connection. Suitable for dev, tests, and single-process apps that
|
|
8
|
+
* don't need to resume an interrupted `iterate: true` turn across
|
|
9
|
+
* restarts.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* import { ai } from "@warlock.js/ai";
|
|
13
|
+
*
|
|
14
|
+
* const orchestrator = ai.orchestrator({
|
|
15
|
+
* name: "support",
|
|
16
|
+
* intents: { ... },
|
|
17
|
+
* iterate: true,
|
|
18
|
+
* snapshotStore: ai.snapshot.memory(),
|
|
19
|
+
* });
|
|
20
|
+
*/
|
|
21
|
+
declare function memory<TSnapshot extends {
|
|
22
|
+
runId: string;
|
|
23
|
+
} = SupervisorSnapshot>(): SnapshotStore<TSnapshot>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { memory };
|
|
26
|
+
//# sourceMappingURL=memory.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/snapshot/memory.ts"],"mappings":";;;;;;AAwFA;;;;;;;;;;;;;;iBAAgB,MAAA;EACM,KAAA;AAAA,IAAkB,kBAAA,KACnC,aAAA,CAAc,SAAA"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//#region ../@warlock.js/ai/src/snapshot/memory.ts
|
|
2
|
+
/**
|
|
3
|
+
* In-memory {@link SnapshotStore} — supervisor run snapshots held in a
|
|
4
|
+
* process-local `Map`, keyed by `runId`, never persisted to disk.
|
|
5
|
+
*
|
|
6
|
+
* Owns: the `runId` → {@link SupervisorSnapshot} mapping for
|
|
7
|
+
* `iterate: true` mid-turn resume. Does NOT own: durability,
|
|
8
|
+
* cross-process sharing, or TTL eviction — it is the zero-config
|
|
9
|
+
* default for dev, tests, and single-process apps. Reach for
|
|
10
|
+
* `ai.snapshot.pg()` / `ai.snapshot.redis()` (Phase 2) when a crashed
|
|
11
|
+
* process must resume an in-flight turn.
|
|
12
|
+
*
|
|
13
|
+
* Front it with the {@link memory} factory — callers never `new` it.
|
|
14
|
+
*/
|
|
15
|
+
var MemorySnapshotStore = class {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.snapshots = /* @__PURE__ */ new Map();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Return the snapshot for a `runId`, or `undefined` when no in-flight
|
|
21
|
+
* run is recorded.
|
|
22
|
+
*/
|
|
23
|
+
async load(runId) {
|
|
24
|
+
return this.snapshots.get(runId);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Persist a snapshot, keyed by its own `runId`. Overwrites any prior
|
|
28
|
+
* snapshot for the same run — a run has exactly one live snapshot.
|
|
29
|
+
*/
|
|
30
|
+
async save(snapshot) {
|
|
31
|
+
this.snapshots.set(snapshot.runId, snapshot);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Drop the snapshot for a `runId`.
|
|
35
|
+
*/
|
|
36
|
+
async delete(runId) {
|
|
37
|
+
this.snapshots.delete(runId);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* List the known run ids, optionally filtered by a prefix.
|
|
41
|
+
*/
|
|
42
|
+
async list(prefix) {
|
|
43
|
+
const runIds = [];
|
|
44
|
+
for (const runId of this.snapshots.keys()) {
|
|
45
|
+
if (prefix !== void 0 && !runId.startsWith(prefix)) continue;
|
|
46
|
+
runIds.push(runId);
|
|
47
|
+
}
|
|
48
|
+
return runIds;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The memory store has no backing table — there is nothing to
|
|
52
|
+
* migrate. Returns an empty string so callers can treat `schema()`
|
|
53
|
+
* uniformly across drivers.
|
|
54
|
+
*/
|
|
55
|
+
schema() {
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Create an in-memory {@link SnapshotStore}. Zero-config — no client,
|
|
61
|
+
* no connection. Suitable for dev, tests, and single-process apps that
|
|
62
|
+
* don't need to resume an interrupted `iterate: true` turn across
|
|
63
|
+
* restarts.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* import { ai } from "@warlock.js/ai";
|
|
67
|
+
*
|
|
68
|
+
* const orchestrator = ai.orchestrator({
|
|
69
|
+
* name: "support",
|
|
70
|
+
* intents: { ... },
|
|
71
|
+
* iterate: true,
|
|
72
|
+
* snapshotStore: ai.snapshot.memory(),
|
|
73
|
+
* });
|
|
74
|
+
*/
|
|
75
|
+
function memory() {
|
|
76
|
+
return new MemorySnapshotStore();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
//#endregion
|
|
80
|
+
export { memory };
|
|
81
|
+
//# sourceMappingURL=memory.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/snapshot/memory.ts"],"sourcesContent":["import type { SnapshotStore } from \"../contracts/orchestrator/snapshot-store.contract\";\nimport type { SupervisorSnapshot } from \"../contracts/supervisor/supervisor-snapshot.type\";\n\n/**\n * In-memory {@link SnapshotStore} — supervisor run snapshots held in a\n * process-local `Map`, keyed by `runId`, never persisted to disk.\n *\n * Owns: the `runId` → {@link SupervisorSnapshot} mapping for\n * `iterate: true` mid-turn resume. Does NOT own: durability,\n * cross-process sharing, or TTL eviction — it is the zero-config\n * default for dev, tests, and single-process apps. Reach for\n * `ai.snapshot.pg()` / `ai.snapshot.redis()` (Phase 2) when a crashed\n * process must resume an in-flight turn.\n *\n * Front it with the {@link memory} factory — callers never `new` it.\n */\nclass MemorySnapshotStore<TSnapshot extends { runId: string }>\n implements SnapshotStore<TSnapshot>\n{\n /** Snapshots keyed by `runId`. */\n private readonly snapshots = new Map<string, TSnapshot>();\n\n /**\n * Return the snapshot for a `runId`, or `undefined` when no in-flight\n * run is recorded.\n */\n public async load(runId: string): Promise<TSnapshot | undefined> {\n return this.snapshots.get(runId);\n }\n\n /**\n * Persist a snapshot, keyed by its own `runId`. Overwrites any prior\n * snapshot for the same run — a run has exactly one live snapshot.\n */\n public async save(snapshot: TSnapshot): Promise<void> {\n this.snapshots.set(snapshot.runId, snapshot);\n }\n\n /**\n * Drop the snapshot for a `runId`.\n */\n public async delete(runId: string): Promise<void> {\n this.snapshots.delete(runId);\n }\n\n /**\n * List the known run ids, optionally filtered by a prefix.\n */\n public async list(prefix?: string): Promise<string[]> {\n const runIds: string[] = [];\n\n for (const runId of this.snapshots.keys()) {\n if (prefix !== undefined && !runId.startsWith(prefix)) {\n continue;\n }\n\n runIds.push(runId);\n }\n\n return runIds;\n }\n\n /**\n * The memory store has no backing table — there is nothing to\n * migrate. Returns an empty string so callers can treat `schema()`\n * uniformly across drivers.\n */\n public schema(): string {\n return \"\";\n }\n}\n\n/**\n * Create an in-memory {@link SnapshotStore}. Zero-config — no client,\n * no connection. Suitable for dev, tests, and single-process apps that\n * don't need to resume an interrupted `iterate: true` turn across\n * restarts.\n *\n * @example\n * import { ai } from \"@warlock.js/ai\";\n *\n * const orchestrator = ai.orchestrator({\n * name: \"support\",\n * intents: { ... },\n * iterate: true,\n * snapshotStore: ai.snapshot.memory(),\n * });\n */\nexport function memory<\n TSnapshot extends { runId: string } = SupervisorSnapshot,\n>(): SnapshotStore<TSnapshot> {\n return new MemorySnapshotStore<TSnapshot>();\n}\n"],"mappings":";;;;;;;;;;;;;;AAgBA,IAAM,sBAAN,MAEA;;mCAE+B,IAAI,IAAuB;;;;;;CAMxD,MAAa,KAAK,OAA+C;EAC/D,OAAO,KAAK,UAAU,IAAI,KAAK;CACjC;;;;;CAMA,MAAa,KAAK,UAAoC;EACpD,KAAK,UAAU,IAAI,SAAS,OAAO,QAAQ;CAC7C;;;;CAKA,MAAa,OAAO,OAA8B;EAChD,KAAK,UAAU,OAAO,KAAK;CAC7B;;;;CAKA,MAAa,KAAK,QAAoC;EACpD,MAAM,SAAmB,CAAC;EAE1B,KAAK,MAAM,SAAS,KAAK,UAAU,KAAK,GAAG;GACzC,IAAI,WAAW,UAAa,CAAC,MAAM,WAAW,MAAM,GAClD;GAGF,OAAO,KAAK,KAAK;EACnB;EAEA,OAAO;CACT;;;;;;CAOA,AAAO,SAAiB;EACtB,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;AAkBA,SAAgB,SAEc;CAC5B,OAAO,IAAI,oBAA+B;AAC5C"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { PgClientLike, SnapshotStore } from "../contracts/orchestrator/snapshot-store.contract.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../@warlock.js/ai/src/snapshot/pg.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Options for {@link pg}. The `client` is an already-built `pg.Pool` /
|
|
6
|
+
* `pg.Client` (anything satisfying {@link PgClientLike}); the store never
|
|
7
|
+
* opens or closes it — connection lifecycle stays with the caller.
|
|
8
|
+
*/
|
|
9
|
+
type PgSnapshotStoreOptions = {
|
|
10
|
+
/** Pre-built pg client. The store only ever calls `query`. */client: PgClientLike; /** Table name. Defaults to `warlock_supervisor_snapshots`. */
|
|
11
|
+
table?: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Create a Postgres-backed {@link SnapshotStore}. Pass a live
|
|
15
|
+
* `pg.Pool`/`pg.Client` — the store never opens or closes it. Schema is
|
|
16
|
+
* not auto-migrated: run {@link SnapshotStore.schema} through your own
|
|
17
|
+
* migration tool first.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* import { Pool } from "pg";
|
|
21
|
+
* import { ai } from "@warlock.js/ai";
|
|
22
|
+
*
|
|
23
|
+
* const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
24
|
+
*
|
|
25
|
+
* const orchestrator = ai.orchestrator({
|
|
26
|
+
* name: "support",
|
|
27
|
+
* intents: { ... },
|
|
28
|
+
* iterate: true,
|
|
29
|
+
* snapshotStore: ai.snapshot.pg({
|
|
30
|
+
* client: pool,
|
|
31
|
+
* table: "warlock_supervisor_snapshots",
|
|
32
|
+
* }),
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // Run once, via your own migration tooling:
|
|
36
|
+
* // await pool.query(orchestrator's store.schema());
|
|
37
|
+
*/
|
|
38
|
+
declare function pg(options: PgSnapshotStoreOptions): SnapshotStore;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { PgSnapshotStoreOptions, pg };
|
|
41
|
+
//# sourceMappingURL=pg.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/snapshot/pg.ts"],"mappings":";;;;;AA2BA;;;KAAY,sBAAA;EAEV,8DAAA,MAAA,EAAQ,YAAY,EAEpB;EAAA,KAAA;AAAA;AAmLF;;;;;;;;AAAkE;;;;;;;;;;;;;;;;;AAAlE,iBAAgB,EAAA,CAAG,OAAA,EAAS,sBAAA,GAAyB,aAAa"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
//#region ../@warlock.js/ai/src/snapshot/pg.ts
|
|
2
|
+
/**
|
|
3
|
+
* Default backing table for the pg snapshot store. Matches the name used
|
|
4
|
+
* in the orchestrator.md §8 reference wiring
|
|
5
|
+
* (`ai.snapshot.pg({ client, table: "warlock_supervisor_snapshots" })`).
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_TABLE = "warlock_supervisor_snapshots";
|
|
8
|
+
/**
|
|
9
|
+
* Allowed characters in a Postgres identifier (table name). The
|
|
10
|
+
* conservative ASCII subset; anything else is rejected because the table
|
|
11
|
+
* name is interpolated directly into DDL/DML, and an arbitrary string
|
|
12
|
+
* there would be a SQL-injection footgun. Mirrors `@warlock.js/cache`'s
|
|
13
|
+
* `PgCacheDriver`.
|
|
14
|
+
*/
|
|
15
|
+
const SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
16
|
+
/**
|
|
17
|
+
* Validate and resolve the table name. Throws on an unsafe identifier so
|
|
18
|
+
* the failure surfaces at construction time, not on the first query.
|
|
19
|
+
*/
|
|
20
|
+
function resolveTable(table) {
|
|
21
|
+
const resolved = table ?? DEFAULT_TABLE;
|
|
22
|
+
if (!SAFE_IDENTIFIER.test(resolved)) throw new Error(`Pg snapshot store: invalid table name '${resolved}'. Allowed: [A-Za-z_][A-Za-z0-9_]*.`);
|
|
23
|
+
return resolved;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Coerce a `payload` column value back into a {@link SupervisorSnapshot}.
|
|
27
|
+
* node-postgres parses `JSONB` into a JS value already, but some pool
|
|
28
|
+
* wrappers hand back the raw string — be defensive across both.
|
|
29
|
+
*/
|
|
30
|
+
function parsePayload(payload) {
|
|
31
|
+
if (typeof payload === "string") return JSON.parse(payload);
|
|
32
|
+
return payload;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Postgres {@link SnapshotStore} — supervisor run snapshots persisted to a
|
|
36
|
+
* single row per `runId` in a dev-provisioned table (orchestrator.md §8).
|
|
37
|
+
*
|
|
38
|
+
* Owns: durable round-tripping of the {@link SupervisorSnapshot} envelope
|
|
39
|
+
* keyed by `runId`, so a crashed mid-turn `iterate: true` iteration can
|
|
40
|
+
* resume after a restart. Does NOT own: the connection (the caller passes
|
|
41
|
+
* a live `pg.Pool`/`pg.Client` and keeps owning its lifecycle) or schema
|
|
42
|
+
* migration ({@link PgSnapshotStore.schema} returns DDL the dev runs
|
|
43
|
+
* themselves — the framework never auto-migrates, §8.5).
|
|
44
|
+
*
|
|
45
|
+
* Unlike the append-only checkpoint store, a run has exactly one live
|
|
46
|
+
* snapshot, so `save()` upserts on the `run_id` primary key.
|
|
47
|
+
*
|
|
48
|
+
* Front it with the {@link pg} factory — callers never `new` it.
|
|
49
|
+
*/
|
|
50
|
+
var PgSnapshotStore = class {
|
|
51
|
+
constructor(options) {
|
|
52
|
+
if (!options || !options.client || typeof options.client.query !== "function") throw new Error("Pg snapshot store requires a 'client' option implementing { query(text, params) } — pass a pg.Pool or pg.Client.");
|
|
53
|
+
this.client = options.client;
|
|
54
|
+
this.table = resolveTable(options.table);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Load the snapshot for a `runId`, or `undefined` when no in-flight run
|
|
58
|
+
* is recorded.
|
|
59
|
+
*/
|
|
60
|
+
async load(runId) {
|
|
61
|
+
const { rows } = await this.client.query(`SELECT payload FROM ${this.table} WHERE run_id = $1`, [runId]);
|
|
62
|
+
if (rows.length === 0) return;
|
|
63
|
+
return parsePayload(rows[0].payload);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Persist a snapshot, keyed by its own `runId`. Upserts — a run has
|
|
67
|
+
* exactly one live snapshot, so a second save for the same `runId`
|
|
68
|
+
* overwrites the payload rather than appending.
|
|
69
|
+
*/
|
|
70
|
+
async save(snapshot) {
|
|
71
|
+
await this.client.query(`INSERT INTO ${this.table} (run_id, payload, saved_at)
|
|
72
|
+
VALUES ($1, $2::jsonb, now())
|
|
73
|
+
ON CONFLICT (run_id) DO UPDATE
|
|
74
|
+
SET payload = EXCLUDED.payload,
|
|
75
|
+
saved_at = EXCLUDED.saved_at`, [snapshot.runId, JSON.stringify(snapshot)]);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Drop the snapshot for a `runId`.
|
|
79
|
+
*/
|
|
80
|
+
async delete(runId) {
|
|
81
|
+
await this.client.query(`DELETE FROM ${this.table} WHERE run_id = $1`, [runId]);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* List the known run ids, optionally filtered by a prefix. The `_` and
|
|
85
|
+
* `%` LIKE wildcards in the prefix are escaped so an opaque runId that
|
|
86
|
+
* happens to contain them is matched literally.
|
|
87
|
+
*/
|
|
88
|
+
async list(prefix) {
|
|
89
|
+
if (prefix === void 0) {
|
|
90
|
+
const { rows } = await this.client.query(`SELECT run_id FROM ${this.table}`);
|
|
91
|
+
return rows.map((row) => row.run_id);
|
|
92
|
+
}
|
|
93
|
+
const escaped = prefix.replace(/\\/g, "\\\\").replace(/_/g, "\\_").replace(/%/g, "\\%");
|
|
94
|
+
const { rows } = await this.client.query(`SELECT run_id FROM ${this.table} WHERE run_id LIKE $1 ESCAPE '\\'`, [`${escaped}%`]);
|
|
95
|
+
return rows.map((row) => row.run_id);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Return the DDL for this store's backing table. Run once via the
|
|
99
|
+
* caller's migration tooling — the store never auto-migrates (§8.5).
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* await pool.query(store.schema());
|
|
103
|
+
*/
|
|
104
|
+
schema() {
|
|
105
|
+
return [
|
|
106
|
+
`CREATE TABLE IF NOT EXISTS ${this.table} (`,
|
|
107
|
+
` run_id TEXT PRIMARY KEY,`,
|
|
108
|
+
` payload JSONB NOT NULL,`,
|
|
109
|
+
` saved_at TIMESTAMPTZ NOT NULL DEFAULT now()`,
|
|
110
|
+
`);`,
|
|
111
|
+
`CREATE INDEX IF NOT EXISTS idx_${this.table}_saved_at ON ${this.table} (saved_at);`
|
|
112
|
+
].join("\n");
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Create a Postgres-backed {@link SnapshotStore}. Pass a live
|
|
117
|
+
* `pg.Pool`/`pg.Client` — the store never opens or closes it. Schema is
|
|
118
|
+
* not auto-migrated: run {@link SnapshotStore.schema} through your own
|
|
119
|
+
* migration tool first.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* import { Pool } from "pg";
|
|
123
|
+
* import { ai } from "@warlock.js/ai";
|
|
124
|
+
*
|
|
125
|
+
* const pool = new Pool({ connectionString: process.env.DATABASE_URL });
|
|
126
|
+
*
|
|
127
|
+
* const orchestrator = ai.orchestrator({
|
|
128
|
+
* name: "support",
|
|
129
|
+
* intents: { ... },
|
|
130
|
+
* iterate: true,
|
|
131
|
+
* snapshotStore: ai.snapshot.pg({
|
|
132
|
+
* client: pool,
|
|
133
|
+
* table: "warlock_supervisor_snapshots",
|
|
134
|
+
* }),
|
|
135
|
+
* });
|
|
136
|
+
*
|
|
137
|
+
* // Run once, via your own migration tooling:
|
|
138
|
+
* // await pool.query(orchestrator's store.schema());
|
|
139
|
+
*/
|
|
140
|
+
function pg(options) {
|
|
141
|
+
return new PgSnapshotStore(options);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
//#endregion
|
|
145
|
+
export { pg };
|
|
146
|
+
//# sourceMappingURL=pg.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pg.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/snapshot/pg.ts"],"sourcesContent":["import type {\n PgClientLike,\n SnapshotStore,\n} from \"../contracts/orchestrator/snapshot-store.contract\";\nimport type { SupervisorSnapshot } from \"../contracts/supervisor/supervisor-snapshot.type\";\n\n/**\n * Default backing table for the pg snapshot store. Matches the name used\n * in the orchestrator.md §8 reference wiring\n * (`ai.snapshot.pg({ client, table: \"warlock_supervisor_snapshots\" })`).\n */\nconst DEFAULT_TABLE = \"warlock_supervisor_snapshots\";\n\n/**\n * Allowed characters in a Postgres identifier (table name). The\n * conservative ASCII subset; anything else is rejected because the table\n * name is interpolated directly into DDL/DML, and an arbitrary string\n * there would be a SQL-injection footgun. Mirrors `@warlock.js/cache`'s\n * `PgCacheDriver`.\n */\nconst SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/**\n * Options for {@link pg}. The `client` is an already-built `pg.Pool` /\n * `pg.Client` (anything satisfying {@link PgClientLike}); the store never\n * opens or closes it — connection lifecycle stays with the caller.\n */\nexport type PgSnapshotStoreOptions = {\n /** Pre-built pg client. The store only ever calls `query`. */\n client: PgClientLike;\n /** Table name. Defaults to `warlock_supervisor_snapshots`. */\n table?: string;\n};\n\n/**\n * Validate and resolve the table name. Throws on an unsafe identifier so\n * the failure surfaces at construction time, not on the first query.\n */\nfunction resolveTable(table: string | undefined): string {\n const resolved = table ?? DEFAULT_TABLE;\n\n if (!SAFE_IDENTIFIER.test(resolved)) {\n throw new Error(\n `Pg snapshot store: invalid table name '${resolved}'. Allowed: [A-Za-z_][A-Za-z0-9_]*.`,\n );\n }\n\n return resolved;\n}\n\n/**\n * Coerce a `payload` column value back into a {@link SupervisorSnapshot}.\n * node-postgres parses `JSONB` into a JS value already, but some pool\n * wrappers hand back the raw string — be defensive across both.\n */\nfunction parsePayload(payload: unknown): SupervisorSnapshot {\n if (typeof payload === \"string\") {\n return JSON.parse(payload) as SupervisorSnapshot;\n }\n\n return payload as SupervisorSnapshot;\n}\n\n/**\n * Postgres {@link SnapshotStore} — supervisor run snapshots persisted to a\n * single row per `runId` in a dev-provisioned table (orchestrator.md §8).\n *\n * Owns: durable round-tripping of the {@link SupervisorSnapshot} envelope\n * keyed by `runId`, so a crashed mid-turn `iterate: true` iteration can\n * resume after a restart. Does NOT own: the connection (the caller passes\n * a live `pg.Pool`/`pg.Client` and keeps owning its lifecycle) or schema\n * migration ({@link PgSnapshotStore.schema} returns DDL the dev runs\n * themselves — the framework never auto-migrates, §8.5).\n *\n * Unlike the append-only checkpoint store, a run has exactly one live\n * snapshot, so `save()` upserts on the `run_id` primary key.\n *\n * Front it with the {@link pg} factory — callers never `new` it.\n */\nclass PgSnapshotStore implements SnapshotStore {\n /** The user-supplied pg client. The store only ever calls `query`. */\n private readonly client: PgClientLike;\n\n /** Validated, resolved table name. Safe to interpolate into SQL. */\n private readonly table: string;\n\n public constructor(options: PgSnapshotStoreOptions) {\n if (!options || !options.client || typeof options.client.query !== \"function\") {\n throw new Error(\n \"Pg snapshot store requires a 'client' option implementing { query(text, params) } — pass a pg.Pool or pg.Client.\",\n );\n }\n\n this.client = options.client;\n this.table = resolveTable(options.table);\n }\n\n /**\n * Load the snapshot for a `runId`, or `undefined` when no in-flight run\n * is recorded.\n */\n public async load(runId: string): Promise<SupervisorSnapshot | undefined> {\n const { rows } = await this.client.query(\n `SELECT payload FROM ${this.table} WHERE run_id = $1`,\n [runId],\n );\n\n if (rows.length === 0) {\n return undefined;\n }\n\n return parsePayload((rows[0] as { payload: unknown }).payload);\n }\n\n /**\n * Persist a snapshot, keyed by its own `runId`. Upserts — a run has\n * exactly one live snapshot, so a second save for the same `runId`\n * overwrites the payload rather than appending.\n */\n public async save(snapshot: SupervisorSnapshot): Promise<void> {\n await this.client.query(\n `INSERT INTO ${this.table} (run_id, payload, saved_at)\n VALUES ($1, $2::jsonb, now())\n ON CONFLICT (run_id) DO UPDATE\n SET payload = EXCLUDED.payload,\n saved_at = EXCLUDED.saved_at`,\n [snapshot.runId, JSON.stringify(snapshot)],\n );\n }\n\n /**\n * Drop the snapshot for a `runId`.\n */\n public async delete(runId: string): Promise<void> {\n await this.client.query(`DELETE FROM ${this.table} WHERE run_id = $1`, [\n runId,\n ]);\n }\n\n /**\n * List the known run ids, optionally filtered by a prefix. The `_` and\n * `%` LIKE wildcards in the prefix are escaped so an opaque runId that\n * happens to contain them is matched literally.\n */\n public async list(prefix?: string): Promise<string[]> {\n if (prefix === undefined) {\n const { rows } = await this.client.query(\n `SELECT run_id FROM ${this.table}`,\n );\n\n return rows.map((row) => (row as { run_id: string }).run_id);\n }\n\n const escaped = prefix\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/_/g, \"\\\\_\")\n .replace(/%/g, \"\\\\%\");\n\n const { rows } = await this.client.query(\n `SELECT run_id FROM ${this.table} WHERE run_id LIKE $1 ESCAPE '\\\\'`,\n [`${escaped}%`],\n );\n\n return rows.map((row) => (row as { run_id: string }).run_id);\n }\n\n /**\n * Return the DDL for this store's backing table. Run once via the\n * caller's migration tooling — the store never auto-migrates (§8.5).\n *\n * @example\n * await pool.query(store.schema());\n */\n public schema(): string {\n return [\n `CREATE TABLE IF NOT EXISTS ${this.table} (`,\n ` run_id TEXT PRIMARY KEY,`,\n ` payload JSONB NOT NULL,`,\n ` saved_at TIMESTAMPTZ NOT NULL DEFAULT now()`,\n `);`,\n `CREATE INDEX IF NOT EXISTS idx_${this.table}_saved_at ON ${this.table} (saved_at);`,\n ].join(\"\\n\");\n }\n}\n\n/**\n * Create a Postgres-backed {@link SnapshotStore}. Pass a live\n * `pg.Pool`/`pg.Client` — the store never opens or closes it. Schema is\n * not auto-migrated: run {@link SnapshotStore.schema} through your own\n * migration tool first.\n *\n * @example\n * import { Pool } from \"pg\";\n * import { ai } from \"@warlock.js/ai\";\n *\n * const pool = new Pool({ connectionString: process.env.DATABASE_URL });\n *\n * const orchestrator = ai.orchestrator({\n * name: \"support\",\n * intents: { ... },\n * iterate: true,\n * snapshotStore: ai.snapshot.pg({\n * client: pool,\n * table: \"warlock_supervisor_snapshots\",\n * }),\n * });\n *\n * // Run once, via your own migration tooling:\n * // await pool.query(orchestrator's store.schema());\n */\nexport function pg(options: PgSnapshotStoreOptions): SnapshotStore {\n return new PgSnapshotStore(options);\n}\n"],"mappings":";;;;;;AAWA,MAAM,gBAAgB;;;;;;;;AAStB,MAAM,kBAAkB;;;;;AAkBxB,SAAS,aAAa,OAAmC;CACvD,MAAM,WAAW,SAAS;CAE1B,IAAI,CAAC,gBAAgB,KAAK,QAAQ,GAChC,MAAM,IAAI,MACR,0CAA0C,SAAS,oCACrD;CAGF,OAAO;AACT;;;;;;AAOA,SAAS,aAAa,SAAsC;CAC1D,IAAI,OAAO,YAAY,UACrB,OAAO,KAAK,MAAM,OAAO;CAG3B,OAAO;AACT;;;;;;;;;;;;;;;;;AAkBA,IAAM,kBAAN,MAA+C;CAO7C,AAAO,YAAY,SAAiC;EAClD,IAAI,CAAC,WAAW,CAAC,QAAQ,UAAU,OAAO,QAAQ,OAAO,UAAU,YACjE,MAAM,IAAI,MACR,kHACF;EAGF,KAAK,SAAS,QAAQ;EACtB,KAAK,QAAQ,aAAa,QAAQ,KAAK;CACzC;;;;;CAMA,MAAa,KAAK,OAAwD;EACxE,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,MACjC,uBAAuB,KAAK,MAAM,qBAClC,CAAC,KAAK,CACR;EAEA,IAAI,KAAK,WAAW,GAClB;EAGF,OAAO,aAAc,KAAK,EAAE,CAA0B,OAAO;CAC/D;;;;;;CAOA,MAAa,KAAK,UAA6C;EAC7D,MAAM,KAAK,OAAO,MAChB,eAAe,KAAK,MAAM;;;;4CAK1B,CAAC,SAAS,OAAO,KAAK,UAAU,QAAQ,CAAC,CAC3C;CACF;;;;CAKA,MAAa,OAAO,OAA8B;EAChD,MAAM,KAAK,OAAO,MAAM,eAAe,KAAK,MAAM,qBAAqB,CACrE,KACF,CAAC;CACH;;;;;;CAOA,MAAa,KAAK,QAAoC;EACpD,IAAI,WAAW,QAAW;GACxB,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,MACjC,sBAAsB,KAAK,OAC7B;GAEA,OAAO,KAAK,KAAK,QAAS,IAA2B,MAAM;EAC7D;EAEA,MAAM,UAAU,OACb,QAAQ,OAAO,MAAM,CAAC,CACtB,QAAQ,MAAM,KAAK,CAAC,CACpB,QAAQ,MAAM,KAAK;EAEtB,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,MACjC,sBAAsB,KAAK,MAAM,oCACjC,CAAC,GAAG,QAAQ,EAAE,CAChB;EAEA,OAAO,KAAK,KAAK,QAAS,IAA2B,MAAM;CAC7D;;;;;;;;CASA,AAAO,SAAiB;EACtB,OAAO;GACL,8BAA8B,KAAK,MAAM;GACzC;GACA;GACA;GACA;GACA,kCAAkC,KAAK,MAAM,eAAe,KAAK,MAAM;EACzE,CAAC,CAAC,KAAK,IAAI;CACb;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,GAAG,SAAgD;CACjE,OAAO,IAAI,gBAAgB,OAAO;AACpC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { RedisClientLike, SnapshotStore } from "../contracts/orchestrator/snapshot-store.contract.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../@warlock.js/ai/src/snapshot/redis.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Options for {@link redis}. The `client` is an already-connected redis
|
|
6
|
+
* client (anything satisfying {@link RedisClientLike}); the store never
|
|
7
|
+
* connects or quits it — connection lifecycle stays with the caller.
|
|
8
|
+
*/
|
|
9
|
+
type RedisSnapshotStoreOptions = {
|
|
10
|
+
/** Pre-connected redis client. The store only calls `get`/`set`/`del`. */client: RedisClientLike;
|
|
11
|
+
/**
|
|
12
|
+
* Key prefix prepended to each `runId`. Defaults to
|
|
13
|
+
* `warlock:supervisor:snapshot:`.
|
|
14
|
+
*/
|
|
15
|
+
prefix?: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Create a Redis-backed {@link SnapshotStore}. Pass a connected redis
|
|
19
|
+
* client — the store never connects or quits it.
|
|
20
|
+
*
|
|
21
|
+
* Note: this store does not implement the optional `list()` — the
|
|
22
|
+
* structural client surface has no `SCAN`/`KEYS`. Use a checkpoint store
|
|
23
|
+
* for the production boot-drain loop where enumeration is needed.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* import { createClient } from "redis";
|
|
27
|
+
* import { ai } from "@warlock.js/ai";
|
|
28
|
+
*
|
|
29
|
+
* const client = createClient({ url: process.env.REDIS_URL });
|
|
30
|
+
* await client.connect();
|
|
31
|
+
*
|
|
32
|
+
* const orchestrator = ai.orchestrator({
|
|
33
|
+
* name: "support",
|
|
34
|
+
* intents: { ... },
|
|
35
|
+
* iterate: true,
|
|
36
|
+
* snapshotStore: ai.snapshot.redis({ client }),
|
|
37
|
+
* });
|
|
38
|
+
*/
|
|
39
|
+
declare function redis(options: RedisSnapshotStoreOptions): SnapshotStore;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { RedisSnapshotStoreOptions, redis };
|
|
42
|
+
//# sourceMappingURL=redis.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/snapshot/redis.ts"],"mappings":";;;;;AAkBA;;;KAAY,yBAAA;EAEV,0EAAA,MAAA,EAAQ,eAAe;EAKvB;;AAAM;AAqHR;EArHE,MAAA;AAAA;;;;;;AAqHsE;;;;;;;;;;;;;;;;;iBAAxD,KAAA,CAAM,OAAA,EAAS,yBAAA,GAA4B,aAAa"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
//#region ../@warlock.js/ai/src/snapshot/redis.ts
|
|
2
|
+
/**
|
|
3
|
+
* Default key prefix the redis store prepends to each `runId`. Namespaces
|
|
4
|
+
* the snapshot keys so they coexist with other data in the same Redis
|
|
5
|
+
* database without collision.
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_PREFIX = "warlock:supervisor:snapshot:";
|
|
8
|
+
/**
|
|
9
|
+
* Redis {@link SnapshotStore} — supervisor run snapshots persisted as one
|
|
10
|
+
* JSON string value per `runId`, under a namespaced key (orchestrator.md
|
|
11
|
+
* §8).
|
|
12
|
+
*
|
|
13
|
+
* Owns: durable round-tripping of the {@link SupervisorSnapshot} envelope
|
|
14
|
+
* keyed by `runId`, so a crashed mid-turn `iterate: true` iteration can
|
|
15
|
+
* resume after a restart. Does NOT own: the connection (the caller passes
|
|
16
|
+
* a live client and keeps owning its lifecycle) or enumeration — the
|
|
17
|
+
* structural {@link RedisClientLike} surface exposes only `get`/`set`/
|
|
18
|
+
* `del`, with no `SCAN`/`KEYS`, so `list()` is intentionally not
|
|
19
|
+
* implemented (the contract allows stores that can't enumerate to omit
|
|
20
|
+
* it). Pair it with a {@link import("../contracts/orchestrator/checkpoint-store.contract").CheckpointStore}
|
|
21
|
+
* for the boot-drain loop, which is where enumeration is actually needed.
|
|
22
|
+
*
|
|
23
|
+
* `save()` overwrites the key — a run has exactly one live snapshot.
|
|
24
|
+
* Redis needs no schema, so {@link RedisSnapshotStore.schema} returns an
|
|
25
|
+
* empty string for uniformity with the other drivers.
|
|
26
|
+
*
|
|
27
|
+
* Front it with the {@link redis} factory — callers never `new` it.
|
|
28
|
+
*/
|
|
29
|
+
var RedisSnapshotStore = class {
|
|
30
|
+
constructor(options) {
|
|
31
|
+
if (!options || !options.client || typeof options.client.get !== "function" || typeof options.client.set !== "function" || typeof options.client.del !== "function") throw new Error("Redis snapshot store requires a 'client' option implementing { get, set, del } — pass a connected redis client.");
|
|
32
|
+
this.client = options.client;
|
|
33
|
+
this.prefix = options.prefix ?? DEFAULT_PREFIX;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build the namespaced Redis key for a `runId`.
|
|
37
|
+
*/
|
|
38
|
+
key(runId) {
|
|
39
|
+
return `${this.prefix}${runId}`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Load the snapshot for a `runId`, or `undefined` when the key is
|
|
43
|
+
* missing. Redis returns `null` for an absent key — converted to
|
|
44
|
+
* `undefined` at the boundary.
|
|
45
|
+
*/
|
|
46
|
+
async load(runId) {
|
|
47
|
+
const value = await this.client.get(this.key(runId));
|
|
48
|
+
if (value === null) return;
|
|
49
|
+
return JSON.parse(value);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Persist a snapshot, keyed by its own `runId`. Overwrites any prior
|
|
53
|
+
* snapshot for the same run — a run has exactly one live snapshot.
|
|
54
|
+
*/
|
|
55
|
+
async save(snapshot) {
|
|
56
|
+
await this.client.set(this.key(snapshot.runId), JSON.stringify(snapshot));
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Drop the snapshot for a `runId`.
|
|
60
|
+
*/
|
|
61
|
+
async delete(runId) {
|
|
62
|
+
await this.client.del(this.key(runId));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Redis needs no backing table — there is nothing to migrate. Returns
|
|
66
|
+
* an empty string so callers can treat `schema()` uniformly across
|
|
67
|
+
* drivers.
|
|
68
|
+
*/
|
|
69
|
+
schema() {
|
|
70
|
+
return "";
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Create a Redis-backed {@link SnapshotStore}. Pass a connected redis
|
|
75
|
+
* client — the store never connects or quits it.
|
|
76
|
+
*
|
|
77
|
+
* Note: this store does not implement the optional `list()` — the
|
|
78
|
+
* structural client surface has no `SCAN`/`KEYS`. Use a checkpoint store
|
|
79
|
+
* for the production boot-drain loop where enumeration is needed.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* import { createClient } from "redis";
|
|
83
|
+
* import { ai } from "@warlock.js/ai";
|
|
84
|
+
*
|
|
85
|
+
* const client = createClient({ url: process.env.REDIS_URL });
|
|
86
|
+
* await client.connect();
|
|
87
|
+
*
|
|
88
|
+
* const orchestrator = ai.orchestrator({
|
|
89
|
+
* name: "support",
|
|
90
|
+
* intents: { ... },
|
|
91
|
+
* iterate: true,
|
|
92
|
+
* snapshotStore: ai.snapshot.redis({ client }),
|
|
93
|
+
* });
|
|
94
|
+
*/
|
|
95
|
+
function redis(options) {
|
|
96
|
+
return new RedisSnapshotStore(options);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
//#endregion
|
|
100
|
+
export { redis };
|
|
101
|
+
//# sourceMappingURL=redis.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/snapshot/redis.ts"],"sourcesContent":["import type {\n RedisClientLike,\n SnapshotStore,\n} from \"../contracts/orchestrator/snapshot-store.contract\";\nimport type { SupervisorSnapshot } from \"../contracts/supervisor/supervisor-snapshot.type\";\n\n/**\n * Default key prefix the redis store prepends to each `runId`. Namespaces\n * the snapshot keys so they coexist with other data in the same Redis\n * database without collision.\n */\nconst DEFAULT_PREFIX = \"warlock:supervisor:snapshot:\";\n\n/**\n * Options for {@link redis}. The `client` is an already-connected redis\n * client (anything satisfying {@link RedisClientLike}); the store never\n * connects or quits it — connection lifecycle stays with the caller.\n */\nexport type RedisSnapshotStoreOptions = {\n /** Pre-connected redis client. The store only calls `get`/`set`/`del`. */\n client: RedisClientLike;\n /**\n * Key prefix prepended to each `runId`. Defaults to\n * `warlock:supervisor:snapshot:`.\n */\n prefix?: string;\n};\n\n/**\n * Redis {@link SnapshotStore} — supervisor run snapshots persisted as one\n * JSON string value per `runId`, under a namespaced key (orchestrator.md\n * §8).\n *\n * Owns: durable round-tripping of the {@link SupervisorSnapshot} envelope\n * keyed by `runId`, so a crashed mid-turn `iterate: true` iteration can\n * resume after a restart. Does NOT own: the connection (the caller passes\n * a live client and keeps owning its lifecycle) or enumeration — the\n * structural {@link RedisClientLike} surface exposes only `get`/`set`/\n * `del`, with no `SCAN`/`KEYS`, so `list()` is intentionally not\n * implemented (the contract allows stores that can't enumerate to omit\n * it). Pair it with a {@link import(\"../contracts/orchestrator/checkpoint-store.contract\").CheckpointStore}\n * for the boot-drain loop, which is where enumeration is actually needed.\n *\n * `save()` overwrites the key — a run has exactly one live snapshot.\n * Redis needs no schema, so {@link RedisSnapshotStore.schema} returns an\n * empty string for uniformity with the other drivers.\n *\n * Front it with the {@link redis} factory — callers never `new` it.\n */\nclass RedisSnapshotStore implements SnapshotStore {\n /** The user-supplied redis client. Only `get`/`set`/`del` are called. */\n private readonly client: RedisClientLike;\n\n /** Key prefix prepended to each `runId`. */\n private readonly prefix: string;\n\n public constructor(options: RedisSnapshotStoreOptions) {\n if (\n !options ||\n !options.client ||\n typeof options.client.get !== \"function\" ||\n typeof options.client.set !== \"function\" ||\n typeof options.client.del !== \"function\"\n ) {\n throw new Error(\n \"Redis snapshot store requires a 'client' option implementing { get, set, del } — pass a connected redis client.\",\n );\n }\n\n this.client = options.client;\n this.prefix = options.prefix ?? DEFAULT_PREFIX;\n }\n\n /**\n * Build the namespaced Redis key for a `runId`.\n */\n private key(runId: string): string {\n return `${this.prefix}${runId}`;\n }\n\n /**\n * Load the snapshot for a `runId`, or `undefined` when the key is\n * missing. Redis returns `null` for an absent key — converted to\n * `undefined` at the boundary.\n */\n public async load(runId: string): Promise<SupervisorSnapshot | undefined> {\n const value = await this.client.get(this.key(runId));\n\n if (value === null) {\n return undefined;\n }\n\n return JSON.parse(value) as SupervisorSnapshot;\n }\n\n /**\n * Persist a snapshot, keyed by its own `runId`. Overwrites any prior\n * snapshot for the same run — a run has exactly one live snapshot.\n */\n public async save(snapshot: SupervisorSnapshot): Promise<void> {\n await this.client.set(this.key(snapshot.runId), JSON.stringify(snapshot));\n }\n\n /**\n * Drop the snapshot for a `runId`.\n */\n public async delete(runId: string): Promise<void> {\n await this.client.del(this.key(runId));\n }\n\n /**\n * Redis needs no backing table — there is nothing to migrate. Returns\n * an empty string so callers can treat `schema()` uniformly across\n * drivers.\n */\n public schema(): string {\n return \"\";\n }\n}\n\n/**\n * Create a Redis-backed {@link SnapshotStore}. Pass a connected redis\n * client — the store never connects or quits it.\n *\n * Note: this store does not implement the optional `list()` — the\n * structural client surface has no `SCAN`/`KEYS`. Use a checkpoint store\n * for the production boot-drain loop where enumeration is needed.\n *\n * @example\n * import { createClient } from \"redis\";\n * import { ai } from \"@warlock.js/ai\";\n *\n * const client = createClient({ url: process.env.REDIS_URL });\n * await client.connect();\n *\n * const orchestrator = ai.orchestrator({\n * name: \"support\",\n * intents: { ... },\n * iterate: true,\n * snapshotStore: ai.snapshot.redis({ client }),\n * });\n */\nexport function redis(options: RedisSnapshotStoreOptions): SnapshotStore {\n return new RedisSnapshotStore(options);\n}\n"],"mappings":";;;;;;AAWA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;AAsCvB,IAAM,qBAAN,MAAkD;CAOhD,AAAO,YAAY,SAAoC;EACrD,IACE,CAAC,WACD,CAAC,QAAQ,UACT,OAAO,QAAQ,OAAO,QAAQ,cAC9B,OAAO,QAAQ,OAAO,QAAQ,cAC9B,OAAO,QAAQ,OAAO,QAAQ,YAE9B,MAAM,IAAI,MACR,iHACF;EAGF,KAAK,SAAS,QAAQ;EACtB,KAAK,SAAS,QAAQ,UAAU;CAClC;;;;CAKA,AAAQ,IAAI,OAAuB;EACjC,OAAO,GAAG,KAAK,SAAS;CAC1B;;;;;;CAOA,MAAa,KAAK,OAAwD;EACxE,MAAM,QAAQ,MAAM,KAAK,OAAO,IAAI,KAAK,IAAI,KAAK,CAAC;EAEnD,IAAI,UAAU,MACZ;EAGF,OAAO,KAAK,MAAM,KAAK;CACzB;;;;;CAMA,MAAa,KAAK,UAA6C;EAC7D,MAAM,KAAK,OAAO,IAAI,KAAK,IAAI,SAAS,KAAK,GAAG,KAAK,UAAU,QAAQ,CAAC;CAC1E;;;;CAKA,MAAa,OAAO,OAA8B;EAChD,MAAM,KAAK,OAAO,IAAI,KAAK,IAAI,KAAK,CAAC;CACvC;;;;;;CAOA,AAAO,SAAiB;EACtB,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,MAAM,SAAmD;CACvE,OAAO,IAAI,mBAAmB,OAAO;AACvC"}
|
|
@@ -24,12 +24,6 @@ import { SupervisorAsToolOptions, SupervisorContract } from "../contracts/superv
|
|
|
24
24
|
* agent sees one uniform error class regardless of which
|
|
25
25
|
* primitive failed.
|
|
26
26
|
*
|
|
27
|
-
* **Usage caveat** (mirrors workflow-as-tool): nested usage is not
|
|
28
|
-
* rolled into the outer agent's `result.usage` today — the
|
|
29
|
-
* supervisor's tokens stay on the supervisor result. Sum manually
|
|
30
|
-
* if you need a combined cost number until nested-usage
|
|
31
|
-
* standardization lands.
|
|
32
|
-
*
|
|
33
27
|
* @example
|
|
34
28
|
* const support = ai.supervisor({ ... });
|
|
35
29
|
* const supportTool = support.asTool({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"as-tool.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/supervisor/as-tool.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"as-tool.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/supervisor/as-tool.ts"],"mappings":";;;;;;AAsCA;;;;;;;;;;;;;;;;;;;;;;;;AAGmC;;;;;iBAHnB,MAAA,sBACd,kBAAA,EAAoB,kBAAA,CAAmB,OAAA,GACvC,OAAA,EAAS,uBAAA,CAAwB,UAAA,IAChC,YAAA,CAAa,UAAA,EAAY,OAAA"}
|
|
@@ -25,12 +25,6 @@ import { compositeAsTool } from "../tool/tool.mjs";
|
|
|
25
25
|
* agent sees one uniform error class regardless of which
|
|
26
26
|
* primitive failed.
|
|
27
27
|
*
|
|
28
|
-
* **Usage caveat** (mirrors workflow-as-tool): nested usage is not
|
|
29
|
-
* rolled into the outer agent's `result.usage` today — the
|
|
30
|
-
* supervisor's tokens stay on the supervisor result. Sum manually
|
|
31
|
-
* if you need a combined cost number until nested-usage
|
|
32
|
-
* standardization lands.
|
|
33
|
-
*
|
|
34
28
|
* @example
|
|
35
29
|
* const support = ai.supervisor({ ... });
|
|
36
30
|
* const supportTool = support.asTool({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"as-tool.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/supervisor/as-tool.ts"],"sourcesContent":["import type {\n SupervisorAsToolOptions,\n SupervisorContract,\n} from \"../contracts/supervisor/supervisor.contract\";\nimport { SupervisorFailedError } from \"../errors\";\nimport { compositeAsTool, type ToolContract } from \"../tool/tool\";\n\n/**\n * Wrap a `SupervisorContract` as a `ToolContract` so an outer agent\n * can invoke it from its tool-call loop. Mirrors\n * `workflow.asTool()` / `agent.asTool()` — same composition pattern,\n * same error-normalization behavior.\n *\n * Behavior:\n * - The tool's `name` mirrors the supervisor's `name` unless the\n * caller overrides via `options.name`. Supervisors without a\n * meaningful name throw `SupervisorFailedError` — an outer agent\n * can't route to an anonymous tool.\n * - Tool `input` is the supplied schema; the validated value is\n * coerced to a string (via `String()` for non-string values, or\n * `JSON.stringify()` for objects) before being forwarded to\n * `supervisor.execute(input)`. Consumers whose inputs need\n * richer shaping should pre-format the string themselves.\n * - On `result.error`, the supervisor error is thrown so the tool\n * wrapper catches it and produces a `ToolExecutionError` with\n * `cause` set to the original typed supervisor error — the outer\n * agent sees one uniform error class regardless of which\n * primitive failed.\n *\n *
|
|
1
|
+
{"version":3,"file":"as-tool.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/supervisor/as-tool.ts"],"sourcesContent":["import type {\n SupervisorAsToolOptions,\n SupervisorContract,\n} from \"../contracts/supervisor/supervisor.contract\";\nimport { SupervisorFailedError } from \"../errors\";\nimport { compositeAsTool, type ToolContract } from \"../tool/tool\";\n\n/**\n * Wrap a `SupervisorContract` as a `ToolContract` so an outer agent\n * can invoke it from its tool-call loop. Mirrors\n * `workflow.asTool()` / `agent.asTool()` — same composition pattern,\n * same error-normalization behavior.\n *\n * Behavior:\n * - The tool's `name` mirrors the supervisor's `name` unless the\n * caller overrides via `options.name`. Supervisors without a\n * meaningful name throw `SupervisorFailedError` — an outer agent\n * can't route to an anonymous tool.\n * - Tool `input` is the supplied schema; the validated value is\n * coerced to a string (via `String()` for non-string values, or\n * `JSON.stringify()` for objects) before being forwarded to\n * `supervisor.execute(input)`. Consumers whose inputs need\n * richer shaping should pre-format the string themselves.\n * - On `result.error`, the supervisor error is thrown so the tool\n * wrapper catches it and produces a `ToolExecutionError` with\n * `cause` set to the original typed supervisor error — the outer\n * agent sees one uniform error class regardless of which\n * primitive failed.\n *\n * @example\n * const support = ai.supervisor({ ... });\n * const supportTool = support.asTool({\n * name: \"handle_support_ticket\",\n * description: \"Process a customer support ticket end-to-end.\",\n * inputSchema: z.object({ ticket: z.string() }),\n * });\n * const concierge = ai.agent({ model, tools: [supportTool] });\n */\nexport function asTool<TOutput, TToolInput>(\n supervisorInstance: SupervisorContract<TOutput>,\n options: SupervisorAsToolOptions<TToolInput>,\n): ToolContract<TToolInput, TOutput> {\n if (!supervisorInstance.name || typeof supervisorInstance.name !== \"string\") {\n throw new SupervisorFailedError(\n \"supervisor.asTool(): supervisor must have a `name` to be wrapped as a tool\",\n );\n }\n\n return compositeAsTool<TToolInput, TOutput>({\n name: options.name ?? supervisorInstance.name,\n description: options.description ?? `Invoke supervisor \"${supervisorInstance.name}\" as a tool.`,\n input: options.inputSchema,\n execute: async (input) => {\n const coerced = coerceInput(input);\n const result = await supervisorInstance.execute(coerced);\n\n if (result.error) {\n // Surface the typed supervisor 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 * Coerce a tool-input value into the `string` shape supervisor\n * `execute()` expects. Strings pass through; everything else gets\n * JSON-stringified so supervisors invoked via tool wrappers receive a\n * predictable textual input regardless of how the outer agent shaped\n * its call.\n */\nfunction coerceInput(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (value === undefined || value === null) {\n return \"\";\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,OACd,oBACA,SACmC;CACnC,IAAI,CAAC,mBAAmB,QAAQ,OAAO,mBAAmB,SAAS,UACjE,MAAM,IAAI,sBACR,4EACF;CAGF,OAAO,gBAAqC;EAC1C,MAAM,QAAQ,QAAQ,mBAAmB;EACzC,aAAa,QAAQ,eAAe,sBAAsB,mBAAmB,KAAK;EAClF,OAAO,QAAQ;EACf,SAAS,OAAO,UAAU;GACxB,MAAM,UAAU,YAAY,KAAK;GACjC,MAAM,SAAS,MAAM,mBAAmB,QAAQ,OAAO;GAEvD,IAAI,OAAO,OAGT,MAAM,OAAO;GAGf,OAAO;IACL,MAAM,OAAO;IACb,OAAO,OAAO;IACd,QAAQ,OAAO;GACjB;EACF;CACF,CAAC;AACH;;;;;;;;AASA,SAAS,YAAY,OAAwB;CAC3C,IAAI,OAAO,UAAU,UACnB,OAAO;CAGT,IAAI,UAAU,UAAa,UAAU,MACnC,OAAO;CAGT,IAAI;EACF,OAAO,KAAK,UAAU,KAAK;CAC7B,QAAQ;EACN,OAAO,OAAO,KAAK;CACrB;AACF"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { SupervisorInput } from "../contracts/supervisor/supervisor-input.type.mjs";
|
|
2
|
-
import { SupervisorConfig } from "../contracts/supervisor/supervisor-config.type.mjs";
|
|
3
|
-
import { SupervisorExecuteOptions } from "../contracts/supervisor/supervisor-execute-options.type.mjs";
|
|
4
1
|
import { SupervisorResult } from "../contracts/result/supervisor-result.type.mjs";
|
|
2
|
+
import { SupervisorInput } from "../contracts/supervisor/supervisor-input.type.mjs";
|
|
5
3
|
import { SupervisorSnapshot } from "../contracts/supervisor/supervisor-snapshot.type.mjs";
|
|
6
|
-
import {
|
|
4
|
+
import { SupervisorExecuteOptions } from "../contracts/supervisor/supervisor-execute-options.type.mjs";
|
|
5
|
+
import { SupervisorConfig } from "../contracts/supervisor/supervisor-config.type.mjs";
|
|
7
6
|
import { ResolvedIntentEntry } from "./entries.mjs";
|
|
7
|
+
import { SupervisorEmitter } from "./emitter.mjs";
|
|
8
8
|
import { SupervisorStreamController } from "./supervisor-stream.mjs";
|
|
9
9
|
|
|
10
10
|
//#region ../@warlock.js/ai/src/supervisor/execution.d.ts
|
|
@@ -59,6 +59,21 @@ declare class SupervisorExecution<TOutput> {
|
|
|
59
59
|
private readonly maxIterations;
|
|
60
60
|
private readonly logger;
|
|
61
61
|
private readonly logModule;
|
|
62
|
+
/**
|
|
63
|
+
* Supervisor-level middleware stack — `config.middleware` (default
|
|
64
|
+
* empty). Each entry's optional `supervisor` hook map fires once
|
|
65
|
+
* around the whole run via `runPipeline(..., "supervisor", ...)` in
|
|
66
|
+
* {@link run}; entries without that hook map are skipped by the
|
|
67
|
+
* pipeline.
|
|
68
|
+
*/
|
|
69
|
+
private readonly middleware;
|
|
70
|
+
/**
|
|
71
|
+
* Per-run shared-state bag threaded through every `supervisor`-level
|
|
72
|
+
* hook (`before` / `after` / `onError`) of this one run. Fresh `Map`
|
|
73
|
+
* per `SupervisorExecution` so two concurrent runs of the same
|
|
74
|
+
* supervisor get isolated bags — mirrors the agent pipeline.
|
|
75
|
+
*/
|
|
76
|
+
private readonly middlewareState;
|
|
62
77
|
private readonly snapshots;
|
|
63
78
|
private readonly childReports;
|
|
64
79
|
private readonly usage;
|
|
@@ -182,12 +197,32 @@ declare class SupervisorExecution<TOutput> {
|
|
|
182
197
|
*/
|
|
183
198
|
private applyAgentsWindow;
|
|
184
199
|
/**
|
|
185
|
-
* Entry point.
|
|
186
|
-
*
|
|
187
|
-
* `
|
|
188
|
-
*
|
|
200
|
+
* Entry point. Wraps the core run (`runCore`) in the
|
|
201
|
+
* `supervisor`-level middleware pipeline, then emits the terminal
|
|
202
|
+
* `supervisor.cancelled` / `supervisor.error` / `supervisor.completed`
|
|
203
|
+
* events and closes the stream (if any) with the post-pipeline result
|
|
204
|
+
* — so a middleware that short-circuits or transforms the final
|
|
205
|
+
* result still produces a well-formed public outcome. Returns the
|
|
206
|
+
* uniform `{ data, report, usage, error }` shape. Never throws.
|
|
189
207
|
*/
|
|
190
208
|
run(): Promise<SupervisorResult<TOutput>>;
|
|
209
|
+
/**
|
|
210
|
+
* Build the `supervisor`-level middleware context — the stable
|
|
211
|
+
* identity of this run plus the per-run shared-state bag every hook
|
|
212
|
+
* sees. Constructed once per run, before the pipeline `before` hooks
|
|
213
|
+
* fire. Mirrors the agent's `buildExecuteContext`, one level up.
|
|
214
|
+
*/
|
|
215
|
+
private buildSupervisorContext;
|
|
216
|
+
/**
|
|
217
|
+
* Inner body wrapped by the `supervisor`-level pipeline. Emits the
|
|
218
|
+
* `supervisor.starting` event, drives the iteration loop, absorbs
|
|
219
|
+
* every iteration-loop failure into `this.error` (so the run never
|
|
220
|
+
* throws from here), and returns the assembled `SupervisorResult`.
|
|
221
|
+
* `supervisor`-level `after` hooks receive this result, with `error`
|
|
222
|
+
* populated when the loop failed; `before` hooks can short-circuit
|
|
223
|
+
* before this ever runs.
|
|
224
|
+
*/
|
|
225
|
+
private runCore;
|
|
191
226
|
/**
|
|
192
227
|
* Drive the iteration loop until a terminal condition fires:
|
|
193
228
|
* `END` / `satisfied:true` / `maxIterations` / signal abort /
|