@zigrivers/scaffold 3.28.0 → 3.29.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/README.md +5 -1
- package/content/guides/.gitkeep +0 -0
- package/content/guides/index.html +1188 -0
- package/content/guides/mmr/.diagrams/diagram-0.svg +1 -0
- package/content/guides/mmr/.diagrams/manifest.json +3 -0
- package/content/guides/mmr/index.html +1728 -0
- package/content/guides/mmr/index.md +403 -0
- package/content/knowledge/VERSION +1 -0
- package/content/knowledge/backend/backend-api-design.md +8 -0
- package/content/knowledge/backend/backend-architecture.md +8 -0
- package/content/knowledge/backend/backend-async-patterns.md +7 -0
- package/content/knowledge/backend/backend-auth-patterns.md +9 -0
- package/content/knowledge/backend/backend-conventions.md +6 -0
- package/content/knowledge/backend/backend-data-modeling.md +7 -0
- package/content/knowledge/backend/backend-deployment.md +8 -0
- package/content/knowledge/backend/backend-dev-environment.md +5 -0
- package/content/knowledge/backend/backend-fintech-broker-integration.md +6 -0
- package/content/knowledge/backend/backend-fintech-compliance.md +10 -2
- package/content/knowledge/backend/backend-fintech-data-modeling.md +6 -0
- package/content/knowledge/backend/backend-fintech-ledger.md +6 -0
- package/content/knowledge/backend/backend-fintech-observability.md +6 -0
- package/content/knowledge/backend/backend-fintech-order-lifecycle.md +6 -0
- package/content/knowledge/backend/backend-fintech-risk-management.md +6 -0
- package/content/knowledge/backend/backend-fintech-testing.md +6 -0
- package/content/knowledge/backend/backend-observability.md +7 -0
- package/content/knowledge/backend/backend-project-structure.md +6 -0
- package/content/knowledge/backend/backend-requirements.md +6 -0
- package/content/knowledge/backend/backend-security.md +7 -0
- package/content/knowledge/backend/backend-testing.md +7 -0
- package/content/knowledge/backend/backend-worker-patterns.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-architecture.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-content-scripts.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-conventions.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-cross-browser.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-dev-environment.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-manifest.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-project-structure.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-requirements.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-security.md +7 -0
- package/content/knowledge/browser-extension/browser-extension-service-workers.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-store-submission.md +6 -0
- package/content/knowledge/browser-extension/browser-extension-testing.md +6 -0
- package/content/knowledge/cli/cli-architecture.md +4 -0
- package/content/knowledge/cli/cli-conventions.md +4 -0
- package/content/knowledge/cli/cli-dev-environment.md +5 -0
- package/content/knowledge/cli/cli-distribution-patterns.md +5 -0
- package/content/knowledge/cli/cli-interactivity-patterns.md +4 -0
- package/content/knowledge/cli/cli-output-patterns.md +4 -0
- package/content/knowledge/cli/cli-project-structure.md +4 -0
- package/content/knowledge/cli/cli-requirements.md +4 -0
- package/content/knowledge/cli/cli-shell-integration.md +4 -0
- package/content/knowledge/cli/cli-testing.md +4 -0
- package/content/knowledge/core/adr-craft.md +8 -0
- package/content/knowledge/core/ai-memory-management.md +6 -0
- package/content/knowledge/core/api-design.md +6 -0
- package/content/knowledge/core/automated-review-tooling.md +8 -0
- package/content/knowledge/core/claude-md-patterns.md +8 -0
- package/content/knowledge/core/coding-conventions.md +8 -0
- package/content/knowledge/core/database-design.md +8 -0
- package/content/knowledge/core/design-system-tokens.md +8 -0
- package/content/knowledge/core/dev-environment.md +4 -0
- package/content/knowledge/core/domain-modeling.md +6 -0
- package/content/knowledge/core/eval-craft.md +6 -0
- package/content/knowledge/core/git-workflow-patterns.md +8 -0
- package/content/knowledge/core/multi-model-research-dispatch.md +6 -0
- package/content/knowledge/core/multi-model-review-dispatch.md +6 -0
- package/content/knowledge/core/multi-service-api-contracts.md +5 -0
- package/content/knowledge/core/multi-service-architecture.md +5 -0
- package/content/knowledge/core/multi-service-auth.md +6 -0
- package/content/knowledge/core/multi-service-data-ownership.md +8 -0
- package/content/knowledge/core/multi-service-observability.md +8 -0
- package/content/knowledge/core/multi-service-resilience.md +5 -0
- package/content/knowledge/core/multi-service-task-decomposition.md +8 -0
- package/content/knowledge/core/multi-service-testing.md +5 -0
- package/content/knowledge/core/operations-runbook.md +8 -0
- package/content/knowledge/core/project-structure-patterns.md +4 -0
- package/content/knowledge/core/review-step-template.md +4 -0
- package/content/knowledge/core/security-best-practices.md +6 -0
- package/content/knowledge/core/system-architecture.md +6 -0
- package/content/knowledge/core/task-decomposition.md +5 -0
- package/content/knowledge/core/task-tracking.md +8 -0
- package/content/knowledge/core/tech-stack-selection.md +8 -0
- package/content/knowledge/core/test-skeleton-generation.md +4 -0
- package/content/knowledge/core/testing-strategy.md +8 -0
- package/content/knowledge/core/user-stories.md +8 -0
- package/content/knowledge/core/user-story-innovation.md +4 -0
- package/content/knowledge/core/ux-specification.md +5 -0
- package/content/knowledge/data-pipeline/data-pipeline-architecture.md +5 -0
- package/content/knowledge/data-pipeline/data-pipeline-batch-patterns.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-conventions.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-dev-environment.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-orchestration.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-project-structure.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-quality.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-requirements.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-schema-management.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-security.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-streaming-patterns.md +4 -0
- package/content/knowledge/data-pipeline/data-pipeline-testing.md +4 -0
- package/content/knowledge/data-science/data-science-architecture.md +5 -0
- package/content/knowledge/data-science/data-science-conventions.md +6 -0
- package/content/knowledge/data-science/data-science-data-versioning.md +6 -0
- package/content/knowledge/data-science/data-science-dev-environment.md +6 -0
- package/content/knowledge/data-science/data-science-experiment-tracking.md +8 -0
- package/content/knowledge/data-science/data-science-model-evaluation.md +5 -0
- package/content/knowledge/data-science/data-science-notebook-discipline.md +5 -0
- package/content/knowledge/data-science/data-science-observability.md +6 -0
- package/content/knowledge/data-science/data-science-project-structure.md +5 -0
- package/content/knowledge/data-science/data-science-reproducibility.md +8 -0
- package/content/knowledge/data-science/data-science-requirements.md +5 -0
- package/content/knowledge/data-science/data-science-security.md +8 -0
- package/content/knowledge/data-science/data-science-testing.md +5 -0
- package/content/knowledge/execution/enhancement-workflow.md +4 -0
- package/content/knowledge/execution/multi-agent-coordination.md +12 -1
- package/content/knowledge/execution/task-claiming-strategy.md +4 -0
- package/content/knowledge/execution/tdd-execution-loop.md +5 -0
- package/content/knowledge/execution/worktree-management.md +5 -0
- package/content/knowledge/finalization/apply-fixes-and-freeze.md +4 -0
- package/content/knowledge/finalization/developer-onboarding.md +4 -0
- package/content/knowledge/finalization/implementation-playbook.md +4 -0
- package/content/knowledge/game/game-accessibility.md +4 -0
- package/content/knowledge/game/game-ai-patterns.md +4 -0
- package/content/knowledge/game/game-asset-pipeline.md +4 -0
- package/content/knowledge/game/game-audio-design.md +4 -0
- package/content/knowledge/game/game-binary-vcs-strategy.md +5 -0
- package/content/knowledge/game/game-design-document.md +4 -0
- package/content/knowledge/game/game-domain-patterns.md +4 -0
- package/content/knowledge/game/game-economy-design.md +4 -0
- package/content/knowledge/game/game-engine-selection.md +4 -0
- package/content/knowledge/game/game-ideation.md +4 -0
- package/content/knowledge/game/game-input-systems.md +4 -0
- package/content/knowledge/game/game-level-content-design.md +4 -0
- package/content/knowledge/game/game-liveops-analytics.md +4 -0
- package/content/knowledge/game/game-localization.md +4 -0
- package/content/knowledge/game/game-milestone-definitions.md +4 -0
- package/content/knowledge/game/game-modding-ugc.md +4 -0
- package/content/knowledge/game/game-narrative-design.md +4 -0
- package/content/knowledge/game/game-networking.md +4 -0
- package/content/knowledge/game/game-performance-budgeting.md +4 -0
- package/content/knowledge/game/game-platform-certification.md +6 -0
- package/content/knowledge/game/game-project-structure.md +4 -0
- package/content/knowledge/game/game-save-systems.md +4 -0
- package/content/knowledge/game/game-testing-strategy.md +4 -0
- package/content/knowledge/game/game-ui-patterns.md +4 -0
- package/content/knowledge/game/game-vr-ar-design.md +6 -0
- package/content/knowledge/library/library-api-design.md +4 -0
- package/content/knowledge/library/library-architecture.md +4 -0
- package/content/knowledge/library/library-bundling.md +4 -0
- package/content/knowledge/library/library-conventions.md +5 -0
- package/content/knowledge/library/library-dev-environment.md +4 -0
- package/content/knowledge/library/library-documentation.md +4 -0
- package/content/knowledge/library/library-project-structure.md +4 -0
- package/content/knowledge/library/library-requirements.md +4 -0
- package/content/knowledge/library/library-security.md +4 -0
- package/content/knowledge/library/library-testing.md +4 -0
- package/content/knowledge/library/library-type-definitions.md +4 -0
- package/content/knowledge/library/library-versioning.md +5 -0
- package/content/knowledge/ml/ml-architecture.md +4 -0
- package/content/knowledge/ml/ml-conventions.md +4 -0
- package/content/knowledge/ml/ml-dev-environment.md +4 -0
- package/content/knowledge/ml/ml-experiment-tracking.md +6 -0
- package/content/knowledge/ml/ml-model-evaluation.md +4 -0
- package/content/knowledge/ml/ml-observability.md +5 -0
- package/content/knowledge/ml/ml-project-structure.md +4 -0
- package/content/knowledge/ml/ml-requirements.md +4 -0
- package/content/knowledge/ml/ml-security.md +5 -0
- package/content/knowledge/ml/ml-serving-patterns.md +4 -0
- package/content/knowledge/ml/ml-testing.md +4 -0
- package/content/knowledge/ml/ml-training-patterns.md +4 -0
- package/content/knowledge/mobile-app/mobile-app-architecture.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-conventions.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-deployment.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-dev-environment.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-distribution.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-observability.md +7 -0
- package/content/knowledge/mobile-app/mobile-app-offline-patterns.md +7 -0
- package/content/knowledge/mobile-app/mobile-app-project-structure.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-push-notifications.md +6 -0
- package/content/knowledge/mobile-app/mobile-app-requirements.md +7 -0
- package/content/knowledge/mobile-app/mobile-app-security.md +8 -0
- package/content/knowledge/mobile-app/mobile-app-testing.md +6 -0
- package/content/knowledge/product/gap-analysis.md +4 -0
- package/content/knowledge/product/ideation-craft.md +4 -0
- package/content/knowledge/product/prd-craft.md +4 -0
- package/content/knowledge/product/prd-innovation.md +4 -0
- package/content/knowledge/product/vision-craft.md +4 -0
- package/content/knowledge/product/vision-innovation.md +4 -0
- package/content/knowledge/research/research-architecture.md +4 -0
- package/content/knowledge/research/research-conventions.md +6 -0
- package/content/knowledge/research/research-dev-environment.md +6 -0
- package/content/knowledge/research/research-experiment-loop.md +4 -0
- package/content/knowledge/research/research-experiment-tracking.md +6 -0
- package/content/knowledge/research/research-ml-architecture-search.md +4 -0
- package/content/knowledge/research/research-ml-evaluation.md +4 -0
- package/content/knowledge/research/research-ml-experiment-tracking.md +6 -0
- package/content/knowledge/research/research-ml-training-patterns.md +4 -0
- package/content/knowledge/research/research-observability.md +5 -0
- package/content/knowledge/research/research-overfitting-prevention.md +5 -0
- package/content/knowledge/research/research-project-structure.md +5 -0
- package/content/knowledge/research/research-quant-backtesting.md +4 -0
- package/content/knowledge/research/research-quant-market-data.md +4 -0
- package/content/knowledge/research/research-quant-metrics.md +4 -0
- package/content/knowledge/research/research-quant-requirements.md +4 -0
- package/content/knowledge/research/research-quant-risk.md +4 -0
- package/content/knowledge/research/research-quant-strategy-patterns.md +4 -0
- package/content/knowledge/research/research-requirements.md +5 -0
- package/content/knowledge/research/research-security.md +5 -0
- package/content/knowledge/research/research-sim-compute-management.md +4 -0
- package/content/knowledge/research/research-sim-engine-patterns.md +4 -0
- package/content/knowledge/research/research-sim-parameter-spaces.md +4 -0
- package/content/knowledge/research/research-sim-validation.md +4 -0
- package/content/knowledge/research/research-testing.md +5 -0
- package/content/knowledge/review/review-adr.md +6 -0
- package/content/knowledge/review/review-api-design.md +6 -0
- package/content/knowledge/review/review-art-bible.md +4 -0
- package/content/knowledge/review/review-database-design.md +5 -0
- package/content/knowledge/review/review-domain-modeling.md +5 -0
- package/content/knowledge/review/review-game-design.md +4 -0
- package/content/knowledge/review/review-game-economy.md +4 -0
- package/content/knowledge/review/review-game-ui.md +5 -0
- package/content/knowledge/review/review-implementation-tasks.md +5 -0
- package/content/knowledge/review/review-methodology.md +4 -0
- package/content/knowledge/review/review-netcode.md +4 -0
- package/content/knowledge/review/review-operations.md +6 -0
- package/content/knowledge/review/review-platform-cert.md +4 -0
- package/content/knowledge/review/review-prd.md +4 -0
- package/content/knowledge/review/review-security.md +7 -0
- package/content/knowledge/review/review-system-architecture.md +6 -0
- package/content/knowledge/review/review-testing-strategy.md +6 -0
- package/content/knowledge/review/review-user-stories.md +5 -0
- package/content/knowledge/review/review-ux-specification.md +6 -0
- package/content/knowledge/review/review-vision.md +4 -0
- package/content/knowledge/tools/post-implementation-review-methodology.md +4 -0
- package/content/knowledge/tools/release-management.md +5 -0
- package/content/knowledge/tools/session-analysis.md +4 -0
- package/content/knowledge/tools/version-strategy.md +4 -0
- package/content/knowledge/validation/critical-path-analysis.md +4 -0
- package/content/knowledge/validation/cross-phase-consistency.md +4 -0
- package/content/knowledge/validation/decision-completeness.md +5 -0
- package/content/knowledge/validation/dependency-validation.md +4 -0
- package/content/knowledge/validation/implementability-review.md +4 -0
- package/content/knowledge/validation/scope-management.md +4 -0
- package/content/knowledge/validation/traceability.md +4 -0
- package/content/knowledge/web-app/web-app-api-patterns.md +6 -0
- package/content/knowledge/web-app/web-app-architecture.md +6 -0
- package/content/knowledge/web-app/web-app-auth-patterns.md +9 -0
- package/content/knowledge/web-app/web-app-conventions.md +5 -0
- package/content/knowledge/web-app/web-app-data-patterns.md +6 -0
- package/content/knowledge/web-app/web-app-deployment-workflow.md +6 -0
- package/content/knowledge/web-app/web-app-deployment.md +6 -0
- package/content/knowledge/web-app/web-app-design-system.md +6 -0
- package/content/knowledge/web-app/web-app-dev-environment.md +6 -0
- package/content/knowledge/web-app/web-app-observability.md +6 -0
- package/content/knowledge/web-app/web-app-project-structure.md +5 -0
- package/content/knowledge/web-app/web-app-rendering-strategies.md +6 -0
- package/content/knowledge/web-app/web-app-requirements.md +6 -0
- package/content/knowledge/web-app/web-app-security.md +8 -0
- package/content/knowledge/web-app/web-app-session-patterns.md +7 -0
- package/content/knowledge/web-app/web-app-testing.md +6 -0
- package/content/knowledge/web-app/web-app-ux-patterns.md +6 -0
- package/content/knowledge/web3/web3-access-control.md +8 -0
- package/content/knowledge/web3/web3-architecture.md +7 -0
- package/content/knowledge/web3/web3-audit-workflow.md +7 -0
- package/content/knowledge/web3/web3-common-vulnerabilities.md +8 -0
- package/content/knowledge/web3/web3-conventions.md +6 -0
- package/content/knowledge/web3/web3-deployment-and-verification.md +7 -0
- package/content/knowledge/web3/web3-dev-environment.md +6 -0
- package/content/knowledge/web3/web3-gas-optimization.md +7 -0
- package/content/knowledge/web3/web3-oracles-and-external-data.md +7 -0
- package/content/knowledge/web3/web3-project-structure.md +6 -0
- package/content/knowledge/web3/web3-requirements.md +6 -0
- package/content/knowledge/web3/web3-security.md +8 -0
- package/content/knowledge/web3/web3-testing.md +6 -0
- package/content/knowledge/web3/web3-upgradeability.md +7 -0
- package/content/tools/knowledge-audit-entry.md +79 -0
- package/content/tools/review-code.md +41 -14
- package/content/tools/review-pr.md +32 -14
- package/dist/cli/commands/dashboard.d.ts +1 -1
- package/dist/cli/commands/dashboard.d.ts.map +1 -1
- package/dist/cli/commands/dashboard.js +10 -10
- package/dist/cli/commands/dashboard.js.map +1 -1
- package/dist/cli/commands/dashboard.test.js +1 -1
- package/dist/cli/commands/dashboard.test.js.map +1 -1
- package/dist/cli/commands/guides.d.ts +24 -0
- package/dist/cli/commands/guides.d.ts.map +1 -0
- package/dist/cli/commands/guides.js +103 -0
- package/dist/cli/commands/guides.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.d.ts +9 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.js +112 -0
- package/dist/cli/commands/knowledge-freshness-anti-over-rewrite.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.d.ts +8 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.js +96 -0
- package/dist/cli/commands/knowledge-freshness-audit-apply.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.d.ts +7 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.js +42 -0
- package/dist/cli/commands/knowledge-freshness-audit-prefilter.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.d.ts +9 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.js +63 -0
- package/dist/cli/commands/knowledge-freshness-audit-run-entry.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.d.ts +8 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.js +34 -0
- package/dist/cli/commands/knowledge-freshness-bump-version.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.d.ts +7 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.js +51 -0
- package/dist/cli/commands/knowledge-freshness-deep-guidance-check.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-link-check.d.ts +7 -0
- package/dist/cli/commands/knowledge-freshness-link-check.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-link-check.js +57 -0
- package/dist/cli/commands/knowledge-freshness-link-check.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.d.ts +8 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.js +58 -0
- package/dist/cli/commands/knowledge-freshness-lint-unsourced.js.map +1 -0
- package/dist/cli/commands/knowledge-freshness.d.ts +4 -0
- package/dist/cli/commands/knowledge-freshness.d.ts.map +1 -0
- package/dist/cli/commands/knowledge-freshness.js +25 -0
- package/dist/cli/commands/knowledge-freshness.js.map +1 -0
- package/dist/cli/commands/observe.d.ts +4 -0
- package/dist/cli/commands/observe.d.ts.map +1 -1
- package/dist/cli/commands/observe.js +13 -0
- package/dist/cli/commands/observe.js.map +1 -1
- package/dist/cli/commands/observe.test.js +46 -0
- package/dist/cli/commands/observe.test.js.map +1 -1
- package/dist/cli/commands/validate-knowledge.d.ts +4 -0
- package/dist/cli/commands/validate-knowledge.d.ts.map +1 -0
- package/dist/cli/commands/validate-knowledge.js +32 -0
- package/dist/cli/commands/validate-knowledge.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +6 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/adapters/claude-code.d.ts.map +1 -1
- package/dist/core/adapters/claude-code.js +6 -3
- package/dist/core/adapters/claude-code.js.map +1 -1
- package/dist/core/adapters/claude-code.test.js +45 -1
- package/dist/core/adapters/claude-code.test.js.map +1 -1
- package/dist/core/assembly/engine.d.ts.map +1 -1
- package/dist/core/assembly/engine.js +7 -3
- package/dist/core/assembly/engine.js.map +1 -1
- package/dist/core/assembly/engine.test.js +45 -1
- package/dist/core/assembly/engine.test.js.map +1 -1
- package/dist/core/assembly/gap-signal-tail.d.ts +18 -0
- package/dist/core/assembly/gap-signal-tail.d.ts.map +1 -0
- package/dist/core/assembly/gap-signal-tail.js +43 -0
- package/dist/core/assembly/gap-signal-tail.js.map +1 -0
- package/dist/core/assembly/gap-signal-tail.test.d.ts +2 -0
- package/dist/core/assembly/gap-signal-tail.test.d.ts.map +1 -0
- package/dist/core/assembly/gap-signal-tail.test.js +49 -0
- package/dist/core/assembly/gap-signal-tail.test.js.map +1 -0
- package/dist/core/assembly/knowledge-loader.d.ts +11 -0
- package/dist/core/assembly/knowledge-loader.d.ts.map +1 -1
- package/dist/core/assembly/knowledge-loader.js +54 -1
- package/dist/core/assembly/knowledge-loader.js.map +1 -1
- package/dist/core/assembly/knowledge-loader.test.js +73 -0
- package/dist/core/assembly/knowledge-loader.test.js.map +1 -1
- package/dist/guides/build.d.ts +12 -0
- package/dist/guides/build.d.ts.map +1 -0
- package/dist/guides/build.js +50 -0
- package/dist/guides/build.js.map +1 -0
- package/dist/guides/build.test.d.ts +2 -0
- package/dist/guides/build.test.d.ts.map +1 -0
- package/dist/guides/build.test.js +74 -0
- package/dist/guides/build.test.js.map +1 -0
- package/dist/guides/chrome.d.ts +24 -0
- package/dist/guides/chrome.d.ts.map +1 -0
- package/dist/guides/chrome.js +118 -0
- package/dist/guides/chrome.js.map +1 -0
- package/dist/guides/cli-guides.test.d.ts +2 -0
- package/dist/guides/cli-guides.test.d.ts.map +1 -0
- package/dist/guides/cli-guides.test.js +41 -0
- package/dist/guides/cli-guides.test.js.map +1 -0
- package/dist/guides/dashboard-theme.css +1073 -0
- package/dist/guides/directives-callout.test.d.ts +2 -0
- package/dist/guides/directives-callout.test.d.ts.map +1 -0
- package/dist/guides/directives-callout.test.js +22 -0
- package/dist/guides/directives-callout.test.js.map +1 -0
- package/dist/guides/directives-chart.test.d.ts +2 -0
- package/dist/guides/directives-chart.test.d.ts.map +1 -0
- package/dist/guides/directives-chart.test.js +25 -0
- package/dist/guides/directives-chart.test.js.map +1 -0
- package/dist/guides/directives-filter-table.test.d.ts +2 -0
- package/dist/guides/directives-filter-table.test.d.ts.map +1 -0
- package/dist/guides/directives-filter-table.test.js +22 -0
- package/dist/guides/directives-filter-table.test.js.map +1 -0
- package/dist/guides/directives-sev.test.d.ts +2 -0
- package/dist/guides/directives-sev.test.d.ts.map +1 -0
- package/dist/guides/directives-sev.test.js +15 -0
- package/dist/guides/directives-sev.test.js.map +1 -0
- package/dist/guides/directives-tabs.test.d.ts +2 -0
- package/dist/guides/directives-tabs.test.d.ts.map +1 -0
- package/dist/guides/directives-tabs.test.js +52 -0
- package/dist/guides/directives-tabs.test.js.map +1 -0
- package/dist/guides/directives.d.ts +7 -0
- package/dist/guides/directives.d.ts.map +1 -0
- package/dist/guides/directives.js +158 -0
- package/dist/guides/directives.js.map +1 -0
- package/dist/guides/fs-guides.test.d.ts +2 -0
- package/dist/guides/fs-guides.test.d.ts.map +1 -0
- package/dist/guides/fs-guides.test.js +14 -0
- package/dist/guides/fs-guides.test.js.map +1 -0
- package/dist/guides/index-page.d.ts +3 -0
- package/dist/guides/index-page.d.ts.map +1 -0
- package/dist/guides/index-page.js +14 -0
- package/dist/guides/index-page.js.map +1 -0
- package/dist/guides/lint.d.ts +6 -0
- package/dist/guides/lint.d.ts.map +1 -0
- package/dist/guides/lint.js +27 -0
- package/dist/guides/lint.js.map +1 -0
- package/dist/guides/lint.test.d.ts +2 -0
- package/dist/guides/lint.test.d.ts.map +1 -0
- package/dist/guides/lint.test.js +24 -0
- package/dist/guides/lint.test.js.map +1 -0
- package/dist/guides/loader.d.ts +4 -0
- package/dist/guides/loader.d.ts.map +1 -0
- package/dist/guides/loader.js +63 -0
- package/dist/guides/loader.js.map +1 -0
- package/dist/guides/loader.test.d.ts +2 -0
- package/dist/guides/loader.test.d.ts.map +1 -0
- package/dist/guides/loader.test.js +85 -0
- package/dist/guides/loader.test.js.map +1 -0
- package/dist/guides/mermaid-sanitize.test.d.ts +2 -0
- package/dist/guides/mermaid-sanitize.test.d.ts.map +1 -0
- package/dist/guides/mermaid-sanitize.test.js +57 -0
- package/dist/guides/mermaid-sanitize.test.js.map +1 -0
- package/dist/guides/mermaid.d.ts +18 -0
- package/dist/guides/mermaid.d.ts.map +1 -0
- package/dist/guides/mermaid.js +137 -0
- package/dist/guides/mermaid.js.map +1 -0
- package/dist/guides/mermaid.test.d.ts +2 -0
- package/dist/guides/mermaid.test.d.ts.map +1 -0
- package/dist/guides/mermaid.test.js +105 -0
- package/dist/guides/mermaid.test.js.map +1 -0
- package/dist/guides/render.d.ts +12 -0
- package/dist/guides/render.d.ts.map +1 -0
- package/dist/guides/render.js +58 -0
- package/dist/guides/render.js.map +1 -0
- package/dist/guides/render.test.d.ts +2 -0
- package/dist/guides/render.test.d.ts.map +1 -0
- package/dist/guides/render.test.js +46 -0
- package/dist/guides/render.test.js.map +1 -0
- package/dist/guides/sanitize.d.ts +3 -0
- package/dist/guides/sanitize.d.ts.map +1 -0
- package/dist/guides/sanitize.js +76 -0
- package/dist/guides/sanitize.js.map +1 -0
- package/dist/guides/sanitize.test.d.ts +2 -0
- package/dist/guides/sanitize.test.d.ts.map +1 -0
- package/dist/guides/sanitize.test.js +45 -0
- package/dist/guides/sanitize.test.js.map +1 -0
- package/dist/guides/template.d.ts +11 -0
- package/dist/guides/template.d.ts.map +1 -0
- package/dist/guides/template.js +38 -0
- package/dist/guides/template.js.map +1 -0
- package/dist/guides/template.test.d.ts +2 -0
- package/dist/guides/template.test.d.ts.map +1 -0
- package/dist/guides/template.test.js +41 -0
- package/dist/guides/template.test.js.map +1 -0
- package/dist/guides/types.d.ts +20 -0
- package/dist/guides/types.d.ts.map +1 -0
- package/dist/guides/types.js +2 -0
- package/dist/guides/types.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.d.ts +64 -0
- package/dist/knowledge-freshness/audit-apply-pr.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.js +309 -0
- package/dist/knowledge-freshness/audit-apply-pr.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.js +211 -0
- package/dist/knowledge-freshness/audit-apply-pr.test.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply.d.ts +16 -0
- package/dist/knowledge-freshness/audit-apply.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply.js +193 -0
- package/dist/knowledge-freshness/audit-apply.js.map +1 -0
- package/dist/knowledge-freshness/audit-apply.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-apply.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-apply.test.js +482 -0
- package/dist/knowledge-freshness/audit-apply.test.js.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.d.ts +12 -0
- package/dist/knowledge-freshness/audit-prefilter.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.js +74 -0
- package/dist/knowledge-freshness/audit-prefilter.js.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-prefilter.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-prefilter.test.js +78 -0
- package/dist/knowledge-freshness/audit-prefilter.test.js.map +1 -0
- package/dist/knowledge-freshness/audit-runner.d.ts +135 -0
- package/dist/knowledge-freshness/audit-runner.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-runner.js +168 -0
- package/dist/knowledge-freshness/audit-runner.js.map +1 -0
- package/dist/knowledge-freshness/audit-runner.test.d.ts +2 -0
- package/dist/knowledge-freshness/audit-runner.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/audit-runner.test.js +130 -0
- package/dist/knowledge-freshness/audit-runner.test.js.map +1 -0
- package/dist/knowledge-freshness/bump-version.d.ts +24 -0
- package/dist/knowledge-freshness/bump-version.d.ts.map +1 -0
- package/dist/knowledge-freshness/bump-version.js +69 -0
- package/dist/knowledge-freshness/bump-version.js.map +1 -0
- package/dist/knowledge-freshness/bump-version.test.d.ts +2 -0
- package/dist/knowledge-freshness/bump-version.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/bump-version.test.js +82 -0
- package/dist/knowledge-freshness/bump-version.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.d.ts +86 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.js +210 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.js.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.js +115 -0
- package/dist/knowledge-freshness/gates/anti-over-rewrite.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/changed-files.d.ts +53 -0
- package/dist/knowledge-freshness/gates/changed-files.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/changed-files.js +128 -0
- package/dist/knowledge-freshness/gates/changed-files.js.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.d.ts +23 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.js +27 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.js.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.js +23 -0
- package/dist/knowledge-freshness/gates/deep-guidance-check.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.d.ts +55 -0
- package/dist/knowledge-freshness/gates/link-check.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.js +161 -0
- package/dist/knowledge-freshness/gates/link-check.js.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/link-check.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/link-check.test.js +76 -0
- package/dist/knowledge-freshness/gates/link-check.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.d.ts +40 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.js +143 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.js.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.js +68 -0
- package/dist/knowledge-freshness/gates/lint-unsourced.test.js.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.d.ts +25 -0
- package/dist/knowledge-freshness/gates/parse-entry.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.js +41 -0
- package/dist/knowledge-freshness/gates/parse-entry.js.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.d.ts +2 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.js +34 -0
- package/dist/knowledge-freshness/gates/parse-entry.test.js.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.d.ts +33 -0
- package/dist/knowledge-freshness/providers/anthropic.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.js +36 -0
- package/dist/knowledge-freshness/providers/anthropic.js.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.test.d.ts +2 -0
- package/dist/knowledge-freshness/providers/anthropic.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/anthropic.test.js +32 -0
- package/dist/knowledge-freshness/providers/anthropic.test.js.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.d.ts +33 -0
- package/dist/knowledge-freshness/providers/deepseek.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.js +157 -0
- package/dist/knowledge-freshness/providers/deepseek.js.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.test.d.ts +2 -0
- package/dist/knowledge-freshness/providers/deepseek.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/deepseek.test.js +142 -0
- package/dist/knowledge-freshness/providers/deepseek.test.js.map +1 -0
- package/dist/knowledge-freshness/providers/index.d.ts +41 -0
- package/dist/knowledge-freshness/providers/index.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/index.js +108 -0
- package/dist/knowledge-freshness/providers/index.js.map +1 -0
- package/dist/knowledge-freshness/providers/index.test.d.ts +2 -0
- package/dist/knowledge-freshness/providers/index.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/providers/index.test.js +97 -0
- package/dist/knowledge-freshness/providers/index.test.js.map +1 -0
- package/dist/knowledge-freshness/source-hash.d.ts +39 -0
- package/dist/knowledge-freshness/source-hash.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-hash.js +180 -0
- package/dist/knowledge-freshness/source-hash.js.map +1 -0
- package/dist/knowledge-freshness/source-hash.test.d.ts +2 -0
- package/dist/knowledge-freshness/source-hash.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-hash.test.js +63 -0
- package/dist/knowledge-freshness/source-hash.test.js.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.d.ts +57 -0
- package/dist/knowledge-freshness/source-url-validator.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.js +304 -0
- package/dist/knowledge-freshness/source-url-validator.js.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.test.d.ts +2 -0
- package/dist/knowledge-freshness/source-url-validator.test.d.ts.map +1 -0
- package/dist/knowledge-freshness/source-url-validator.test.js +167 -0
- package/dist/knowledge-freshness/source-url-validator.test.js.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.d.ts +3 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.js +165 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.js.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.d.ts +2 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.js +421 -0
- package/dist/observability/checks/lens-i-knowledge-gaps.test.js.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.d.ts +16 -0
- package/dist/observability/checks/lens-i-lessons-scanner.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.js +106 -0
- package/dist/observability/checks/lens-i-lessons-scanner.js.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.d.ts +2 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.d.ts.map +1 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.js +174 -0
- package/dist/observability/checks/lens-i-lessons-scanner.test.js.map +1 -0
- package/dist/observability/engine/api.d.ts +4 -0
- package/dist/observability/engine/api.d.ts.map +1 -1
- package/dist/observability/engine/api.js +17 -1
- package/dist/observability/engine/api.js.map +1 -1
- package/dist/observability/engine/checks/observability-config.d.ts +4 -0
- package/dist/observability/engine/checks/observability-config.d.ts.map +1 -1
- package/dist/observability/engine/checks/observability-config.js +1 -0
- package/dist/observability/engine/checks/observability-config.js.map +1 -1
- package/dist/observability/engine/checks/registry.d.ts.map +1 -1
- package/dist/observability/engine/checks/registry.js +7 -0
- package/dist/observability/engine/checks/registry.js.map +1 -1
- package/dist/observability/engine/checks/registry.test.js +3 -2
- package/dist/observability/engine/checks/registry.test.js.map +1 -1
- package/dist/observability/engine/checks/runner.d.ts +30 -0
- package/dist/observability/engine/checks/runner.d.ts.map +1 -1
- package/dist/observability/engine/checks/runner.js +8 -1
- package/dist/observability/engine/checks/runner.js.map +1 -1
- package/dist/observability/engine/checks/runner.test.js +74 -0
- package/dist/observability/engine/checks/runner.test.js.map +1 -1
- package/dist/observability/engine/event-schemas.d.ts.map +1 -1
- package/dist/observability/engine/event-schemas.js +41 -3
- package/dist/observability/engine/event-schemas.js.map +1 -1
- package/dist/observability/engine/event-schemas.test.js +105 -0
- package/dist/observability/engine/event-schemas.test.js.map +1 -1
- package/dist/observability/engine/fix-flow.d.ts +7 -0
- package/dist/observability/engine/fix-flow.d.ts.map +1 -1
- package/dist/observability/engine/fix-flow.js +5 -3
- package/dist/observability/engine/fix-flow.js.map +1 -1
- package/dist/observability/engine/knowledge-root-integration.test.d.ts +2 -0
- package/dist/observability/engine/knowledge-root-integration.test.d.ts.map +1 -0
- package/dist/observability/engine/knowledge-root-integration.test.js +103 -0
- package/dist/observability/engine/knowledge-root-integration.test.js.map +1 -0
- package/dist/observability/engine/types.d.ts +20 -1
- package/dist/observability/engine/types.d.ts.map +1 -1
- package/dist/observability/engine/types.test.js +1 -1
- package/dist/observability/engine/types.test.js.map +1 -1
- package/dist/observability/knowledge-index.d.ts +145 -0
- package/dist/observability/knowledge-index.d.ts.map +1 -0
- package/dist/observability/knowledge-index.js +353 -0
- package/dist/observability/knowledge-index.js.map +1 -0
- package/dist/observability/knowledge-index.test.d.ts +2 -0
- package/dist/observability/knowledge-index.test.d.ts.map +1 -0
- package/dist/observability/knowledge-index.test.js +364 -0
- package/dist/observability/knowledge-index.test.js.map +1 -0
- package/dist/observability/renderers/markdown.d.ts.map +1 -1
- package/dist/observability/renderers/markdown.js +14 -0
- package/dist/observability/renderers/markdown.js.map +1 -1
- package/dist/observability/renderers/markdown.test.js +30 -0
- package/dist/observability/renderers/markdown.test.js.map +1 -1
- package/dist/types/assembly.d.ts +10 -0
- package/dist/types/assembly.d.ts.map +1 -1
- package/dist/utils/fs.d.ts +6 -0
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +13 -0
- package/dist/utils/fs.js.map +1 -1
- package/dist/validation/knowledge-frontmatter-validator.d.ts +15 -0
- package/dist/validation/knowledge-frontmatter-validator.d.ts.map +1 -0
- package/dist/validation/knowledge-frontmatter-validator.js +131 -0
- package/dist/validation/knowledge-frontmatter-validator.js.map +1 -0
- package/dist/validation/knowledge-frontmatter-validator.test.d.ts +2 -0
- package/dist/validation/knowledge-frontmatter-validator.test.d.ts.map +1 -0
- package/dist/validation/knowledge-frontmatter-validator.test.js +66 -0
- package/dist/validation/knowledge-frontmatter-validator.test.js.map +1 -0
- package/package.json +13 -4
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { fetch as undiciFetch } from 'undici';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* SECURITY: like decision #7's anthropic-subprocess invariant, the
|
|
5
|
+
* DeepSeek URL and the model-name allowlist are HARDCODED. Project-local
|
|
6
|
+
* config can never redirect this dispatcher at a different host or run
|
|
7
|
+
* an unsupported model. Future contributors who feel tempted to read a
|
|
8
|
+
* URL from `.scaffold/observability.yaml` here should re-read the parent
|
|
9
|
+
* design doc's Resolved Decisions table first.
|
|
10
|
+
*/
|
|
11
|
+
export const DEEPSEEK_URL = 'https://api.deepseek.com/chat/completions';
|
|
12
|
+
/**
|
|
13
|
+
* Hardcoded allowlist of DeepSeek model names. KNOWLEDGE_FRESHNESS_DEEPSEEK_MODEL
|
|
14
|
+
* may override the default, but only to a value in this set — never to
|
|
15
|
+
* arbitrary text. The previously-supported `deepseek-chat` and
|
|
16
|
+
* `deepseek-reasoner` IDs are deprecated and intentionally excluded.
|
|
17
|
+
*/
|
|
18
|
+
const ALLOWED_MODELS = ['deepseek-v4-flash', 'deepseek-v4-pro'];
|
|
19
|
+
export const DEFAULT_DEEPSEEK_MODEL = 'deepseek-v4-flash';
|
|
20
|
+
const MAX_TOKENS = 8192;
|
|
21
|
+
/**
|
|
22
|
+
* Minimal Zod schema for the DeepSeek (OpenAI-compatible) response. We
|
|
23
|
+
* validate only the path we actually consume — `choices[0].message.content`
|
|
24
|
+
* — rather than the whole API surface. Replaces the previous inline
|
|
25
|
+
* `as { choices?: … }` cast (round-2 F-003) so the response shape is
|
|
26
|
+
* checked at parse time, not implicitly via optional-chaining-then-typeof.
|
|
27
|
+
*/
|
|
28
|
+
const responseSchema = z.object({
|
|
29
|
+
choices: z.array(z.object({
|
|
30
|
+
message: z.object({ content: z.string() }),
|
|
31
|
+
})).min(1),
|
|
32
|
+
});
|
|
33
|
+
export function buildDeepseekDispatcher(opts) {
|
|
34
|
+
const model = opts.model ?? DEFAULT_DEEPSEEK_MODEL;
|
|
35
|
+
if (!ALLOWED_MODELS.includes(model)) {
|
|
36
|
+
throw new Error(`unsupported DeepSeek model "${model}". Allowed values: ${ALLOWED_MODELS.join(', ')}. ` +
|
|
37
|
+
'Set KNOWLEDGE_FRESHNESS_DEEPSEEK_MODEL to one of those, or unset it to use the default.');
|
|
38
|
+
}
|
|
39
|
+
if (!opts.apiKey) {
|
|
40
|
+
throw new Error('DEEPSEEK_API_KEY is required to use the deepseek provider');
|
|
41
|
+
}
|
|
42
|
+
const doFetch = opts.fetchImpl ?? undiciFetch;
|
|
43
|
+
const timeoutMs = opts.timeoutSec * 1000;
|
|
44
|
+
return async (prompt) => {
|
|
45
|
+
const body = JSON.stringify({
|
|
46
|
+
model,
|
|
47
|
+
messages: [{ role: 'user', content: prompt }],
|
|
48
|
+
// Thinking mode defaults ON for v4 models and IGNORES temperature
|
|
49
|
+
// (per https://api-docs.deepseek.com/guides/thinking_mode). The
|
|
50
|
+
// audit prompt produces structured JSON via the runner's schema-
|
|
51
|
+
// aware extractor — chain-of-thought reasoning before the JSON
|
|
52
|
+
// wastes the output token budget and produces non-deterministic
|
|
53
|
+
// text. Disable thinking so temperature: 0 actually takes effect
|
|
54
|
+
// and the response goes straight to the verdict.
|
|
55
|
+
thinking: { type: 'disabled' },
|
|
56
|
+
temperature: 0,
|
|
57
|
+
max_tokens: MAX_TOKENS,
|
|
58
|
+
stream: false,
|
|
59
|
+
});
|
|
60
|
+
// Timeout via AbortSignal.timeout — stable since Node 16.14 / 17.3
|
|
61
|
+
// (verified at https://nodejs.org/api/globals.html#abortsignaltimeoutdelay).
|
|
62
|
+
// The same pattern is already used in source-hash.ts and link-check.ts;
|
|
63
|
+
// an earlier review-round claim that this method was unavailable on
|
|
64
|
+
// 18.17 turned out to be a hallucination.
|
|
65
|
+
//
|
|
66
|
+
// EVERY step from doFetch through response-body read is wrapped in a
|
|
67
|
+
// single try/catch that normalizes any thrown error — DNS failure,
|
|
68
|
+
// connection reset, timeout abort (whether during headers or body
|
|
69
|
+
// read), JSON parse failure, schema violation, empty content — into
|
|
70
|
+
// a `deepseek dispatcher: …` prefixed Error so cron logs are
|
|
71
|
+
// actionable and consistent with the anthropic path's error shape.
|
|
72
|
+
try {
|
|
73
|
+
const res = await doFetch(DEEPSEEK_URL, {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
headers: {
|
|
76
|
+
'Authorization': `Bearer ${opts.apiKey}`,
|
|
77
|
+
'Content-Type': 'application/json',
|
|
78
|
+
},
|
|
79
|
+
body,
|
|
80
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
81
|
+
});
|
|
82
|
+
// Always read the body as TEXT first so we can produce a useful
|
|
83
|
+
// diagnostic on both non-2xx AND malformed-JSON responses
|
|
84
|
+
// (round-2 F-004: previously `await res.json()` propagated a raw
|
|
85
|
+
// SyntaxError that masked the actual response body).
|
|
86
|
+
const rawText = await res.text();
|
|
87
|
+
if (res.status < 200 || res.status >= 300) {
|
|
88
|
+
throw new Error(`deepseek dispatcher: HTTP ${res.status} from ${DEEPSEEK_URL}. ` +
|
|
89
|
+
`Body (first 200 chars): ${rawText.slice(0, 200)}`);
|
|
90
|
+
}
|
|
91
|
+
let parsed;
|
|
92
|
+
try {
|
|
93
|
+
parsed = JSON.parse(rawText);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
throw new Error('deepseek dispatcher: response was not valid JSON. ' +
|
|
97
|
+
`Body (first 200 chars): ${rawText.slice(0, 200)}`);
|
|
98
|
+
}
|
|
99
|
+
const result = responseSchema.safeParse(parsed);
|
|
100
|
+
if (!result.success) {
|
|
101
|
+
throw new Error('deepseek dispatcher: response missing choices[0].message.content. ' +
|
|
102
|
+
`Truncated response: ${rawText.slice(0, 200)}`);
|
|
103
|
+
}
|
|
104
|
+
const content = result.data.choices[0].message.content;
|
|
105
|
+
// Round-6 grok finding: an empty-string content satisfies the zod
|
|
106
|
+
// schema but is useless to the runner's JSON extractor and produces
|
|
107
|
+
// a confusing downstream parse error. Surface the empty-response
|
|
108
|
+
// case with a clear message and the truncated body.
|
|
109
|
+
if (content.trim() === '') {
|
|
110
|
+
throw new Error('deepseek dispatcher: model returned empty content. ' +
|
|
111
|
+
`Truncated response: ${rawText.slice(0, 200)}`);
|
|
112
|
+
}
|
|
113
|
+
return content;
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
// Re-throw our own already-prefixed errors verbatim; wrap everything
|
|
117
|
+
// else (transport failures, abort errors, etc.) so cron logs see a
|
|
118
|
+
// consistent "deepseek dispatcher: …" prefix (round-7 grok finding:
|
|
119
|
+
// the round-6 fix only covered the initial doFetch call, leaving
|
|
120
|
+
// body-read aborts and stream errors unwrapped).
|
|
121
|
+
if (err instanceof Error && err.message.startsWith('deepseek dispatcher: '))
|
|
122
|
+
throw err;
|
|
123
|
+
// Surface the underlying transport detail. undici's fetch rejects
|
|
124
|
+
// with `TypeError: fetch failed` and stashes the actionable
|
|
125
|
+
// ENOTFOUND/ECONNRESET/TLS detail in `err.cause` — without
|
|
126
|
+
// unwrapping that, cron logs would show the unhelpful
|
|
127
|
+
// "deepseek dispatcher: fetch failed: fetch failed" (PR #393 MMR
|
|
128
|
+
// F-002).
|
|
129
|
+
const reason = describeFetchError(err);
|
|
130
|
+
throw new Error(`deepseek dispatcher: fetch failed: ${reason}`);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Pull out a useful message from a thrown fetch error. undici wraps
|
|
136
|
+
* transport-layer failures (DNS, connection reset, TLS) in a
|
|
137
|
+
* `TypeError: fetch failed` whose `cause` carries the actionable detail
|
|
138
|
+
* (ENOTFOUND, ECONNRESET, etc.). Without unwrapping `cause`, cron logs
|
|
139
|
+
* would lose that detail and show only "fetch failed" — useless for
|
|
140
|
+
* triage. We compose the outer message with the cause's `code` and
|
|
141
|
+
* `message` when present.
|
|
142
|
+
*/
|
|
143
|
+
function describeFetchError(err) {
|
|
144
|
+
if (!(err instanceof Error))
|
|
145
|
+
return String(err);
|
|
146
|
+
const cause = err.cause;
|
|
147
|
+
if (cause instanceof Error) {
|
|
148
|
+
const code = cause.code;
|
|
149
|
+
const tail = code ? `${code}: ${cause.message}` : cause.message;
|
|
150
|
+
return `${err.message} (${tail})`;
|
|
151
|
+
}
|
|
152
|
+
if (typeof cause === 'string' && cause) {
|
|
153
|
+
return `${err.message} (${cause})`;
|
|
154
|
+
}
|
|
155
|
+
return err.message;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=deepseek.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepseek.js","sourceRoot":"","sources":["../../../src/knowledge-freshness/providers/deepseek.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepseek.test.d.ts","sourceRoot":"","sources":["../../../src/knowledge-freshness/providers/deepseek.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { buildDeepseekDispatcher } from './deepseek.js';
|
|
3
|
+
const ok = (body) => new Response(JSON.stringify(body), { status: 200, headers: { 'content-type': 'application/json' } });
|
|
4
|
+
describe('deepseek provider — happy path', () => {
|
|
5
|
+
it('POSTs to api.deepseek.com/chat/completions with bearer auth and the prompt as user message', async () => {
|
|
6
|
+
// Keep a separate reference to the raw vi.fn() result BEFORE casting to
|
|
7
|
+
// DeepseekFetch, so we can read .mock.calls without an `as unknown as`
|
|
8
|
+
// dive into vitest internals (round-6 grok finding).
|
|
9
|
+
const rawFetchMock = vi.fn(async () => ok({
|
|
10
|
+
choices: [{ message: { content: '{"verdict":"current"}' } }],
|
|
11
|
+
}));
|
|
12
|
+
const fetchSpy = rawFetchMock;
|
|
13
|
+
const dispatcher = buildDeepseekDispatcher({
|
|
14
|
+
apiKey: 'sk-test-key',
|
|
15
|
+
timeoutSec: 600,
|
|
16
|
+
fetchImpl: fetchSpy,
|
|
17
|
+
});
|
|
18
|
+
const result = await dispatcher('the meta-prompt body');
|
|
19
|
+
expect(result).toBe('{"verdict":"current"}');
|
|
20
|
+
// Verify the request shape exactly.
|
|
21
|
+
expect(rawFetchMock).toHaveBeenCalledWith('https://api.deepseek.com/chat/completions', expect.objectContaining({
|
|
22
|
+
method: 'POST',
|
|
23
|
+
headers: expect.objectContaining({
|
|
24
|
+
'Authorization': 'Bearer sk-test-key',
|
|
25
|
+
'Content-Type': 'application/json',
|
|
26
|
+
}),
|
|
27
|
+
body: expect.any(String),
|
|
28
|
+
}));
|
|
29
|
+
// Parse the JSON body to verify the request shape precisely.
|
|
30
|
+
const sentBody = JSON.parse(rawFetchMock.mock.calls[0][1].body);
|
|
31
|
+
expect(sentBody).toEqual({
|
|
32
|
+
model: 'deepseek-v4-flash',
|
|
33
|
+
messages: [{ role: 'user', content: 'the meta-prompt body' }],
|
|
34
|
+
// Round-5 F-001: thinking mode is explicitly disabled so temperature: 0
|
|
35
|
+
// takes effect and the model goes straight to the JSON verdict.
|
|
36
|
+
thinking: { type: 'disabled' },
|
|
37
|
+
temperature: 0,
|
|
38
|
+
max_tokens: 8192,
|
|
39
|
+
stream: false,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it('uses the model from KNOWLEDGE_FRESHNESS_DEEPSEEK_MODEL when set (allowlist member)', async () => {
|
|
43
|
+
const rawFetchMock = vi.fn(async () => ok({
|
|
44
|
+
choices: [{ message: { content: 'response' } }],
|
|
45
|
+
}));
|
|
46
|
+
const fetchSpy = rawFetchMock;
|
|
47
|
+
const dispatcher = buildDeepseekDispatcher({
|
|
48
|
+
apiKey: 'k',
|
|
49
|
+
timeoutSec: 60,
|
|
50
|
+
model: 'deepseek-v4-pro',
|
|
51
|
+
fetchImpl: fetchSpy,
|
|
52
|
+
});
|
|
53
|
+
await dispatcher('x');
|
|
54
|
+
expect(JSON.parse(rawFetchMock.mock.calls[0][1].body).model).toBe('deepseek-v4-pro');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe('deepseek provider — error paths', () => {
|
|
58
|
+
it('throws on non-2xx response with status + truncated body', async () => {
|
|
59
|
+
const fetchSpy = vi.fn(async () => new Response('{"error":{"message":"rate limited","type":"rate_limit_error"}}', { status: 429 }));
|
|
60
|
+
const dispatcher = buildDeepseekDispatcher({ apiKey: 'k', timeoutSec: 60, fetchImpl: fetchSpy });
|
|
61
|
+
await expect(dispatcher('x')).rejects.toThrow(/HTTP 429.*rate limited/i);
|
|
62
|
+
});
|
|
63
|
+
it('throws on a 200 response that lacks choices[0].message.content', async () => {
|
|
64
|
+
const fetchSpy = vi.fn(async () => new Response(JSON.stringify({ choices: [] }), { status: 200 }));
|
|
65
|
+
const dispatcher = buildDeepseekDispatcher({ apiKey: 'k', timeoutSec: 60, fetchImpl: fetchSpy });
|
|
66
|
+
await expect(dispatcher('x')).rejects.toThrow(/missing choices\[0\]\.message\.content/i);
|
|
67
|
+
});
|
|
68
|
+
it('throws a diagnostic error on a 200 response whose body is not JSON', async () => {
|
|
69
|
+
// Round-2 F-004: must NOT propagate a bare SyntaxError. The dispatcher
|
|
70
|
+
// catches the parse failure and throws a message containing the
|
|
71
|
+
// truncated body so cron logs are actionable.
|
|
72
|
+
const fetchSpy = vi.fn(async () => new Response('not json at all', {
|
|
73
|
+
status: 200, headers: { 'content-type': 'application/json' },
|
|
74
|
+
}));
|
|
75
|
+
const dispatcher = buildDeepseekDispatcher({ apiKey: 'k', timeoutSec: 60, fetchImpl: fetchSpy });
|
|
76
|
+
await expect(dispatcher('x')).rejects.toThrow(/response was not valid JSON.*not json at all/i);
|
|
77
|
+
});
|
|
78
|
+
it('rejects an unsupported model at construction time (not at fetch time)', () => {
|
|
79
|
+
expect(() => buildDeepseekDispatcher({
|
|
80
|
+
apiKey: 'k', timeoutSec: 60, model: 'gpt-4',
|
|
81
|
+
})).toThrow(/unsupported DeepSeek model "gpt-4".*deepseek-v4-flash.*deepseek-v4-pro/i);
|
|
82
|
+
});
|
|
83
|
+
it('rejects construction when apiKey is empty', () => {
|
|
84
|
+
expect(() => buildDeepseekDispatcher({ apiKey: '', timeoutSec: 60 })).toThrow(/DEEPSEEK_API_KEY is required/);
|
|
85
|
+
});
|
|
86
|
+
it('normalizes transport errors (DNS / reset / reject) → deepseek-prefixed message (round-6 grok)', async () => {
|
|
87
|
+
// The dispatcher must wrap the fetch call so raw undici / DOMException
|
|
88
|
+
// errors don't leak to the cron logs unstyled. Mock a fetch that
|
|
89
|
+
// rejects synchronously; assert the wrapped error has the diagnostic
|
|
90
|
+
// prefix.
|
|
91
|
+
const fetchSpy = vi.fn(async () => {
|
|
92
|
+
throw new Error('getaddrinfo ENOTFOUND api.deepseek.com');
|
|
93
|
+
});
|
|
94
|
+
const dispatcher = buildDeepseekDispatcher({ apiKey: 'k', timeoutSec: 60, fetchImpl: fetchSpy });
|
|
95
|
+
await expect(dispatcher('x')).rejects.toThrow(/deepseek dispatcher: fetch failed.*ENOTFOUND/i);
|
|
96
|
+
});
|
|
97
|
+
it('unwraps err.cause when undici throws TypeError + cause (PR-393 F-002)', async () => {
|
|
98
|
+
// undici's actual transport-layer rejection shape: outer
|
|
99
|
+
// `TypeError: fetch failed` with the actionable code+message in
|
|
100
|
+
// `err.cause`. Without unwrapping cause, cron logs lose the
|
|
101
|
+
// ENOTFOUND/ECONNRESET signal we need for triage.
|
|
102
|
+
const cause = Object.assign(new Error('getaddrinfo ENOTFOUND api.deepseek.com'), {
|
|
103
|
+
code: 'ENOTFOUND',
|
|
104
|
+
});
|
|
105
|
+
const outer = new TypeError('fetch failed');
|
|
106
|
+
outer.cause = cause;
|
|
107
|
+
const fetchSpy = vi.fn(async () => { throw outer; });
|
|
108
|
+
const dispatcher = buildDeepseekDispatcher({ apiKey: 'k', timeoutSec: 60, fetchImpl: fetchSpy });
|
|
109
|
+
// The wrapped message must contain BOTH the outer "fetch failed" and
|
|
110
|
+
// the inner ENOTFOUND code, otherwise the cron log entry is useless.
|
|
111
|
+
await expect(dispatcher('x')).rejects.toThrow(/deepseek dispatcher: fetch failed.*ENOTFOUND.*api\.deepseek\.com/i);
|
|
112
|
+
});
|
|
113
|
+
it('normalizes a body-read abort (headers OK, body hangs) → deepseek-prefixed (round-7 grok)', async () => {
|
|
114
|
+
// The post-fetch phase (res.text(), JSON.parse, zod, content check) must
|
|
115
|
+
// also be wrapped — a slow server that returns 200 headers fast then
|
|
116
|
+
// hangs during body read causes the AbortSignal.timeout to fire after
|
|
117
|
+
// headers but during streaming, and res.text() rejects with a raw
|
|
118
|
+
// AbortError. The dispatcher's outer catch normalizes that into a
|
|
119
|
+
// diagnostic message.
|
|
120
|
+
const fetchSpy = vi.fn(async () => {
|
|
121
|
+
// Build a Response whose body rejects with a synthetic AbortError on
|
|
122
|
+
// read, simulating the headers-fast-body-hangs scenario.
|
|
123
|
+
const body = new ReadableStream({
|
|
124
|
+
start(controller) {
|
|
125
|
+
controller.error(new DOMException('The operation was aborted.', 'AbortError'));
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
return new Response(body, { status: 200 });
|
|
129
|
+
});
|
|
130
|
+
const dispatcher = buildDeepseekDispatcher({ apiKey: 'k', timeoutSec: 60, fetchImpl: fetchSpy });
|
|
131
|
+
await expect(dispatcher('x')).rejects.toThrow(/deepseek dispatcher: fetch failed.*[Aa]bort/i);
|
|
132
|
+
});
|
|
133
|
+
it('throws a diagnostic error when the model returns empty content (round-6 grok)', async () => {
|
|
134
|
+
// A 200 response with content === "" satisfies the zod schema but is
|
|
135
|
+
// useless to the runner's JSON extractor. The dispatcher must surface
|
|
136
|
+
// it with a clear message rather than handing back an empty string.
|
|
137
|
+
const fetchSpy = vi.fn(async () => new Response(JSON.stringify({ choices: [{ message: { content: ' ' } }] }), { status: 200 }));
|
|
138
|
+
const dispatcher = buildDeepseekDispatcher({ apiKey: 'k', timeoutSec: 60, fetchImpl: fetchSpy });
|
|
139
|
+
await expect(dispatcher('x')).rejects.toThrow(/model returned empty content/i);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
//# sourceMappingURL=deepseek.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepseek.test.js","sourceRoot":"","sources":["../../../src/knowledge-freshness/providers/deepseek.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAE,uBAAuB,EAAsB,MAAM,eAAe,CAAA;AAE3E,MAAM,EAAE,GAAG,CAAC,IAAa,EAAY,EAAE,CACrC,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAA;AAEtG,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,4FAA4F,EAAE,KAAK,IAAI,EAAE;QAC1G,wEAAwE;QACxE,uEAAuE;QACvE,qDAAqD;QACrD,MAAM,YAAY,GAAG,EAAE,CAAC,EAAE,CAAgB,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,uBAAuB,EAAE,EAAE,CAAC;SAC7D,CAAC,CAAC,CAAA;QACH,MAAM,QAAQ,GAAG,YAAwC,CAAA;QACzD,MAAM,UAAU,GAAG,uBAAuB,CAAC;YACzC,MAAM,EAAE,aAAa;YACrB,UAAU,EAAE,GAAG;YACf,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAA;QACF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,sBAAsB,CAAC,CAAA;QACvD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAA;QAC5C,oCAAoC;QACpC,MAAM,CAAC,YAAY,CAAC,CAAC,oBAAoB,CACvC,2CAA2C,EAC3C,MAAM,CAAC,gBAAgB,CAAC;YACtB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,MAAM,CAAC,gBAAgB,CAAC;gBAC/B,eAAe,EAAE,oBAAoB;gBACrC,cAAc,EAAE,kBAAkB;aACnC,CAAC;YACF,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;SACzB,CAAC,CACH,CAAA;QACD,6DAA6D;QAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,IAAc,CAAC,CAAA;QAC1E,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;YACvB,KAAK,EAAE,mBAAmB;YAC1B,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;YAC7D,wEAAwE;YACxE,gEAAgE;YAChE,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC9B,WAAW,EAAE,CAAC;YACd,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,KAAK;SACd,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;QAClG,MAAM,YAAY,GAAG,EAAE,CAAC,EAAE,CAAgB,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,CAAC;SAChD,CAAC,CAAC,CAAA;QACH,MAAM,QAAQ,GAAG,YAAwC,CAAA;QACzD,MAAM,UAAU,GAAG,uBAAuB,CAAC;YACzC,MAAM,EAAE,GAAG;YACX,UAAU,EAAE,EAAE;YACd,KAAK,EAAE,iBAAiB;YACxB,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAA;QACF,MAAM,UAAU,CAAC,GAAG,CAAC,CAAA;QACrB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,IAAc,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IACjG,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,QAAQ,GAAkB,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAC/C,IAAI,QAAQ,CAAC,gEAAgE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CACpE,CAAA;QAC7B,MAAM,UAAU,GAAG,uBAAuB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;QAChG,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAA;IAC1E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,QAAQ,GAAkB,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAC/C,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CACnC,CAAA;QAC7B,MAAM,UAAU,GAAG,uBAAuB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;QAChG,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAA;IAC1F,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,uEAAuE;QACvE,gEAAgE;QAChE,8CAA8C;QAC9C,MAAM,QAAQ,GAAkB,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAC/C,IAAI,QAAQ,CAAC,iBAAiB,EAAE;YAC9B,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAC7D,CAAC,CACyB,CAAA;QAC7B,MAAM,UAAU,GAAG,uBAAuB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;QAChG,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAA;IAChG,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,MAAM,CAAC,GAAG,EAAE,CAAC,uBAAuB,CAAC;YACnC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO;SAC5C,CAAC,CAAC,CAAC,OAAO,CAAC,yEAAyE,CAAC,CAAA;IACxF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,GAAG,EAAE,CAAC,uBAAuB,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAA;IAC/G,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+FAA+F,EAAE,KAAK,IAAI,EAAE;QAC7G,uEAAuE;QACvE,iEAAiE;QACjE,qEAAqE;QACrE,UAAU;QACV,MAAM,QAAQ,GAAkB,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAC/C,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAA;QAC3D,CAAC,CAA6B,CAAA;QAC9B,MAAM,UAAU,GAAG,uBAAuB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;QAChG,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAAA;IAChG,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uEAAuE,EAAE,KAAK,IAAI,EAAE;QACrF,yDAAyD;QACzD,gEAAgE;QAChE,4DAA4D;QAC5D,kDAAkD;QAClD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,wCAAwC,CAAC,EAAE;YAC/E,IAAI,EAAE,WAAW;SAClB,CAAC,CAAA;QACF,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,cAAc,CAAC,CAC1C;QAAC,KAAqC,CAAC,KAAK,GAAG,KAAK,CAAA;QACrD,MAAM,QAAQ,GAAkB,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAG,MAAM,KAAK,CAAA,CAAC,CAAC,CAA6B,CAAA;QAC9F,MAAM,UAAU,GAAG,uBAAuB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;QAChG,qEAAqE;QACrE,qEAAqE;QACrE,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mEAAmE,CAAC,CAAA;IACpH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0FAA0F,EAAE,KAAK,IAAI,EAAE;QACxG,yEAAyE;QACzE,qEAAqE;QACrE,sEAAsE;QACtE,kEAAkE;QAClE,kEAAkE;QAClE,sBAAsB;QACtB,MAAM,QAAQ,GAAkB,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;YAC/C,qEAAqE;YACrE,yDAAyD;YACzD,MAAM,IAAI,GAAG,IAAI,cAAc,CAAa;gBAC1C,KAAK,CAAC,UAAU;oBACd,UAAU,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,4BAA4B,EAAE,YAAY,CAAC,CAAC,CAAA;gBAChF,CAAC;aACF,CAAC,CAAA;YACF,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;QAC5C,CAAC,CAA6B,CAAA;QAC9B,MAAM,UAAU,GAAG,uBAAuB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;QAChG,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAA;IAC/F,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,qEAAqE;QACrE,sEAAsE;QACtE,oEAAoE;QACpE,MAAM,QAAQ,GAAkB,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAC/C,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAClE,CAAA;QAC7B,MAAM,UAAU,GAAG,uBAAuB,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;QAChG,MAAM,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Dispatcher } from '../audit-runner.js';
|
|
2
|
+
export type Provider = 'anthropic' | 'deepseek';
|
|
3
|
+
export interface ResolveProviderInput {
|
|
4
|
+
/** Process env. Pass `process.env` in production; inject a stub in tests. */
|
|
5
|
+
env: Record<string, string | undefined>;
|
|
6
|
+
/** Parsed CLI args. `provider` is set when the operator passed `--provider`. */
|
|
7
|
+
args: {
|
|
8
|
+
provider?: string;
|
|
9
|
+
};
|
|
10
|
+
/** Whether the `claude` CLI is available on PATH. Inject in tests. */
|
|
11
|
+
claudeOnPath: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve which LLM provider the audit runner should use.
|
|
15
|
+
*
|
|
16
|
+
* Precedence (highest first):
|
|
17
|
+
* 1. --provider <name> (explicit flag — operator override)
|
|
18
|
+
* 2. KNOWLEDGE_FRESHNESS_PROVIDER env var
|
|
19
|
+
* 3. Single API key in env (inferred)
|
|
20
|
+
* 4. Both API keys present → error (ambiguous)
|
|
21
|
+
* 5. No env, claude on PATH → anthropic (subprocess uses keychain)
|
|
22
|
+
* 6. Nothing → error (no provider configured)
|
|
23
|
+
*
|
|
24
|
+
* Errors are thrown with operator-facing messages that name the exact env
|
|
25
|
+
* var or flag the operator should set.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveProvider(input: ResolveProviderInput): Provider;
|
|
28
|
+
/**
|
|
29
|
+
* Construct a Dispatcher for the chosen provider. Each provider's
|
|
30
|
+
* implementation lives in its own file. This factory is the ONLY place
|
|
31
|
+
* the audit-run-entry CLI knows about provider differences.
|
|
32
|
+
*/
|
|
33
|
+
export interface BuildDispatcherOptions {
|
|
34
|
+
/** Per-fetch / per-subprocess timeout in seconds. */
|
|
35
|
+
timeoutSec: number;
|
|
36
|
+
/** Process env (production: `process.env`). Used by provider implementations
|
|
37
|
+
* for API keys and any optional overrides (e.g. model name). */
|
|
38
|
+
env: Record<string, string | undefined>;
|
|
39
|
+
}
|
|
40
|
+
export declare function buildDispatcher(provider: Provider, opts: BuildDispatcherOptions): Dispatcher;
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/knowledge-freshness/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAIpD,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,UAAU,CAAA;AAQ/C,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IACvC,gFAAgF;IAChF,IAAI,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3B,sEAAsE;IACtE,YAAY,EAAE,OAAO,CAAA;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,QAAQ,CAqBrE;AAsDD;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAA;IAClB;qEACiE;IACjE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACxC;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,sBAAsB,GAAG,UAAU,CAsB5F"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { buildAnthropicDispatcher } from './anthropic.js';
|
|
2
|
+
import { buildDeepseekDispatcher } from './deepseek.js';
|
|
3
|
+
const KNOWN_PROVIDERS = ['anthropic', 'deepseek'];
|
|
4
|
+
function isKnownProvider(s) {
|
|
5
|
+
return KNOWN_PROVIDERS.includes(s);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolve which LLM provider the audit runner should use.
|
|
9
|
+
*
|
|
10
|
+
* Precedence (highest first):
|
|
11
|
+
* 1. --provider <name> (explicit flag — operator override)
|
|
12
|
+
* 2. KNOWLEDGE_FRESHNESS_PROVIDER env var
|
|
13
|
+
* 3. Single API key in env (inferred)
|
|
14
|
+
* 4. Both API keys present → error (ambiguous)
|
|
15
|
+
* 5. No env, claude on PATH → anthropic (subprocess uses keychain)
|
|
16
|
+
* 6. Nothing → error (no provider configured)
|
|
17
|
+
*
|
|
18
|
+
* Errors are thrown with operator-facing messages that name the exact env
|
|
19
|
+
* var or flag the operator should set.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveProvider(input) {
|
|
22
|
+
const choice = pickProviderFromRules(input);
|
|
23
|
+
// Post-resolution runtime validation: ANY path that ends in 'anthropic'
|
|
24
|
+
// requires the `claude` CLI on PATH because the dispatcher shells out.
|
|
25
|
+
// This check covers BOTH inferred (rule-3b) and explicit (rule-1 flag,
|
|
26
|
+
// rule-2 env) paths so an operator can't pick anthropic via flag/env and
|
|
27
|
+
// then get a confusing command-not-found at first audit (round-4 F-001
|
|
28
|
+
// of the plan review).
|
|
29
|
+
if (choice === 'anthropic' && !input.claudeOnPath) {
|
|
30
|
+
throw new Error('anthropic provider selected but the `claude` CLI is not on PATH. ' +
|
|
31
|
+
'The dispatcher invokes `claude -p` as a subprocess, so the CLI is ' +
|
|
32
|
+
'required regardless of how the provider was chosen (--provider flag, ' +
|
|
33
|
+
'KNOWLEDGE_FRESHNESS_PROVIDER env, or ANTHROPIC_API_KEY inference). ' +
|
|
34
|
+
'Install Claude Code (`brew install anthropic/claude-code/claude-code` ' +
|
|
35
|
+
'or `npm install -g @anthropic-ai/claude-code`), OR switch to the ' +
|
|
36
|
+
'deepseek provider (export DEEPSEEK_API_KEY and set ' +
|
|
37
|
+
'KNOWLEDGE_FRESHNESS_PROVIDER=deepseek).');
|
|
38
|
+
}
|
|
39
|
+
return choice;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Apply rules 1-6 to pick a Provider — does NOT enforce runtime
|
|
43
|
+
* preconditions (claudeOnPath for anthropic). The wrapper above is the
|
|
44
|
+
* single place where those preconditions are validated, so we only have
|
|
45
|
+
* to maintain that invariant in one location.
|
|
46
|
+
*/
|
|
47
|
+
function pickProviderFromRules(input) {
|
|
48
|
+
// Rule 1: explicit flag wins.
|
|
49
|
+
if (input.args.provider) {
|
|
50
|
+
if (!isKnownProvider(input.args.provider)) {
|
|
51
|
+
throw new Error(`unknown provider "${input.args.provider}" passed to --provider. ` +
|
|
52
|
+
`Supported values: ${KNOWN_PROVIDERS.join(', ')}.`);
|
|
53
|
+
}
|
|
54
|
+
return input.args.provider;
|
|
55
|
+
}
|
|
56
|
+
// Rule 2: env var.
|
|
57
|
+
const envChoice = input.env['KNOWLEDGE_FRESHNESS_PROVIDER'];
|
|
58
|
+
if (envChoice) {
|
|
59
|
+
if (!isKnownProvider(envChoice)) {
|
|
60
|
+
throw new Error(`unknown provider "${envChoice}" set in KNOWLEDGE_FRESHNESS_PROVIDER. ` +
|
|
61
|
+
`Supported values: ${KNOWN_PROVIDERS.join(', ')}.`);
|
|
62
|
+
}
|
|
63
|
+
return envChoice;
|
|
64
|
+
}
|
|
65
|
+
// Rules 3/4: infer from API keys.
|
|
66
|
+
const hasAnthropic = !!input.env['ANTHROPIC_API_KEY'];
|
|
67
|
+
const hasDeepseek = !!input.env['DEEPSEEK_API_KEY'];
|
|
68
|
+
if (hasAnthropic && hasDeepseek) {
|
|
69
|
+
throw new Error('provider selection ambiguous: both ANTHROPIC_API_KEY and DEEPSEEK_API_KEY are set. ' +
|
|
70
|
+
'Set KNOWLEDGE_FRESHNESS_PROVIDER=anthropic|deepseek (or pass --provider) to disambiguate.');
|
|
71
|
+
}
|
|
72
|
+
if (hasDeepseek)
|
|
73
|
+
return 'deepseek';
|
|
74
|
+
if (hasAnthropic)
|
|
75
|
+
return 'anthropic';
|
|
76
|
+
// Rule 5: PATH probe (no env vars set, but Claude Code is installed and
|
|
77
|
+
// already authenticated via `claude /login`).
|
|
78
|
+
if (input.claudeOnPath)
|
|
79
|
+
return 'anthropic';
|
|
80
|
+
// Rule 6: nothing.
|
|
81
|
+
throw new Error('no provider configured for the knowledge-freshness audit. Either:\n' +
|
|
82
|
+
' - install Claude Code and run `claude /login` (anthropic provider), OR\n' +
|
|
83
|
+
' - export ANTHROPIC_API_KEY AND have `claude` on PATH (anthropic, env-var auth), OR\n' +
|
|
84
|
+
' - export DEEPSEEK_API_KEY (deepseek provider, no CLI install needed).\n' +
|
|
85
|
+
'See docs/knowledge-freshness/operations.md §4 for details.');
|
|
86
|
+
}
|
|
87
|
+
export function buildDispatcher(provider, opts) {
|
|
88
|
+
if (provider === 'anthropic') {
|
|
89
|
+
return buildAnthropicDispatcher({ timeoutSec: opts.timeoutSec });
|
|
90
|
+
}
|
|
91
|
+
if (provider === 'deepseek') {
|
|
92
|
+
const apiKey = opts.env['DEEPSEEK_API_KEY'];
|
|
93
|
+
if (!apiKey) {
|
|
94
|
+
throw new Error('deepseek provider selected but DEEPSEEK_API_KEY env var is not set. ' +
|
|
95
|
+
'Either export the key or pick a different provider via --provider / ' +
|
|
96
|
+
'KNOWLEDGE_FRESHNESS_PROVIDER.');
|
|
97
|
+
}
|
|
98
|
+
const modelOverride = opts.env['KNOWLEDGE_FRESHNESS_DEEPSEEK_MODEL'];
|
|
99
|
+
return buildDeepseekDispatcher({
|
|
100
|
+
apiKey,
|
|
101
|
+
timeoutSec: opts.timeoutSec,
|
|
102
|
+
model: modelOverride,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// Unreachable: the type narrowing above is exhaustive.
|
|
106
|
+
throw new Error(`unknown provider ${provider}`);
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/knowledge-freshness/providers/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/knowledge-freshness/providers/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { resolveProvider, buildDispatcher } from './index.js';
|
|
3
|
+
// `claudeOnPath` is injected so tests don't depend on the host's $PATH.
|
|
4
|
+
// We type `env` as `Record<string, string | undefined>` directly rather
|
|
5
|
+
// than via a narrow named `interface` — round-3 F-003 of the plan review:
|
|
6
|
+
// a narrow interface lacks an index signature and won't satisfy the
|
|
7
|
+
// `Record<string, string | undefined>` parameter of `resolveProvider` in
|
|
8
|
+
// strict mode.
|
|
9
|
+
const opts = (env, args = {}, claudeOnPath = false) => ({ env, args, claudeOnPath });
|
|
10
|
+
describe('resolveProvider', () => {
|
|
11
|
+
it('rule 1: --provider flag wins over everything', () => {
|
|
12
|
+
const env = { ANTHROPIC_API_KEY: 'a', DEEPSEEK_API_KEY: 'd', KNOWLEDGE_FRESHNESS_PROVIDER: 'anthropic' };
|
|
13
|
+
// deepseek skips the PATH check entirely so claudeOnPath defaults to false here.
|
|
14
|
+
expect(resolveProvider(opts(env, { provider: 'deepseek' }))).toBe('deepseek');
|
|
15
|
+
// anthropic requires `claude` on PATH (round-4 F-001). The flag wins over env/keys,
|
|
16
|
+
// but the post-resolution PATH precondition still applies, so pass claudeOnPath=true.
|
|
17
|
+
expect(resolveProvider(opts(env, { provider: 'anthropic' }, true))).toBe('anthropic');
|
|
18
|
+
});
|
|
19
|
+
it('rule 2: KNOWLEDGE_FRESHNESS_PROVIDER env var when no flag', () => {
|
|
20
|
+
const env = { ANTHROPIC_API_KEY: 'a', DEEPSEEK_API_KEY: 'd', KNOWLEDGE_FRESHNESS_PROVIDER: 'deepseek' };
|
|
21
|
+
expect(resolveProvider(opts(env))).toBe('deepseek');
|
|
22
|
+
});
|
|
23
|
+
it('rule 3a: only DEEPSEEK_API_KEY set → deepseek', () => {
|
|
24
|
+
expect(resolveProvider(opts({ DEEPSEEK_API_KEY: 'd' }))).toBe('deepseek');
|
|
25
|
+
});
|
|
26
|
+
it('rule 3b: ANTHROPIC_API_KEY set AND claude on PATH → anthropic', () => {
|
|
27
|
+
expect(resolveProvider(opts({ ANTHROPIC_API_KEY: 'a' }, {}, true))).toBe('anthropic');
|
|
28
|
+
});
|
|
29
|
+
it('rule 3b error: ANTHROPIC_API_KEY set but claude NOT on PATH → error', () => {
|
|
30
|
+
// Round-3 F-001: the env var alone is insufficient because the
|
|
31
|
+
// anthropic dispatcher shells out to `claude -p`. Surface this at
|
|
32
|
+
// resolveProvider time, not at first audit dispatch.
|
|
33
|
+
const call = () => resolveProvider(opts({ ANTHROPIC_API_KEY: 'a' }, {}, false));
|
|
34
|
+
expect(call).toThrow(/`claude` CLI is not on PATH/);
|
|
35
|
+
});
|
|
36
|
+
it('rule-1 error: --provider anthropic but claude NOT on PATH → error', () => {
|
|
37
|
+
// Round-4 F-001: the post-resolution PATH check covers EVERY anthropic
|
|
38
|
+
// selection path, not just the inferred-from-env one. An operator who
|
|
39
|
+
// explicitly forces --provider anthropic on a machine without Claude
|
|
40
|
+
// Code installed gets a clear early error instead of command-not-found
|
|
41
|
+
// at first audit.
|
|
42
|
+
const call = () => resolveProvider(opts({}, { provider: 'anthropic' }, false));
|
|
43
|
+
expect(call).toThrow(/`claude` CLI is not on PATH/);
|
|
44
|
+
});
|
|
45
|
+
it('rule-2 error: KNOWLEDGE_FRESHNESS_PROVIDER=anthropic but claude NOT on PATH → error', () => {
|
|
46
|
+
// Same protection on the env-var path.
|
|
47
|
+
const call = () => resolveProvider(opts({ KNOWLEDGE_FRESHNESS_PROVIDER: 'anthropic' }, {}, false));
|
|
48
|
+
expect(call).toThrow(/`claude` CLI is not on PATH/);
|
|
49
|
+
});
|
|
50
|
+
it('rule-1 explicit deepseek skips the PATH check entirely', () => {
|
|
51
|
+
// Sanity check: the PATH precondition is anthropic-only. deepseek
|
|
52
|
+
// doesn't need a CLI.
|
|
53
|
+
expect(resolveProvider(opts({ DEEPSEEK_API_KEY: 'd' }, { provider: 'deepseek' }, false))).toBe('deepseek');
|
|
54
|
+
});
|
|
55
|
+
it('rule 4: both keys set without explicit choice → error with helpful message', () => {
|
|
56
|
+
// The thrown message can list the env-var and the --provider flag in
|
|
57
|
+
// either order — assert each substring independently so a wording
|
|
58
|
+
// change to the message doesn't break the test.
|
|
59
|
+
const call = () => resolveProvider(opts({ ANTHROPIC_API_KEY: 'a', DEEPSEEK_API_KEY: 'd' }));
|
|
60
|
+
expect(call).toThrow(/ambiguous/i);
|
|
61
|
+
expect(call).toThrow(/KNOWLEDGE_FRESHNESS_PROVIDER/);
|
|
62
|
+
expect(call).toThrow(/--provider/);
|
|
63
|
+
});
|
|
64
|
+
it('rule 5: no env vars but claude on PATH → anthropic (keychain delegation)', () => {
|
|
65
|
+
expect(resolveProvider(opts({}, {}, true))).toBe('anthropic');
|
|
66
|
+
});
|
|
67
|
+
it('rule 6: no env vars and no claude on PATH → error with setup instructions', () => {
|
|
68
|
+
// The setup-instructions message spans multiple lines — use [\s\S]* so
|
|
69
|
+
// the match crosses newlines, and assert each key substring independently
|
|
70
|
+
// since they appear in human-readable order (ANTHROPIC then DEEPSEEK).
|
|
71
|
+
const call = () => resolveProvider(opts({}, {}, false));
|
|
72
|
+
expect(call).toThrow(/no provider configured/i);
|
|
73
|
+
expect(call).toThrow(/ANTHROPIC_API_KEY/);
|
|
74
|
+
expect(call).toThrow(/DEEPSEEK_API_KEY/);
|
|
75
|
+
});
|
|
76
|
+
it('rejects an invalid --provider flag value', () => {
|
|
77
|
+
expect(() => resolveProvider(opts({}, { provider: 'openai' }, true)))
|
|
78
|
+
.toThrow(/unknown provider "openai"/i);
|
|
79
|
+
});
|
|
80
|
+
it('rejects an invalid KNOWLEDGE_FRESHNESS_PROVIDER env value', () => {
|
|
81
|
+
expect(() => resolveProvider(opts({ KNOWLEDGE_FRESHNESS_PROVIDER: 'gemini' }, {}, true)))
|
|
82
|
+
.toThrow(/unknown provider "gemini"/i);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('buildDispatcher — deepseek wiring', () => {
|
|
86
|
+
it('throws when deepseek is selected but DEEPSEEK_API_KEY is not in env', () => {
|
|
87
|
+
expect(() => buildDispatcher('deepseek', { timeoutSec: 60, env: {} }))
|
|
88
|
+
.toThrow(/DEEPSEEK_API_KEY env var is not set/);
|
|
89
|
+
});
|
|
90
|
+
it('constructs a Dispatcher when DEEPSEEK_API_KEY is set', () => {
|
|
91
|
+
// We don't call the dispatcher (no fetch mock here) — just verify
|
|
92
|
+
// construction succeeds.
|
|
93
|
+
const d = buildDispatcher('deepseek', { timeoutSec: 60, env: { DEEPSEEK_API_KEY: 'sk-x' } });
|
|
94
|
+
expect(typeof d).toBe('function');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/knowledge-freshness/providers/index.test.ts"],"names":[],"mappings":"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"}
|