@soleri/core 2.12.0 → 8.0.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/data/flows/build.flow.yaml +128 -0
- package/data/flows/deliver.flow.yaml +110 -0
- package/data/flows/design.flow.yaml +108 -0
- package/data/flows/enhance.flow.yaml +90 -0
- package/data/flows/explore.flow.yaml +84 -0
- package/data/flows/fix.flow.yaml +90 -0
- package/data/flows/plan.flow.yaml +87 -0
- package/data/flows/review.flow.yaml +90 -0
- package/dist/agency/agency-manager.d.ts +27 -1
- package/dist/agency/agency-manager.d.ts.map +1 -1
- package/dist/agency/agency-manager.js +180 -9
- package/dist/agency/agency-manager.js.map +1 -1
- package/dist/agency/default-rules.d.ts +7 -0
- package/dist/agency/default-rules.d.ts.map +1 -0
- package/dist/agency/default-rules.js +79 -0
- package/dist/agency/default-rules.js.map +1 -0
- package/dist/agency/types.d.ts +48 -0
- package/dist/agency/types.d.ts.map +1 -1
- package/dist/brain/brain.d.ts +17 -2
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +118 -8
- package/dist/brain/brain.js.map +1 -1
- package/dist/brain/intelligence.d.ts.map +1 -1
- package/dist/brain/intelligence.js +16 -2
- package/dist/brain/intelligence.js.map +1 -1
- package/dist/brain/knowledge-synthesizer.d.ts +37 -0
- package/dist/brain/knowledge-synthesizer.d.ts.map +1 -0
- package/dist/brain/knowledge-synthesizer.js +161 -0
- package/dist/brain/knowledge-synthesizer.js.map +1 -0
- package/dist/brain/learning-radar.d.ts +96 -0
- package/dist/brain/learning-radar.d.ts.map +1 -0
- package/dist/brain/learning-radar.js +202 -0
- package/dist/brain/learning-radar.js.map +1 -0
- package/dist/brain/types.d.ts +15 -0
- package/dist/brain/types.d.ts.map +1 -1
- package/dist/capabilities/chain-mapping.d.ts +21 -0
- package/dist/capabilities/chain-mapping.d.ts.map +1 -0
- package/dist/capabilities/chain-mapping.js +86 -0
- package/dist/capabilities/chain-mapping.js.map +1 -0
- package/dist/capabilities/index.d.ts +10 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +8 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/capabilities/registry.d.ts +95 -0
- package/dist/capabilities/registry.d.ts.map +1 -0
- package/dist/capabilities/registry.js +227 -0
- package/dist/capabilities/registry.js.map +1 -0
- package/dist/capabilities/types.d.ts +106 -0
- package/dist/capabilities/types.d.ts.map +1 -0
- package/dist/capabilities/types.js +12 -0
- package/dist/capabilities/types.js.map +1 -0
- package/dist/context/context-engine.d.ts.map +1 -1
- package/dist/context/context-engine.js +82 -17
- package/dist/context/context-engine.js.map +1 -1
- package/dist/context/types.d.ts +5 -0
- package/dist/context/types.d.ts.map +1 -1
- package/dist/control/intent-router.d.ts +12 -1
- package/dist/control/intent-router.d.ts.map +1 -1
- package/dist/control/intent-router.js +126 -2
- package/dist/control/intent-router.js.map +1 -1
- package/dist/control/types.d.ts +17 -0
- package/dist/control/types.d.ts.map +1 -1
- package/dist/curator/classifier.d.ts +18 -0
- package/dist/curator/classifier.d.ts.map +1 -0
- package/dist/curator/classifier.js +61 -0
- package/dist/curator/classifier.js.map +1 -0
- package/dist/curator/quality-gate.d.ts +29 -0
- package/dist/curator/quality-gate.d.ts.map +1 -0
- package/dist/curator/quality-gate.js +88 -0
- package/dist/curator/quality-gate.js.map +1 -0
- package/dist/domain-packs/index.d.ts +8 -0
- package/dist/domain-packs/index.d.ts.map +1 -0
- package/dist/domain-packs/index.js +8 -0
- package/dist/domain-packs/index.js.map +1 -0
- package/dist/domain-packs/inject-rules.d.ts +24 -0
- package/dist/domain-packs/inject-rules.d.ts.map +1 -0
- package/dist/domain-packs/inject-rules.js +65 -0
- package/dist/domain-packs/inject-rules.js.map +1 -0
- package/dist/domain-packs/knowledge-installer.d.ts +27 -0
- package/dist/domain-packs/knowledge-installer.d.ts.map +1 -0
- package/dist/domain-packs/knowledge-installer.js +89 -0
- package/dist/domain-packs/knowledge-installer.js.map +1 -0
- package/dist/domain-packs/loader.d.ts +28 -0
- package/dist/domain-packs/loader.d.ts.map +1 -0
- package/dist/domain-packs/loader.js +105 -0
- package/dist/domain-packs/loader.js.map +1 -0
- package/dist/domain-packs/pack-runtime.d.ts +80 -0
- package/dist/domain-packs/pack-runtime.d.ts.map +1 -0
- package/dist/domain-packs/pack-runtime.js +36 -0
- package/dist/domain-packs/pack-runtime.js.map +1 -0
- package/dist/domain-packs/skills-installer.d.ts +21 -0
- package/dist/domain-packs/skills-installer.d.ts.map +1 -0
- package/dist/domain-packs/skills-installer.js +38 -0
- package/dist/domain-packs/skills-installer.js.map +1 -0
- package/dist/domain-packs/token-resolver.d.ts +37 -0
- package/dist/domain-packs/token-resolver.d.ts.map +1 -0
- package/dist/domain-packs/token-resolver.js +109 -0
- package/dist/domain-packs/token-resolver.js.map +1 -0
- package/dist/domain-packs/types.d.ts +91 -0
- package/dist/domain-packs/types.d.ts.map +1 -0
- package/dist/domain-packs/types.js +122 -0
- package/dist/domain-packs/types.js.map +1 -0
- package/dist/engine/bin/soleri-engine.d.ts +12 -0
- package/dist/engine/bin/soleri-engine.d.ts.map +1 -0
- package/dist/engine/bin/soleri-engine.js +184 -0
- package/dist/engine/bin/soleri-engine.js.map +1 -0
- package/dist/engine/core-ops.d.ts +27 -0
- package/dist/engine/core-ops.d.ts.map +1 -0
- package/dist/engine/core-ops.js +159 -0
- package/dist/engine/core-ops.js.map +1 -0
- package/dist/engine/index.d.ts +19 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +17 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/register-engine.d.ts +54 -0
- package/dist/engine/register-engine.d.ts.map +1 -0
- package/dist/engine/register-engine.js +270 -0
- package/dist/engine/register-engine.js.map +1 -0
- package/dist/engine/test-helpers.d.ts +30 -0
- package/dist/engine/test-helpers.d.ts.map +1 -0
- package/dist/engine/test-helpers.js +59 -0
- package/dist/engine/test-helpers.js.map +1 -0
- package/dist/events/event-bus.d.ts +30 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/event-bus.js +51 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/flows/chain-runner.d.ts +46 -0
- package/dist/flows/chain-runner.d.ts.map +1 -0
- package/dist/flows/chain-runner.js +271 -0
- package/dist/flows/chain-runner.js.map +1 -0
- package/dist/flows/chain-types.d.ts +103 -0
- package/dist/flows/chain-types.d.ts.map +1 -0
- package/dist/flows/chain-types.js +23 -0
- package/dist/flows/chain-types.js.map +1 -0
- package/dist/flows/context-router.d.ts +39 -0
- package/dist/flows/context-router.d.ts.map +1 -0
- package/dist/flows/context-router.js +206 -0
- package/dist/flows/context-router.js.map +1 -0
- package/dist/flows/dispatch-registry.d.ts +24 -0
- package/dist/flows/dispatch-registry.d.ts.map +1 -0
- package/dist/flows/dispatch-registry.js +70 -0
- package/dist/flows/dispatch-registry.js.map +1 -0
- package/dist/flows/epilogue.d.ts +24 -0
- package/dist/flows/epilogue.d.ts.map +1 -0
- package/dist/flows/epilogue.js +52 -0
- package/dist/flows/epilogue.js.map +1 -0
- package/dist/flows/executor.d.ts +25 -0
- package/dist/flows/executor.d.ts.map +1 -0
- package/dist/flows/executor.js +153 -0
- package/dist/flows/executor.js.map +1 -0
- package/dist/flows/gate-evaluator.d.ts +26 -0
- package/dist/flows/gate-evaluator.d.ts.map +1 -0
- package/dist/flows/gate-evaluator.js +162 -0
- package/dist/flows/gate-evaluator.js.map +1 -0
- package/dist/flows/index.d.ts +14 -0
- package/dist/flows/index.d.ts.map +1 -0
- package/dist/flows/index.js +20 -0
- package/dist/flows/index.js.map +1 -0
- package/dist/flows/loader.d.ts +17 -0
- package/dist/flows/loader.d.ts.map +1 -0
- package/dist/flows/loader.js +61 -0
- package/dist/flows/loader.js.map +1 -0
- package/dist/flows/plan-builder.d.ts +40 -0
- package/dist/flows/plan-builder.d.ts.map +1 -0
- package/dist/flows/plan-builder.js +213 -0
- package/dist/flows/plan-builder.js.map +1 -0
- package/dist/flows/probes.d.ts +11 -0
- package/dist/flows/probes.d.ts.map +1 -0
- package/dist/flows/probes.js +62 -0
- package/dist/flows/probes.js.map +1 -0
- package/dist/flows/types.d.ts +950 -0
- package/dist/flows/types.d.ts.map +1 -0
- package/dist/flows/types.js +105 -0
- package/dist/flows/types.js.map +1 -0
- package/dist/health/doctor-checks.d.ts +15 -0
- package/dist/health/doctor-checks.d.ts.map +1 -0
- package/dist/health/doctor-checks.js +98 -0
- package/dist/health/doctor-checks.js.map +1 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/intake/text-ingester.d.ts +52 -0
- package/dist/intake/text-ingester.d.ts.map +1 -0
- package/dist/intake/text-ingester.js +181 -0
- package/dist/intake/text-ingester.js.map +1 -0
- package/dist/intelligence/loader.d.ts +19 -0
- package/dist/intelligence/loader.d.ts.map +1 -1
- package/dist/intelligence/loader.js +35 -0
- package/dist/intelligence/loader.js.map +1 -1
- package/dist/intelligence/types.d.ts +1 -0
- package/dist/intelligence/types.d.ts.map +1 -1
- package/dist/llm/llm-client.d.ts.map +1 -1
- package/dist/llm/llm-client.js +37 -1
- package/dist/llm/llm-client.js.map +1 -1
- package/dist/llm/oauth-discovery.d.ts +26 -0
- package/dist/llm/oauth-discovery.d.ts.map +1 -0
- package/dist/llm/oauth-discovery.js +149 -0
- package/dist/llm/oauth-discovery.js.map +1 -0
- package/dist/packs/types.d.ts +58 -19
- package/dist/packs/types.d.ts.map +1 -1
- package/dist/packs/types.js +14 -0
- package/dist/packs/types.js.map +1 -1
- package/dist/planning/evidence-collector.d.ts +41 -0
- package/dist/planning/evidence-collector.d.ts.map +1 -0
- package/dist/planning/evidence-collector.js +194 -0
- package/dist/planning/evidence-collector.js.map +1 -0
- package/dist/planning/planner.d.ts +4 -0
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +11 -0
- package/dist/planning/planner.js.map +1 -1
- package/dist/playbooks/generic/onboarding.d.ts +9 -0
- package/dist/playbooks/generic/onboarding.d.ts.map +1 -0
- package/dist/playbooks/generic/onboarding.js +74 -0
- package/dist/playbooks/generic/onboarding.js.map +1 -0
- package/dist/playbooks/playbook-registry.d.ts.map +1 -1
- package/dist/playbooks/playbook-registry.js +2 -0
- package/dist/playbooks/playbook-registry.js.map +1 -1
- package/dist/queue/job-queue.d.ts +92 -0
- package/dist/queue/job-queue.d.ts.map +1 -0
- package/dist/queue/job-queue.js +180 -0
- package/dist/queue/job-queue.js.map +1 -0
- package/dist/queue/pipeline-runner.d.ts +62 -0
- package/dist/queue/pipeline-runner.d.ts.map +1 -0
- package/dist/queue/pipeline-runner.js +126 -0
- package/dist/queue/pipeline-runner.js.map +1 -0
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -1
- package/dist/runtime/admin-extra-ops.js +15 -9
- package/dist/runtime/admin-extra-ops.js.map +1 -1
- package/dist/runtime/admin-ops.js +4 -4
- package/dist/runtime/admin-ops.js.map +1 -1
- package/dist/runtime/admin-setup-ops.d.ts +20 -0
- package/dist/runtime/admin-setup-ops.d.ts.map +1 -0
- package/dist/runtime/admin-setup-ops.js +583 -0
- package/dist/runtime/admin-setup-ops.js.map +1 -0
- package/dist/runtime/capture-ops.d.ts.map +1 -1
- package/dist/runtime/capture-ops.js +33 -1
- package/dist/runtime/capture-ops.js.map +1 -1
- package/dist/runtime/chain-ops.d.ts +9 -0
- package/dist/runtime/chain-ops.d.ts.map +1 -0
- package/dist/runtime/chain-ops.js +107 -0
- package/dist/runtime/chain-ops.js.map +1 -0
- package/dist/runtime/claude-md-helpers.d.ts +65 -0
- package/dist/runtime/claude-md-helpers.d.ts.map +1 -0
- package/dist/runtime/claude-md-helpers.js +173 -0
- package/dist/runtime/claude-md-helpers.js.map +1 -0
- package/dist/runtime/curator-extra-ops.d.ts +3 -2
- package/dist/runtime/curator-extra-ops.d.ts.map +1 -1
- package/dist/runtime/curator-extra-ops.js +81 -3
- package/dist/runtime/curator-extra-ops.js.map +1 -1
- package/dist/runtime/domain-ops.d.ts +21 -5
- package/dist/runtime/domain-ops.d.ts.map +1 -1
- package/dist/runtime/domain-ops.js +64 -6
- package/dist/runtime/domain-ops.js.map +1 -1
- package/dist/runtime/facades/admin-facade.d.ts.map +1 -1
- package/dist/runtime/facades/admin-facade.js +4 -0
- package/dist/runtime/facades/admin-facade.js.map +1 -1
- package/dist/runtime/facades/agency-facade.d.ts.map +1 -1
- package/dist/runtime/facades/agency-facade.js +64 -0
- package/dist/runtime/facades/agency-facade.js.map +1 -1
- package/dist/runtime/facades/brain-facade.d.ts.map +1 -1
- package/dist/runtime/facades/brain-facade.js +122 -1
- package/dist/runtime/facades/brain-facade.js.map +1 -1
- package/dist/runtime/facades/cognee-facade.d.ts.map +1 -1
- package/dist/runtime/facades/cognee-facade.js +3 -1
- package/dist/runtime/facades/cognee-facade.js.map +1 -1
- package/dist/runtime/facades/control-facade.d.ts.map +1 -1
- package/dist/runtime/facades/control-facade.js +42 -0
- package/dist/runtime/facades/control-facade.js.map +1 -1
- package/dist/runtime/facades/index.d.ts.map +1 -1
- package/dist/runtime/facades/index.js +10 -6
- package/dist/runtime/facades/index.js.map +1 -1
- package/dist/runtime/facades/memory-facade.d.ts.map +1 -1
- package/dist/runtime/facades/memory-facade.js +20 -2
- package/dist/runtime/facades/memory-facade.js.map +1 -1
- package/dist/runtime/facades/plan-facade.d.ts.map +1 -1
- package/dist/runtime/facades/plan-facade.js +2 -0
- package/dist/runtime/facades/plan-facade.js.map +1 -1
- package/dist/runtime/facades/vault-facade.d.ts.map +1 -1
- package/dist/runtime/facades/vault-facade.js +27 -5
- package/dist/runtime/facades/vault-facade.js.map +1 -1
- package/dist/runtime/intake-ops.d.ts +7 -5
- package/dist/runtime/intake-ops.d.ts.map +1 -1
- package/dist/runtime/intake-ops.js +98 -5
- package/dist/runtime/intake-ops.js.map +1 -1
- package/dist/runtime/memory-extra-ops.d.ts +6 -3
- package/dist/runtime/memory-extra-ops.d.ts.map +1 -1
- package/dist/runtime/memory-extra-ops.js +292 -4
- package/dist/runtime/memory-extra-ops.js.map +1 -1
- package/dist/runtime/orchestrate-ops.d.ts +8 -7
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -1
- package/dist/runtime/orchestrate-ops.js +217 -61
- package/dist/runtime/orchestrate-ops.js.map +1 -1
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -1
- package/dist/runtime/planning-extra-ops.js +85 -0
- package/dist/runtime/planning-extra-ops.js.map +1 -1
- package/dist/runtime/playbook-ops.js +1 -1
- package/dist/runtime/playbook-ops.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +165 -18
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/session-briefing.d.ts +23 -0
- package/dist/runtime/session-briefing.d.ts.map +1 -0
- package/dist/runtime/session-briefing.js +140 -0
- package/dist/runtime/session-briefing.js.map +1 -0
- package/dist/runtime/types.d.ts +29 -2
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-linking-ops.d.ts +13 -0
- package/dist/runtime/vault-linking-ops.d.ts.map +1 -0
- package/dist/runtime/vault-linking-ops.js +365 -0
- package/dist/runtime/vault-linking-ops.js.map +1 -0
- package/dist/vault/linking.d.ts +46 -0
- package/dist/vault/linking.d.ts.map +1 -0
- package/dist/vault/linking.js +275 -0
- package/dist/vault/linking.js.map +1 -0
- package/dist/vault/vault-types.d.ts +37 -0
- package/dist/vault/vault-types.d.ts.map +1 -1
- package/dist/vault/vault.d.ts +37 -0
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +152 -9
- package/dist/vault/vault.js.map +1 -1
- package/package.json +4 -1
- package/src/__tests__/admin-extra-ops.test.ts +1 -1
- package/src/__tests__/admin-ops.test.ts +2 -1
- package/src/__tests__/admin-setup-ops.test.ts +355 -0
- package/src/__tests__/async-infrastructure.test.ts +307 -0
- package/src/__tests__/cognee-client-gaps.test.ts +474 -0
- package/src/__tests__/cognee-hybrid-search.test.ts +492 -0
- package/src/__tests__/cognee-sync-manager-deep.test.ts +654 -0
- package/src/__tests__/cognee-sync-manager.test.ts +1 -0
- package/src/__tests__/core-ops.test.ts +9 -61
- package/src/__tests__/curator-extra-ops.test.ts +6 -2
- package/src/__tests__/curator-pipeline-e2e.test.ts +358 -0
- package/src/__tests__/domain-packs.test.ts +421 -0
- package/src/__tests__/flows.test.ts +604 -0
- package/src/__tests__/memory-extra-ops.test.ts +2 -2
- package/src/__tests__/planning-extra-ops.test.ts +2 -2
- package/src/__tests__/playbook-registry.test.ts +2 -2
- package/src/__tests__/playbook-seeder.test.ts +8 -8
- package/src/__tests__/playbook.test.ts +5 -5
- package/src/__tests__/second-brain-features.test.ts +583 -0
- package/src/__tests__/token-resolver.test.ts +79 -0
- package/src/agency/agency-manager.ts +217 -9
- package/src/agency/default-rules.ts +83 -0
- package/src/agency/types.ts +61 -0
- package/src/brain/brain.ts +110 -8
- package/src/brain/intelligence.ts +21 -2
- package/src/brain/knowledge-synthesizer.ts +218 -0
- package/src/brain/learning-radar.ts +340 -0
- package/src/brain/types.ts +16 -0
- package/src/capabilities/chain-mapping.ts +93 -0
- package/src/capabilities/index.ts +21 -0
- package/src/capabilities/registry.ts +290 -0
- package/src/capabilities/types.ts +143 -0
- package/src/context/context-engine.ts +114 -15
- package/src/context/types.ts +5 -0
- package/src/control/intent-router.ts +153 -2
- package/src/control/types.ts +10 -0
- package/src/curator/classifier.ts +88 -0
- package/src/curator/quality-gate.ts +129 -0
- package/src/domain-packs/index.ts +27 -0
- package/src/domain-packs/inject-rules.ts +74 -0
- package/src/domain-packs/knowledge-installer.ts +116 -0
- package/src/domain-packs/loader.ts +124 -0
- package/src/domain-packs/pack-runtime.ts +99 -0
- package/src/domain-packs/skills-installer.ts +56 -0
- package/src/domain-packs/token-resolver.ts +126 -0
- package/src/domain-packs/types.ts +229 -0
- package/src/engine/__tests__/register-engine.test.ts +104 -0
- package/src/engine/bin/soleri-engine.ts +218 -0
- package/src/engine/core-ops.ts +178 -0
- package/src/engine/index.ts +19 -0
- package/src/engine/register-engine.ts +385 -0
- package/src/engine/test-helpers.ts +83 -0
- package/src/events/event-bus.ts +58 -0
- package/src/flows/chain-runner.ts +369 -0
- package/src/flows/chain-types.ts +57 -0
- package/src/flows/context-router.ts +257 -0
- package/src/flows/dispatch-registry.ts +80 -0
- package/src/flows/epilogue.ts +65 -0
- package/src/flows/executor.ts +182 -0
- package/src/flows/gate-evaluator.ts +171 -0
- package/src/flows/index.ts +52 -0
- package/src/flows/loader.ts +63 -0
- package/src/flows/plan-builder.ts +250 -0
- package/src/flows/probes.ts +70 -0
- package/src/flows/types.ts +217 -0
- package/src/health/doctor-checks.ts +115 -0
- package/src/index.ts +68 -1
- package/src/intake/text-ingester.ts +234 -0
- package/src/intelligence/loader.ts +38 -0
- package/src/intelligence/types.ts +1 -0
- package/src/llm/llm-client.ts +38 -1
- package/src/llm/oauth-discovery.ts +169 -0
- package/src/packs/types.ts +19 -0
- package/src/planning/evidence-collector.ts +247 -0
- package/src/planning/planner.ts +11 -0
- package/src/playbooks/generic/onboarding.ts +79 -0
- package/src/playbooks/playbook-registry.ts +2 -0
- package/src/queue/job-queue.ts +281 -0
- package/src/queue/pipeline-runner.ts +149 -0
- package/src/runtime/admin-extra-ops.ts +14 -8
- package/src/runtime/admin-ops.ts +4 -4
- package/src/runtime/admin-setup-ops.ts +664 -0
- package/src/runtime/capture-ops.ts +40 -1
- package/src/runtime/chain-ops.ts +121 -0
- package/src/runtime/claude-md-helpers.ts +236 -0
- package/src/runtime/curator-extra-ops.ts +86 -3
- package/src/runtime/domain-ops.ts +71 -5
- package/src/runtime/facades/admin-facade.ts +4 -0
- package/src/runtime/facades/agency-facade.ts +68 -0
- package/src/runtime/facades/brain-facade.ts +142 -1
- package/src/runtime/facades/cognee-facade.ts +3 -1
- package/src/runtime/facades/control-facade.ts +45 -0
- package/src/runtime/facades/index.ts +12 -6
- package/src/runtime/facades/memory-facade.ts +20 -2
- package/src/runtime/facades/plan-facade.ts +2 -0
- package/src/runtime/facades/vault-facade.ts +30 -5
- package/src/runtime/intake-ops.ts +107 -5
- package/src/runtime/memory-extra-ops.ts +312 -4
- package/src/runtime/orchestrate-ops.ts +261 -65
- package/src/runtime/planning-extra-ops.ts +94 -0
- package/src/runtime/playbook-ops.ts +1 -1
- package/src/runtime/runtime.ts +164 -19
- package/src/runtime/session-briefing.ts +161 -0
- package/src/runtime/types.ts +29 -2
- package/src/runtime/vault-linking-ops.ts +452 -0
- package/src/vault/linking.ts +333 -0
- package/src/vault/vault-types.ts +46 -0
- package/src/vault/vault.ts +173 -11
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evidence Collector — cross-references plan tasks against git reality.
|
|
3
|
+
*
|
|
4
|
+
* Runs `git diff` to find what actually changed, then matches file changes
|
|
5
|
+
* against planned tasks to produce an evidence-based drift report.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { execFileSync } from 'node:child_process';
|
|
9
|
+
import type { Plan, PlanTask } from './planner.js';
|
|
10
|
+
|
|
11
|
+
export interface FileChange {
|
|
12
|
+
path: string;
|
|
13
|
+
status: 'added' | 'modified' | 'deleted' | 'renamed';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface GitTaskEvidence {
|
|
17
|
+
taskId: string;
|
|
18
|
+
taskTitle: string;
|
|
19
|
+
plannedStatus: string;
|
|
20
|
+
matchedFiles: FileChange[];
|
|
21
|
+
verdict: 'DONE' | 'PARTIAL' | 'MISSING' | 'SKIPPED';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface UnplannedChange {
|
|
25
|
+
file: FileChange;
|
|
26
|
+
possibleReason: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface EvidenceReport {
|
|
30
|
+
planId: string;
|
|
31
|
+
planObjective: string;
|
|
32
|
+
accuracy: number;
|
|
33
|
+
evidenceSources: string[];
|
|
34
|
+
taskEvidence: GitTaskEvidence[];
|
|
35
|
+
unplannedChanges: UnplannedChange[];
|
|
36
|
+
missingWork: GitTaskEvidence[];
|
|
37
|
+
summary: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Collect git diff evidence for a plan.
|
|
42
|
+
*
|
|
43
|
+
* @param plan - The plan to verify
|
|
44
|
+
* @param projectPath - Project root (must be a git repo)
|
|
45
|
+
* @param baseBranch - Compare against this branch (default: 'main')
|
|
46
|
+
*/
|
|
47
|
+
export function collectGitEvidence(
|
|
48
|
+
plan: Plan,
|
|
49
|
+
projectPath: string,
|
|
50
|
+
baseBranch: string = 'main',
|
|
51
|
+
): EvidenceReport {
|
|
52
|
+
const fileChanges = getGitDiff(projectPath, baseBranch);
|
|
53
|
+
const taskEvidence: GitTaskEvidence[] = [];
|
|
54
|
+
const matchedFiles = new Set<string>();
|
|
55
|
+
|
|
56
|
+
for (const task of plan.tasks) {
|
|
57
|
+
const matches = findMatchingFiles(task, fileChanges);
|
|
58
|
+
for (const m of matches) matchedFiles.add(m.path);
|
|
59
|
+
|
|
60
|
+
const verdict = determineVerdict(task, matches);
|
|
61
|
+
taskEvidence.push({
|
|
62
|
+
taskId: task.id,
|
|
63
|
+
taskTitle: task.title,
|
|
64
|
+
plannedStatus: task.status,
|
|
65
|
+
matchedFiles: matches,
|
|
66
|
+
verdict,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const unplannedChanges: UnplannedChange[] = fileChanges
|
|
71
|
+
.filter((f) => !matchedFiles.has(f.path))
|
|
72
|
+
.map((f) => ({
|
|
73
|
+
file: f,
|
|
74
|
+
possibleReason: inferReason(f),
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
const missingWork = taskEvidence.filter((te) => te.verdict === 'MISSING');
|
|
78
|
+
|
|
79
|
+
const totalTasks = taskEvidence.length;
|
|
80
|
+
const doneTasks = taskEvidence.filter((te) => te.verdict === 'DONE').length;
|
|
81
|
+
const partialTasks = taskEvidence.filter((te) => te.verdict === 'PARTIAL').length;
|
|
82
|
+
const skippedTasks = taskEvidence.filter((te) => te.verdict === 'SKIPPED').length;
|
|
83
|
+
const accuracy =
|
|
84
|
+
totalTasks > 0
|
|
85
|
+
? Math.round(((doneTasks + partialTasks * 0.5 + skippedTasks * 0.25) / totalTasks) * 100)
|
|
86
|
+
: 100;
|
|
87
|
+
|
|
88
|
+
const summary = buildSummary(
|
|
89
|
+
totalTasks,
|
|
90
|
+
doneTasks,
|
|
91
|
+
partialTasks,
|
|
92
|
+
missingWork.length,
|
|
93
|
+
unplannedChanges.length,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
planId: plan.id,
|
|
98
|
+
planObjective: plan.objective,
|
|
99
|
+
accuracy,
|
|
100
|
+
evidenceSources: ['git'],
|
|
101
|
+
taskEvidence,
|
|
102
|
+
unplannedChanges,
|
|
103
|
+
missingWork,
|
|
104
|
+
summary,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function getGitDiff(projectPath: string, baseBranch: string): FileChange[] {
|
|
109
|
+
try {
|
|
110
|
+
const currentBranch = execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
|
111
|
+
cwd: projectPath,
|
|
112
|
+
encoding: 'utf-8',
|
|
113
|
+
timeout: 5000,
|
|
114
|
+
}).trim();
|
|
115
|
+
|
|
116
|
+
const diffTarget = currentBranch === baseBranch ? 'HEAD~10' : baseBranch;
|
|
117
|
+
|
|
118
|
+
let output: string;
|
|
119
|
+
try {
|
|
120
|
+
output = execFileSync('git', ['diff', '--name-status', `${diffTarget}...HEAD`], {
|
|
121
|
+
cwd: projectPath,
|
|
122
|
+
encoding: 'utf-8',
|
|
123
|
+
timeout: 10000,
|
|
124
|
+
});
|
|
125
|
+
} catch {
|
|
126
|
+
output = execFileSync('git', ['diff', '--name-status', 'HEAD~5'], {
|
|
127
|
+
cwd: projectPath,
|
|
128
|
+
encoding: 'utf-8',
|
|
129
|
+
timeout: 10000,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return output
|
|
134
|
+
.trim()
|
|
135
|
+
.split('\n')
|
|
136
|
+
.filter((line) => line.length > 0)
|
|
137
|
+
.map(parseGitDiffLine)
|
|
138
|
+
.filter((f): f is FileChange => f !== null);
|
|
139
|
+
} catch {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function parseGitDiffLine(line: string): FileChange | null {
|
|
145
|
+
const match = line.match(/^([AMDRC])\d*\t(.+?)(?:\t(.+))?$/);
|
|
146
|
+
if (!match) return null;
|
|
147
|
+
|
|
148
|
+
const statusChar = match[1];
|
|
149
|
+
const path = match[3] ?? match[2];
|
|
150
|
+
|
|
151
|
+
const statusMap: Record<string, FileChange['status']> = {
|
|
152
|
+
A: 'added',
|
|
153
|
+
M: 'modified',
|
|
154
|
+
D: 'deleted',
|
|
155
|
+
R: 'renamed',
|
|
156
|
+
C: 'added',
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
return { path, status: statusMap[statusChar] ?? 'modified' };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function findMatchingFiles(task: PlanTask, files: FileChange[]): FileChange[] {
|
|
163
|
+
const keywords = extractKeywords(task.title + ' ' + task.description);
|
|
164
|
+
if (keywords.length === 0) return [];
|
|
165
|
+
|
|
166
|
+
return files.filter((f) => {
|
|
167
|
+
const pathLower = f.path.toLowerCase();
|
|
168
|
+
return keywords.some((kw) => pathLower.includes(kw));
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function extractKeywords(text: string): string[] {
|
|
173
|
+
const stopWords = new Set([
|
|
174
|
+
'the',
|
|
175
|
+
'and',
|
|
176
|
+
'for',
|
|
177
|
+
'with',
|
|
178
|
+
'that',
|
|
179
|
+
'this',
|
|
180
|
+
'from',
|
|
181
|
+
'into',
|
|
182
|
+
'add',
|
|
183
|
+
'create',
|
|
184
|
+
'implement',
|
|
185
|
+
'update',
|
|
186
|
+
'fix',
|
|
187
|
+
'remove',
|
|
188
|
+
'delete',
|
|
189
|
+
'new',
|
|
190
|
+
'use',
|
|
191
|
+
'should',
|
|
192
|
+
'must',
|
|
193
|
+
'will',
|
|
194
|
+
'can',
|
|
195
|
+
'all',
|
|
196
|
+
'each',
|
|
197
|
+
'when',
|
|
198
|
+
'not',
|
|
199
|
+
'are',
|
|
200
|
+
'has',
|
|
201
|
+
'have',
|
|
202
|
+
'been',
|
|
203
|
+
'was',
|
|
204
|
+
]);
|
|
205
|
+
|
|
206
|
+
const words = text
|
|
207
|
+
.toLowerCase()
|
|
208
|
+
.replace(/[^a-z0-9\s\-_/.]/g, ' ')
|
|
209
|
+
.split(/[\s\-_/]+/)
|
|
210
|
+
.filter((w) => w.length >= 3 && !stopWords.has(w));
|
|
211
|
+
|
|
212
|
+
return [...new Set(words)];
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function determineVerdict(task: PlanTask, matches: FileChange[]): GitTaskEvidence['verdict'] {
|
|
216
|
+
if (task.status === 'skipped') return 'SKIPPED';
|
|
217
|
+
if (matches.length === 0) return 'MISSING';
|
|
218
|
+
if (task.status === 'completed') return 'DONE';
|
|
219
|
+
if (matches.length > 0) return 'PARTIAL';
|
|
220
|
+
return 'MISSING';
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function inferReason(file: FileChange): string {
|
|
224
|
+
const path = file.path.toLowerCase();
|
|
225
|
+
if (path.includes('index.') || path.includes('barrel')) return 'likely re-export update';
|
|
226
|
+
if (path.includes('config') || path.includes('.env')) return 'configuration change';
|
|
227
|
+
if (path.includes('test') || path.includes('spec')) return 'test file';
|
|
228
|
+
if (path.includes('package.json') || path.includes('lock')) return 'dependency update';
|
|
229
|
+
if (path.includes('readme') || path.includes('.md')) return 'documentation';
|
|
230
|
+
if (path.includes('types') || path.includes('.d.ts')) return 'type definition update';
|
|
231
|
+
return 'unplanned scope';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function buildSummary(
|
|
235
|
+
total: number,
|
|
236
|
+
done: number,
|
|
237
|
+
partial: number,
|
|
238
|
+
missing: number,
|
|
239
|
+
unplanned: number,
|
|
240
|
+
): string {
|
|
241
|
+
const parts: string[] = [];
|
|
242
|
+
parts.push(`${done}/${total} tasks verified by git evidence`);
|
|
243
|
+
if (partial > 0) parts.push(`${partial} partially done`);
|
|
244
|
+
if (missing > 0) parts.push(`${missing} with no file evidence`);
|
|
245
|
+
if (unplanned > 0) parts.push(`${unplanned} unplanned file changes`);
|
|
246
|
+
return parts.join(', ');
|
|
247
|
+
}
|
package/src/planning/planner.ts
CHANGED
|
@@ -385,6 +385,17 @@ export class Planner {
|
|
|
385
385
|
return [...this.store.plans];
|
|
386
386
|
}
|
|
387
387
|
|
|
388
|
+
/**
|
|
389
|
+
* Permanently remove a plan by ID. Returns true if found and removed.
|
|
390
|
+
*/
|
|
391
|
+
remove(planId: string): boolean {
|
|
392
|
+
const idx = this.store.plans.findIndex((p) => p.id === planId);
|
|
393
|
+
if (idx < 0) return false;
|
|
394
|
+
this.store.plans.splice(idx, 1);
|
|
395
|
+
this.save();
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
|
|
388
399
|
/**
|
|
389
400
|
* Transition a plan to a new status using the typed FSM.
|
|
390
401
|
* Validates that the transition is allowed before applying it.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic Playbook: New User Onboarding
|
|
3
|
+
*
|
|
4
|
+
* Guides first-time users through the agent's capabilities.
|
|
5
|
+
* Activates when vault is empty or user asks "what can you do?"
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { PlaybookDefinition } from '../playbook-types.js';
|
|
9
|
+
|
|
10
|
+
export const onboardingPlaybook: PlaybookDefinition = {
|
|
11
|
+
id: 'generic-onboarding',
|
|
12
|
+
tier: 'generic',
|
|
13
|
+
title: 'New User Onboarding',
|
|
14
|
+
trigger:
|
|
15
|
+
'Use when the user is new (vault is empty, no session history) or when they ask "what can you do?", "how do I use you?", "help", "getting started", "what is this?", "features", "capabilities".',
|
|
16
|
+
description:
|
|
17
|
+
"Walks a new user through the agent's capabilities in a friendly, progressive way. Shows what's available, demonstrates the 5-step rhythm with a quick example, and suggests next actions based on the user's goals.",
|
|
18
|
+
steps: `1. INTRODUCE — Explain who you are
|
|
19
|
+
- Your name, role, and current domains (from activation context)
|
|
20
|
+
- What makes you different: you learn, remember, and improve
|
|
21
|
+
- Your installed packs and what they enable
|
|
22
|
+
|
|
23
|
+
2. SHOW CAPABILITIES — Walk through what you can do
|
|
24
|
+
- Vault: "I search my knowledge base before every decision"
|
|
25
|
+
- Planning: "I create structured plans with approval gates"
|
|
26
|
+
- Brain: "I learn from past sessions and recommend patterns"
|
|
27
|
+
- Memory: "I remember across conversations and projects"
|
|
28
|
+
- Domains: list each domain and what it covers
|
|
29
|
+
- If packs are missing: "You can add more capabilities with soleri pack install"
|
|
30
|
+
|
|
31
|
+
3. DEMONSTRATE — Quick live example
|
|
32
|
+
- Run a vault search on something relevant to the user's project
|
|
33
|
+
- Show the result: "This is what I already know about your domain"
|
|
34
|
+
- If vault is empty: "Let's capture our first pattern together"
|
|
35
|
+
|
|
36
|
+
4. ORIENT — Help the user find their starting point
|
|
37
|
+
- Ask: "What are you working on?" or "What problem are you trying to solve?"
|
|
38
|
+
- Based on their answer, suggest the right workflow:
|
|
39
|
+
- Building something new → "Let me create a plan"
|
|
40
|
+
- Fixing a bug → "Let me search for known patterns"
|
|
41
|
+
- Learning the codebase → "Let me explore and capture what I find"
|
|
42
|
+
- Setting up → "Let me run a health check: op:admin_health"
|
|
43
|
+
|
|
44
|
+
5. HANDOFF — Set expectations
|
|
45
|
+
- "From now on, just describe what you need — I'll figure out the workflow"
|
|
46
|
+
- "If you want me to remember something, say 'capture this' or 'remember'"
|
|
47
|
+
- "Say 'what do you know about X?' to search my vault anytime"`,
|
|
48
|
+
expectedOutcome:
|
|
49
|
+
'User understands what the agent can do, has seen a live demonstration, and has a clear first task to work on. The agent transitions from onboarding to productive work.',
|
|
50
|
+
category: 'methodology',
|
|
51
|
+
tags: ['onboarding', 'getting-started', 'help', 'capabilities', 'generic'],
|
|
52
|
+
matchIntents: ['PLAN'],
|
|
53
|
+
matchKeywords: [
|
|
54
|
+
'what can you do',
|
|
55
|
+
'help',
|
|
56
|
+
'getting started',
|
|
57
|
+
'how do I use',
|
|
58
|
+
'features',
|
|
59
|
+
'capabilities',
|
|
60
|
+
'onboarding',
|
|
61
|
+
'introduce',
|
|
62
|
+
'what is this',
|
|
63
|
+
'new here',
|
|
64
|
+
'first time',
|
|
65
|
+
],
|
|
66
|
+
gates: [],
|
|
67
|
+
taskTemplates: [],
|
|
68
|
+
toolInjections: [
|
|
69
|
+
'op:activate — show current capabilities and system status',
|
|
70
|
+
'op:admin_health — demonstrate health check',
|
|
71
|
+
'op:search_intelligent — live demo of vault search',
|
|
72
|
+
'op:brain_recommend — show brain recommendations',
|
|
73
|
+
],
|
|
74
|
+
verificationCriteria: [
|
|
75
|
+
'User received a clear overview of agent capabilities',
|
|
76
|
+
'User saw a live demonstration of at least one capability',
|
|
77
|
+
'User expressed a first task or area of interest',
|
|
78
|
+
],
|
|
79
|
+
};
|
|
@@ -23,6 +23,7 @@ import { codeReviewPlaybook } from './generic/code-review.js';
|
|
|
23
23
|
import { subagentExecutionPlaybook } from './generic/subagent-execution.js';
|
|
24
24
|
import { systematicDebuggingPlaybook } from './generic/systematic-debugging.js';
|
|
25
25
|
import { verificationPlaybook } from './generic/verification.js';
|
|
26
|
+
import { onboardingPlaybook } from './generic/onboarding.js';
|
|
26
27
|
|
|
27
28
|
// =============================================================================
|
|
28
29
|
// SCORING WEIGHTS
|
|
@@ -49,6 +50,7 @@ const BUILTIN_PLAYBOOKS: PlaybookDefinition[] = [
|
|
|
49
50
|
subagentExecutionPlaybook,
|
|
50
51
|
systematicDebuggingPlaybook,
|
|
51
52
|
verificationPlaybook,
|
|
53
|
+
onboardingPlaybook,
|
|
52
54
|
];
|
|
53
55
|
|
|
54
56
|
/**
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Job Queue — SQLite-backed FIFO queue with DAG dependencies and retries.
|
|
3
|
+
*
|
|
4
|
+
* Generic infrastructure — not curator-specific. Reusable by agency, intake, etc.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Persistent jobs (survive process restarts)
|
|
8
|
+
* - DAG dependency resolution (job B waits for job A)
|
|
9
|
+
* - Pipeline grouping (group related jobs under one ID)
|
|
10
|
+
* - Configurable retries with max limit
|
|
11
|
+
* - Status tracking: pending → running → completed | failed
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { randomUUID } from 'node:crypto';
|
|
15
|
+
import type { PersistenceProvider } from '../persistence/types.js';
|
|
16
|
+
|
|
17
|
+
// ─── Types ───────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
export type JobStatus = 'pending' | 'running' | 'completed' | 'failed';
|
|
20
|
+
|
|
21
|
+
export interface Job {
|
|
22
|
+
id: string;
|
|
23
|
+
type: string;
|
|
24
|
+
status: JobStatus;
|
|
25
|
+
entryId: string | null;
|
|
26
|
+
payload: Record<string, unknown>;
|
|
27
|
+
dependsOn: string[];
|
|
28
|
+
pipelineId: string | null;
|
|
29
|
+
retryCount: number;
|
|
30
|
+
maxRetries: number;
|
|
31
|
+
result: unknown | null;
|
|
32
|
+
error: string | null;
|
|
33
|
+
createdAt: string;
|
|
34
|
+
startedAt: string | null;
|
|
35
|
+
completedAt: string | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface JobQueueStats {
|
|
39
|
+
pending: number;
|
|
40
|
+
running: number;
|
|
41
|
+
completed: number;
|
|
42
|
+
failed: number;
|
|
43
|
+
total: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface EnqueueOptions {
|
|
47
|
+
entryId?: string;
|
|
48
|
+
payload?: Record<string, unknown>;
|
|
49
|
+
dependsOn?: string[];
|
|
50
|
+
pipelineId?: string;
|
|
51
|
+
maxRetries?: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ─── Class ───────────────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
export class JobQueue {
|
|
57
|
+
private provider: PersistenceProvider;
|
|
58
|
+
|
|
59
|
+
constructor(provider: PersistenceProvider) {
|
|
60
|
+
this.provider = provider;
|
|
61
|
+
this.initializeTable();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private initializeTable(): void {
|
|
65
|
+
this.provider.execSql(`
|
|
66
|
+
CREATE TABLE IF NOT EXISTS job_queue (
|
|
67
|
+
id TEXT PRIMARY KEY,
|
|
68
|
+
type TEXT NOT NULL,
|
|
69
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
70
|
+
entry_id TEXT,
|
|
71
|
+
payload TEXT DEFAULT '{}',
|
|
72
|
+
depends_on TEXT DEFAULT '[]',
|
|
73
|
+
pipeline_id TEXT,
|
|
74
|
+
retry_count INTEGER DEFAULT 0,
|
|
75
|
+
max_retries INTEGER DEFAULT 3,
|
|
76
|
+
result TEXT,
|
|
77
|
+
error TEXT,
|
|
78
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
79
|
+
started_at TEXT,
|
|
80
|
+
completed_at TEXT
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
CREATE INDEX IF NOT EXISTS idx_job_queue_status ON job_queue(status);
|
|
84
|
+
CREATE INDEX IF NOT EXISTS idx_job_queue_pipeline ON job_queue(pipeline_id);
|
|
85
|
+
`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Enqueue a new job. Returns the job ID.
|
|
90
|
+
*/
|
|
91
|
+
enqueue(type: string, options?: EnqueueOptions): string {
|
|
92
|
+
const id = randomUUID().slice(0, 12);
|
|
93
|
+
this.provider.run(
|
|
94
|
+
`INSERT INTO job_queue (id, type, entry_id, payload, depends_on, pipeline_id, max_retries)
|
|
95
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
96
|
+
[
|
|
97
|
+
id,
|
|
98
|
+
type,
|
|
99
|
+
options?.entryId ?? null,
|
|
100
|
+
JSON.stringify(options?.payload ?? {}),
|
|
101
|
+
JSON.stringify(options?.dependsOn ?? []),
|
|
102
|
+
options?.pipelineId ?? null,
|
|
103
|
+
options?.maxRetries ?? 3,
|
|
104
|
+
],
|
|
105
|
+
);
|
|
106
|
+
return id;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Dequeue the oldest pending job with all dependencies completed.
|
|
111
|
+
* Marks it as running. Returns null if no ready jobs.
|
|
112
|
+
*/
|
|
113
|
+
dequeue(): Job | null {
|
|
114
|
+
const ready = this.dequeueReady(1);
|
|
115
|
+
return ready.length > 0 ? ready[0] : null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Dequeue up to `limit` pending jobs whose dependencies are all completed.
|
|
120
|
+
*/
|
|
121
|
+
dequeueReady(limit: number = 10): Job[] {
|
|
122
|
+
const rows = this.provider.all<JobRow>(
|
|
123
|
+
"SELECT * FROM job_queue WHERE status = 'pending' ORDER BY created_at ASC LIMIT ?",
|
|
124
|
+
[limit * 3], // Over-fetch to filter by deps
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
const ready: Job[] = [];
|
|
128
|
+
for (const row of rows) {
|
|
129
|
+
if (ready.length >= limit) break;
|
|
130
|
+
const deps = JSON.parse(row.depends_on) as string[];
|
|
131
|
+
if (deps.length === 0 || this.allDepsCompleted(deps)) {
|
|
132
|
+
this.provider.run(
|
|
133
|
+
"UPDATE job_queue SET status = 'running', started_at = datetime('now') WHERE id = ?",
|
|
134
|
+
[row.id],
|
|
135
|
+
);
|
|
136
|
+
const job = rowToJob(row);
|
|
137
|
+
job.status = 'running';
|
|
138
|
+
ready.push(job);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return ready;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Mark a job as completed with an optional result.
|
|
146
|
+
*/
|
|
147
|
+
complete(jobId: string, result?: unknown): void {
|
|
148
|
+
this.provider.run(
|
|
149
|
+
"UPDATE job_queue SET status = 'completed', completed_at = datetime('now'), result = ? WHERE id = ?",
|
|
150
|
+
[result !== undefined ? JSON.stringify(result) : null, jobId],
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Mark a job as failed with an error message.
|
|
156
|
+
*/
|
|
157
|
+
fail(jobId: string, error: string): void {
|
|
158
|
+
this.provider.run(
|
|
159
|
+
"UPDATE job_queue SET status = 'failed', completed_at = datetime('now'), error = ? WHERE id = ?",
|
|
160
|
+
[error, jobId],
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Retry a failed job (resets to pending). Returns false if max retries exceeded.
|
|
166
|
+
*/
|
|
167
|
+
retry(jobId: string): boolean {
|
|
168
|
+
const row = this.provider.get<JobRow>('SELECT * FROM job_queue WHERE id = ?', [jobId]);
|
|
169
|
+
if (!row) return false;
|
|
170
|
+
if (row.retry_count >= row.max_retries) return false;
|
|
171
|
+
|
|
172
|
+
this.provider.run(
|
|
173
|
+
"UPDATE job_queue SET status = 'pending', retry_count = retry_count + 1, error = NULL, started_at = NULL, completed_at = NULL WHERE id = ?",
|
|
174
|
+
[jobId],
|
|
175
|
+
);
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Get queue statistics.
|
|
181
|
+
*/
|
|
182
|
+
getStats(): JobQueueStats {
|
|
183
|
+
const rows = this.provider.all<{ status: string; count: number }>(
|
|
184
|
+
'SELECT status, COUNT(*) as count FROM job_queue GROUP BY status',
|
|
185
|
+
);
|
|
186
|
+
const byStatus: Record<string, number> = {};
|
|
187
|
+
let total = 0;
|
|
188
|
+
for (const row of rows) {
|
|
189
|
+
byStatus[row.status] = row.count;
|
|
190
|
+
total += row.count;
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
pending: byStatus['pending'] ?? 0,
|
|
194
|
+
running: byStatus['running'] ?? 0,
|
|
195
|
+
completed: byStatus['completed'] ?? 0,
|
|
196
|
+
failed: byStatus['failed'] ?? 0,
|
|
197
|
+
total,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get all jobs for a pipeline.
|
|
203
|
+
*/
|
|
204
|
+
getByPipeline(pipelineId: string): Job[] {
|
|
205
|
+
const rows = this.provider.all<JobRow>(
|
|
206
|
+
'SELECT * FROM job_queue WHERE pipeline_id = ? ORDER BY created_at ASC',
|
|
207
|
+
[pipelineId],
|
|
208
|
+
);
|
|
209
|
+
return rows.map(rowToJob);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get a single job by ID.
|
|
214
|
+
*/
|
|
215
|
+
get(jobId: string): Job | null {
|
|
216
|
+
const row = this.provider.get<JobRow>('SELECT * FROM job_queue WHERE id = ?', [jobId]);
|
|
217
|
+
return row ? rowToJob(row) : null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Purge completed/failed jobs older than N days.
|
|
222
|
+
*/
|
|
223
|
+
purge(olderThanDays: number = 30): number {
|
|
224
|
+
const result = this.provider.run(
|
|
225
|
+
"DELETE FROM job_queue WHERE status IN ('completed', 'failed') AND completed_at < datetime('now', ?)",
|
|
226
|
+
[`-${olderThanDays} days`],
|
|
227
|
+
);
|
|
228
|
+
return result.changes;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ─── Internal ──────────────────────────────────────────────────────
|
|
232
|
+
|
|
233
|
+
private allDepsCompleted(deps: string[]): boolean {
|
|
234
|
+
for (const depId of deps) {
|
|
235
|
+
const row = this.provider.get<{ status: string }>(
|
|
236
|
+
'SELECT status FROM job_queue WHERE id = ?',
|
|
237
|
+
[depId],
|
|
238
|
+
);
|
|
239
|
+
if (!row || row.status !== 'completed') return false;
|
|
240
|
+
}
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ─── Row Types ───────────────────────────────────────────────────────
|
|
246
|
+
|
|
247
|
+
interface JobRow {
|
|
248
|
+
id: string;
|
|
249
|
+
type: string;
|
|
250
|
+
status: string;
|
|
251
|
+
entry_id: string | null;
|
|
252
|
+
payload: string;
|
|
253
|
+
depends_on: string;
|
|
254
|
+
pipeline_id: string | null;
|
|
255
|
+
retry_count: number;
|
|
256
|
+
max_retries: number;
|
|
257
|
+
result: string | null;
|
|
258
|
+
error: string | null;
|
|
259
|
+
created_at: string;
|
|
260
|
+
started_at: string | null;
|
|
261
|
+
completed_at: string | null;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function rowToJob(row: JobRow): Job {
|
|
265
|
+
return {
|
|
266
|
+
id: row.id,
|
|
267
|
+
type: row.type,
|
|
268
|
+
status: row.status as JobStatus,
|
|
269
|
+
entryId: row.entry_id,
|
|
270
|
+
payload: JSON.parse(row.payload) as Record<string, unknown>,
|
|
271
|
+
dependsOn: JSON.parse(row.depends_on) as string[],
|
|
272
|
+
pipelineId: row.pipeline_id,
|
|
273
|
+
retryCount: row.retry_count,
|
|
274
|
+
maxRetries: row.max_retries,
|
|
275
|
+
result: row.result ? JSON.parse(row.result) : null,
|
|
276
|
+
error: row.error,
|
|
277
|
+
createdAt: row.created_at,
|
|
278
|
+
startedAt: row.started_at,
|
|
279
|
+
completedAt: row.completed_at,
|
|
280
|
+
};
|
|
281
|
+
}
|