@ashlr/hub 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1158 -0
- package/LICENSE +21 -0
- package/README.md +833 -0
- package/bin/ashlr +8 -0
- package/dist/api/core.d.ts +28 -0
- package/dist/api/core.js +42 -0
- package/dist/api/core.js.map +1 -0
- package/dist/api/index.d.ts +9 -0
- package/dist/api/index.js +9 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/plugin.d.ts +12 -0
- package/dist/api/plugin.js +13 -0
- package/dist/api/plugin.js.map +1 -0
- package/dist/api/types.d.ts +9 -0
- package/dist/api/types.js +9 -0
- package/dist/api/types.js.map +1 -0
- package/dist/cli/args.d.ts +20 -0
- package/dist/cli/args.js +23 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/ask.d.ts +22 -0
- package/dist/cli/ask.js +240 -0
- package/dist/cli/ask.js.map +1 -0
- package/dist/cli/audit.d.ts +26 -0
- package/dist/cli/audit.js +199 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/backlog.d.ts +26 -0
- package/dist/cli/backlog.js +322 -0
- package/dist/cli/backlog.js.map +1 -0
- package/dist/cli/completions.d.ts +18 -0
- package/dist/cli/completions.js +156 -0
- package/dist/cli/completions.js.map +1 -0
- package/dist/cli/daemon.d.ts +31 -0
- package/dist/cli/daemon.js +334 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/demo-sandbox.d.ts +78 -0
- package/dist/cli/demo-sandbox.js +227 -0
- package/dist/cli/demo-sandbox.js.map +1 -0
- package/dist/cli/demo.d.ts +76 -0
- package/dist/cli/demo.js +285 -0
- package/dist/cli/demo.js.map +1 -0
- package/dist/cli/digest.d.ts +46 -0
- package/dist/cli/digest.js +352 -0
- package/dist/cli/digest.js.map +1 -0
- package/dist/cli/doctor-init.d.ts +28 -0
- package/dist/cli/doctor-init.js +335 -0
- package/dist/cli/doctor-init.js.map +1 -0
- package/dist/cli/genome.d.ts +62 -0
- package/dist/cli/genome.js +1061 -0
- package/dist/cli/genome.js.map +1 -0
- package/dist/cli/gh.d.ts +27 -0
- package/dist/cli/gh.js +322 -0
- package/dist/cli/gh.js.map +1 -0
- package/dist/cli/goals.d.ts +55 -0
- package/dist/cli/goals.js +667 -0
- package/dist/cli/goals.js.map +1 -0
- package/dist/cli/health.d.ts +56 -0
- package/dist/cli/health.js +407 -0
- package/dist/cli/health.js.map +1 -0
- package/dist/cli/help.d.ts +51 -0
- package/dist/cli/help.js +436 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/inbox.d.ts +28 -0
- package/dist/cli/inbox.js +589 -0
- package/dist/cli/inbox.js.map +1 -0
- package/dist/cli/index.d.ts +41 -0
- package/dist/cli/index.js +1208 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/knowledge.d.ts +33 -0
- package/dist/cli/knowledge.js +575 -0
- package/dist/cli/knowledge.js.map +1 -0
- package/dist/cli/mcp.d.ts +26 -0
- package/dist/cli/mcp.js +487 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/models.d.ts +26 -0
- package/dist/cli/models.js +435 -0
- package/dist/cli/models.js.map +1 -0
- package/dist/cli/new.d.ts +32 -0
- package/dist/cli/new.js +565 -0
- package/dist/cli/new.js.map +1 -0
- package/dist/cli/notify.d.ts +20 -0
- package/dist/cli/notify.js +188 -0
- package/dist/cli/notify.js.map +1 -0
- package/dist/cli/onboard.d.ts +85 -0
- package/dist/cli/onboard.js +305 -0
- package/dist/cli/onboard.js.map +1 -0
- package/dist/cli/open.d.ts +38 -0
- package/dist/cli/open.js +86 -0
- package/dist/cli/open.js.map +1 -0
- package/dist/cli/orient.d.ts +14 -0
- package/dist/cli/orient.js +110 -0
- package/dist/cli/orient.js.map +1 -0
- package/dist/cli/picker.d.ts +21 -0
- package/dist/cli/picker.js +177 -0
- package/dist/cli/picker.js.map +1 -0
- package/dist/cli/plugins.d.ts +21 -0
- package/dist/cli/plugins.js +394 -0
- package/dist/cli/plugins.js.map +1 -0
- package/dist/cli/preflight.d.ts +29 -0
- package/dist/cli/preflight.js +131 -0
- package/dist/cli/preflight.js.map +1 -0
- package/dist/cli/pulse.d.ts +26 -0
- package/dist/cli/pulse.js +482 -0
- package/dist/cli/pulse.js.map +1 -0
- package/dist/cli/reflect.d.ts +42 -0
- package/dist/cli/reflect.js +381 -0
- package/dist/cli/reflect.js.map +1 -0
- package/dist/cli/run.d.ts +29 -0
- package/dist/cli/run.js +687 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/sandbox.d.ts +20 -0
- package/dist/cli/sandbox.js +345 -0
- package/dist/cli/sandbox.js.map +1 -0
- package/dist/cli/seams.d.ts +41 -0
- package/dist/cli/seams.js +167 -0
- package/dist/cli/seams.js.map +1 -0
- package/dist/cli/serve.d.ts +25 -0
- package/dist/cli/serve.js +249 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/ship.d.ts +33 -0
- package/dist/cli/ship.js +433 -0
- package/dist/cli/ship.js.map +1 -0
- package/dist/cli/spec.d.ts +19 -0
- package/dist/cli/spec.js +478 -0
- package/dist/cli/spec.js.map +1 -0
- package/dist/cli/swarm.d.ts +42 -0
- package/dist/cli/swarm.js +1365 -0
- package/dist/cli/swarm.js.map +1 -0
- package/dist/cli/telemetry.d.ts +26 -0
- package/dist/cli/telemetry.js +364 -0
- package/dist/cli/telemetry.js.map +1 -0
- package/dist/cli/tui.d.ts +17 -0
- package/dist/cli/tui.js +52 -0
- package/dist/cli/tui.js.map +1 -0
- package/dist/cli/ui.d.ts +53 -0
- package/dist/cli/ui.js +66 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/cli/update.d.ts +38 -0
- package/dist/cli/update.js +682 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/vercel.d.ts +20 -0
- package/dist/cli/vercel.js +193 -0
- package/dist/cli/vercel.js.map +1 -0
- package/dist/cli/verify-safety.d.ts +96 -0
- package/dist/cli/verify-safety.js +509 -0
- package/dist/cli/verify-safety.js.map +1 -0
- package/dist/cli/wire.d.ts +22 -0
- package/dist/cli/wire.js +205 -0
- package/dist/cli/wire.js.map +1 -0
- package/dist/core/classify.d.ts +51 -0
- package/dist/core/classify.js +450 -0
- package/dist/core/classify.js.map +1 -0
- package/dist/core/config.d.ts +63 -0
- package/dist/core/config.js +474 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/daemon/loop.d.ts +74 -0
- package/dist/core/daemon/loop.js +618 -0
- package/dist/core/daemon/loop.js.map +1 -0
- package/dist/core/daemon/state.d.ts +66 -0
- package/dist/core/daemon/state.js +197 -0
- package/dist/core/daemon/state.js.map +1 -0
- package/dist/core/dashboard.d.ts +40 -0
- package/dist/core/dashboard.js +463 -0
- package/dist/core/dashboard.js.map +1 -0
- package/dist/core/digest/build.d.ts +51 -0
- package/dist/core/digest/build.js +230 -0
- package/dist/core/digest/build.js.map +1 -0
- package/dist/core/digest/deliver.d.ts +47 -0
- package/dist/core/digest/deliver.js +230 -0
- package/dist/core/digest/deliver.js.map +1 -0
- package/dist/core/digest/store.d.ts +57 -0
- package/dist/core/digest/store.js +223 -0
- package/dist/core/digest/store.js.map +1 -0
- package/dist/core/doctor-fix.d.ts +21 -0
- package/dist/core/doctor-fix.js +440 -0
- package/dist/core/doctor-fix.js.map +1 -0
- package/dist/core/doctor.d.ts +18 -0
- package/dist/core/doctor.js +806 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/env-bridge.d.ts +64 -0
- package/dist/core/env-bridge.js +103 -0
- package/dist/core/env-bridge.js.map +1 -0
- package/dist/core/genome/capture.d.ts +49 -0
- package/dist/core/genome/capture.js +352 -0
- package/dist/core/genome/capture.js.map +1 -0
- package/dist/core/genome/consolidate.d.ts +38 -0
- package/dist/core/genome/consolidate.js +426 -0
- package/dist/core/genome/consolidate.js.map +1 -0
- package/dist/core/genome/export.d.ts +29 -0
- package/dist/core/genome/export.js +102 -0
- package/dist/core/genome/export.js.map +1 -0
- package/dist/core/genome/playbook.d.ts +33 -0
- package/dist/core/genome/playbook.js +320 -0
- package/dist/core/genome/playbook.js.map +1 -0
- package/dist/core/genome/recall.d.ts +45 -0
- package/dist/core/genome/recall.js +293 -0
- package/dist/core/genome/recall.js.map +1 -0
- package/dist/core/genome/store.d.ts +62 -0
- package/dist/core/genome/store.js +711 -0
- package/dist/core/genome/store.js.map +1 -0
- package/dist/core/git.d.ts +34 -0
- package/dist/core/git.js +115 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/goals/advance.d.ts +82 -0
- package/dist/core/goals/advance.js +263 -0
- package/dist/core/goals/advance.js.map +1 -0
- package/dist/core/goals/planner.d.ts +58 -0
- package/dist/core/goals/planner.js +233 -0
- package/dist/core/goals/planner.js.map +1 -0
- package/dist/core/goals/store.d.ts +128 -0
- package/dist/core/goals/store.js +442 -0
- package/dist/core/goals/store.js.map +1 -0
- package/dist/core/inbox/apply.d.ts +36 -0
- package/dist/core/inbox/apply.js +407 -0
- package/dist/core/inbox/apply.js.map +1 -0
- package/dist/core/inbox/notify-proposal.d.ts +13 -0
- package/dist/core/inbox/notify-proposal.js +21 -0
- package/dist/core/inbox/notify-proposal.js.map +1 -0
- package/dist/core/inbox/store.d.ts +67 -0
- package/dist/core/inbox/store.js +258 -0
- package/dist/core/inbox/store.js.map +1 -0
- package/dist/core/index-engine.d.ts +62 -0
- package/dist/core/index-engine.js +486 -0
- package/dist/core/index-engine.js.map +1 -0
- package/dist/core/integrations/desktop-notify.d.ts +18 -0
- package/dist/core/integrations/desktop-notify.js +42 -0
- package/dist/core/integrations/desktop-notify.js.map +1 -0
- package/dist/core/integrations/editors.d.ts +50 -0
- package/dist/core/integrations/editors.js +216 -0
- package/dist/core/integrations/editors.js.map +1 -0
- package/dist/core/integrations/github.d.ts +66 -0
- package/dist/core/integrations/github.js +332 -0
- package/dist/core/integrations/github.js.map +1 -0
- package/dist/core/integrations/identity.d.ts +29 -0
- package/dist/core/integrations/identity.js +359 -0
- package/dist/core/integrations/identity.js.map +1 -0
- package/dist/core/integrations/notify.d.ts +23 -0
- package/dist/core/integrations/notify.js +96 -0
- package/dist/core/integrations/notify.js.map +1 -0
- package/dist/core/integrations/vercel.d.ts +37 -0
- package/dist/core/integrations/vercel.js +192 -0
- package/dist/core/integrations/vercel.js.map +1 -0
- package/dist/core/knowledge/ask.d.ts +34 -0
- package/dist/core/knowledge/ask.js +325 -0
- package/dist/core/knowledge/ask.js.map +1 -0
- package/dist/core/knowledge/graph.d.ts +51 -0
- package/dist/core/knowledge/graph.js +564 -0
- package/dist/core/knowledge/graph.js.map +1 -0
- package/dist/core/knowledge/index.d.ts +74 -0
- package/dist/core/knowledge/index.js +586 -0
- package/dist/core/knowledge/index.js.map +1 -0
- package/dist/core/learn/playbooks.d.ts +84 -0
- package/dist/core/learn/playbooks.js +241 -0
- package/dist/core/learn/playbooks.js.map +1 -0
- package/dist/core/learn/reflect.d.ts +87 -0
- package/dist/core/learn/reflect.js +435 -0
- package/dist/core/learn/reflect.js.map +1 -0
- package/dist/core/learn/store.d.ts +51 -0
- package/dist/core/learn/store.js +165 -0
- package/dist/core/learn/store.js.map +1 -0
- package/dist/core/learn/tuning.d.ts +48 -0
- package/dist/core/learn/tuning.js +201 -0
- package/dist/core/learn/tuning.js.map +1 -0
- package/dist/core/lifecycle/scaffold.d.ts +43 -0
- package/dist/core/lifecycle/scaffold.js +260 -0
- package/dist/core/lifecycle/scaffold.js.map +1 -0
- package/dist/core/lifecycle/ship.d.ts +48 -0
- package/dist/core/lifecycle/ship.js +513 -0
- package/dist/core/lifecycle/ship.js.map +1 -0
- package/dist/core/lifecycle/templates.d.ts +20 -0
- package/dist/core/lifecycle/templates.js +605 -0
- package/dist/core/lifecycle/templates.js.map +1 -0
- package/dist/core/mcp-gateway.d.ts +59 -0
- package/dist/core/mcp-gateway.js +385 -0
- package/dist/core/mcp-gateway.js.map +1 -0
- package/dist/core/mcp-native.d.ts +53 -0
- package/dist/core/mcp-native.js +507 -0
- package/dist/core/mcp-native.js.map +1 -0
- package/dist/core/mcp-registry.d.ts +36 -0
- package/dist/core/mcp-registry.js +180 -0
- package/dist/core/mcp-registry.js.map +1 -0
- package/dist/core/observability/budget-alert.d.ts +18 -0
- package/dist/core/observability/budget-alert.js +90 -0
- package/dist/core/observability/budget-alert.js.map +1 -0
- package/dist/core/observability/estimate.d.ts +27 -0
- package/dist/core/observability/estimate.js +188 -0
- package/dist/core/observability/estimate.js.map +1 -0
- package/dist/core/observability/forecast.d.ts +19 -0
- package/dist/core/observability/forecast.js +101 -0
- package/dist/core/observability/forecast.js.map +1 -0
- package/dist/core/observability/governance.d.ts +28 -0
- package/dist/core/observability/governance.js +101 -0
- package/dist/core/observability/governance.js.map +1 -0
- package/dist/core/observability/otlp.d.ts +88 -0
- package/dist/core/observability/otlp.js +217 -0
- package/dist/core/observability/otlp.js.map +1 -0
- package/dist/core/observability/rollup.d.ts +35 -0
- package/dist/core/observability/rollup.js +311 -0
- package/dist/core/observability/rollup.js.map +1 -0
- package/dist/core/observability/telemetry-sink.d.ts +63 -0
- package/dist/core/observability/telemetry-sink.js +350 -0
- package/dist/core/observability/telemetry-sink.js.map +1 -0
- package/dist/core/observability/usage-source.d.ts +60 -0
- package/dist/core/observability/usage-source.js +347 -0
- package/dist/core/observability/usage-source.js.map +1 -0
- package/dist/core/onboard.d.ts +27 -0
- package/dist/core/onboard.js +288 -0
- package/dist/core/onboard.js.map +1 -0
- package/dist/core/orient.d.ts +23 -0
- package/dist/core/orient.js +135 -0
- package/dist/core/orient.js.map +1 -0
- package/dist/core/phantom.d.ts +23 -0
- package/dist/core/phantom.js +279 -0
- package/dist/core/phantom.js.map +1 -0
- package/dist/core/plugins/host-api.d.ts +29 -0
- package/dist/core/plugins/host-api.js +113 -0
- package/dist/core/plugins/host-api.js.map +1 -0
- package/dist/core/plugins/integrity.d.ts +36 -0
- package/dist/core/plugins/integrity.js +73 -0
- package/dist/core/plugins/integrity.js.map +1 -0
- package/dist/core/plugins/manifest.d.ts +31 -0
- package/dist/core/plugins/manifest.js +316 -0
- package/dist/core/plugins/manifest.js.map +1 -0
- package/dist/core/plugins/registry.d.ts +87 -0
- package/dist/core/plugins/registry.js +415 -0
- package/dist/core/plugins/registry.js.map +1 -0
- package/dist/core/plugins/types.d.ts +182 -0
- package/dist/core/plugins/types.js +40 -0
- package/dist/core/plugins/types.js.map +1 -0
- package/dist/core/plugins/wrappers.d.ts +40 -0
- package/dist/core/plugins/wrappers.js +229 -0
- package/dist/core/plugins/wrappers.js.map +1 -0
- package/dist/core/portfolio/backlog.d.ts +40 -0
- package/dist/core/portfolio/backlog.js +177 -0
- package/dist/core/portfolio/backlog.js.map +1 -0
- package/dist/core/portfolio/scanners.d.ts +21 -0
- package/dist/core/portfolio/scanners.js +600 -0
- package/dist/core/portfolio/scanners.js.map +1 -0
- package/dist/core/providers.d.ts +34 -0
- package/dist/core/providers.js +250 -0
- package/dist/core/providers.js.map +1 -0
- package/dist/core/quality/conventions.d.ts +35 -0
- package/dist/core/quality/conventions.js +267 -0
- package/dist/core/quality/conventions.js.map +1 -0
- package/dist/core/quality/fixes.d.ts +56 -0
- package/dist/core/quality/fixes.js +209 -0
- package/dist/core/quality/fixes.js.map +1 -0
- package/dist/core/quality/health.d.ts +69 -0
- package/dist/core/quality/health.js +350 -0
- package/dist/core/quality/health.js.map +1 -0
- package/dist/core/quality/store.d.ts +56 -0
- package/dist/core/quality/store.js +195 -0
- package/dist/core/quality/store.js.map +1 -0
- package/dist/core/readiness.d.ts +112 -0
- package/dist/core/readiness.js +431 -0
- package/dist/core/readiness.js.map +1 -0
- package/dist/core/run/agent-loop.d.ts +40 -0
- package/dist/core/run/agent-loop.js +291 -0
- package/dist/core/run/agent-loop.js.map +1 -0
- package/dist/core/run/budget.d.ts +47 -0
- package/dist/core/run/budget.js +113 -0
- package/dist/core/run/budget.js.map +1 -0
- package/dist/core/run/engines.d.ts +75 -0
- package/dist/core/run/engines.js +199 -0
- package/dist/core/run/engines.js.map +1 -0
- package/dist/core/run/model-manager.d.ts +64 -0
- package/dist/core/run/model-manager.js +339 -0
- package/dist/core/run/model-manager.js.map +1 -0
- package/dist/core/run/orchestrator.d.ts +100 -0
- package/dist/core/run/orchestrator.js +1515 -0
- package/dist/core/run/orchestrator.js.map +1 -0
- package/dist/core/run/provider-client.d.ts +46 -0
- package/dist/core/run/provider-client.js +796 -0
- package/dist/core/run/provider-client.js.map +1 -0
- package/dist/core/run/retry.d.ts +19 -0
- package/dist/core/run/retry.js +68 -0
- package/dist/core/run/retry.js.map +1 -0
- package/dist/core/run/router.d.ts +50 -0
- package/dist/core/run/router.js +257 -0
- package/dist/core/run/router.js.map +1 -0
- package/dist/core/run/self-heal.d.ts +52 -0
- package/dist/core/run/self-heal.js +181 -0
- package/dist/core/run/self-heal.js.map +1 -0
- package/dist/core/run/streaming.d.ts +31 -0
- package/dist/core/run/streaming.js +122 -0
- package/dist/core/run/streaming.js.map +1 -0
- package/dist/core/run/verify.d.ts +30 -0
- package/dist/core/run/verify.js +204 -0
- package/dist/core/run/verify.js.map +1 -0
- package/dist/core/sandbox/audit.d.ts +31 -0
- package/dist/core/sandbox/audit.js +169 -0
- package/dist/core/sandbox/audit.js.map +1 -0
- package/dist/core/sandbox/policy.d.ts +61 -0
- package/dist/core/sandbox/policy.js +211 -0
- package/dist/core/sandbox/policy.js.map +1 -0
- package/dist/core/sandbox/worktree.d.ts +175 -0
- package/dist/core/sandbox/worktree.js +673 -0
- package/dist/core/sandbox/worktree.js.map +1 -0
- package/dist/core/seams/backlog.d.ts +47 -0
- package/dist/core/seams/backlog.js +47 -0
- package/dist/core/seams/backlog.js.map +1 -0
- package/dist/core/seams/daemon-coordinator.d.ts +72 -0
- package/dist/core/seams/daemon-coordinator.js +76 -0
- package/dist/core/seams/daemon-coordinator.js.map +1 -0
- package/dist/core/seams/genome.d.ts +45 -0
- package/dist/core/seams/genome.js +53 -0
- package/dist/core/seams/genome.js.map +1 -0
- package/dist/core/seams/identity.d.ts +40 -0
- package/dist/core/seams/identity.js +44 -0
- package/dist/core/seams/identity.js.map +1 -0
- package/dist/core/seams/inbox.d.ts +60 -0
- package/dist/core/seams/inbox.js +66 -0
- package/dist/core/seams/inbox.js.map +1 -0
- package/dist/core/seams/index.d.ts +20 -0
- package/dist/core/seams/index.js +21 -0
- package/dist/core/seams/index.js.map +1 -0
- package/dist/core/seams/portfolio.d.ts +50 -0
- package/dist/core/seams/portfolio.js +61 -0
- package/dist/core/seams/portfolio.js.map +1 -0
- package/dist/core/seams/registry.d.ts +42 -0
- package/dist/core/seams/registry.js +128 -0
- package/dist/core/seams/registry.js.map +1 -0
- package/dist/core/seams/run-swarm.d.ts +66 -0
- package/dist/core/seams/run-swarm.js +74 -0
- package/dist/core/seams/run-swarm.js.map +1 -0
- package/dist/core/seams/types.d.ts +123 -0
- package/dist/core/seams/types.js +35 -0
- package/dist/core/seams/types.js.map +1 -0
- package/dist/core/spec/spec-store.d.ts +62 -0
- package/dist/core/spec/spec-store.js +359 -0
- package/dist/core/spec/spec-store.js.map +1 -0
- package/dist/core/swarm/gate.d.ts +45 -0
- package/dist/core/swarm/gate.js +114 -0
- package/dist/core/swarm/gate.js.map +1 -0
- package/dist/core/swarm/planner.d.ts +32 -0
- package/dist/core/swarm/planner.js +293 -0
- package/dist/core/swarm/planner.js.map +1 -0
- package/dist/core/swarm/rollback.d.ts +56 -0
- package/dist/core/swarm/rollback.js +266 -0
- package/dist/core/swarm/rollback.js.map +1 -0
- package/dist/core/swarm/runner.d.ts +62 -0
- package/dist/core/swarm/runner.js +1263 -0
- package/dist/core/swarm/runner.js.map +1 -0
- package/dist/core/swarm/sign.d.ts +71 -0
- package/dist/core/swarm/sign.js +362 -0
- package/dist/core/swarm/sign.js.map +1 -0
- package/dist/core/swarm/store.d.ts +52 -0
- package/dist/core/swarm/store.js +195 -0
- package/dist/core/swarm/store.js.map +1 -0
- package/dist/core/tidy.d.ts +32 -0
- package/dist/core/tidy.js +354 -0
- package/dist/core/tidy.js.map +1 -0
- package/dist/core/tools-registry.d.ts +16 -0
- package/dist/core/tools-registry.js +308 -0
- package/dist/core/tools-registry.js.map +1 -0
- package/dist/core/types.d.ts +2545 -0
- package/dist/core/types.js +9 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/web/api.d.ts +53 -0
- package/dist/core/web/api.js +698 -0
- package/dist/core/web/api.js.map +1 -0
- package/dist/core/web/public/app.js +1906 -0
- package/dist/core/web/public/index.html +721 -0
- package/dist/core/web/public/styles.css +2007 -0
- package/dist/core/web/server.d.ts +18 -0
- package/dist/core/web/server.js +122 -0
- package/dist/core/web/server.js.map +1 -0
- package/dist/core/web/static.d.ts +18 -0
- package/dist/core/web/static.js +122 -0
- package/dist/core/web/static.js.map +1 -0
- package/dist/tui/app.d.ts +33 -0
- package/dist/tui/app.js +350 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/render.d.ts +20 -0
- package/dist/tui/render.js +558 -0
- package/dist/tui/render.js.map +1 -0
- package/package.json +80 -0
- package/schema/config.schema.json +223 -0
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* portfolio/scanners.ts — Work-discovery scanners for `ashlr backlog`.
|
|
3
|
+
*
|
|
4
|
+
* GUARDRAILS (enforced throughout this file):
|
|
5
|
+
* - READ-ONLY: no file writes, no git mutations, no installs, no fixes,
|
|
6
|
+
* no `npm test`/`npm run build`.
|
|
7
|
+
* - No shell: all child-process invocations use execFile with arg arrays
|
|
8
|
+
* (no shell:true, no string interpolation of repo paths into a shell string).
|
|
9
|
+
* - Bounded: skip node_modules/.git/dist/build; cap output/files/time.
|
|
10
|
+
* - Never throws: every scanner returns [] on any error/timeout/missing-tool.
|
|
11
|
+
* - Enrollment-scoped: callers (buildBacklog) only pass listEnrolled() paths.
|
|
12
|
+
* - No secrets in any emitted WorkItem.
|
|
13
|
+
*/
|
|
14
|
+
import { execFile } from 'node:child_process';
|
|
15
|
+
import { promisify } from 'node:util';
|
|
16
|
+
import { existsSync, statSync, readFileSync } from 'node:fs';
|
|
17
|
+
import { join, basename } from 'node:path';
|
|
18
|
+
import { createHash } from 'node:crypto';
|
|
19
|
+
import { listIssues, githubStatus } from '../integrations/github.js';
|
|
20
|
+
const execFileAsync = promisify(execFile);
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Constants
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
const SCAN_TIMEOUT_MS = 15_000;
|
|
25
|
+
const NPM_TIMEOUT_MS = 20_000;
|
|
26
|
+
const MAX_TODO_HITS = 200;
|
|
27
|
+
const MAX_OUTDATED_ITEMS = 50;
|
|
28
|
+
const MAX_VULN_ITEMS = 20;
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Helpers
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
/**
|
|
33
|
+
* Deterministic stable id for a WorkItem.
|
|
34
|
+
* Format: `<repoBasename>:<source>:<hash(discriminator)>`
|
|
35
|
+
*/
|
|
36
|
+
function makeId(repo, source, discriminator) {
|
|
37
|
+
const hash = createHash('sha1')
|
|
38
|
+
.update(repo + ':' + discriminator)
|
|
39
|
+
.digest('hex')
|
|
40
|
+
.slice(0, 10);
|
|
41
|
+
return `${basename(repo)}:${source}:${hash}`;
|
|
42
|
+
}
|
|
43
|
+
function nowIso() {
|
|
44
|
+
return new Date().toISOString();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Clamp a number to the 1..5 range.
|
|
48
|
+
*/
|
|
49
|
+
function clamp(n) {
|
|
50
|
+
return Math.max(1, Math.min(5, Math.round(n)));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Import scoreItem lazily to avoid a circular dep if backlog.ts imports us.
|
|
54
|
+
* We inline the same pure formula here so scanners.ts is self-contained.
|
|
55
|
+
* Must match backlog.ts#scoreItem exactly: value / max(1, effort), clamped.
|
|
56
|
+
*/
|
|
57
|
+
function score(value, effort) {
|
|
58
|
+
const v = clamp(value);
|
|
59
|
+
const e = Math.max(1, clamp(effort));
|
|
60
|
+
return Math.round((v / e) * 100) / 100;
|
|
61
|
+
}
|
|
62
|
+
function makeItem(repo, source, discriminator, title, detail, value, effort, tags) {
|
|
63
|
+
const v = clamp(value);
|
|
64
|
+
const e = clamp(effort);
|
|
65
|
+
return {
|
|
66
|
+
id: makeId(repo, source, discriminator),
|
|
67
|
+
repo,
|
|
68
|
+
source,
|
|
69
|
+
title,
|
|
70
|
+
detail,
|
|
71
|
+
value: v,
|
|
72
|
+
effort: e,
|
|
73
|
+
score: score(v, e),
|
|
74
|
+
tags,
|
|
75
|
+
ts: nowIso(),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// scanIssues — open GitHub issues via M18 listIssues
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
export async function scanIssues(repo) {
|
|
82
|
+
try {
|
|
83
|
+
const issues = listIssues(repo);
|
|
84
|
+
if (!Array.isArray(issues) || issues.length === 0)
|
|
85
|
+
return [];
|
|
86
|
+
const items = [];
|
|
87
|
+
for (const issue of issues) {
|
|
88
|
+
// Value heuristic: all open issues are worth attention.
|
|
89
|
+
// We don't have label/age data from the current listIssues shape
|
|
90
|
+
// (it returns number, title, url, state, author), so use a flat value=3.
|
|
91
|
+
const value = 3;
|
|
92
|
+
const effort = 3;
|
|
93
|
+
items.push(makeItem(repo, 'issue', `issue:${issue.number}`, `Issue #${issue.number}: ${issue.title}`, issue.url, value, effort, ['issue', `#${issue.number}`]));
|
|
94
|
+
}
|
|
95
|
+
return items;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// scanTodos — TODO/FIXME/HACK/XXX comments via rg/grep
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
/**
|
|
105
|
+
* Run rg if available, else grep. Returns raw stdout or null.
|
|
106
|
+
* Uses execFile (no shell). Excludes node_modules/.git/dist/build.
|
|
107
|
+
* Caps at MAX_TODO_HITS lines.
|
|
108
|
+
*/
|
|
109
|
+
async function rgOrGrep(repo) {
|
|
110
|
+
// Try ripgrep first (faster, respects .gitignore)
|
|
111
|
+
try {
|
|
112
|
+
const { stdout } = await execFileAsync('rg', [
|
|
113
|
+
'--line-number',
|
|
114
|
+
'--no-heading',
|
|
115
|
+
'--glob', '!node_modules',
|
|
116
|
+
'--glob', '!.git',
|
|
117
|
+
'--glob', '!dist',
|
|
118
|
+
'--glob', '!build',
|
|
119
|
+
'--max-count', String(MAX_TODO_HITS),
|
|
120
|
+
'-e', 'TODO|FIXME|HACK|XXX',
|
|
121
|
+
'.',
|
|
122
|
+
], {
|
|
123
|
+
cwd: repo,
|
|
124
|
+
timeout: SCAN_TIMEOUT_MS,
|
|
125
|
+
maxBuffer: 1024 * 1024, // 1 MB cap
|
|
126
|
+
});
|
|
127
|
+
return stdout ?? null;
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
// rg exits 1 when no matches — that's not a tool-missing error
|
|
131
|
+
const e = err;
|
|
132
|
+
if (e?.stdout && typeof e.stdout === 'string') {
|
|
133
|
+
// rg found matches but hit max-count or returned non-zero for other reason
|
|
134
|
+
return e.stdout;
|
|
135
|
+
}
|
|
136
|
+
if (e?.code === '1') {
|
|
137
|
+
// exit code 1 = no matches found
|
|
138
|
+
return '';
|
|
139
|
+
}
|
|
140
|
+
// rg not available (ENOENT) — fall through to grep
|
|
141
|
+
}
|
|
142
|
+
// Fallback: GNU/BSD grep
|
|
143
|
+
try {
|
|
144
|
+
const { stdout } = await execFileAsync('grep', [
|
|
145
|
+
'-rn',
|
|
146
|
+
'--include=*.ts',
|
|
147
|
+
'--include=*.tsx',
|
|
148
|
+
'--include=*.js',
|
|
149
|
+
'--include=*.jsx',
|
|
150
|
+
'--include=*.mjs',
|
|
151
|
+
'--include=*.cjs',
|
|
152
|
+
'--include=*.py',
|
|
153
|
+
'--include=*.go',
|
|
154
|
+
'--include=*.rb',
|
|
155
|
+
'--include=*.java',
|
|
156
|
+
'--include=*.cs',
|
|
157
|
+
'--include=*.swift',
|
|
158
|
+
'--include=*.rs',
|
|
159
|
+
'--exclude-dir=node_modules',
|
|
160
|
+
'--exclude-dir=.git',
|
|
161
|
+
'--exclude-dir=dist',
|
|
162
|
+
'--exclude-dir=build',
|
|
163
|
+
'-m', String(MAX_TODO_HITS),
|
|
164
|
+
'-E', 'TODO|FIXME|HACK|XXX',
|
|
165
|
+
'.',
|
|
166
|
+
], {
|
|
167
|
+
cwd: repo,
|
|
168
|
+
timeout: SCAN_TIMEOUT_MS,
|
|
169
|
+
maxBuffer: 1024 * 1024,
|
|
170
|
+
});
|
|
171
|
+
return stdout ?? null;
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
const e = err;
|
|
175
|
+
if (e?.stdout && typeof e.stdout === 'string')
|
|
176
|
+
return e.stdout;
|
|
177
|
+
if (e?.code === '1')
|
|
178
|
+
return ''; // no matches
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
export async function scanTodos(repo) {
|
|
183
|
+
try {
|
|
184
|
+
const raw = await rgOrGrep(repo);
|
|
185
|
+
if (!raw || raw.trim() === '')
|
|
186
|
+
return [];
|
|
187
|
+
const lines = raw.split('\n').filter(Boolean).slice(0, MAX_TODO_HITS);
|
|
188
|
+
// Cluster by file: emit one WorkItem per file (to avoid flooding).
|
|
189
|
+
const byFile = new Map();
|
|
190
|
+
for (const line of lines) {
|
|
191
|
+
// rg/grep -n output: "path/to/file:42:...comment..."
|
|
192
|
+
const colonIdx = line.indexOf(':');
|
|
193
|
+
if (colonIdx < 0)
|
|
194
|
+
continue;
|
|
195
|
+
const rest = line.slice(colonIdx + 1);
|
|
196
|
+
const colonIdx2 = rest.indexOf(':');
|
|
197
|
+
const filePath = line.slice(0, colonIdx);
|
|
198
|
+
const commentText = colonIdx2 >= 0 ? rest.slice(colonIdx2 + 1).trim() : rest.trim();
|
|
199
|
+
// Detect which marker type
|
|
200
|
+
const tags = [];
|
|
201
|
+
if (/TODO/i.test(commentText))
|
|
202
|
+
tags.push('todo');
|
|
203
|
+
if (/FIXME/i.test(commentText))
|
|
204
|
+
tags.push('fixme');
|
|
205
|
+
if (/HACK/i.test(commentText))
|
|
206
|
+
tags.push('hack');
|
|
207
|
+
if (/XXX/i.test(commentText))
|
|
208
|
+
tags.push('xxx');
|
|
209
|
+
const existing = byFile.get(filePath);
|
|
210
|
+
if (existing) {
|
|
211
|
+
existing.count++;
|
|
212
|
+
for (const t of tags) {
|
|
213
|
+
if (!existing.tags.includes(t))
|
|
214
|
+
existing.tags.push(t);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
byFile.set(filePath, { count: 1, sample: commentText.slice(0, 120), tags });
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const items = [];
|
|
222
|
+
for (const [filePath, info] of byFile) {
|
|
223
|
+
const plural = info.count > 1 ? `${info.count} markers` : '1 marker';
|
|
224
|
+
items.push(makeItem(repo, 'todo', `todo:${filePath}`, `${plural} in ${filePath}`, info.sample, 2, 2, ['todo', ...info.tags]));
|
|
225
|
+
}
|
|
226
|
+
return items;
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return [];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
233
|
+
// scanTests — CI state + test-script heuristic (DO NOT run the test suite)
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
export async function scanTests(repo) {
|
|
236
|
+
try {
|
|
237
|
+
const items = [];
|
|
238
|
+
// 1. Check package.json for a test script (heuristic, read-only)
|
|
239
|
+
const pkgPath = join(repo, 'package.json');
|
|
240
|
+
let hasTestScript = false;
|
|
241
|
+
if (existsSync(pkgPath)) {
|
|
242
|
+
try {
|
|
243
|
+
const raw = readFileSync(pkgPath, 'utf8');
|
|
244
|
+
const pkg = JSON.parse(raw);
|
|
245
|
+
const scripts = pkg['scripts'];
|
|
246
|
+
if (scripts !== null &&
|
|
247
|
+
typeof scripts === 'object' &&
|
|
248
|
+
!Array.isArray(scripts)) {
|
|
249
|
+
const s = scripts;
|
|
250
|
+
if (typeof s['test'] === 'string' && s['test'].trim() !== '') {
|
|
251
|
+
hasTestScript = true;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
// malformed package.json — treat as no test script
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (!hasTestScript) {
|
|
260
|
+
// Only emit "no tests" if there's a package.json at all (i.e. it's a Node project)
|
|
261
|
+
if (existsSync(pkgPath)) {
|
|
262
|
+
items.push(makeItem(repo, 'test', 'test:no-test-script', 'No test script found in package.json', 'package.json has no "test" script — consider adding a test suite.', 3, 3, ['test', 'no-tests']));
|
|
263
|
+
}
|
|
264
|
+
// No point checking CI if there's no test script (might still have CI though)
|
|
265
|
+
}
|
|
266
|
+
// 2. Check CI state via M18 githubStatus (reads gh run list, never runs tests)
|
|
267
|
+
const status = githubStatus(repo);
|
|
268
|
+
if (status.isRepo && status.ci === 'failing') {
|
|
269
|
+
items.push(makeItem(repo, 'test', 'test:ci-failing', 'CI is failing', `GitHub Actions: latest run status is failing for ${status.repo ?? repo}`, 4, 2, ['test', 'ci', 'failing']));
|
|
270
|
+
}
|
|
271
|
+
else if (status.isRepo && status.ci === 'pending') {
|
|
272
|
+
items.push(makeItem(repo, 'test', 'test:ci-pending', 'CI is pending', `GitHub Actions: latest run is still in progress for ${status.repo ?? repo}`, 2, 1, ['test', 'ci', 'pending']));
|
|
273
|
+
}
|
|
274
|
+
return items;
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
// scanDeps — npm outdated + npm audit (metadata only, no installs)
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
/**
|
|
284
|
+
* Run `npm outdated --json` in repo. Returns parsed JSON or null.
|
|
285
|
+
* Bounded: timeout, never installs, --no-fund suppresses network noise.
|
|
286
|
+
*/
|
|
287
|
+
async function npmOutdated(repo) {
|
|
288
|
+
try {
|
|
289
|
+
// npm outdated exits 1 when there are outdated packages — capture stdout anyway
|
|
290
|
+
const { stdout } = await execFileAsync('npm', ['outdated', '--json', '--no-fund', '--ignore-scripts'], {
|
|
291
|
+
cwd: repo,
|
|
292
|
+
timeout: NPM_TIMEOUT_MS,
|
|
293
|
+
maxBuffer: 512 * 1024,
|
|
294
|
+
}).catch((err) => {
|
|
295
|
+
// npm outdated exits non-zero when packages are outdated but still emits JSON stdout
|
|
296
|
+
const e = err;
|
|
297
|
+
if (e?.stdout)
|
|
298
|
+
return { stdout: e.stdout };
|
|
299
|
+
throw err;
|
|
300
|
+
});
|
|
301
|
+
if (!stdout || stdout.trim() === '')
|
|
302
|
+
return null;
|
|
303
|
+
const parsed = JSON.parse(stdout);
|
|
304
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
|
|
305
|
+
return null;
|
|
306
|
+
return parsed;
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Run `npm audit --json` in repo. Returns parsed JSON or null.
|
|
314
|
+
* Bounded: timeout, never installs.
|
|
315
|
+
*/
|
|
316
|
+
async function npmAudit(repo) {
|
|
317
|
+
try {
|
|
318
|
+
const { stdout } = await execFileAsync('npm', ['audit', '--json', '--no-fund', '--ignore-scripts'], {
|
|
319
|
+
cwd: repo,
|
|
320
|
+
timeout: NPM_TIMEOUT_MS,
|
|
321
|
+
maxBuffer: 512 * 1024,
|
|
322
|
+
}).catch((err) => {
|
|
323
|
+
// npm audit exits non-zero when vulnerabilities are found but still emits JSON
|
|
324
|
+
const e = err;
|
|
325
|
+
if (e?.stdout)
|
|
326
|
+
return { stdout: e.stdout };
|
|
327
|
+
throw err;
|
|
328
|
+
});
|
|
329
|
+
if (!stdout || stdout.trim() === '')
|
|
330
|
+
return null;
|
|
331
|
+
const parsed = JSON.parse(stdout);
|
|
332
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
|
|
333
|
+
return null;
|
|
334
|
+
return parsed;
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
export async function scanDeps(repo) {
|
|
341
|
+
try {
|
|
342
|
+
const pkgPath = join(repo, 'package.json');
|
|
343
|
+
if (!existsSync(pkgPath))
|
|
344
|
+
return [];
|
|
345
|
+
const items = [];
|
|
346
|
+
let count = 0;
|
|
347
|
+
// 1. Outdated deps
|
|
348
|
+
const outdated = await npmOutdated(repo);
|
|
349
|
+
if (outdated) {
|
|
350
|
+
for (const [pkg, info] of Object.entries(outdated)) {
|
|
351
|
+
if (count >= MAX_OUTDATED_ITEMS)
|
|
352
|
+
break;
|
|
353
|
+
if (typeof info !== 'object' || info === null)
|
|
354
|
+
continue;
|
|
355
|
+
const dep = info;
|
|
356
|
+
const current = typeof dep['current'] === 'string' ? dep['current'] : '?';
|
|
357
|
+
const wanted = typeof dep['wanted'] === 'string' ? dep['wanted'] : '?';
|
|
358
|
+
const latest = typeof dep['latest'] === 'string' ? dep['latest'] : '?';
|
|
359
|
+
const type = typeof dep['type'] === 'string' ? dep['type'] : 'dependency';
|
|
360
|
+
// Assess major version jump
|
|
361
|
+
const currentMajorStr = current.split('.')[0];
|
|
362
|
+
const latestMajorStr = latest.split('.')[0];
|
|
363
|
+
const currentMajor = currentMajorStr !== undefined ? parseInt(currentMajorStr, 10) : NaN;
|
|
364
|
+
const latestMajor = latestMajorStr !== undefined ? parseInt(latestMajorStr, 10) : NaN;
|
|
365
|
+
const isMajorBump = !isNaN(currentMajor) && !isNaN(latestMajor) && latestMajor > currentMajor;
|
|
366
|
+
const value = isMajorBump ? 3 : 2;
|
|
367
|
+
const effort = isMajorBump ? 3 : 2;
|
|
368
|
+
items.push(makeItem(repo, 'dep', `dep:outdated:${pkg}`, `Outdated: ${pkg} (${current} → ${latest})`, `current: ${current}, wanted: ${wanted}, latest: ${latest}, type: ${type}`, value, effort, ['dep', 'outdated', isMajorBump ? 'major' : 'minor', type]));
|
|
369
|
+
count++;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// 2. Vulnerabilities from npm audit
|
|
373
|
+
const audit = await npmAudit(repo);
|
|
374
|
+
if (audit) {
|
|
375
|
+
// npm audit --json v7+ shape: { vulnerabilities: { ... } } or { metadata: { vulnerabilities: { ... } } }
|
|
376
|
+
let vulnCounts = {};
|
|
377
|
+
// Try v7+ shape first: audit.metadata.vulnerabilities
|
|
378
|
+
const metadata = audit['metadata'];
|
|
379
|
+
if (metadata !== null &&
|
|
380
|
+
typeof metadata === 'object' &&
|
|
381
|
+
!Array.isArray(metadata)) {
|
|
382
|
+
const meta = metadata;
|
|
383
|
+
const v = meta['vulnerabilities'];
|
|
384
|
+
if (v !== null && typeof v === 'object' && !Array.isArray(v)) {
|
|
385
|
+
vulnCounts = v;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// Try legacy shape: audit.vulnerabilities (object of vuln entries, count manually)
|
|
389
|
+
if (Object.keys(vulnCounts).length === 0) {
|
|
390
|
+
const vulns = audit['vulnerabilities'];
|
|
391
|
+
if (vulns !== null && typeof vulns === 'object' && !Array.isArray(vulns)) {
|
|
392
|
+
const entries = vulns;
|
|
393
|
+
const severityCount = {};
|
|
394
|
+
for (const entry of Object.values(entries)) {
|
|
395
|
+
if (entry !== null && typeof entry === 'object') {
|
|
396
|
+
const e = entry;
|
|
397
|
+
const sev = typeof e['severity'] === 'string' ? e['severity'] : 'unknown';
|
|
398
|
+
severityCount[sev] = (severityCount[sev] ?? 0) + 1;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
vulnCounts = severityCount;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
// Emit one WorkItem per non-zero severity
|
|
405
|
+
const SEVERITY_ORDER = ['critical', 'high', 'moderate', 'low', 'info'];
|
|
406
|
+
let vulnCount = 0;
|
|
407
|
+
for (const sev of SEVERITY_ORDER) {
|
|
408
|
+
if (vulnCount >= MAX_VULN_ITEMS)
|
|
409
|
+
break;
|
|
410
|
+
const n = typeof vulnCounts[sev] === 'number' ? vulnCounts[sev] : 0;
|
|
411
|
+
if (n === 0)
|
|
412
|
+
continue;
|
|
413
|
+
const value = sev === 'critical' ? 5 : sev === 'high' ? 4 : sev === 'moderate' ? 3 : 2;
|
|
414
|
+
const effort = 2;
|
|
415
|
+
items.push(makeItem(repo, 'dep', `dep:vuln:${sev}`, `${n} ${sev} npm vulnerabilit${n === 1 ? 'y' : 'ies'}`, `Run \`npm audit\` in ${basename(repo)} to see details. Severity: ${sev}.`, value, effort, ['dep', 'vulnerability', sev]));
|
|
416
|
+
vulnCount++;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return items;
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
return [];
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
// ---------------------------------------------------------------------------
|
|
426
|
+
// scanDocs — heuristics for missing/thin README, LICENSE, CONTRIBUTING
|
|
427
|
+
// ---------------------------------------------------------------------------
|
|
428
|
+
function fileExistsInsensitive(dir, names) {
|
|
429
|
+
for (const name of names) {
|
|
430
|
+
if (existsSync(join(dir, name)))
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
function fileSizeBytes(dir, names) {
|
|
436
|
+
for (const name of names) {
|
|
437
|
+
const p = join(dir, name);
|
|
438
|
+
if (existsSync(p)) {
|
|
439
|
+
try {
|
|
440
|
+
return statSync(p).size;
|
|
441
|
+
}
|
|
442
|
+
catch {
|
|
443
|
+
return 0;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return 0;
|
|
448
|
+
}
|
|
449
|
+
export async function scanDocs(repo) {
|
|
450
|
+
try {
|
|
451
|
+
const items = [];
|
|
452
|
+
// 1. README presence + size
|
|
453
|
+
const readmeNames = [
|
|
454
|
+
'README.md', 'README.txt', 'README', 'readme.md', 'Readme.md',
|
|
455
|
+
];
|
|
456
|
+
const hasReadme = fileExistsInsensitive(repo, readmeNames);
|
|
457
|
+
if (!hasReadme) {
|
|
458
|
+
items.push(makeItem(repo, 'doc', 'doc:missing-readme', 'Missing README', 'No README file found at the repo root.', 3, 2, ['doc', 'readme', 'missing']));
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
const size = fileSizeBytes(repo, readmeNames);
|
|
462
|
+
if (size < 300) {
|
|
463
|
+
items.push(makeItem(repo, 'doc', 'doc:thin-readme', 'README is very short (< 300 bytes)', `README is only ${size} bytes. Consider expanding with usage, setup, and contribution info.`, 2, 2, ['doc', 'readme', 'thin']));
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
// 2. LICENSE presence
|
|
467
|
+
const licenseNames = ['LICENSE', 'LICENSE.md', 'LICENSE.txt', 'LICENCE', 'LICENCE.md'];
|
|
468
|
+
if (!fileExistsInsensitive(repo, licenseNames)) {
|
|
469
|
+
items.push(makeItem(repo, 'doc', 'doc:missing-license', 'Missing LICENSE file', 'No LICENSE file found. Open-source projects should declare a license.', 3, 1, ['doc', 'license', 'missing']));
|
|
470
|
+
}
|
|
471
|
+
// 3. CONTRIBUTING presence
|
|
472
|
+
const contributingNames = [
|
|
473
|
+
'CONTRIBUTING.md', 'CONTRIBUTING.txt', 'CONTRIBUTING', 'contributing.md',
|
|
474
|
+
];
|
|
475
|
+
if (!fileExistsInsensitive(repo, contributingNames)) {
|
|
476
|
+
items.push(makeItem(repo, 'doc', 'doc:missing-contributing', 'Missing CONTRIBUTING file', 'No CONTRIBUTING guide found. Helps onboard new contributors.', 2, 2, ['doc', 'contributing', 'missing']));
|
|
477
|
+
}
|
|
478
|
+
// 4. Low test presence heuristic (no __tests__ dir and no *.test.* / *.spec.* files at top level)
|
|
479
|
+
const testDirExists = existsSync(join(repo, '__tests__')) ||
|
|
480
|
+
existsSync(join(repo, 'test')) ||
|
|
481
|
+
existsSync(join(repo, 'tests')) ||
|
|
482
|
+
existsSync(join(repo, 'spec'));
|
|
483
|
+
// Quick check: look for any test file in src or root (bounded, no deep traversal)
|
|
484
|
+
let hasTestFiles = testDirExists;
|
|
485
|
+
if (!hasTestFiles) {
|
|
486
|
+
try {
|
|
487
|
+
const { stdout } = await execFileAsync('find', [
|
|
488
|
+
'.',
|
|
489
|
+
'-maxdepth', '3',
|
|
490
|
+
'-not', '-path', '*/node_modules/*',
|
|
491
|
+
'-not', '-path', '*/.git/*',
|
|
492
|
+
'-not', '-path', '*/dist/*',
|
|
493
|
+
'-name', '*.test.*',
|
|
494
|
+
'-o', '-name', '*.spec.*',
|
|
495
|
+
], { cwd: repo, timeout: SCAN_TIMEOUT_MS, maxBuffer: 64 * 1024 });
|
|
496
|
+
hasTestFiles = stdout.trim().length > 0;
|
|
497
|
+
}
|
|
498
|
+
catch {
|
|
499
|
+
// find not available or error — skip this heuristic
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
if (!hasTestFiles) {
|
|
503
|
+
items.push(makeItem(repo, 'doc', 'doc:low-test-presence', 'Low test coverage signal', 'No test directories or test files detected. Consider adding tests.', 3, 4, ['doc', 'tests', 'coverage']));
|
|
504
|
+
}
|
|
505
|
+
return items;
|
|
506
|
+
}
|
|
507
|
+
catch {
|
|
508
|
+
return [];
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
// ---------------------------------------------------------------------------
|
|
512
|
+
// scanSecurity — binshield (read-only) if installed, else []
|
|
513
|
+
// ---------------------------------------------------------------------------
|
|
514
|
+
/**
|
|
515
|
+
* Check if `binshield` is on PATH using `which` / `command -v`.
|
|
516
|
+
* Returns true if found.
|
|
517
|
+
*/
|
|
518
|
+
async function binshieldAvailable() {
|
|
519
|
+
try {
|
|
520
|
+
await execFileAsync('which', ['binshield'], { timeout: 3_000 });
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
catch {
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
export async function scanSecurity(repo) {
|
|
528
|
+
try {
|
|
529
|
+
if (!(await binshieldAvailable()))
|
|
530
|
+
return [];
|
|
531
|
+
// Run binshield in read-only/scan mode.
|
|
532
|
+
// We pass `scan` as a subcommand and `--json` for structured output.
|
|
533
|
+
// If binshield doesn't support these flags it will exit non-zero and we return [].
|
|
534
|
+
const { stdout } = await execFileAsync('binshield', ['scan', '--json', repo], {
|
|
535
|
+
timeout: SCAN_TIMEOUT_MS,
|
|
536
|
+
maxBuffer: 512 * 1024,
|
|
537
|
+
// No cwd needed — we pass repo as arg
|
|
538
|
+
});
|
|
539
|
+
if (!stdout || stdout.trim() === '')
|
|
540
|
+
return [];
|
|
541
|
+
let parsed;
|
|
542
|
+
try {
|
|
543
|
+
parsed = JSON.parse(stdout);
|
|
544
|
+
}
|
|
545
|
+
catch {
|
|
546
|
+
return [];
|
|
547
|
+
}
|
|
548
|
+
// Accept array of findings or { findings: [...] }
|
|
549
|
+
let findings = [];
|
|
550
|
+
if (Array.isArray(parsed)) {
|
|
551
|
+
findings = parsed;
|
|
552
|
+
}
|
|
553
|
+
else if (parsed !== null &&
|
|
554
|
+
typeof parsed === 'object' &&
|
|
555
|
+
Array.isArray(parsed['findings'])) {
|
|
556
|
+
findings = parsed['findings'];
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
return [];
|
|
560
|
+
}
|
|
561
|
+
const items = [];
|
|
562
|
+
for (const f of findings) {
|
|
563
|
+
if (f === null || typeof f !== 'object' || Array.isArray(f))
|
|
564
|
+
continue;
|
|
565
|
+
const finding = f;
|
|
566
|
+
const title = typeof finding['title'] === 'string'
|
|
567
|
+
? finding['title']
|
|
568
|
+
: typeof finding['name'] === 'string'
|
|
569
|
+
? finding['name']
|
|
570
|
+
: 'binshield finding';
|
|
571
|
+
// Sanitize detail — no secrets (skip any key that looks secret-like)
|
|
572
|
+
const rawDetail = typeof finding['description'] === 'string'
|
|
573
|
+
? finding['description']
|
|
574
|
+
: typeof finding['detail'] === 'string'
|
|
575
|
+
? finding['detail']
|
|
576
|
+
: '';
|
|
577
|
+
// Strip anything that looks like a token/key (long hex/base64 strings)
|
|
578
|
+
const detail = rawDetail.replace(/[A-Za-z0-9+/]{32,}/g, '[REDACTED]');
|
|
579
|
+
const sev = typeof finding['severity'] === 'string' ? finding['severity'] : 'medium';
|
|
580
|
+
const value = sev === 'critical' ? 5 : sev === 'high' ? 4 : sev === 'medium' ? 3 : 2;
|
|
581
|
+
items.push(makeItem(repo, 'security', `security:${title}`, title, detail, value, 2, ['security', 'binshield', sev]));
|
|
582
|
+
}
|
|
583
|
+
return items;
|
|
584
|
+
}
|
|
585
|
+
catch {
|
|
586
|
+
return [];
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
// ---------------------------------------------------------------------------
|
|
590
|
+
// SCANNERS — all six, exported as a ReadonlyArray
|
|
591
|
+
// ---------------------------------------------------------------------------
|
|
592
|
+
export const SCANNERS = [
|
|
593
|
+
scanIssues,
|
|
594
|
+
scanTodos,
|
|
595
|
+
scanTests,
|
|
596
|
+
scanDeps,
|
|
597
|
+
scanDocs,
|
|
598
|
+
scanSecurity,
|
|
599
|
+
];
|
|
600
|
+
//# sourceMappingURL=scanners.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanners.js","sourceRoot":"","sources":["../../../src/core/portfolio/scanners.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAErE,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,MAAM,eAAe,GAAG,MAAM,CAAC;AAC/B,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAC9B,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;GAGG;AACH,SAAS,MAAM,CAAC,IAAY,EAAE,MAAkB,EAAE,aAAqB;IACrE,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC;SAC5B,MAAM,CAAC,IAAI,GAAG,GAAG,GAAG,aAAa,CAAC;SAClC,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,MAAM;IACb,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAS,KAAK,CAAC,CAAS;IACtB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,SAAS,KAAK,CAAC,KAAa,EAAE,MAAc;IAC1C,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACvB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;AACzC,CAAC;AAED,SAAS,QAAQ,CACf,IAAY,EACZ,MAAkB,EAClB,aAAqB,EACrB,KAAa,EACb,MAAc,EACd,KAAa,EACb,MAAc,EACd,IAAc;IAEd,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACvB,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC;QACvC,IAAI;QACJ,MAAM;QACN,KAAK;QACL,MAAM;QACN,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;QACT,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAClB,IAAI;QACJ,EAAE,EAAE,MAAM,EAAE;KACb,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,qDAAqD;AACrD,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAE7D,MAAM,KAAK,GAAe,EAAE,CAAC;QAE7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,wDAAwD;YACxD,iEAAiE;YACjE,yEAAyE;YACzE,MAAM,KAAK,GAAG,CAAC,CAAC;YAChB,MAAM,MAAM,GAAG,CAAC,CAAC;YAEjB,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,OAAO,EACP,SAAS,KAAK,CAAC,MAAM,EAAE,EACvB,UAAU,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,KAAK,EAAE,EACxC,KAAK,CAAC,GAAG,EACT,KAAK,EACL,MAAM,EACN,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,CAC9B,CACF,CAAC;QACJ,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,uDAAuD;AACvD,8EAA8E;AAE9E;;;;GAIG;AACH,KAAK,UAAU,QAAQ,CAAC,IAAY;IAClC,kDAAkD;IAClD,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,IAAI,EACJ;YACE,eAAe;YACf,cAAc;YACd,QAAQ,EAAE,eAAe;YACzB,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE,OAAO;YACjB,QAAQ,EAAE,QAAQ;YAClB,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC;YACpC,IAAI,EAAE,qBAAqB;YAC3B,GAAG;SACJ,EACD;YACE,GAAG,EAAE,IAAI;YACT,OAAO,EAAE,eAAe;YACxB,SAAS,EAAE,IAAI,GAAG,IAAI,EAAE,WAAW;SACpC,CACF,CAAC;QACF,OAAO,MAAM,IAAI,IAAI,CAAC;IACxB,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,+DAA+D;QAC/D,MAAM,CAAC,GAAG,GAA0E,CAAC;QACrF,IAAI,CAAC,EAAE,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC9C,2EAA2E;YAC3E,OAAO,CAAC,CAAC,MAAM,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,EAAE,IAAI,KAAK,GAAG,EAAE,CAAC;YACpB,iCAAiC;YACjC,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,mDAAmD;IACrD,CAAC;IAED,yBAAyB;IACzB,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,MAAM,EACN;YACE,KAAK;YACL,gBAAgB;YAChB,iBAAiB;YACjB,gBAAgB;YAChB,iBAAiB;YACjB,iBAAiB;YACjB,iBAAiB;YACjB,gBAAgB;YAChB,gBAAgB;YAChB,gBAAgB;YAChB,kBAAkB;YAClB,gBAAgB;YAChB,mBAAmB;YACnB,gBAAgB;YAChB,4BAA4B;YAC5B,oBAAoB;YACpB,oBAAoB;YACpB,qBAAqB;YACrB,IAAI,EAAE,MAAM,CAAC,aAAa,CAAC;YAC3B,IAAI,EAAE,qBAAqB;YAC3B,GAAG;SACJ,EACD;YACE,GAAG,EAAE,IAAI;YACT,OAAO,EAAE,eAAe;YACxB,SAAS,EAAE,IAAI,GAAG,IAAI;SACvB,CACF,CAAC;QACF,OAAO,MAAM,IAAI,IAAI,CAAC;IACxB,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,GAA0E,CAAC;QACrF,IAAI,CAAC,EAAE,MAAM,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO,CAAC,CAAC,MAAM,CAAC;QAC/D,IAAI,CAAC,EAAE,IAAI,KAAK,GAAG;YAAE,OAAO,EAAE,CAAC,CAAC,aAAa;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY;IAC1C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,CAAC;QAEzC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;QAEtE,mEAAmE;QACnE,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6D,CAAC;QAEpF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,qDAAqD;YACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,QAAQ,GAAG,CAAC;gBAAE,SAAS;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;YACtC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YACzC,MAAM,WAAW,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAEpF,2BAA2B;YAC3B,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjD,IAAI,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnD,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjD,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAE/C,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACtC,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACjB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;oBACrB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;wBAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACxD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAe,EAAE,CAAC;QAC7B,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;YACrE,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,MAAM,EACN,QAAQ,QAAQ,EAAE,EAClB,GAAG,MAAM,OAAO,QAAQ,EAAE,EAC1B,IAAI,CAAC,MAAM,EACX,CAAC,EACD,CAAC,EACD,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CACvB,CACF,CAAC;QACJ,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,2EAA2E;AAC3E,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY;IAC1C,IAAI,CAAC;QACH,MAAM,KAAK,GAAe,EAAE,CAAC;QAE7B,iEAAiE;QACjE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAC3C,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;gBACvD,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;gBAC/B,IACE,OAAO,KAAK,IAAI;oBAChB,OAAO,OAAO,KAAK,QAAQ;oBAC3B,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EACvB,CAAC;oBACD,MAAM,CAAC,GAAG,OAAkC,CAAC;oBAC7C,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;wBAC7D,aAAa,GAAG,IAAI,CAAC;oBACvB,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,mDAAmD;YACrD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,mFAAmF;YACnF,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,MAAM,EACN,qBAAqB,EACrB,sCAAsC,EACtC,mEAAmE,EACnE,CAAC,EACD,CAAC,EACD,CAAC,MAAM,EAAE,UAAU,CAAC,CACrB,CACF,CAAC;YACJ,CAAC;YACD,8EAA8E;QAChF,CAAC;QAED,+EAA+E;QAC/E,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC7C,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,MAAM,EACN,iBAAiB,EACjB,eAAe,EACf,oDAAoD,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,EACzE,CAAC,EACD,CAAC,EACD,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAC1B,CACF,CAAC;QACJ,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YACpD,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,MAAM,EACN,iBAAiB,EACjB,eAAe,EACf,uDAAuD,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,EAC5E,CAAC,EACD,CAAC,EACD,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAC1B,CACF,CAAC;QACJ,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,mEAAmE;AACnE,8EAA8E;AAE9E;;;GAGG;AACH,KAAK,UAAU,WAAW,CAAC,IAAY;IACrC,IAAI,CAAC;QACH,gFAAgF;QAChF,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,KAAK,EACL,CAAC,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,CAAC,EACvD;YACE,GAAG,EAAE,IAAI;YACT,OAAO,EAAE,cAAc;YACvB,SAAS,EAAE,GAAG,GAAG,IAAI;SACtB,CACF,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACvB,qFAAqF;YACrF,MAAM,CAAC,GAAG,GAA0B,CAAC;YACrC,IAAI,CAAC,EAAE,MAAM;gBAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAY,CAAC;QAC7C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QACxF,OAAO,MAAiC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,QAAQ,CAAC,IAAY;IAClC,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,KAAK,EACL,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,CAAC,EACpD;YACE,GAAG,EAAE,IAAI;YACT,OAAO,EAAE,cAAc;YACvB,SAAS,EAAE,GAAG,GAAG,IAAI;SACtB,CACF,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACvB,+EAA+E;YAC/E,MAAM,CAAC,GAAG,GAA0B,CAAC;YACrC,IAAI,CAAC,EAAE,MAAM;gBAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAY,CAAC;QAC7C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QACxF,OAAO,MAAiC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAC3C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,CAAC;QAEpC,MAAM,KAAK,GAAe,EAAE,CAAC;QAC7B,IAAI,KAAK,GAAG,CAAC,CAAC;QAEd,mBAAmB;QACnB,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACnD,IAAI,KAAK,IAAI,kBAAkB;oBAAE,MAAM;gBACvC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;oBAAE,SAAS;gBACxD,MAAM,GAAG,GAAG,IAA+B,CAAC;gBAE5C,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC1E,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBACvE,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBACvE,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;gBAE1E,4BAA4B;gBACxB,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACtD,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5C,MAAM,YAAY,GAAG,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBACzF,MAAM,WAAW,GAAG,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBACtF,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,YAAY,CAAC;gBAE1F,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClC,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAEnC,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,KAAK,EACL,gBAAgB,GAAG,EAAE,EACrB,aAAa,GAAG,KAAK,OAAO,MAAM,MAAM,GAAG,EAC3C,YAAY,OAAO,aAAa,MAAM,aAAa,MAAM,WAAW,IAAI,EAAE,EAC1E,KAAK,EACL,MAAM,EACN,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAC3D,CACF,CAAC;gBACF,KAAK,EAAE,CAAC;YACV,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,KAAK,EAAE,CAAC;YACV,yGAAyG;YACzG,IAAI,UAAU,GAA2B,EAAE,CAAC;YAE5C,sDAAsD;YACtD,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;YACnC,IACE,QAAQ,KAAK,IAAI;gBACjB,OAAO,QAAQ,KAAK,QAAQ;gBAC5B,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EACxB,CAAC;gBACD,MAAM,IAAI,GAAG,QAAmC,CAAC;gBACjD,MAAM,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBAClC,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7D,UAAU,GAAG,CAA2B,CAAC;gBAC3C,CAAC;YACH,CAAC;YAED,mFAAmF;YACnF,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzC,MAAM,KAAK,GAAG,KAAK,CAAC,iBAAiB,CAAC,CAAC;gBACvC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzE,MAAM,OAAO,GAAG,KAAgC,CAAC;oBACjD,MAAM,aAAa,GAA2B,EAAE,CAAC;oBACjD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;wBAC3C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;4BAChD,MAAM,CAAC,GAAG,KAAgC,CAAC;4BAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,UAAU,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;4BAC1E,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;wBACrD,CAAC;oBACH,CAAC;oBACD,UAAU,GAAG,aAAa,CAAC;gBAC7B,CAAC;YACH,CAAC;YAED,0CAA0C;YAC1C,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YACvE,IAAI,SAAS,GAAG,CAAC,CAAC;YAClB,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;gBACjC,IAAI,SAAS,IAAI,cAAc;oBAAE,MAAM;gBACvC,MAAM,CAAC,GAAG,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpE,IAAI,CAAC,KAAK,CAAC;oBAAE,SAAS;gBAEtB,MAAM,KAAK,GAAG,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACvF,MAAM,MAAM,GAAG,CAAC,CAAC;gBAEjB,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,KAAK,EACL,YAAY,GAAG,EAAE,EACjB,GAAG,CAAC,IAAI,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,EACtD,wBAAwB,QAAQ,CAAC,IAAI,CAAC,8BAA8B,GAAG,GAAG,EAC1E,KAAK,EACL,MAAM,EACN,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,CAAC,CAC9B,CACF,CAAC;gBACF,SAAS,EAAE,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,uEAAuE;AACvE,8EAA8E;AAE9E,SAAS,qBAAqB,CAAC,GAAW,EAAE,KAAe;IACzD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IAC/C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,KAAe;IACjD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,IAAI,CAAC;gBACH,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,CAAC;YACX,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,KAAK,GAAe,EAAE,CAAC;QAE7B,4BAA4B;QAC5B,MAAM,WAAW,GAAG;YAClB,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW;SAC9D,CAAC;QACF,MAAM,SAAS,GAAG,qBAAqB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC3D,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,KAAK,EACL,oBAAoB,EACpB,gBAAgB,EAChB,wCAAwC,EACxC,CAAC,EACD,CAAC,EACD,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,CAC7B,CACF,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAC9C,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC;gBACf,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,KAAK,EACL,iBAAiB,EACjB,oCAAoC,EACpC,kBAAkB,IAAI,sEAAsE,EAC5F,CAAC,EACD,CAAC,EACD,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAC1B,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,sBAAsB;QACtB,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;QACvF,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,KAAK,EACL,qBAAqB,EACrB,sBAAsB,EACtB,uEAAuE,EACvE,CAAC,EACD,CAAC,EACD,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,CAC9B,CACF,CAAC;QACJ,CAAC;QAED,2BAA2B;QAC3B,MAAM,iBAAiB,GAAG;YACxB,iBAAiB,EAAE,kBAAkB,EAAE,cAAc,EAAE,iBAAiB;SACzE,CAAC;QACF,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,CAAC;YACpD,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,KAAK,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,8DAA8D,EAC9D,CAAC,EACD,CAAC,EACD,CAAC,KAAK,EAAE,cAAc,EAAE,SAAS,CAAC,CACnC,CACF,CAAC;QACJ,CAAC;QAED,kGAAkG;QAClG,MAAM,aAAa,GACjB,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YACnC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC/B,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAEjC,kFAAkF;QAClF,IAAI,YAAY,GAAG,aAAa,CAAC;QACjC,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,IAAI,CAAC;gBACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,MAAM,EACN;oBACE,GAAG;oBACH,WAAW,EAAE,GAAG;oBAChB,MAAM,EAAE,OAAO,EAAE,kBAAkB;oBACnC,MAAM,EAAE,OAAO,EAAE,UAAU;oBAC3B,MAAM,EAAE,OAAO,EAAE,UAAU;oBAC3B,OAAO,EAAE,UAAU;oBACnB,IAAI,EAAE,OAAO,EAAE,UAAU;iBAC1B,EACD,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,EAAE,CAC9D,CAAC;gBACF,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,oDAAoD;YACtD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,KAAK,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,oEAAoE,EACpE,CAAC,EACD,CAAC,EACD,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,CAC7B,CACF,CAAC;QACJ,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,6DAA6D;AAC7D,8EAA8E;AAE9E;;;GAGG;AACH,KAAK,UAAU,kBAAkB;IAC/B,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY;IAC7C,IAAI,CAAC;QACH,IAAI,CAAC,CAAC,MAAM,kBAAkB,EAAE,CAAC;YAAE,OAAO,EAAE,CAAC;QAE7C,wCAAwC;QACxC,qEAAqE;QACrE,mFAAmF;QACnF,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,WAAW,EACX,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,EACxB;YACE,OAAO,EAAE,eAAe;YACxB,SAAS,EAAE,GAAG,GAAG,IAAI;YACrB,sCAAsC;SACvC,CACF,CAAC;QAEF,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,CAAC;QAE/C,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,kDAAkD;QAClD,IAAI,QAAQ,GAAc,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,QAAQ,GAAG,MAAM,CAAC;QACpB,CAAC;aAAM,IACL,MAAM,KAAK,IAAI;YACf,OAAO,MAAM,KAAK,QAAQ;YAC1B,KAAK,CAAC,OAAO,CAAE,MAAkC,CAAC,UAAU,CAAC,CAAC,EAC9D,CAAC;YACD,QAAQ,GAAI,MAAkC,CAAC,UAAU,CAAc,CAAC;QAC1E,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,KAAK,GAAe,EAAE,CAAC;QAC7B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;gBAAE,SAAS;YACtE,MAAM,OAAO,GAAG,CAA4B,CAAC;YAE7C,MAAM,KAAK,GAAG,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,QAAQ;gBAChD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;gBAClB,CAAC,CAAC,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,QAAQ;oBACnC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;oBACjB,CAAC,CAAC,mBAAmB,CAAC;YAE1B,qEAAqE;YACrE,MAAM,SAAS,GAAG,OAAO,OAAO,CAAC,aAAa,CAAC,KAAK,QAAQ;gBAC1D,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;gBACxB,CAAC,CAAC,OAAO,OAAO,CAAC,QAAQ,CAAC,KAAK,QAAQ;oBACrC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;oBACnB,CAAC,CAAC,EAAE,CAAC;YACT,uEAAuE;YACvE,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE,YAAY,CAAC,CAAC;YAEtE,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,UAAU,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YACrF,MAAM,KAAK,GAAG,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAErF,KAAK,CAAC,IAAI,CACR,QAAQ,CACN,IAAI,EACJ,UAAU,EACV,YAAY,KAAK,EAAE,EACnB,KAAK,EACL,MAAM,EACN,KAAK,EACL,CAAC,EACD,CAAC,UAAU,EAAE,WAAW,EAAE,GAAG,CAAC,CAC/B,CACF,CAAC;QACJ,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,kDAAkD;AAClD,8EAA8E;AAE9E,MAAM,CAAC,MAAM,QAAQ,GAAyD;IAC5E,UAAU;IACV,SAAS;IACT,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,YAAY;CACJ,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider registry — probes local-model endpoints (LM Studio, Ollama) and
|
|
3
|
+
* resolves the active provider from the configured chain.
|
|
4
|
+
*
|
|
5
|
+
* Rules:
|
|
6
|
+
* - NEVER throws; all probes return typed results with up:false on failure.
|
|
7
|
+
* - Uses global fetch (Node 22+) with a 2-second AbortController timeout.
|
|
8
|
+
* - Cloud providers (e.g. 'anthropic') are treated as up when the relevant
|
|
9
|
+
* env var is present (ANTHROPIC_API_KEY), else skipped.
|
|
10
|
+
*/
|
|
11
|
+
import type { AshlrConfig, ProviderEndpoint, ProviderRegistry } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Probe a single provider endpoint with a 2-second timeout.
|
|
14
|
+
*
|
|
15
|
+
* - For LM Studio: GET <url>/v1/models (appended if not already present)
|
|
16
|
+
* - For Ollama: GET <url>/api/tags (appended if not already present)
|
|
17
|
+
* - For other ids: url is used as-is (caller must supply full probe URL)
|
|
18
|
+
*
|
|
19
|
+
* Never throws — returns up:false with an error string on any failure.
|
|
20
|
+
*/
|
|
21
|
+
export declare function probeEndpoint(id: string, url: string): Promise<ProviderEndpoint>;
|
|
22
|
+
/**
|
|
23
|
+
* Build the full ProviderRegistry from the current config.
|
|
24
|
+
*
|
|
25
|
+
* - Probes cfg.models.lmstudio and cfg.models.ollama in parallel.
|
|
26
|
+
* - Walks cfg.models.providerChain in order to find the first up provider.
|
|
27
|
+
* - Cloud providers (e.g. 'anthropic') count as up if their env key exists.
|
|
28
|
+
* - Local providers not in the config (unknown ids) are skipped gracefully.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getProviderRegistry(cfg: AshlrConfig): Promise<ProviderRegistry>;
|
|
31
|
+
/**
|
|
32
|
+
* Convenience wrapper — returns the id of the active provider, or null.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveActiveProvider(cfg: AshlrConfig): Promise<string | null>;
|