@warlock.js/ai 4.4.0 → 4.6.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 +63 -52
- package/cjs/index.cjs +240 -14147
- package/cjs/src-Bmajk4Qg.cjs +30 -0
- package/cjs/src-OZyDYHxm.cjs +25089 -0
- package/cjs/src-OZyDYHxm.cjs.map +1 -0
- package/esm/agent/agent-config.type.d.mts +119 -1
- package/esm/agent/agent-config.type.d.mts.map +1 -1
- package/esm/agent/agent-input-builder.mjs +27 -6
- package/esm/agent/agent-input-builder.mjs.map +1 -1
- package/esm/agent/agent.d.mts +40 -1
- package/esm/agent/agent.d.mts.map +1 -1
- package/esm/agent/agent.mjs +328 -36
- 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/judge-config.type.d.mts +33 -0
- package/esm/agent/judge-config.type.d.mts.map +1 -0
- package/esm/agent/judge-config.type.mjs +13 -0
- package/esm/agent/judge-config.type.mjs.map +1 -0
- package/esm/agent/signature.mjs +57 -0
- package/esm/agent/signature.mjs.map +1 -0
- package/esm/agent/snapshot.mjs +101 -0
- package/esm/agent/snapshot.mjs.map +1 -0
- package/esm/ai-openai/src/embedder.mjs +4 -0
- package/esm/ai-openai/src/image.mjs +5 -0
- package/esm/ai-openai/src/index.mjs +7 -0
- package/esm/ai-openai/src/model.mjs +5 -0
- package/esm/ai-openai/src/sdk.mjs +9 -0
- package/esm/ai-openai/src/speech.mjs +5 -0
- package/esm/ai-openai/src/transcription.mjs +6 -0
- package/esm/ai-openai/src/utils/index.mjs +5 -0
- package/esm/ai-openai/src/utils/to-openai-messages.mjs +3 -0
- package/esm/ai-openai/src/utils/to-openai-tools.mjs +3 -0
- package/esm/ai-openai/src/utils/wrap-openai-error.mjs +4 -0
- package/esm/ai.d.mts +164 -53
- package/esm/ai.d.mts.map +1 -1
- package/esm/ai.mjs +79 -8
- package/esm/ai.mjs.map +1 -1
- package/esm/batch/batch.d.mts.map +1 -1
- package/esm/batch/batch.mjs +21 -1
- package/esm/batch/batch.mjs.map +1 -1
- package/esm/batch/batch.type.d.mts +11 -4
- package/esm/batch/batch.type.d.mts.map +1 -1
- package/esm/config.d.mts +39 -3
- package/esm/config.d.mts.map +1 -1
- package/esm/config.mjs +26 -2
- package/esm/config.mjs.map +1 -1
- package/esm/contracts/agent/agent-options.type.d.mts +33 -5
- package/esm/contracts/agent/agent-options.type.d.mts.map +1 -1
- package/esm/contracts/agent/agent-snapshot.type.d.mts +90 -0
- package/esm/contracts/agent/agent-snapshot.type.d.mts.map +1 -0
- package/esm/contracts/agent/agent.contract.d.mts +29 -1
- package/esm/contracts/agent/agent.contract.d.mts.map +1 -1
- package/esm/contracts/agent/eval.type.d.mts +43 -2
- package/esm/contracts/agent/eval.type.d.mts.map +1 -1
- package/esm/contracts/agent/index.d.mts +2 -1
- package/esm/contracts/attachment-policy.type.d.mts +51 -0
- package/esm/contracts/attachment-policy.type.d.mts.map +1 -0
- package/esm/contracts/attachment.type.d.mts +16 -7
- package/esm/contracts/attachment.type.d.mts.map +1 -1
- package/esm/contracts/content-part.type.d.mts +14 -5
- package/esm/contracts/content-part.type.d.mts.map +1 -1
- package/esm/contracts/events/supervisor-events.type.d.mts.map +1 -1
- package/esm/contracts/image-model.contract.d.mts +156 -0
- package/esm/contracts/image-model.contract.d.mts.map +1 -0
- package/esm/contracts/index.d.mts +13 -6
- package/esm/contracts/model.contract.d.mts +11 -8
- package/esm/contracts/model.contract.d.mts.map +1 -1
- package/esm/contracts/orchestrator/index.d.mts +1 -0
- package/esm/contracts/orchestrator/orchestrator-config.type.d.mts +31 -2
- package/esm/contracts/orchestrator/orchestrator-config.type.d.mts.map +1 -1
- package/esm/contracts/orchestrator/session-lock.contract.d.mts +47 -0
- package/esm/contracts/orchestrator/session-lock.contract.d.mts.map +1 -0
- package/esm/contracts/planner/index.d.mts +3 -2
- package/esm/contracts/planner/planner-config.type.d.mts +61 -0
- package/esm/contracts/planner/planner-config.type.d.mts.map +1 -1
- package/esm/contracts/planner/planner-execute-options.type.d.mts +60 -1
- package/esm/contracts/planner/planner-execute-options.type.d.mts.map +1 -1
- package/esm/contracts/planner/planner-result.type.d.mts +8 -0
- package/esm/contracts/planner/planner-result.type.d.mts.map +1 -1
- package/esm/contracts/planner/planner-snapshot.type.d.mts +77 -0
- package/esm/contracts/planner/planner-snapshot.type.d.mts.map +1 -0
- package/esm/contracts/planner/planner.contract.d.mts +21 -1
- package/esm/contracts/planner/planner.contract.d.mts.map +1 -1
- package/esm/contracts/result/agent-result.type.d.mts +6 -4
- package/esm/contracts/result/agent-result.type.d.mts.map +1 -1
- package/esm/contracts/result/base-report.type.d.mts +21 -3
- 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/execution-report.type.d.mts +53 -1
- package/esm/contracts/result/execution-report.type.d.mts.map +1 -1
- package/esm/contracts/result/supervisor-result.type.d.mts +14 -2
- package/esm/contracts/result/supervisor-result.type.d.mts.map +1 -1
- package/esm/contracts/result/workflow-result.type.d.mts +2 -1
- package/esm/contracts/result/workflow-result.type.d.mts.map +1 -1
- package/esm/contracts/sdk-adapter.contract.d.mts +37 -0
- package/esm/contracts/sdk-adapter.contract.d.mts.map +1 -1
- package/esm/contracts/speech-model.contract.d.mts +97 -0
- package/esm/contracts/speech-model.contract.d.mts.map +1 -0
- package/esm/contracts/supervisor/supervisor-config.type.d.mts +29 -0
- package/esm/contracts/supervisor/supervisor-config.type.d.mts.map +1 -1
- package/esm/contracts/system-prompt.contract.d.mts +103 -1
- package/esm/contracts/system-prompt.contract.d.mts.map +1 -1
- package/esm/contracts/team/index.d.mts +1 -0
- package/esm/contracts/team/team-config.type.d.mts +127 -0
- package/esm/contracts/team/team-config.type.d.mts.map +1 -0
- package/esm/contracts/tool.contract.d.mts +4 -2
- package/esm/contracts/tool.contract.d.mts.map +1 -1
- package/esm/contracts/transcription-model.contract.d.mts +101 -0
- package/esm/contracts/transcription-model.contract.d.mts.map +1 -0
- package/esm/contracts/workflow/step.contract.d.mts +30 -5
- package/esm/contracts/workflow/step.contract.d.mts.map +1 -1
- package/esm/contracts/workflow/workflow.contract.d.mts +16 -0
- package/esm/contracts/workflow/workflow.contract.d.mts.map +1 -1
- package/esm/errors/agent-drift-error.d.mts +32 -0
- package/esm/errors/agent-drift-error.d.mts.map +1 -0
- package/esm/errors/agent-drift-error.mjs +31 -0
- package/esm/errors/agent-drift-error.mjs.map +1 -0
- package/esm/errors/error-code.type.d.mts +1 -1
- package/esm/errors/index.d.mts +3 -0
- package/esm/errors/index.mjs +3 -0
- package/esm/errors/outbound-policy-error.d.mts +27 -0
- package/esm/errors/outbound-policy-error.d.mts.map +1 -0
- package/esm/errors/outbound-policy-error.mjs +32 -0
- package/esm/errors/outbound-policy-error.mjs.map +1 -0
- package/esm/errors/planner-drift-error.d.mts +34 -0
- package/esm/errors/planner-drift-error.d.mts.map +1 -0
- package/esm/errors/planner-drift-error.mjs +33 -0
- package/esm/errors/planner-drift-error.mjs.map +1 -0
- package/esm/eval/dataset.d.mts +28 -0
- package/esm/eval/dataset.d.mts.map +1 -0
- package/esm/eval/dataset.mjs +112 -0
- package/esm/eval/dataset.mjs.map +1 -0
- package/esm/eval/dataset.type.d.mts +53 -0
- package/esm/eval/dataset.type.d.mts.map +1 -0
- package/esm/eval/eval-runner.d.mts.map +1 -1
- package/esm/eval/eval-runner.mjs +16 -2
- package/esm/eval/eval-runner.mjs.map +1 -1
- package/esm/eval/index.d.mts +20 -1
- package/esm/eval/index.d.mts.map +1 -1
- package/esm/eval/index.mjs +20 -2
- package/esm/eval/index.mjs.map +1 -1
- package/esm/eval/regression.d.mts +30 -0
- package/esm/eval/regression.d.mts.map +1 -0
- package/esm/eval/regression.mjs +51 -0
- package/esm/eval/regression.mjs.map +1 -0
- package/esm/eval/report-json.d.mts +30 -0
- package/esm/eval/report-json.d.mts.map +1 -0
- package/esm/eval/report-json.mjs +33 -0
- package/esm/eval/report-json.mjs.map +1 -0
- package/esm/eval/report-junit.d.mts +22 -0
- package/esm/eval/report-junit.d.mts.map +1 -0
- package/esm/eval/report-junit.mjs +60 -0
- package/esm/eval/report-junit.mjs.map +1 -0
- package/esm/guard/contracts/guard-options.type.d.mts +165 -0
- package/esm/guard/contracts/guard-options.type.d.mts.map +1 -0
- package/esm/guard/contracts/guardrail.contract.d.mts +78 -0
- package/esm/guard/contracts/guardrail.contract.d.mts.map +1 -0
- package/esm/guard/contracts/index.d.mts +4 -0
- package/esm/guard/contracts/openai-client.contract.d.mts +51 -0
- package/esm/guard/contracts/openai-client.contract.d.mts.map +1 -0
- package/esm/guard/contracts/verdict.type.d.mts +76 -0
- package/esm/guard/contracts/verdict.type.d.mts.map +1 -0
- package/esm/guard/detectors/index.d.mts +4 -0
- package/esm/guard/detectors/index.mjs +6 -0
- package/esm/guard/detectors/injection.d.mts +34 -0
- package/esm/guard/detectors/injection.d.mts.map +1 -0
- package/esm/guard/detectors/injection.mjs +254 -0
- package/esm/guard/detectors/injection.mjs.map +1 -0
- package/esm/guard/detectors/moderation.d.mts +32 -0
- package/esm/guard/detectors/moderation.d.mts.map +1 -0
- package/esm/guard/detectors/moderation.mjs +134 -0
- package/esm/guard/detectors/moderation.mjs.map +1 -0
- package/esm/guard/detectors/pii.d.mts +41 -0
- package/esm/guard/detectors/pii.d.mts.map +1 -0
- package/esm/guard/detectors/pii.mjs +199 -0
- package/esm/guard/detectors/pii.mjs.map +1 -0
- package/esm/guard/detectors/topic.d.mts +29 -0
- package/esm/guard/detectors/topic.d.mts.map +1 -0
- package/esm/guard/detectors/topic.mjs +99 -0
- package/esm/guard/detectors/topic.mjs.map +1 -0
- package/esm/guard/errors.d.mts +12 -0
- package/esm/guard/errors.d.mts.map +1 -0
- package/esm/guard/errors.mjs +18 -0
- package/esm/guard/errors.mjs.map +1 -0
- package/esm/guard/guard.d.mts +67 -0
- package/esm/guard/guard.d.mts.map +1 -0
- package/esm/guard/guard.mjs +209 -0
- package/esm/guard/guard.mjs.map +1 -0
- package/esm/guard/guardrail.d.mts +39 -0
- package/esm/guard/guardrail.d.mts.map +1 -0
- package/esm/guard/guardrail.mjs +22 -0
- package/esm/guard/guardrail.mjs.map +1 -0
- package/esm/human/contracts/approval.type.d.mts +154 -0
- package/esm/human/contracts/approval.type.d.mts.map +1 -0
- package/esm/human/contracts/human-approval.type.d.mts +38 -0
- package/esm/human/contracts/human-approval.type.d.mts.map +1 -0
- package/esm/human/contracts/index.d.mts +4 -0
- package/esm/human/contracts/interrupt-store.contract.d.mts +112 -0
- package/esm/human/contracts/interrupt-store.contract.d.mts.map +1 -0
- package/esm/human/contracts/resume.type.d.mts +77 -0
- package/esm/human/contracts/resume.type.d.mts.map +1 -0
- package/esm/human/errors.d.mts +84 -0
- package/esm/human/errors.d.mts.map +1 -0
- package/esm/human/errors.mjs +60 -0
- package/esm/human/errors.mjs.map +1 -0
- package/esm/human/human-approval.d.mts +57 -0
- package/esm/human/human-approval.d.mts.map +1 -0
- package/esm/human/human-approval.mjs +170 -0
- package/esm/human/human-approval.mjs.map +1 -0
- package/esm/human/policy.d.mts +55 -0
- package/esm/human/policy.d.mts.map +1 -0
- package/esm/human/policy.mjs +67 -0
- package/esm/human/policy.mjs.map +1 -0
- package/esm/human/register.mjs +37 -0
- package/esm/human/register.mjs.map +1 -0
- package/esm/human/resume-seed.mjs +53 -0
- package/esm/human/resume-seed.mjs.map +1 -0
- package/esm/human/resume.d.mts +54 -0
- package/esm/human/resume.d.mts.map +1 -0
- package/esm/human/resume.mjs +121 -0
- package/esm/human/resume.mjs.map +1 -0
- package/esm/human/stores/index.mjs +5 -0
- package/esm/human/stores/memory.d.mts +30 -0
- package/esm/human/stores/memory.d.mts.map +1 -0
- package/esm/human/stores/memory.mjs +91 -0
- package/esm/human/stores/memory.mjs.map +1 -0
- package/esm/human/stores/pg.d.mts +59 -0
- package/esm/human/stores/pg.d.mts.map +1 -0
- package/esm/human/stores/pg.mjs +220 -0
- package/esm/human/stores/pg.mjs.map +1 -0
- package/esm/human/stores/redis.d.mts +56 -0
- package/esm/human/stores/redis.d.mts.map +1 -0
- package/esm/human/stores/redis.mjs +201 -0
- package/esm/human/stores/redis.mjs.map +1 -0
- package/esm/image/image-cost.d.mts +32 -0
- package/esm/image/image-cost.d.mts.map +1 -0
- package/esm/image/image-cost.mjs +55 -0
- package/esm/image/image-cost.mjs.map +1 -0
- package/esm/image/image.d.mts +92 -0
- package/esm/image/image.d.mts.map +1 -0
- package/esm/image/image.mjs +113 -0
- package/esm/image/image.mjs.map +1 -0
- package/esm/image/index.mjs +4 -0
- package/esm/index.d.mts +137 -24
- package/esm/index.mjs +101 -11
- package/esm/middleware/builtins/budget.mjs +6 -2
- package/esm/middleware/builtins/budget.mjs.map +1 -1
- package/esm/middleware/utils/extract-user-text.d.mts +8 -1
- package/esm/middleware/utils/extract-user-text.d.mts.map +1 -1
- package/esm/middleware/utils/extract-user-text.mjs +8 -1
- package/esm/middleware/utils/extract-user-text.mjs.map +1 -1
- package/esm/mock/index.d.mts +3 -0
- package/esm/mock/index.mjs +3 -0
- package/esm/mock/mock-config.type.d.mts +22 -0
- package/esm/mock/mock-config.type.d.mts.map +1 -1
- package/esm/mock/mock-image-model.d.mts +41 -0
- package/esm/mock/mock-image-model.d.mts.map +1 -0
- package/esm/mock/mock-image-model.mjs +52 -0
- package/esm/mock/mock-image-model.mjs.map +1 -0
- package/esm/mock/mock-sdk.d.mts +7 -1
- package/esm/mock/mock-sdk.d.mts.map +1 -1
- package/esm/mock/mock-sdk.mjs +27 -0
- package/esm/mock/mock-sdk.mjs.map +1 -1
- package/esm/mock/mock-speech-model.d.mts +31 -0
- package/esm/mock/mock-speech-model.d.mts.map +1 -0
- package/esm/mock/mock-speech-model.mjs +39 -0
- package/esm/mock/mock-speech-model.mjs.map +1 -0
- package/esm/mock/mock-transcription-model.d.mts +32 -0
- package/esm/mock/mock-transcription-model.d.mts.map +1 -0
- package/esm/mock/mock-transcription-model.mjs +36 -0
- package/esm/mock/mock-transcription-model.mjs.map +1 -0
- package/esm/object-stream/index.d.mts +2 -0
- package/esm/object-stream/index.mjs +4 -0
- package/esm/object-stream/parse-partial-json.d.mts +22 -0
- package/esm/object-stream/parse-partial-json.d.mts.map +1 -0
- package/esm/object-stream/parse-partial-json.mjs +78 -0
- package/esm/object-stream/parse-partial-json.mjs.map +1 -0
- package/esm/object-stream/stream-object.d.mts +68 -0
- package/esm/object-stream/stream-object.d.mts.map +1 -0
- package/esm/object-stream/stream-object.mjs +104 -0
- package/esm/object-stream/stream-object.mjs.map +1 -0
- package/esm/observe/index.mjs +4 -0
- package/esm/observe/observer-registry.d.mts +30 -0
- package/esm/observe/observer-registry.d.mts.map +1 -0
- package/esm/observe/observer-registry.mjs +51 -0
- package/esm/observe/observer-registry.mjs.map +1 -0
- package/esm/observe/observer.contract.d.mts +40 -0
- package/esm/observe/observer.contract.d.mts.map +1 -0
- package/esm/observe/resolve-observers.d.mts +40 -0
- package/esm/observe/resolve-observers.d.mts.map +1 -0
- package/esm/observe/resolve-observers.mjs +73 -0
- package/esm/observe/resolve-observers.mjs.map +1 -0
- package/esm/orchestrator/execution.d.mts.map +1 -1
- package/esm/orchestrator/execution.mjs +5 -2
- package/esm/orchestrator/execution.mjs.map +1 -1
- package/esm/orchestrator/index.d.mts +1 -0
- package/esm/orchestrator/index.mjs +1 -0
- package/esm/orchestrator/orchestrator.d.mts.map +1 -1
- package/esm/orchestrator/orchestrator.mjs +39 -6
- package/esm/orchestrator/orchestrator.mjs.map +1 -1
- package/esm/orchestrator/session-lock.d.mts +25 -0
- package/esm/orchestrator/session-lock.d.mts.map +1 -0
- package/esm/orchestrator/session-lock.mjs +83 -0
- package/esm/orchestrator/session-lock.mjs.map +1 -0
- package/esm/planner/dag-scheduler.mjs +97 -0
- package/esm/planner/dag-scheduler.mjs.map +1 -0
- package/esm/planner/plan-prompt.d.mts +1 -1
- package/esm/planner/plan-prompt.d.mts.map +1 -1
- package/esm/planner/plan-prompt.mjs +2 -1
- package/esm/planner/plan-prompt.mjs.map +1 -1
- package/esm/planner/planner-run.d.mts +8 -0
- package/esm/planner/planner-run.d.mts.map +1 -1
- package/esm/planner/planner-run.mjs +457 -31
- package/esm/planner/planner-run.mjs.map +1 -1
- package/esm/planner/planner.d.mts.map +1 -1
- package/esm/planner/planner.mjs +26 -2
- package/esm/planner/planner.mjs.map +1 -1
- package/esm/planner/snapshot.mjs +95 -0
- package/esm/planner/snapshot.mjs.map +1 -0
- package/esm/prompt/errors.d.mts +57 -0
- package/esm/prompt/errors.d.mts.map +1 -0
- package/esm/prompt/errors.mjs +73 -0
- package/esm/prompt/errors.mjs.map +1 -0
- package/esm/prompt/index.d.mts +3 -0
- package/esm/prompt/index.mjs +4 -0
- package/esm/prompt/prompt-langfuse-sync.mjs +104 -0
- package/esm/prompt/prompt-langfuse-sync.mjs.map +1 -0
- package/esm/prompt/prompt-langfuse-sync.type.d.mts +32 -0
- package/esm/prompt/prompt-langfuse-sync.type.d.mts.map +1 -0
- package/esm/prompt/prompt-validate.mjs +170 -0
- package/esm/prompt/prompt-validate.mjs.map +1 -0
- package/esm/prompt/prompt.d.mts +54 -0
- package/esm/prompt/prompt.d.mts.map +1 -0
- package/esm/prompt/prompt.mjs +218 -0
- package/esm/prompt/prompt.mjs.map +1 -0
- package/esm/prompt/prompt.type.d.mts +174 -0
- package/esm/prompt/prompt.type.d.mts.map +1 -0
- package/esm/prompts/index.d.mts +3 -0
- package/esm/prompts/index.mjs +3 -0
- package/esm/prompts/prompts-manager.contract.d.mts +154 -0
- package/esm/prompts/prompts-manager.contract.d.mts.map +1 -0
- package/esm/prompts/prompts-manager.d.mts +38 -0
- package/esm/prompts/prompts-manager.d.mts.map +1 -0
- package/esm/prompts/prompts-manager.mjs +410 -0
- package/esm/prompts/prompts-manager.mjs.map +1 -0
- package/esm/prompts/prompts-manager.type.d.mts +172 -0
- package/esm/prompts/prompts-manager.type.d.mts.map +1 -0
- package/esm/prompts/prompts-validate.mjs +200 -0
- package/esm/prompts/prompts-validate.mjs.map +1 -0
- package/esm/rag/as-tool.mjs +48 -0
- package/esm/rag/as-tool.mjs.map +1 -0
- package/esm/rag/chunk/chunk.d.mts +24 -0
- package/esm/rag/chunk/chunk.d.mts.map +1 -0
- package/esm/rag/chunk/chunk.mjs +44 -0
- package/esm/rag/chunk/chunk.mjs.map +1 -0
- package/esm/rag/chunk/fixed.mjs +32 -0
- package/esm/rag/chunk/fixed.mjs.map +1 -0
- package/esm/rag/chunk/markdown.mjs +75 -0
- package/esm/rag/chunk/markdown.mjs.map +1 -0
- package/esm/rag/chunk/recursive.mjs +132 -0
- package/esm/rag/chunk/recursive.mjs.map +1 -0
- package/esm/rag/chunk/sentence.mjs +73 -0
- package/esm/rag/chunk/sentence.mjs.map +1 -0
- package/esm/rag/contracts/chunk-options.type.d.mts +35 -0
- package/esm/rag/contracts/chunk-options.type.d.mts.map +1 -0
- package/esm/rag/contracts/citation.type.d.mts +35 -0
- package/esm/rag/contracts/citation.type.d.mts.map +1 -0
- package/esm/rag/contracts/index.d.mts +4 -0
- package/esm/rag/contracts/rag-config.type.d.mts +68 -0
- package/esm/rag/contracts/rag-config.type.d.mts.map +1 -0
- package/esm/rag/contracts/rag-document.type.d.mts +21 -0
- package/esm/rag/contracts/rag-document.type.d.mts.map +1 -0
- package/esm/rag/hybrid/bm25.d.mts +23 -0
- package/esm/rag/hybrid/bm25.d.mts.map +1 -0
- package/esm/rag/hybrid/bm25.mjs +51 -0
- package/esm/rag/hybrid/bm25.mjs.map +1 -0
- package/esm/rag/hybrid/hybrid-rank.d.mts +33 -0
- package/esm/rag/hybrid/hybrid-rank.d.mts.map +1 -0
- package/esm/rag/hybrid/hybrid-rank.mjs +29 -0
- package/esm/rag/hybrid/hybrid-rank.mjs.map +1 -0
- package/esm/rag/hybrid/rrf.d.mts +25 -0
- package/esm/rag/hybrid/rrf.d.mts.map +1 -0
- package/esm/rag/hybrid/rrf.mjs +30 -0
- package/esm/rag/hybrid/rrf.mjs.map +1 -0
- package/esm/rag/index.d.mts +22 -0
- package/esm/rag/index.mjs +18 -0
- package/esm/rag/loaders/errors.d.mts +19 -0
- package/esm/rag/loaders/errors.d.mts.map +1 -0
- package/esm/rag/loaders/errors.mjs +25 -0
- package/esm/rag/loaders/errors.mjs.map +1 -0
- package/esm/rag/loaders/index.mjs +7 -0
- package/esm/rag/loaders/load-html.d.mts +26 -0
- package/esm/rag/loaders/load-html.d.mts.map +1 -0
- package/esm/rag/loaders/load-html.mjs +138 -0
- package/esm/rag/loaders/load-html.mjs.map +1 -0
- package/esm/rag/loaders/load-pdf.d.mts +38 -0
- package/esm/rag/loaders/load-pdf.d.mts.map +1 -0
- package/esm/rag/loaders/load-pdf.mjs +150 -0
- package/esm/rag/loaders/load-pdf.mjs.map +1 -0
- package/esm/rag/loaders/load-text.d.mts +47 -0
- package/esm/rag/loaders/load-text.d.mts.map +1 -0
- package/esm/rag/loaders/load-text.mjs +60 -0
- package/esm/rag/loaders/load-text.mjs.map +1 -0
- package/esm/rag/loaders/load-web.d.mts +42 -0
- package/esm/rag/loaders/load-web.d.mts.map +1 -0
- package/esm/rag/loaders/load-web.mjs +89 -0
- package/esm/rag/loaders/load-web.mjs.map +1 -0
- package/esm/rag/loaders/loader.type.d.mts +89 -0
- package/esm/rag/loaders/loader.type.d.mts.map +1 -0
- package/esm/rag/rag.d.mts +38 -0
- package/esm/rag/rag.d.mts.map +1 -0
- package/esm/rag/rag.mjs +126 -0
- package/esm/rag/rag.mjs.map +1 -0
- package/esm/rag/rerank/keyword-reranker.d.mts +32 -0
- package/esm/rag/rerank/keyword-reranker.d.mts.map +1 -0
- package/esm/rag/rerank/keyword-reranker.mjs +58 -0
- package/esm/rag/rerank/keyword-reranker.mjs.map +1 -0
- package/esm/rag/rerank/llm-reranker.d.mts +36 -0
- package/esm/rag/rerank/llm-reranker.d.mts.map +1 -0
- package/esm/rag/rerank/llm-reranker.mjs +85 -0
- package/esm/rag/rerank/llm-reranker.mjs.map +1 -0
- package/esm/rag/rerank/reranker.contract.d.mts +28 -0
- package/esm/rag/rerank/reranker.contract.d.mts.map +1 -0
- package/esm/rag/retrieve.mjs +68 -0
- package/esm/rag/retrieve.mjs.map +1 -0
- package/esm/rag/store/cache-vector-store.d.mts +27 -0
- package/esm/rag/store/cache-vector-store.d.mts.map +1 -0
- package/esm/rag/store/cache-vector-store.mjs +48 -0
- package/esm/rag/store/cache-vector-store.mjs.map +1 -0
- package/esm/rag/store/pg-vector-store.d.mts +139 -0
- package/esm/rag/store/pg-vector-store.d.mts.map +1 -0
- package/esm/rag/store/pg-vector-store.mjs +328 -0
- package/esm/rag/store/pg-vector-store.mjs.map +1 -0
- package/esm/rag/store/vector-store.contract.d.mts +38 -0
- package/esm/rag/store/vector-store.contract.d.mts.map +1 -0
- package/esm/rag/transforms/multi-query.d.mts +27 -0
- package/esm/rag/transforms/multi-query.d.mts.map +1 -0
- package/esm/rag/transforms/multi-query.mjs +41 -0
- package/esm/rag/transforms/multi-query.mjs.map +1 -0
- package/esm/security/index.mjs +5 -0
- package/esm/security/outbound-policy.d.mts +46 -0
- package/esm/security/outbound-policy.d.mts.map +1 -0
- package/esm/security/outbound-policy.mjs +187 -0
- package/esm/security/outbound-policy.mjs.map +1 -0
- package/esm/security/outbound-policy.type.d.mts +74 -0
- package/esm/security/outbound-policy.type.d.mts.map +1 -0
- package/esm/security/private-ip.d.mts +15 -0
- package/esm/security/private-ip.d.mts.map +1 -0
- package/esm/security/private-ip.mjs +48 -0
- package/esm/security/private-ip.mjs.map +1 -0
- package/esm/security/redact.d.mts +59 -0
- package/esm/security/redact.d.mts.map +1 -0
- package/esm/security/redact.mjs +122 -0
- package/esm/security/redact.mjs.map +1 -0
- package/esm/serve/serve.d.mts +50 -0
- package/esm/serve/serve.d.mts.map +1 -0
- package/esm/serve/serve.mjs +90 -0
- package/esm/serve/serve.mjs.map +1 -0
- package/esm/serve/sse.d.mts +20 -0
- package/esm/serve/sse.d.mts.map +1 -0
- package/esm/serve/sse.mjs +25 -0
- package/esm/serve/sse.mjs.map +1 -0
- package/esm/serve/stream-to-sse.d.mts +29 -0
- package/esm/serve/stream-to-sse.d.mts.map +1 -0
- package/esm/serve/stream-to-sse.mjs +37 -0
- package/esm/serve/stream-to-sse.mjs.map +1 -0
- package/esm/skills/catalog.d.mts +49 -0
- package/esm/skills/catalog.d.mts.map +1 -0
- package/esm/skills/catalog.mjs +140 -0
- package/esm/skills/catalog.mjs.map +1 -0
- package/esm/skills/contracts/skill-record.type.d.mts +37 -0
- package/esm/skills/contracts/skill-record.type.d.mts.map +1 -0
- package/esm/skills/contracts/skills-config.type.d.mts +108 -0
- package/esm/skills/contracts/skills-config.type.d.mts.map +1 -0
- package/esm/skills/contracts/skills-store.contract.d.mts +28 -0
- package/esm/skills/contracts/skills-store.contract.d.mts.map +1 -0
- package/esm/skills/contracts/skills.contract.d.mts +43 -0
- package/esm/skills/contracts/skills.contract.d.mts.map +1 -0
- package/esm/skills/index.d.mts +16 -0
- package/esm/skills/index.mjs +14 -0
- package/esm/skills/load-skill-tool.d.mts +38 -0
- package/esm/skills/load-skill-tool.d.mts.map +1 -0
- package/esm/skills/load-skill-tool.mjs +65 -0
- package/esm/skills/load-skill-tool.mjs.map +1 -0
- package/esm/skills/review-gate.d.mts +33 -0
- package/esm/skills/review-gate.d.mts.map +1 -0
- package/esm/skills/review-gate.mjs +60 -0
- package/esm/skills/review-gate.mjs.map +1 -0
- package/esm/skills/save-skill-tool.d.mts +39 -0
- package/esm/skills/save-skill-tool.d.mts.map +1 -0
- package/esm/skills/save-skill-tool.mjs +65 -0
- package/esm/skills/save-skill-tool.mjs.map +1 -0
- package/esm/skills/skills.d.mts +33 -0
- package/esm/skills/skills.d.mts.map +1 -0
- package/esm/skills/skills.mjs +109 -0
- package/esm/skills/skills.mjs.map +1 -0
- package/esm/skills/sources/directory-source.d.mts +19 -0
- package/esm/skills/sources/directory-source.d.mts.map +1 -0
- package/esm/skills/sources/directory-source.mjs +108 -0
- package/esm/skills/sources/directory-source.mjs.map +1 -0
- package/esm/skills/sources/index.d.mts +18 -0
- package/esm/skills/sources/index.d.mts.map +1 -0
- package/esm/skills/sources/index.mjs +27 -0
- package/esm/skills/sources/index.mjs.map +1 -0
- package/esm/skills/sources/parse-frontmatter.d.mts +27 -0
- package/esm/skills/sources/parse-frontmatter.d.mts.map +1 -0
- package/esm/skills/sources/parse-frontmatter.mjs +46 -0
- package/esm/skills/sources/parse-frontmatter.mjs.map +1 -0
- package/esm/skills/sources/store-source.d.mts +14 -0
- package/esm/skills/sources/store-source.d.mts.map +1 -0
- package/esm/skills/sources/store-source.mjs +15 -0
- package/esm/skills/sources/store-source.mjs.map +1 -0
- package/esm/skills/sources/url-source.d.mts +29 -0
- package/esm/skills/sources/url-source.d.mts.map +1 -0
- package/esm/skills/sources/url-source.mjs +117 -0
- package/esm/skills/sources/url-source.mjs.map +1 -0
- package/esm/skills/store/mock-skills-store.d.mts +57 -0
- package/esm/skills/store/mock-skills-store.d.mts.map +1 -0
- package/esm/skills/store/mock-skills-store.mjs +100 -0
- package/esm/skills/store/mock-skills-store.mjs.map +1 -0
- package/esm/skills/store/procedural-skill-store.d.mts +30 -0
- package/esm/skills/store/procedural-skill-store.d.mts.map +1 -0
- package/esm/skills/store/procedural-skill-store.mjs +125 -0
- package/esm/skills/store/procedural-skill-store.mjs.map +1 -0
- package/esm/speech/index.mjs +3 -0
- package/esm/speech/speech.d.mts +65 -0
- package/esm/speech/speech.d.mts.map +1 -0
- package/esm/speech/speech.mjs +123 -0
- package/esm/speech/speech.mjs.map +1 -0
- package/esm/supervisor/as-tool.mjs +2 -2
- package/esm/supervisor/as-tool.mjs.map +1 -1
- package/esm/supervisor/entries.mjs +2 -2
- package/esm/supervisor/entries.mjs.map +1 -1
- package/esm/supervisor/execution.d.mts.map +1 -1
- package/esm/supervisor/execution.mjs +31 -28
- package/esm/supervisor/execution.mjs.map +1 -1
- package/esm/supervisor/supervisor.d.mts.map +1 -1
- package/esm/supervisor/supervisor.mjs +8 -3
- package/esm/supervisor/supervisor.mjs.map +1 -1
- package/esm/system-prompt/index.d.mts +4 -0
- package/esm/system-prompt/system-prompt.d.mts +68 -4
- package/esm/system-prompt/system-prompt.d.mts.map +1 -1
- package/esm/system-prompt/system-prompt.mjs +89 -5
- package/esm/system-prompt/system-prompt.mjs.map +1 -1
- package/esm/team/gates.mjs +48 -0
- package/esm/team/gates.mjs.map +1 -0
- package/esm/team/index.d.mts +1 -0
- package/esm/team/index.mjs +3 -0
- package/esm/team/team.d.mts +42 -0
- package/esm/team/team.d.mts.map +1 -0
- package/esm/team/team.mjs +94 -0
- package/esm/team/team.mjs.map +1 -0
- package/esm/tool/executable-as-tool.d.mts.map +1 -1
- package/esm/tool/executable-as-tool.mjs +2 -2
- package/esm/tool/executable-as-tool.mjs.map +1 -1
- package/esm/tool/tool.d.mts.map +1 -1
- package/esm/tool/tool.mjs +2 -2
- package/esm/tool/tool.mjs.map +1 -1
- package/esm/transcribe/audio-input.d.mts +47 -0
- package/esm/transcribe/audio-input.d.mts.map +1 -0
- package/esm/transcribe/audio-input.mjs +84 -0
- package/esm/transcribe/audio-input.mjs.map +1 -0
- package/esm/transcribe/index.mjs +4 -0
- package/esm/transcribe/transcribe.d.mts +64 -0
- package/esm/transcribe/transcribe.d.mts.map +1 -0
- package/esm/transcribe/transcribe.mjs +128 -0
- package/esm/transcribe/transcribe.mjs.map +1 -0
- package/esm/utils/compute-cost.d.mts +17 -1
- package/esm/utils/compute-cost.d.mts.map +1 -1
- package/esm/utils/compute-cost.mjs +26 -1
- package/esm/utils/compute-cost.mjs.map +1 -1
- package/esm/utils/extract-json-lenient.d.mts +42 -0
- package/esm/utils/extract-json-lenient.d.mts.map +1 -0
- package/esm/utils/extract-json-lenient.mjs +97 -0
- package/esm/utils/extract-json-lenient.mjs.map +1 -0
- package/esm/utils/index.d.mts +4 -2
- package/esm/utils/index.mjs +3 -1
- package/esm/utils/json-schema.d.mts +1 -1
- package/esm/utils/prepare-attachment-part.d.mts +10 -1
- package/esm/utils/prepare-attachment-part.d.mts.map +1 -1
- package/esm/utils/prepare-attachment-part.mjs +103 -11
- package/esm/utils/prepare-attachment-part.mjs.map +1 -1
- package/esm/utils/resolve-attachment.d.mts +4 -3
- package/esm/utils/resolve-attachment.d.mts.map +1 -1
- package/esm/utils/resolve-attachment.mjs +4 -3
- package/esm/utils/resolve-attachment.mjs.map +1 -1
- package/esm/utils/run-context.d.mts +94 -0
- package/esm/utils/run-context.d.mts.map +1 -0
- package/esm/utils/run-context.mjs +98 -0
- package/esm/utils/run-context.mjs.map +1 -0
- package/esm/vcr/cassette-io.mjs +57 -0
- package/esm/vcr/cassette-io.mjs.map +1 -0
- package/esm/vcr/errors.d.mts +42 -0
- package/esm/vcr/errors.d.mts.map +1 -0
- package/esm/vcr/errors.mjs +37 -0
- package/esm/vcr/errors.mjs.map +1 -0
- package/esm/vcr/hash-request.d.mts +28 -0
- package/esm/vcr/hash-request.d.mts.map +1 -0
- package/esm/vcr/hash-request.mjs +118 -0
- package/esm/vcr/hash-request.mjs.map +1 -0
- package/esm/vcr/index.d.mts +4 -0
- package/esm/vcr/index.mjs +5 -0
- package/esm/vcr/vcr.d.mts +32 -0
- package/esm/vcr/vcr.d.mts.map +1 -0
- package/esm/vcr/vcr.mjs +248 -0
- package/esm/vcr/vcr.mjs.map +1 -0
- package/esm/vcr/vcr.type.d.mts +118 -0
- package/esm/vcr/vcr.type.d.mts.map +1 -0
- package/esm/workflow/as-tool.mjs +2 -2
- package/esm/workflow/as-tool.mjs.map +1 -1
- package/esm/workflow/engine.mjs +1 -0
- package/esm/workflow/engine.mjs.map +1 -1
- package/esm/workflow/step-runner.mjs +19 -20
- package/esm/workflow/step-runner.mjs.map +1 -1
- package/esm/workflow/workflow.d.mts.map +1 -1
- package/esm/workflow/workflow.mjs +8 -3
- package/esm/workflow/workflow.mjs.map +1 -1
- package/llms-full.txt +2572 -204
- package/llms.txt +21 -4
- package/package.json +7 -3
- package/skills/README.md +44 -4
- package/skills/ai-dx-helpers/SKILL.md +2 -2
- package/skills/approve-tool-calls/SKILL.md +134 -0
- package/skills/attach-ai-middleware/SKILL.md +1 -1
- package/skills/detect-and-redact-pii/SKILL.md +104 -0
- package/skills/durable-agent-runs/SKILL.md +135 -0
- package/skills/durable-resume/SKILL.md +128 -0
- package/skills/escalate-block-to-human/SKILL.md +85 -0
- package/skills/eval-datasets-and-ci/SKILL.md +117 -0
- package/skills/generate-images/SKILL.md +138 -0
- package/skills/generate-speech/SKILL.md +139 -0
- package/skills/guard-input-output/SKILL.md +117 -0
- package/skills/manage-prompts/SKILL.md +186 -0
- package/skills/observe-ai-flows/SKILL.md +94 -0
- package/skills/rag-loaders-and-stores/SKILL.md +164 -0
- package/skills/record-replay-llm/SKILL.md +92 -0
- package/skills/run-ai-agent/SKILL.md +26 -1
- package/skills/run-ai-rag/SKILL.md +139 -0
- package/skills/run-ai-team/SKILL.md +107 -0
- package/skills/run-orchestrator/SKILL.md +2 -0
- package/skills/run-planner/SKILL.md +73 -8
- package/skills/run-supervisor/SKILL.md +20 -1
- package/skills/transcribe-audio/SKILL.md +157 -0
- package/skills/use-runtime-skills/SKILL.md +106 -0
- package/skills/write-system-prompt/SKILL.md +30 -1
- package/cjs/index.cjs.map +0 -1
- package/esm/contracts/result/index.d.mts +0 -15
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { ApprovalRequest } from "./approval.type.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../@warlock.js/ai/src/human/contracts/interrupt-store.contract.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Lifecycle status of a persisted interrupt.
|
|
6
|
+
*
|
|
7
|
+
* `"pending"` until a decision lands; the record is marked
|
|
8
|
+
* `"resolved"` (then deleted) once `ai.human.resume(...)` applies a
|
|
9
|
+
* decision. Discriminator is `status` (a closed string union), so a
|
|
10
|
+
* caller can branch idempotently — a second resume of a `"resolved"`
|
|
11
|
+
* (or already-deleted) interrupt is a no-op, never a double-apply.
|
|
12
|
+
*/
|
|
13
|
+
type PendingInterruptStatus = "pending" | "resolved";
|
|
14
|
+
/**
|
|
15
|
+
* A persisted, awaiting-decision interrupt — the durable counterpart of
|
|
16
|
+
* an in-flight {@link ApprovalRequest}.
|
|
17
|
+
*
|
|
18
|
+
* Mirrors the shape the snapshot/checkpoint stores persist: a flat
|
|
19
|
+
* record keyed by a single id (`interruptId`) that the store round-trips
|
|
20
|
+
* verbatim. The `request` is everything a reviewer (in another process,
|
|
21
|
+
* hours later) needs to rule on the call; `status` tracks the lifecycle;
|
|
22
|
+
* `savedAt` is the ISO-8601 write time.
|
|
23
|
+
*/
|
|
24
|
+
interface PendingInterrupt {
|
|
25
|
+
/** Stable id; the store keys the record on it. */
|
|
26
|
+
interruptId: string;
|
|
27
|
+
/** The pending call the human is asked to rule on. */
|
|
28
|
+
request: ApprovalRequest;
|
|
29
|
+
/** `"pending"` until a decision lands; then `"resolved"` and deleted. */
|
|
30
|
+
status: PendingInterruptStatus;
|
|
31
|
+
/** When the record was written, as an ISO-8601 timestamp. */
|
|
32
|
+
savedAt: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Durable store for {@link PendingInterrupt} records — the persistence
|
|
36
|
+
* seam behind durable human-in-the-loop approval.
|
|
37
|
+
*
|
|
38
|
+
* Deliberately shaped like the `@warlock.js/ai`
|
|
39
|
+
* `SnapshotStore` / `CheckpointStore` contracts (`load` / `save` /
|
|
40
|
+
* `delete` / optional `list` / `schema`), so a consumer already running
|
|
41
|
+
* an orchestrator can reuse the **same** `pg.Pool` / redis client for
|
|
42
|
+
* the interrupt table. Keyed by `interruptId`. Schema is never
|
|
43
|
+
* auto-migrated — {@link InterruptStore.schema} returns a DDL string the
|
|
44
|
+
* dev runs through their own migration tooling.
|
|
45
|
+
*
|
|
46
|
+
* Implementations: `ai.human.interrupt.{memory,pg,redis}()`. The memory
|
|
47
|
+
* impl ships first (pure in-process `Map`, zero deps); pg/redis lazily
|
|
48
|
+
* import their client via {@link PgClientLike} / {@link RedisClientLike}
|
|
49
|
+
* so neither driver is a hard dependency.
|
|
50
|
+
*/
|
|
51
|
+
interface InterruptStore {
|
|
52
|
+
/**
|
|
53
|
+
* Persist a pending interrupt, keyed by its own `interruptId`.
|
|
54
|
+
* Overwrites any prior record for the same id (a call has exactly one
|
|
55
|
+
* live interrupt).
|
|
56
|
+
*/
|
|
57
|
+
save(record: PendingInterrupt): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Load the interrupt for an `interruptId`, or `undefined` when none is
|
|
60
|
+
* recorded (never raised, or already resolved + deleted).
|
|
61
|
+
*/
|
|
62
|
+
load(interruptId: string): Promise<PendingInterrupt | undefined>;
|
|
63
|
+
/**
|
|
64
|
+
* Drop the interrupt for an `interruptId`. Idempotent — deleting an
|
|
65
|
+
* absent id is a no-op.
|
|
66
|
+
*/
|
|
67
|
+
delete(interruptId: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* List the interrupt ids the store knows, optionally filtered by a
|
|
70
|
+
* prefix. Optional — stores that can't enumerate (e.g. a key/value
|
|
71
|
+
* driver with no `SCAN`) omit it.
|
|
72
|
+
*/
|
|
73
|
+
list?(prefix?: string): Promise<string[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Return the DDL string for this store's backing table. The dev runs
|
|
76
|
+
* it through their migration tool; the framework never auto-migrates.
|
|
77
|
+
* Stores with no backing table (memory, redis) return an empty string
|
|
78
|
+
* so callers can treat `schema()` uniformly across drivers.
|
|
79
|
+
*/
|
|
80
|
+
schema(): string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Minimal `pg`-compatible client surface the Postgres
|
|
84
|
+
* {@link InterruptStore} depends on. Both `pg.Pool` and `pg.Client`
|
|
85
|
+
* satisfy it — the store only ever calls `query`.
|
|
86
|
+
*
|
|
87
|
+
* `@warlock.js/ai` takes **no** hard dependency on `pg`; the dev
|
|
88
|
+
* installs it (an optional peer) and passes the client in. Structurally
|
|
89
|
+
* identical to the orchestrator stores' `PgClientLike`, so a single pool
|
|
90
|
+
* can back the checkpoint/snapshot stores and the interrupt table alike.
|
|
91
|
+
*/
|
|
92
|
+
interface PgClientLike {
|
|
93
|
+
query(text: string, params?: unknown[]): Promise<{
|
|
94
|
+
rows: unknown[];
|
|
95
|
+
}>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Minimal `redis`-compatible client surface the Redis
|
|
99
|
+
* {@link InterruptStore} depends on.
|
|
100
|
+
*
|
|
101
|
+
* `@warlock.js/ai` takes **no** hard dependency on `redis`; the dev
|
|
102
|
+
* installs it (an optional peer) and passes the connected client in. The
|
|
103
|
+
* store only calls `get` / `set` / `del`.
|
|
104
|
+
*/
|
|
105
|
+
interface RedisClientLike {
|
|
106
|
+
get(key: string): Promise<string | null>;
|
|
107
|
+
set(key: string, value: string, ...args: unknown[]): Promise<unknown>;
|
|
108
|
+
del(key: string): Promise<number>;
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { InterruptStore, PendingInterrupt, PendingInterruptStatus, PgClientLike, RedisClientLike };
|
|
112
|
+
//# sourceMappingURL=interrupt-store.contract.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interrupt-store.contract.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/human/contracts/interrupt-store.contract.ts"],"mappings":";;;;;AAWA;;;;AAAkC;AAYlC;;KAZY,sBAAA;;;;;;;;;AAuBH;AAoBT;UA/BiB,gBAAA;;EAEf,WAAA;EAmCgC;EAhChC,OAAA,EAAS,eAAA;EAsCkB;EAnC3B,MAAA,EAAQ,sBAAsB;EAgDN;EA7CxB,OAAA;AAAA;;;;;;;;;;;;;;;;;AAqDM;UAjCS,cAAA;EA8CY;;;;;EAxC3B,IAAA,CAAK,MAAA,EAAQ,gBAAA,GAAmB,OAAA;EAyCS;;;AAAc;EAnCvD,IAAA,CAAK,WAAA,WAAsB,OAAA,CAAQ,gBAAA;EA8CL;;;;EAxC9B,MAAA,CAAO,WAAA,WAAsB,OAAA;EA2CJ;;;;;EApCzB,IAAA,EAAM,MAAA,YAAkB,OAAA;EAmCpB;;;;;;EA3BJ,MAAA;AAAA;AA4ByB;;;;;;;;;;AAAA,UAfV,YAAA;EACf,KAAA,CAAM,IAAA,UAAc,MAAA,eAAqB,OAAO;IAAG,IAAA;EAAA;AAAA;;;;;;;;;UAWpC,eAAA;EACf,GAAA,CAAI,GAAA,WAAc,OAAA;EAClB,GAAA,CAAI,GAAA,UAAa,KAAA,aAAkB,IAAA,cAAkB,OAAA;EACrD,GAAA,CAAI,GAAA,WAAc,OAAA;AAAA"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { AgentResult } from "../../contracts/result/agent-result.type.mjs";
|
|
2
|
+
import { AgentContract } from "../../contracts/agent/agent.contract.mjs";
|
|
3
|
+
import { AgentExecuteOptions } from "../../contracts/agent/agent-options.type.mjs";
|
|
4
|
+
import { ApprovalDecision } from "./approval.type.mjs";
|
|
5
|
+
import { InterruptStore } from "./interrupt-store.contract.mjs";
|
|
6
|
+
|
|
7
|
+
//#region ../@warlock.js/ai/src/human/contracts/resume.type.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* Options for `ai.human.resume(interruptId, decision, options)` — the
|
|
10
|
+
* out-of-process resume entry point behind durable human-in-the-loop
|
|
11
|
+
* approval.
|
|
12
|
+
*
|
|
13
|
+
* The `store` is always required: it is where the persisted
|
|
14
|
+
* {@link import("./interrupt-store.contract").PendingInterrupt} is loaded
|
|
15
|
+
* from and deleted after the decision is applied.
|
|
16
|
+
*
|
|
17
|
+
* **Two resume shapes share this one options bag:**
|
|
18
|
+
* - **apply-only** — omit `agent`. The decision is loaded, validated
|
|
19
|
+
* against the persisted request, the pending record is deleted, and the
|
|
20
|
+
* `{ interruptId, decision }` is returned for the caller to re-drive the
|
|
21
|
+
* agent itself (e.g. a custom transport). No turn is re-run.
|
|
22
|
+
* - **re-run** — pass `agent` (and optionally an `input` override). v1
|
|
23
|
+
* durable resume re-executes the agent turn with the decision
|
|
24
|
+
* **pre-seeded**, so the gated tool call this time resolves to the
|
|
25
|
+
* human's ruling instead of pausing again. The original prompt is
|
|
26
|
+
* re-used unless `input` overrides it.
|
|
27
|
+
*/
|
|
28
|
+
interface ResumeOptions<TOutput = unknown> {
|
|
29
|
+
/**
|
|
30
|
+
* The durable store holding the {@link PendingInterrupt}. Loaded to find
|
|
31
|
+
* the original request, then deleted once the decision is applied.
|
|
32
|
+
*/
|
|
33
|
+
store: InterruptStore;
|
|
34
|
+
/**
|
|
35
|
+
* The agent to re-drive with the decision pre-seeded. Omit for the
|
|
36
|
+
* apply-only shape (load + validate + delete, return the decision for a
|
|
37
|
+
* caller-owned re-drive).
|
|
38
|
+
*/
|
|
39
|
+
agent?: AgentContract<TOutput>;
|
|
40
|
+
/**
|
|
41
|
+
* Prompt for the re-run. Defaults to the original prompt captured on the
|
|
42
|
+
* persisted {@link PendingInterrupt} request context; pass it to override
|
|
43
|
+
* (e.g. to append the reviewer's note). Ignored when `agent` is omitted.
|
|
44
|
+
*/
|
|
45
|
+
input?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Extra options forwarded to `agent.execute(input, executeOptions)` on
|
|
48
|
+
* the re-run (history, placeholders, output schema, signal, …). Ignored
|
|
49
|
+
* when `agent` is omitted.
|
|
50
|
+
*/
|
|
51
|
+
executeOptions?: AgentExecuteOptions<TOutput>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Outcome of `ai.human.resume(...)`.
|
|
55
|
+
*
|
|
56
|
+
* A discriminated union keyed on `type` (never `kind`):
|
|
57
|
+
* - `"applied"` — a live `"pending"` interrupt was found, the decision was
|
|
58
|
+
* applied, and the record deleted. When the caller passed an `agent`,
|
|
59
|
+
* `result` carries the re-run's {@link AgentResult}; otherwise the caller
|
|
60
|
+
* re-drives the agent itself using the returned `decision`.
|
|
61
|
+
* - `"already-resolved"` — no live interrupt for this id (already resolved
|
|
62
|
+
* + deleted, or never raised). Idempotent no-op — the decision is **not**
|
|
63
|
+
* re-applied and no turn is re-run, mirroring the orchestrator resume's
|
|
64
|
+
* drain idempotency.
|
|
65
|
+
*/
|
|
66
|
+
type ResumeResult<TOutput = unknown> = {
|
|
67
|
+
type: "applied"; /** The id of the interrupt the decision was applied to. */
|
|
68
|
+
interruptId: string; /** The decision that was applied. */
|
|
69
|
+
decision: ApprovalDecision; /** The re-run agent result, present only when an `agent` was supplied. */
|
|
70
|
+
result?: AgentResult<TOutput>;
|
|
71
|
+
} | {
|
|
72
|
+
type: "already-resolved"; /** The id that had no live interrupt to resume. */
|
|
73
|
+
interruptId: string;
|
|
74
|
+
};
|
|
75
|
+
//#endregion
|
|
76
|
+
export { ResumeOptions, ResumeResult };
|
|
77
|
+
//# sourceMappingURL=resume.type.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.type.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/human/contracts/resume.type.ts"],"mappings":";;;;;;;;;AA0BA;;;;;;;;;;;;;;;;;;UAAiB,aAAA;EA0BsB;;AAAO;AAgB9C;EArCE,KAAA,EAAO,cAAA;EAqCe;;;;;EA9BtB,KAAA,GAAQ,aAAA,CAAc,OAAA;EA8BC;;;;;EAvBvB,KAAA;EA+Ba;;;;;EAxBb,cAAA,GAAiB,mBAAA,CAAoB,OAAA;AAAA;;;;;;;;;;;;;;KAgB3B,YAAA;EAEN,IAAA;EAEA,WAAA;EAEA,QAAA,EAAU,gBAAA;EAEV,MAAA,GAAS,WAAA,CAAY,OAAA;AAAA;EAGrB,IAAA;EAEA,WAAA;AAAA"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { AIError, AIErrorOptions } from "../errors/ai-error.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../@warlock.js/ai/src/human/errors.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Stable, machine-readable codes this package raises.
|
|
6
|
+
*
|
|
7
|
+
* `@warlock.js/ai`'s `AIErrorCode` is a closed union that (by design)
|
|
8
|
+
* does not enumerate satellite-package codes, and this package must not
|
|
9
|
+
* modify the core union. These codes are therefore declared locally and
|
|
10
|
+
* narrowed into the base `AIError` `code` slot at the single `super(...)`
|
|
11
|
+
* call — the runtime string is exactly what a consumer branches on via
|
|
12
|
+
* `error.code`, identical to every other `AIError`.
|
|
13
|
+
*/
|
|
14
|
+
type HumanErrorCode = "INTERRUPT_SUSPENDED" | "APPROVAL_REJECTED";
|
|
15
|
+
/**
|
|
16
|
+
* Payload for {@link InterruptSuspendedError}. `interruptId` is the key a
|
|
17
|
+
* later `ai.human.resume(interruptId, decision)` call uses to replay the
|
|
18
|
+
* decision against the persisted interrupt.
|
|
19
|
+
*/
|
|
20
|
+
type InterruptSuspendedErrorOptions = AIErrorOptions & {
|
|
21
|
+
/** Id of the persisted interrupt awaiting a decision. */interruptId: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* A durable approval handler suspended the run rather than denying the
|
|
25
|
+
* call.
|
|
26
|
+
*
|
|
27
|
+
* **Role.** The sentinel a durable {@link import("./contracts").ApprovalHandler}
|
|
28
|
+
* throws after persisting a
|
|
29
|
+
* {@link import("./contracts").PendingInterrupt}. The approval
|
|
30
|
+
* middleware recognizes its own sentinel (an `instanceof` check) and
|
|
31
|
+
* re-throws so the agent run unwinds; the dispatch records it as a failed
|
|
32
|
+
* tool call carrying this typed error. The caller reads
|
|
33
|
+
* `error.interruptId` off the surfaced `result.error`, surfaces it to the
|
|
34
|
+
* reviewer, and later calls `ai.human.resume(...)`.
|
|
35
|
+
*
|
|
36
|
+
* Surfaced via `result.error` like every other `AIError` — the middleware
|
|
37
|
+
* never lets it escape `execute()`.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* if (result.error instanceof InterruptSuspendedError) {
|
|
41
|
+
* await notifyReviewer(result.error.interruptId);
|
|
42
|
+
* return { status: "awaiting-approval", interruptId: result.error.interruptId };
|
|
43
|
+
* }
|
|
44
|
+
*/
|
|
45
|
+
declare class InterruptSuspendedError extends AIError {
|
|
46
|
+
/** Id of the persisted interrupt awaiting a human decision. */
|
|
47
|
+
readonly interruptId: string;
|
|
48
|
+
constructor(message: string, options: InterruptSuspendedErrorOptions);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Payload for {@link ApprovalRejectedError}. `reason` is the reviewer's
|
|
52
|
+
* explanation, surfaced to the model on the next trip so it can
|
|
53
|
+
* self-correct; `toolName` names the call that was rejected.
|
|
54
|
+
*/
|
|
55
|
+
type ApprovalRejectedErrorOptions = AIErrorOptions & {
|
|
56
|
+
/** The reviewer's explanation for rejecting the call. */reason: string; /** Name of the tool whose call was rejected. */
|
|
57
|
+
toolName: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* A human rejected a gated tool call.
|
|
61
|
+
*
|
|
62
|
+
* **Role.** The typed result of an `{ type: "reject", reason }` decision.
|
|
63
|
+
* The approval middleware throws it from `tool.before`; the agent
|
|
64
|
+
* dispatch records a failed tool call and writes a `role: "tool"`
|
|
65
|
+
* message carrying `reason`, so the **next trip lets the model
|
|
66
|
+
* self-correct** — exactly the existing tool-error feedback path.
|
|
67
|
+
*
|
|
68
|
+
* Surfaced via `result.error` like every other `AIError`.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* if (result.error instanceof ApprovalRejectedError) {
|
|
72
|
+
* logAudit(`${result.error.toolName} rejected: ${result.error.reason}`);
|
|
73
|
+
* }
|
|
74
|
+
*/
|
|
75
|
+
declare class ApprovalRejectedError extends AIError {
|
|
76
|
+
/** The reviewer's explanation for rejecting the call. */
|
|
77
|
+
readonly reason: string;
|
|
78
|
+
/** Name of the tool whose call was rejected. */
|
|
79
|
+
readonly toolName: string;
|
|
80
|
+
constructor(message: string, options: ApprovalRejectedErrorOptions);
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { ApprovalRejectedError, ApprovalRejectedErrorOptions, HumanErrorCode, InterruptSuspendedError, InterruptSuspendedErrorOptions };
|
|
84
|
+
//# sourceMappingURL=errors.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/human/errors.ts"],"mappings":";;;;;AAaA;;;;AAA0B;AAO1B;;;KAPY,cAAA;AASC;AAyBb;;;;AAzBa,KAFD,8BAAA,GAAiC,cAAc;EA6BzC,yDA3BhB,WAAW;AAAA;;;;AA6BgE;AAa7E;;;;;;;;AAIU;AAmBV;;;;;;;;;cAxCa,uBAAA,SAAgC,OAAO;EA+Cd;EAAA,SA7CpB,WAAA;cAEG,OAAA,UAAiB,OAAA,EAAS,8BAAA;AAAA;;;;;;KAanC,4BAAA,GAA+B,cAAc;2DAEvD,MAAA;EAEA,QAAA;AAAA;;;;;;;;;;;;;;;;;cAmBW,qBAAA,SAA8B,OAAO;;WAEhC,MAAA;;WAGA,QAAA;cAEG,OAAA,UAAiB,OAAA,EAAS,4BAAA;AAAA"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AIError } from "../errors/ai-error.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../@warlock.js/ai/src/human/errors.ts
|
|
4
|
+
/**
|
|
5
|
+
* A durable approval handler suspended the run rather than denying the
|
|
6
|
+
* call.
|
|
7
|
+
*
|
|
8
|
+
* **Role.** The sentinel a durable {@link import("./contracts").ApprovalHandler}
|
|
9
|
+
* throws after persisting a
|
|
10
|
+
* {@link import("./contracts").PendingInterrupt}. The approval
|
|
11
|
+
* middleware recognizes its own sentinel (an `instanceof` check) and
|
|
12
|
+
* re-throws so the agent run unwinds; the dispatch records it as a failed
|
|
13
|
+
* tool call carrying this typed error. The caller reads
|
|
14
|
+
* `error.interruptId` off the surfaced `result.error`, surfaces it to the
|
|
15
|
+
* reviewer, and later calls `ai.human.resume(...)`.
|
|
16
|
+
*
|
|
17
|
+
* Surfaced via `result.error` like every other `AIError` — the middleware
|
|
18
|
+
* never lets it escape `execute()`.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* if (result.error instanceof InterruptSuspendedError) {
|
|
22
|
+
* await notifyReviewer(result.error.interruptId);
|
|
23
|
+
* return { status: "awaiting-approval", interruptId: result.error.interruptId };
|
|
24
|
+
* }
|
|
25
|
+
*/
|
|
26
|
+
var InterruptSuspendedError = class extends AIError {
|
|
27
|
+
constructor(message, options) {
|
|
28
|
+
super("INTERRUPT_SUSPENDED", message, options);
|
|
29
|
+
this.name = "InterruptSuspendedError";
|
|
30
|
+
this.interruptId = options.interruptId;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A human rejected a gated tool call.
|
|
35
|
+
*
|
|
36
|
+
* **Role.** The typed result of an `{ type: "reject", reason }` decision.
|
|
37
|
+
* The approval middleware throws it from `tool.before`; the agent
|
|
38
|
+
* dispatch records a failed tool call and writes a `role: "tool"`
|
|
39
|
+
* message carrying `reason`, so the **next trip lets the model
|
|
40
|
+
* self-correct** — exactly the existing tool-error feedback path.
|
|
41
|
+
*
|
|
42
|
+
* Surfaced via `result.error` like every other `AIError`.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* if (result.error instanceof ApprovalRejectedError) {
|
|
46
|
+
* logAudit(`${result.error.toolName} rejected: ${result.error.reason}`);
|
|
47
|
+
* }
|
|
48
|
+
*/
|
|
49
|
+
var ApprovalRejectedError = class extends AIError {
|
|
50
|
+
constructor(message, options) {
|
|
51
|
+
super("APPROVAL_REJECTED", message, options);
|
|
52
|
+
this.name = "ApprovalRejectedError";
|
|
53
|
+
this.reason = options.reason;
|
|
54
|
+
this.toolName = options.toolName;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
export { ApprovalRejectedError, InterruptSuspendedError };
|
|
60
|
+
//# sourceMappingURL=errors.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/human/errors.ts"],"sourcesContent":["import { AIError, type AIErrorOptions } from \"../errors/ai-error\";\nimport type { AIErrorCode } from \"../errors/error-code.type\";\n\n/**\n * Stable, machine-readable codes this package raises.\n *\n * `@warlock.js/ai`'s `AIErrorCode` is a closed union that (by design)\n * does not enumerate satellite-package codes, and this package must not\n * modify the core union. These codes are therefore declared locally and\n * narrowed into the base `AIError` `code` slot at the single `super(...)`\n * call — the runtime string is exactly what a consumer branches on via\n * `error.code`, identical to every other `AIError`.\n */\nexport type HumanErrorCode = \"INTERRUPT_SUSPENDED\" | \"APPROVAL_REJECTED\";\n\n/**\n * Payload for {@link InterruptSuspendedError}. `interruptId` is the key a\n * later `ai.human.resume(interruptId, decision)` call uses to replay the\n * decision against the persisted interrupt.\n */\nexport type InterruptSuspendedErrorOptions = AIErrorOptions & {\n /** Id of the persisted interrupt awaiting a decision. */\n interruptId: string;\n};\n\n/**\n * A durable approval handler suspended the run rather than denying the\n * call.\n *\n * **Role.** The sentinel a durable {@link import(\"./contracts\").ApprovalHandler}\n * throws after persisting a\n * {@link import(\"./contracts\").PendingInterrupt}. The approval\n * middleware recognizes its own sentinel (an `instanceof` check) and\n * re-throws so the agent run unwinds; the dispatch records it as a failed\n * tool call carrying this typed error. The caller reads\n * `error.interruptId` off the surfaced `result.error`, surfaces it to the\n * reviewer, and later calls `ai.human.resume(...)`.\n *\n * Surfaced via `result.error` like every other `AIError` — the middleware\n * never lets it escape `execute()`.\n *\n * @example\n * if (result.error instanceof InterruptSuspendedError) {\n * await notifyReviewer(result.error.interruptId);\n * return { status: \"awaiting-approval\", interruptId: result.error.interruptId };\n * }\n */\nexport class InterruptSuspendedError extends AIError {\n /** Id of the persisted interrupt awaiting a human decision. */\n public readonly interruptId: string;\n\n public constructor(message: string, options: InterruptSuspendedErrorOptions) {\n super(\"INTERRUPT_SUSPENDED\" as AIErrorCode, message, options);\n\n this.name = \"InterruptSuspendedError\";\n this.interruptId = options.interruptId;\n }\n}\n\n/**\n * Payload for {@link ApprovalRejectedError}. `reason` is the reviewer's\n * explanation, surfaced to the model on the next trip so it can\n * self-correct; `toolName` names the call that was rejected.\n */\nexport type ApprovalRejectedErrorOptions = AIErrorOptions & {\n /** The reviewer's explanation for rejecting the call. */\n reason: string;\n /** Name of the tool whose call was rejected. */\n toolName: string;\n};\n\n/**\n * A human rejected a gated tool call.\n *\n * **Role.** The typed result of an `{ type: \"reject\", reason }` decision.\n * The approval middleware throws it from `tool.before`; the agent\n * dispatch records a failed tool call and writes a `role: \"tool\"`\n * message carrying `reason`, so the **next trip lets the model\n * self-correct** — exactly the existing tool-error feedback path.\n *\n * Surfaced via `result.error` like every other `AIError`.\n *\n * @example\n * if (result.error instanceof ApprovalRejectedError) {\n * logAudit(`${result.error.toolName} rejected: ${result.error.reason}`);\n * }\n */\nexport class ApprovalRejectedError extends AIError {\n /** The reviewer's explanation for rejecting the call. */\n public readonly reason: string;\n\n /** Name of the tool whose call was rejected. */\n public readonly toolName: string;\n\n public constructor(message: string, options: ApprovalRejectedErrorOptions) {\n super(\"APPROVAL_REJECTED\" as AIErrorCode, message, options);\n\n this.name = \"ApprovalRejectedError\";\n this.reason = options.reason;\n this.toolName = options.toolName;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,IAAa,0BAAb,cAA6C,QAAQ;CAInD,AAAO,YAAY,SAAiB,SAAyC;EAC3E,MAAM,uBAAsC,SAAS,OAAO;EAE5D,KAAK,OAAO;EACZ,KAAK,cAAc,QAAQ;CAC7B;AACF;;;;;;;;;;;;;;;;;AA8BA,IAAa,wBAAb,cAA2C,QAAQ;CAOjD,AAAO,YAAY,SAAiB,SAAuC;EACzE,MAAM,qBAAoC,SAAS,OAAO;EAE1D,KAAK,OAAO;EACZ,KAAK,SAAS,QAAQ;EACtB,KAAK,WAAW,QAAQ;CAC1B;AACF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { AgentMiddleware } from "../contracts/middleware/middleware.contract.mjs";
|
|
2
|
+
import { HumanApprovalOptions } from "./contracts/human-approval.type.mjs";
|
|
3
|
+
//#region ../@warlock.js/ai/src/human/human-approval.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Human-in-the-loop approval gate for an agent's tool calls — the
|
|
6
|
+
* middleware behind `ai.human.approval(options)`.
|
|
7
|
+
*
|
|
8
|
+
* **Role.** Pauses *before a specific tool call* and routes it to a human
|
|
9
|
+
* who can **approve** (run the real tool unchanged), **reject** (the model
|
|
10
|
+
* sees a typed error and self-corrects), or **edit** (run the tool with
|
|
11
|
+
* reviewer-replaced args). The dangerous subset is chosen by an
|
|
12
|
+
* {@link import("./contracts").InterruptPolicy} (allowlist / denylist /
|
|
13
|
+
* predicate); every other call passes through untouched.
|
|
14
|
+
*
|
|
15
|
+
* **One hook.** Declares only `tool.before`. On each tool dispatch it:
|
|
16
|
+
* 1. evaluates the policy — not gated → returns `void`, the real tool runs;
|
|
17
|
+
* 2. for a gated call, builds an {@link ApprovalRequest} and calls the
|
|
18
|
+
* {@link import("./contracts").ApprovalHandler};
|
|
19
|
+
* 3. applies the returned {@link ApprovalDecision}:
|
|
20
|
+
* - `approve` → returns `void`, the real tool runs;
|
|
21
|
+
* - `reject` → short-circuits a failed `ToolInvokeResult` carrying an
|
|
22
|
+
* {@link ApprovalRejectedError} (the reviewer's `reason` reaches the
|
|
23
|
+
* model);
|
|
24
|
+
* - `edit` → rewrites `ctx.request.input` to the reviewer's args and
|
|
25
|
+
* returns `void`, so the real tool runs with the edited args (schema
|
|
26
|
+
* validation still applies — bad edits surface as a tool error).
|
|
27
|
+
*
|
|
28
|
+
* **Durable mode.** When a `store` is configured and the handler throws
|
|
29
|
+
* {@link InterruptSuspendedError} (after persisting the interrupt
|
|
30
|
+
* out-of-band), the middleware catches its **own** sentinel and
|
|
31
|
+
* short-circuits a failed result carrying it — so the caller reads
|
|
32
|
+
* `result.error.interruptId` and later calls
|
|
33
|
+
* `ai.human.resume(interruptId, decision)`. The middleware **never throws
|
|
34
|
+
* out of the pipeline**: every outcome (skip, approve, reject, edit,
|
|
35
|
+
* suspend) returns normally; only a *handler bug* (a non-sentinel throw)
|
|
36
|
+
* propagates, and even then the agent dispatch funnels it onto
|
|
37
|
+
* `result.error` — `execute()` still never throws.
|
|
38
|
+
*
|
|
39
|
+
* @param options - Policy, handler, optional durable store, optional name.
|
|
40
|
+
* @returns An {@link AgentMiddleware} declaring a single `tool.before` hook.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* const support = ai.agent({
|
|
44
|
+
* model,
|
|
45
|
+
* tools: [refundCustomer],
|
|
46
|
+
* middleware: [
|
|
47
|
+
* humanApproval({
|
|
48
|
+
* policy: { type: "allowlist", tools: ["refundCustomer"], tags: () => ["money"] },
|
|
49
|
+
* handler: async (req) => ui.prompt(req), // { type: "edit", args: { amount: 5 } }
|
|
50
|
+
* }),
|
|
51
|
+
* ],
|
|
52
|
+
* });
|
|
53
|
+
*/
|
|
54
|
+
declare function humanApproval(options: HumanApprovalOptions): AgentMiddleware;
|
|
55
|
+
//#endregion
|
|
56
|
+
export { humanApproval };
|
|
57
|
+
//# sourceMappingURL=human-approval.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"human-approval.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/human/human-approval.ts"],"mappings":";;;;;;AAyKA;;;;;;;;AAA6E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA7D,aAAA,CAAc,OAAA,EAAS,oBAAA,GAAuB,eAAe"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { generateRunId } from "../utils/generate-run-id.mjs";
|
|
2
|
+
import { ApprovalRejectedError, InterruptSuspendedError } from "./errors.mjs";
|
|
3
|
+
import { evaluatePolicy } from "./policy.mjs";
|
|
4
|
+
import { takeSeededDecision } from "./resume-seed.mjs";
|
|
5
|
+
|
|
6
|
+
//#region ../@warlock.js/ai/src/human/human-approval.ts
|
|
7
|
+
/** Default middleware name when {@link HumanApprovalOptions.name} is omitted. */
|
|
8
|
+
const DEFAULT_NAME = "human-approval";
|
|
9
|
+
/** Zero usage for a synthetic, no-LLM-spend short-circuit result. */
|
|
10
|
+
const ZERO_USAGE = Object.freeze({
|
|
11
|
+
input: 0,
|
|
12
|
+
output: 0,
|
|
13
|
+
total: 0
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* Derive the read-only {@link PolicyContext} the policy + request are
|
|
17
|
+
* built from out of the wrapping {@link MiddlewareToolContext}.
|
|
18
|
+
*/
|
|
19
|
+
function toPolicyContext(ctx) {
|
|
20
|
+
return {
|
|
21
|
+
toolName: ctx.tool.name,
|
|
22
|
+
toolDescription: ctx.tool.description,
|
|
23
|
+
args: ctx.request.input,
|
|
24
|
+
agentName: ctx.agent.name,
|
|
25
|
+
tripIndex: ctx.tripIndex,
|
|
26
|
+
sessionId: ctx.options?.sessionId
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate a stable, unique id for a pending interrupt. Shaped
|
|
31
|
+
* `${agentName}.${sessionId ?? "nosession"}.${tripIndex}.${random}` so a
|
|
32
|
+
* reviewer can eyeball the originating run, while the trailing random
|
|
33
|
+
* segment guarantees per-call uniqueness even within one trip.
|
|
34
|
+
*/
|
|
35
|
+
function makeInterruptId(ctx) {
|
|
36
|
+
const session = ctx.options?.sessionId ?? "nosession";
|
|
37
|
+
const random = generateRunId("interrupt");
|
|
38
|
+
return `${ctx.agent.name}.${session}.${ctx.tripIndex}.${random}`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Build the {@link ApprovalRequest} a human rules on, from the tool
|
|
42
|
+
* context and the policy-derived tags.
|
|
43
|
+
*/
|
|
44
|
+
function buildRequest(ctx, interruptId, tags) {
|
|
45
|
+
return {
|
|
46
|
+
interruptId,
|
|
47
|
+
toolName: ctx.tool.name,
|
|
48
|
+
toolDescription: ctx.tool.description,
|
|
49
|
+
args: ctx.request.input,
|
|
50
|
+
context: {
|
|
51
|
+
agentName: ctx.agent.name,
|
|
52
|
+
tripIndex: ctx.tripIndex,
|
|
53
|
+
sessionId: ctx.options?.sessionId,
|
|
54
|
+
originalInput: ctx.input,
|
|
55
|
+
...tags ? { tags } : {}
|
|
56
|
+
},
|
|
57
|
+
requestedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Synthesize a failed {@link ToolInvokeResult} carrying a typed error.
|
|
62
|
+
*
|
|
63
|
+
* The approval middleware returns this from `tool.before` to
|
|
64
|
+
* **short-circuit** the real tool without throwing: the pipeline treats a
|
|
65
|
+
* defined return as the tool's result, the agent records a failed
|
|
66
|
+
* `ToolCall`, and the model sees `{ error }` on the next trip — exactly
|
|
67
|
+
* the existing tool-error feedback path. Used for both `reject`
|
|
68
|
+
* (`ApprovalRejectedError`) and durable suspend (`InterruptSuspendedError`).
|
|
69
|
+
*/
|
|
70
|
+
function failedResult(error, toolName) {
|
|
71
|
+
const runId = generateRunId("tool");
|
|
72
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
73
|
+
return {
|
|
74
|
+
error,
|
|
75
|
+
usage: ZERO_USAGE,
|
|
76
|
+
report: {
|
|
77
|
+
runId,
|
|
78
|
+
rootRunId: runId,
|
|
79
|
+
name: toolName,
|
|
80
|
+
type: "tool",
|
|
81
|
+
status: "failed",
|
|
82
|
+
startedAt: nowIso,
|
|
83
|
+
endedAt: nowIso,
|
|
84
|
+
duration: 0,
|
|
85
|
+
usage: ZERO_USAGE,
|
|
86
|
+
children: []
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Human-in-the-loop approval gate for an agent's tool calls — the
|
|
92
|
+
* middleware behind `ai.human.approval(options)`.
|
|
93
|
+
*
|
|
94
|
+
* **Role.** Pauses *before a specific tool call* and routes it to a human
|
|
95
|
+
* who can **approve** (run the real tool unchanged), **reject** (the model
|
|
96
|
+
* sees a typed error and self-corrects), or **edit** (run the tool with
|
|
97
|
+
* reviewer-replaced args). The dangerous subset is chosen by an
|
|
98
|
+
* {@link import("./contracts").InterruptPolicy} (allowlist / denylist /
|
|
99
|
+
* predicate); every other call passes through untouched.
|
|
100
|
+
*
|
|
101
|
+
* **One hook.** Declares only `tool.before`. On each tool dispatch it:
|
|
102
|
+
* 1. evaluates the policy — not gated → returns `void`, the real tool runs;
|
|
103
|
+
* 2. for a gated call, builds an {@link ApprovalRequest} and calls the
|
|
104
|
+
* {@link import("./contracts").ApprovalHandler};
|
|
105
|
+
* 3. applies the returned {@link ApprovalDecision}:
|
|
106
|
+
* - `approve` → returns `void`, the real tool runs;
|
|
107
|
+
* - `reject` → short-circuits a failed `ToolInvokeResult` carrying an
|
|
108
|
+
* {@link ApprovalRejectedError} (the reviewer's `reason` reaches the
|
|
109
|
+
* model);
|
|
110
|
+
* - `edit` → rewrites `ctx.request.input` to the reviewer's args and
|
|
111
|
+
* returns `void`, so the real tool runs with the edited args (schema
|
|
112
|
+
* validation still applies — bad edits surface as a tool error).
|
|
113
|
+
*
|
|
114
|
+
* **Durable mode.** When a `store` is configured and the handler throws
|
|
115
|
+
* {@link InterruptSuspendedError} (after persisting the interrupt
|
|
116
|
+
* out-of-band), the middleware catches its **own** sentinel and
|
|
117
|
+
* short-circuits a failed result carrying it — so the caller reads
|
|
118
|
+
* `result.error.interruptId` and later calls
|
|
119
|
+
* `ai.human.resume(interruptId, decision)`. The middleware **never throws
|
|
120
|
+
* out of the pipeline**: every outcome (skip, approve, reject, edit,
|
|
121
|
+
* suspend) returns normally; only a *handler bug* (a non-sentinel throw)
|
|
122
|
+
* propagates, and even then the agent dispatch funnels it onto
|
|
123
|
+
* `result.error` — `execute()` still never throws.
|
|
124
|
+
*
|
|
125
|
+
* @param options - Policy, handler, optional durable store, optional name.
|
|
126
|
+
* @returns An {@link AgentMiddleware} declaring a single `tool.before` hook.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* const support = ai.agent({
|
|
130
|
+
* model,
|
|
131
|
+
* tools: [refundCustomer],
|
|
132
|
+
* middleware: [
|
|
133
|
+
* humanApproval({
|
|
134
|
+
* policy: { type: "allowlist", tools: ["refundCustomer"], tags: () => ["money"] },
|
|
135
|
+
* handler: async (req) => ui.prompt(req), // { type: "edit", args: { amount: 5 } }
|
|
136
|
+
* }),
|
|
137
|
+
* ],
|
|
138
|
+
* });
|
|
139
|
+
*/
|
|
140
|
+
function humanApproval(options) {
|
|
141
|
+
const name = options.name ?? DEFAULT_NAME;
|
|
142
|
+
const { policy, handler } = options;
|
|
143
|
+
return {
|
|
144
|
+
name,
|
|
145
|
+
tool: { async before(ctx) {
|
|
146
|
+
const verdict = evaluatePolicy(policy, toPolicyContext(ctx));
|
|
147
|
+
if (!verdict.requiresApproval) return;
|
|
148
|
+
const request = buildRequest(ctx, makeInterruptId(ctx), verdict.tags);
|
|
149
|
+
const seeded = takeSeededDecision(ctx.agent.name);
|
|
150
|
+
let decision;
|
|
151
|
+
if (seeded !== void 0) decision = seeded;
|
|
152
|
+
else try {
|
|
153
|
+
decision = await handler(request);
|
|
154
|
+
} catch (thrown) {
|
|
155
|
+
if (thrown instanceof InterruptSuspendedError) return failedResult(thrown, ctx.tool.name);
|
|
156
|
+
throw thrown;
|
|
157
|
+
}
|
|
158
|
+
if (decision.type === "approve") return;
|
|
159
|
+
if (decision.type === "reject") return failedResult(new ApprovalRejectedError(`Tool call "${ctx.tool.name}" rejected by reviewer — ${decision.reason}`, {
|
|
160
|
+
reason: decision.reason,
|
|
161
|
+
toolName: ctx.tool.name
|
|
162
|
+
}), ctx.tool.name);
|
|
163
|
+
ctx.request.input = decision.args;
|
|
164
|
+
} }
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
//#endregion
|
|
169
|
+
export { humanApproval };
|
|
170
|
+
//# sourceMappingURL=human-approval.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"human-approval.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/human/human-approval.ts"],"sourcesContent":["import type { AgentMiddleware } from \"../contracts/middleware/middleware.contract\";\nimport type { MiddlewareToolContext } from \"../contracts/middleware/middleware-context.type\";\nimport type { BaseReport } from \"../contracts/result/base-report.type\";\nimport type { Usage } from \"../contracts/result/usage.type\";\nimport type { AIError } from \"../errors/ai-error\";\nimport type { ToolInvokeResult } from \"../tool/tool\";\nimport { generateRunId } from \"../utils/generate-run-id\";\nimport type {\n ApprovalDecision,\n ApprovalRequest,\n HumanApprovalOptions,\n PolicyContext,\n} from \"./contracts\";\nimport { ApprovalRejectedError, InterruptSuspendedError } from \"./errors\";\nimport { evaluatePolicy } from \"./policy\";\nimport { takeSeededDecision } from \"./resume-seed\";\n\n/** Default middleware name when {@link HumanApprovalOptions.name} is omitted. */\nconst DEFAULT_NAME = \"human-approval\";\n\n/** Zero usage for a synthetic, no-LLM-spend short-circuit result. */\nconst ZERO_USAGE: Usage = Object.freeze({ input: 0, output: 0, total: 0 });\n\n/**\n * Mutable view of {@link MiddlewareToolContext.request} used only to\n * apply an `edit` decision. The context types `request.input` as\n * `readonly`, but the agent dispatch reads `request.input` (the SAME\n * object) when it invokes the real tool *after* the `tool.before`\n * pipeline returns — so reassigning it here is how an edited-args\n * decision reaches the tool. This narrow local type makes that one\n * deliberate write explicit instead of casting away the whole context.\n */\ninterface MutableToolRequest {\n input: unknown;\n}\n\n/**\n * Derive the read-only {@link PolicyContext} the policy + request are\n * built from out of the wrapping {@link MiddlewareToolContext}.\n */\nfunction toPolicyContext(ctx: MiddlewareToolContext): PolicyContext {\n return {\n toolName: ctx.tool.name,\n toolDescription: ctx.tool.description,\n args: ctx.request.input,\n agentName: ctx.agent.name,\n tripIndex: ctx.tripIndex,\n sessionId: ctx.options?.sessionId,\n };\n}\n\n/**\n * Generate a stable, unique id for a pending interrupt. Shaped\n * `${agentName}.${sessionId ?? \"nosession\"}.${tripIndex}.${random}` so a\n * reviewer can eyeball the originating run, while the trailing random\n * segment guarantees per-call uniqueness even within one trip.\n */\nfunction makeInterruptId(ctx: MiddlewareToolContext): string {\n const session = ctx.options?.sessionId ?? \"nosession\";\n const random = generateRunId(\"interrupt\");\n\n return `${ctx.agent.name}.${session}.${ctx.tripIndex}.${random}`;\n}\n\n/**\n * Build the {@link ApprovalRequest} a human rules on, from the tool\n * context and the policy-derived tags.\n */\nfunction buildRequest(\n ctx: MiddlewareToolContext,\n interruptId: string,\n tags: string[] | undefined,\n): ApprovalRequest {\n return {\n interruptId,\n toolName: ctx.tool.name,\n toolDescription: ctx.tool.description,\n args: ctx.request.input,\n context: {\n agentName: ctx.agent.name,\n tripIndex: ctx.tripIndex,\n sessionId: ctx.options?.sessionId,\n originalInput: ctx.input,\n ...(tags ? { tags } : {}),\n },\n requestedAt: new Date().toISOString(),\n };\n}\n\n/**\n * Synthesize a failed {@link ToolInvokeResult} carrying a typed error.\n *\n * The approval middleware returns this from `tool.before` to\n * **short-circuit** the real tool without throwing: the pipeline treats a\n * defined return as the tool's result, the agent records a failed\n * `ToolCall`, and the model sees `{ error }` on the next trip — exactly\n * the existing tool-error feedback path. Used for both `reject`\n * (`ApprovalRejectedError`) and durable suspend (`InterruptSuspendedError`).\n */\nfunction failedResult(error: AIError, toolName: string): ToolInvokeResult<unknown> {\n const runId = generateRunId(\"tool\");\n const nowIso = new Date().toISOString();\n\n const report: BaseReport = {\n runId,\n rootRunId: runId,\n name: toolName,\n type: \"tool\",\n status: \"failed\",\n startedAt: nowIso,\n endedAt: nowIso,\n duration: 0,\n usage: ZERO_USAGE,\n children: [],\n };\n\n return { error, usage: ZERO_USAGE, report };\n}\n\n/**\n * Human-in-the-loop approval gate for an agent's tool calls — the\n * middleware behind `ai.human.approval(options)`.\n *\n * **Role.** Pauses *before a specific tool call* and routes it to a human\n * who can **approve** (run the real tool unchanged), **reject** (the model\n * sees a typed error and self-corrects), or **edit** (run the tool with\n * reviewer-replaced args). The dangerous subset is chosen by an\n * {@link import(\"./contracts\").InterruptPolicy} (allowlist / denylist /\n * predicate); every other call passes through untouched.\n *\n * **One hook.** Declares only `tool.before`. On each tool dispatch it:\n * 1. evaluates the policy — not gated → returns `void`, the real tool runs;\n * 2. for a gated call, builds an {@link ApprovalRequest} and calls the\n * {@link import(\"./contracts\").ApprovalHandler};\n * 3. applies the returned {@link ApprovalDecision}:\n * - `approve` → returns `void`, the real tool runs;\n * - `reject` → short-circuits a failed `ToolInvokeResult` carrying an\n * {@link ApprovalRejectedError} (the reviewer's `reason` reaches the\n * model);\n * - `edit` → rewrites `ctx.request.input` to the reviewer's args and\n * returns `void`, so the real tool runs with the edited args (schema\n * validation still applies — bad edits surface as a tool error).\n *\n * **Durable mode.** When a `store` is configured and the handler throws\n * {@link InterruptSuspendedError} (after persisting the interrupt\n * out-of-band), the middleware catches its **own** sentinel and\n * short-circuits a failed result carrying it — so the caller reads\n * `result.error.interruptId` and later calls\n * `ai.human.resume(interruptId, decision)`. The middleware **never throws\n * out of the pipeline**: every outcome (skip, approve, reject, edit,\n * suspend) returns normally; only a *handler bug* (a non-sentinel throw)\n * propagates, and even then the agent dispatch funnels it onto\n * `result.error` — `execute()` still never throws.\n *\n * @param options - Policy, handler, optional durable store, optional name.\n * @returns An {@link AgentMiddleware} declaring a single `tool.before` hook.\n *\n * @example\n * const support = ai.agent({\n * model,\n * tools: [refundCustomer],\n * middleware: [\n * humanApproval({\n * policy: { type: \"allowlist\", tools: [\"refundCustomer\"], tags: () => [\"money\"] },\n * handler: async (req) => ui.prompt(req), // { type: \"edit\", args: { amount: 5 } }\n * }),\n * ],\n * });\n */\nexport function humanApproval(options: HumanApprovalOptions): AgentMiddleware {\n const name = options.name ?? DEFAULT_NAME;\n const { policy, handler } = options;\n\n return {\n name,\n tool: {\n async before(\n ctx: MiddlewareToolContext,\n ): Promise<ToolInvokeResult<unknown> | void> {\n const verdict = evaluatePolicy(policy, toPolicyContext(ctx));\n\n // Not gated — let the real tool run unchanged.\n if (!verdict.requiresApproval) {\n return;\n }\n\n const interruptId = makeInterruptId(ctx);\n const request = buildRequest(ctx, interruptId, verdict.tags);\n\n // Durable resume: `ai.human.resume(...)` re-runs this same agent\n // with the human's decision pre-seeded (keyed by agent name). On a\n // hit we replay the seeded decision exactly once and skip the\n // author's handler entirely — the gated call resolves to the\n // ruling instead of pausing again.\n const seeded = takeSeededDecision(ctx.agent.name);\n\n let decision: ApprovalDecision;\n\n if (seeded !== undefined) {\n decision = seeded;\n } else {\n try {\n decision = await handler(request);\n } catch (thrown) {\n // A durable handler signals suspension by throwing our OWN\n // sentinel after persisting the interrupt. Recognize it and\n // short-circuit a failed result carrying it — the caller reads\n // `error.interruptId` and resumes later. Any OTHER throw is a\n // handler bug; re-throw so the agent dispatch funnels it onto\n // `result.error` (we never swallow a bug into silent approval).\n if (thrown instanceof InterruptSuspendedError) {\n return failedResult(thrown, ctx.tool.name);\n }\n\n throw thrown;\n }\n }\n\n if (decision.type === \"approve\") {\n // Run the real tool with the model's original args.\n return;\n }\n\n if (decision.type === \"reject\") {\n const error = new ApprovalRejectedError(\n `Tool call \"${ctx.tool.name}\" rejected by reviewer — ${decision.reason}`,\n { reason: decision.reason, toolName: ctx.tool.name },\n );\n\n return failedResult(error, ctx.tool.name);\n }\n\n // `edit` — rewrite the pending args, then let the real tool run.\n // The agent dispatch reads `request.input` (this same object) when\n // it invokes the tool after this hook returns, so the reassignment\n // takes effect. Bad edits still fail the tool's own schema check.\n (ctx.request as unknown as MutableToolRequest).input = decision.args;\n\n return;\n },\n },\n };\n}\n"],"mappings":";;;;;;;AAkBA,MAAM,eAAe;;AAGrB,MAAM,aAAoB,OAAO,OAAO;CAAE,OAAO;CAAG,QAAQ;CAAG,OAAO;AAAE,CAAC;;;;;AAmBzE,SAAS,gBAAgB,KAA2C;CAClE,OAAO;EACL,UAAU,IAAI,KAAK;EACnB,iBAAiB,IAAI,KAAK;EAC1B,MAAM,IAAI,QAAQ;EAClB,WAAW,IAAI,MAAM;EACrB,WAAW,IAAI;EACf,WAAW,IAAI,SAAS;CAC1B;AACF;;;;;;;AAQA,SAAS,gBAAgB,KAAoC;CAC3D,MAAM,UAAU,IAAI,SAAS,aAAa;CAC1C,MAAM,SAAS,cAAc,WAAW;CAExC,OAAO,GAAG,IAAI,MAAM,KAAK,GAAG,QAAQ,GAAG,IAAI,UAAU,GAAG;AAC1D;;;;;AAMA,SAAS,aACP,KACA,aACA,MACiB;CACjB,OAAO;EACL;EACA,UAAU,IAAI,KAAK;EACnB,iBAAiB,IAAI,KAAK;EAC1B,MAAM,IAAI,QAAQ;EAClB,SAAS;GACP,WAAW,IAAI,MAAM;GACrB,WAAW,IAAI;GACf,WAAW,IAAI,SAAS;GACxB,eAAe,IAAI;GACnB,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;EACzB;EACA,8BAAa,IAAI,KAAK,EAAC,CAAC,YAAY;CACtC;AACF;;;;;;;;;;;AAYA,SAAS,aAAa,OAAgB,UAA6C;CACjF,MAAM,QAAQ,cAAc,MAAM;CAClC,MAAM,0BAAS,IAAI,KAAK,EAAC,CAAC,YAAY;CAetC,OAAO;EAAE;EAAO,OAAO;EAAY;GAZjC;GACA,WAAW;GACX,MAAM;GACN,MAAM;GACN,QAAQ;GACR,WAAW;GACX,SAAS;GACT,UAAU;GACV,OAAO;GACP,UAAU,CAAC;EAG2B;CAAE;AAC5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,SAAgB,cAAc,SAAgD;CAC5E,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,EAAE,QAAQ,YAAY;CAE5B,OAAO;EACL;EACA,MAAM,EACJ,MAAM,OACJ,KAC2C;GAC3C,MAAM,UAAU,eAAe,QAAQ,gBAAgB,GAAG,CAAC;GAG3D,IAAI,CAAC,QAAQ,kBACX;GAIF,MAAM,UAAU,aAAa,KADT,gBAAgB,GACQ,GAAG,QAAQ,IAAI;GAO3D,MAAM,SAAS,mBAAmB,IAAI,MAAM,IAAI;GAEhD,IAAI;GAEJ,IAAI,WAAW,QACb,WAAW;QAEX,IAAI;IACF,WAAW,MAAM,QAAQ,OAAO;GAClC,SAAS,QAAQ;IAOf,IAAI,kBAAkB,yBACpB,OAAO,aAAa,QAAQ,IAAI,KAAK,IAAI;IAG3C,MAAM;GACR;GAGF,IAAI,SAAS,SAAS,WAEpB;GAGF,IAAI,SAAS,SAAS,UAMpB,OAAO,aAAa,IALF,sBAChB,cAAc,IAAI,KAAK,KAAK,2BAA2B,SAAS,UAChE;IAAE,QAAQ,SAAS;IAAQ,UAAU,IAAI,KAAK;GAAK,CAG7B,GAAG,IAAI,KAAK,IAAI;GAO1C,AAAC,IAAI,QAA0C,QAAQ,SAAS;EAGlE,EACF;CACF;AACF"}
|