peaks-loop 4.1.3 → 4.1.4
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/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +56 -0
- package/README-en.md +1 -1
- package/README.md +1 -1
- package/dist/cli/commands/asset-command-shared.d.ts +12 -0
- package/dist/cli/commands/asset-command-shared.js +45 -0
- package/dist/cli/commands/asset-commands.d.ts +6 -1
- package/dist/cli/commands/asset-commands.js +11 -372
- package/dist/cli/commands/asset-crystallize-command.d.ts +3 -0
- package/dist/cli/commands/asset-crystallize-command.js +60 -0
- package/dist/cli/commands/asset-crystallize-payload.d.ts +47 -0
- package/dist/cli/commands/asset-crystallize-payload.js +85 -0
- package/dist/cli/commands/asset-crystallize-runner.d.ts +3 -0
- package/dist/cli/commands/asset-crystallize-runner.js +133 -0
- package/dist/cli/commands/asset-dispose-command.d.ts +3 -0
- package/dist/cli/commands/asset-dispose-command.js +99 -0
- package/dist/cli/commands/asset-status-command.d.ts +3 -0
- package/dist/cli/commands/asset-status-command.js +100 -0
- package/dist/cli/commands/baseline-audit-command.d.ts +3 -0
- package/dist/cli/commands/baseline-audit-command.js +64 -0
- package/dist/cli/commands/baseline-command-shared.d.ts +23 -0
- package/dist/cli/commands/baseline-command-shared.js +39 -0
- package/dist/cli/commands/baseline-commands.js +33 -313
- package/dist/cli/commands/baseline-freeze-commands.d.ts +4 -0
- package/dist/cli/commands/baseline-freeze-commands.js +81 -0
- package/dist/cli/commands/baseline-guard-command.d.ts +3 -0
- package/dist/cli/commands/baseline-guard-command.js +52 -0
- package/dist/cli/commands/baseline-read-commands.d.ts +5 -0
- package/dist/cli/commands/baseline-read-commands.js +72 -0
- package/dist/cli/commands/baseline-rollback-commands.d.ts +4 -0
- package/dist/cli/commands/baseline-rollback-commands.js +88 -0
- package/dist/cli/commands/classify-downgrade-command.d.ts +9 -0
- package/dist/cli/commands/classify-downgrade-command.js +21 -0
- package/dist/cli/commands/classify-run-command.d.ts +9 -0
- package/dist/cli/commands/classify-run-command.js +73 -0
- package/dist/cli/commands/classify-signals.d.ts +5 -0
- package/dist/cli/commands/classify-signals.js +104 -0
- package/dist/cli/commands/code-emit-handoff-command.js +40 -3
- package/dist/cli/commands/code-gate-step-08-command.js +25 -9
- package/dist/cli/commands/codegraph-command-options.d.ts +22 -0
- package/dist/cli/commands/codegraph-command-options.js +22 -0
- package/dist/cli/commands/codegraph-commands.d.ts +2 -2
- package/dist/cli/commands/codegraph-commands.js +14 -397
- package/dist/cli/commands/codegraph-config-restore-command.d.ts +3 -0
- package/dist/cli/commands/codegraph-config-restore-command.js +200 -0
- package/dist/cli/commands/codegraph-proxy-commands.d.ts +10 -0
- package/dist/cli/commands/codegraph-proxy-commands.js +159 -0
- package/dist/cli/commands/codegraph-repair-commands.d.ts +3 -0
- package/dist/cli/commands/codegraph-repair-commands.js +94 -0
- package/dist/cli/commands/codegraph-status-command.d.ts +1 -1
- package/dist/cli/commands/codegraph-status-command.js +27 -214
- package/dist/cli/commands/codegraph-status-integrity.d.ts +44 -0
- package/dist/cli/commands/codegraph-status-integrity.js +121 -0
- package/dist/cli/commands/codegraph-status-json.d.ts +5 -0
- package/dist/cli/commands/codegraph-status-json.js +127 -0
- package/dist/cli/commands/container-command-shared.d.ts +60 -0
- package/dist/cli/commands/container-command-shared.js +52 -0
- package/dist/cli/commands/container-commands.d.ts +1 -1
- package/dist/cli/commands/container-commands.js +4 -216
- package/dist/cli/commands/container-release-command.d.ts +3 -0
- package/dist/cli/commands/container-release-command.js +105 -0
- package/dist/cli/commands/container-spawn-command.d.ts +3 -0
- package/dist/cli/commands/container-spawn-command.js +148 -0
- package/dist/cli/commands/context-check-command.d.ts +3 -0
- package/dist/cli/commands/context-check-command.js +81 -0
- package/dist/cli/commands/context-commands.d.ts +2 -7
- package/dist/cli/commands/context-commands.js +6 -276
- package/dist/cli/commands/context-layer-command.d.ts +3 -0
- package/dist/cli/commands/context-layer-command.js +34 -0
- package/dist/cli/commands/context-layer-fetchers.d.ts +15 -0
- package/dist/cli/commands/context-layer-fetchers.js +162 -0
- package/dist/cli/commands/context-status-command.d.ts +17 -0
- package/dist/cli/commands/context-status-command.js +41 -0
- package/dist/cli/commands/contract-write-command.d.ts +3 -0
- package/dist/cli/commands/contract-write-command.js +144 -0
- package/dist/cli/commands/core/doctor-bindings.d.ts +17 -0
- package/dist/cli/commands/core/doctor-bindings.js +30 -0
- package/dist/cli/commands/core/doctor-command.d.ts +4 -18
- package/dist/cli/commands/core/doctor-command.js +2 -323
- package/dist/cli/commands/core/doctor-logs.d.ts +8 -0
- package/dist/cli/commands/core/doctor-logs.js +32 -0
- package/dist/cli/commands/core/doctor-probes.d.ts +3 -0
- package/dist/cli/commands/core/doctor-probes.js +55 -0
- package/dist/cli/commands/core/doctor-run-command.d.ts +12 -0
- package/dist/cli/commands/core/doctor-run-command.js +172 -0
- package/dist/cli/commands/core/doctor-summary.d.ts +7 -0
- package/dist/cli/commands/core/doctor-summary.js +39 -0
- package/dist/cli/commands/core/memory-command-shared.d.ts +25 -0
- package/dist/cli/commands/core/memory-command-shared.js +20 -0
- package/dist/cli/commands/core/memory-command.d.ts +1 -1
- package/dist/cli/commands/core/memory-command.js +6 -227
- package/dist/cli/commands/core/memory-delegated-verbs.d.ts +4 -0
- package/dist/cli/commands/core/memory-delegated-verbs.js +178 -0
- package/dist/cli/commands/core/memory-extract-command.d.ts +3 -0
- package/dist/cli/commands/core/memory-extract-command.js +90 -0
- package/dist/cli/commands/core/memory-sync-command.d.ts +3 -0
- package/dist/cli/commands/core/memory-sync-command.js +38 -0
- package/dist/cli/commands/core/session-command.d.ts +1 -1
- package/dist/cli/commands/core/session-command.js +12 -206
- package/dist/cli/commands/core/session-info-command.d.ts +3 -0
- package/dist/cli/commands/core/session-info-command.js +142 -0
- package/dist/cli/commands/core/session-verb-commands.d.ts +5 -0
- package/dist/cli/commands/core/session-verb-commands.js +58 -0
- package/dist/cli/commands/core/standards-command.d.ts +1 -24
- package/dist/cli/commands/core/standards-command.js +33 -201
- package/dist/cli/commands/core/standards-init-command.d.ts +3 -0
- package/dist/cli/commands/core/standards-init-command.js +87 -0
- package/dist/cli/commands/core/standards-lint.d.ts +24 -0
- package/dist/cli/commands/core/standards-lint.js +57 -0
- package/dist/cli/commands/core/standards-migrate-command.d.ts +3 -0
- package/dist/cli/commands/core/standards-migrate-command.js +57 -0
- package/dist/cli/commands/cron-scheduler-commands.d.ts +5 -1
- package/dist/cli/commands/cron-scheduler-commands.js +36 -206
- package/dist/cli/commands/cron-scheduler-run-once-command.d.ts +7 -0
- package/dist/cli/commands/cron-scheduler-run-once-command.js +35 -0
- package/dist/cli/commands/cron-scheduler-shared.d.ts +6 -0
- package/dist/cli/commands/cron-scheduler-shared.js +48 -0
- package/dist/cli/commands/cron-scheduler-start-command.d.ts +7 -0
- package/dist/cli/commands/cron-scheduler-start-command.js +65 -0
- package/dist/cli/commands/cron-scheduler-status-command.d.ts +7 -0
- package/dist/cli/commands/cron-scheduler-status-command.js +46 -0
- package/dist/cli/commands/cron-scheduler-stop-command.d.ts +7 -0
- package/dist/cli/commands/cron-scheduler-stop-command.js +61 -0
- package/dist/cli/commands/dispatch-dag-envelope.d.ts +41 -0
- package/dist/cli/commands/dispatch-dag-envelope.js +49 -0
- package/dist/cli/commands/dispatch-dag-failure.d.ts +18 -0
- package/dist/cli/commands/dispatch-dag-failure.js +16 -0
- package/dist/cli/commands/dispatch-dag-preflight.d.ts +51 -0
- package/dist/cli/commands/dispatch-dag-preflight.js +105 -0
- package/dist/cli/commands/dispatch-dag-runners.d.ts +48 -0
- package/dist/cli/commands/dispatch-dag-runners.js +73 -0
- package/dist/cli/commands/dispatch-from-dag.d.ts +27 -0
- package/dist/cli/commands/dispatch-from-dag.js +87 -257
- package/dist/cli/commands/final-review-command-envelopes.d.ts +44 -0
- package/dist/cli/commands/final-review-command-envelopes.js +100 -0
- package/dist/cli/commands/final-review-command-shared.d.ts +52 -0
- package/dist/cli/commands/final-review-command-shared.js +35 -0
- package/dist/cli/commands/final-review-commands.d.ts +7 -27
- package/dist/cli/commands/final-review-commands.js +13 -240
- package/dist/cli/commands/final-review-prepare-command.d.ts +3 -0
- package/dist/cli/commands/final-review-prepare-command.js +200 -0
- package/dist/cli/commands/governance-classify-contract-commands.d.ts +23 -9
- package/dist/cli/commands/governance-classify-contract-commands.js +26 -269
- package/dist/cli/commands/hooks-command-shared.d.ts +42 -0
- package/dist/cli/commands/hooks-command-shared.js +32 -0
- package/dist/cli/commands/hooks-commands.d.ts +20 -0
- package/dist/cli/commands/hooks-commands.js +75 -309
- package/dist/cli/commands/hooks-install-envelopes.d.ts +6 -0
- package/dist/cli/commands/hooks-install-envelopes.js +144 -0
- package/dist/cli/commands/hooks-status-command.d.ts +3 -0
- package/dist/cli/commands/hooks-status-command.js +93 -0
- package/dist/cli/commands/hooks-uninstall-command.d.ts +3 -0
- package/dist/cli/commands/hooks-uninstall-command.js +43 -0
- package/dist/cli/commands/loop-command-shared.d.ts +31 -0
- package/dist/cli/commands/loop-command-shared.js +15 -0
- package/dist/cli/commands/loop-commands.d.ts +12 -17
- package/dist/cli/commands/loop-commands.js +56 -238
- package/dist/cli/commands/loop-export-command.d.ts +3 -0
- package/dist/cli/commands/loop-export-command.js +73 -0
- package/dist/cli/commands/loop-goal-compose-command.d.ts +3 -0
- package/dist/cli/commands/loop-goal-compose-command.js +36 -0
- package/dist/cli/commands/loop-import-command.d.ts +3 -0
- package/dist/cli/commands/loop-import-command.js +86 -0
- package/dist/cli/commands/loop-placeholder-commands.d.ts +3 -0
- package/dist/cli/commands/loop-placeholder-commands.js +52 -0
- package/dist/cli/commands/memory-command-shared.d.ts +59 -0
- package/dist/cli/commands/memory-command-shared.js +39 -0
- package/dist/cli/commands/memory-commands.d.ts +6 -79
- package/dist/cli/commands/memory-commands.js +19 -309
- package/dist/cli/commands/memory-ingest-command.d.ts +3 -0
- package/dist/cli/commands/memory-ingest-command.js +50 -0
- package/dist/cli/commands/memory-list-command.d.ts +16 -0
- package/dist/cli/commands/memory-list-command.js +129 -0
- package/dist/cli/commands/memory-reindex-command.d.ts +9 -0
- package/dist/cli/commands/memory-reindex-command.js +78 -0
- package/dist/cli/commands/memory-rotate-command.d.ts +3 -0
- package/dist/cli/commands/memory-rotate-command.js +55 -0
- package/dist/cli/commands/memory-search-command.d.ts +7 -0
- package/dist/cli/commands/memory-search-command.js +46 -0
- package/dist/cli/commands/openspec-archive-command.d.ts +3 -0
- package/dist/cli/commands/openspec-archive-command.js +55 -0
- package/dist/cli/commands/openspec-command-shared.d.ts +62 -0
- package/dist/cli/commands/openspec-command-shared.js +135 -0
- package/dist/cli/commands/openspec-commands.d.ts +1 -1
- package/dist/cli/commands/openspec-commands.js +33 -306
- package/dist/cli/commands/openspec-from-doctor-command.d.ts +3 -0
- package/dist/cli/commands/openspec-from-doctor-command.js +66 -0
- package/dist/cli/commands/openspec-init-command.d.ts +3 -0
- package/dist/cli/commands/openspec-init-command.js +49 -0
- package/dist/cli/commands/openspec-list-command.d.ts +3 -0
- package/dist/cli/commands/openspec-list-command.js +27 -0
- package/dist/cli/commands/openspec-render-command.d.ts +3 -0
- package/dist/cli/commands/openspec-render-command.js +33 -0
- package/dist/cli/commands/openspec-show-command.d.ts +3 -0
- package/dist/cli/commands/openspec-show-command.js +33 -0
- package/dist/cli/commands/openspec-to-rd-command.d.ts +3 -0
- package/dist/cli/commands/openspec-to-rd-command.js +33 -0
- package/dist/cli/commands/openspec-validate-command.d.ts +3 -0
- package/dist/cli/commands/openspec-validate-command.js +45 -0
- package/dist/cli/commands/playwright-browser-command.d.ts +8 -0
- package/dist/cli/commands/playwright-browser-command.js +61 -0
- package/dist/cli/commands/playwright-commands.d.ts +10 -62
- package/dist/cli/commands/playwright-commands.js +77 -400
- package/dist/cli/commands/playwright-envelope.d.ts +8 -0
- package/dist/cli/commands/playwright-envelope.js +29 -0
- package/dist/cli/commands/playwright-ls-stop-commands.d.ts +4 -0
- package/dist/cli/commands/playwright-ls-stop-commands.js +74 -0
- package/dist/cli/commands/playwright-session-store.d.ts +65 -0
- package/dist/cli/commands/playwright-session-store.js +189 -0
- package/dist/cli/commands/project-commands.d.ts +19 -0
- package/dist/cli/commands/project-commands.js +98 -259
- package/dist/cli/commands/project-context-command.d.ts +3 -0
- package/dist/cli/commands/project-context-command.js +44 -0
- package/dist/cli/commands/project-dashboard-command.d.ts +3 -0
- package/dist/cli/commands/project-dashboard-command.js +74 -0
- package/dist/cli/commands/project-knowledge-command.d.ts +3 -0
- package/dist/cli/commands/project-knowledge-command.js +48 -0
- package/dist/cli/commands/project-memories-show-command.d.ts +3 -0
- package/dist/cli/commands/project-memories-show-command.js +87 -0
- package/dist/cli/commands/project-memory-index-command.d.ts +3 -0
- package/dist/cli/commands/project-memory-index-command.js +31 -0
- package/dist/cli/commands/qa-archive-screenshots-command.d.ts +3 -0
- package/dist/cli/commands/qa-archive-screenshots-command.js +53 -0
- package/dist/cli/commands/qa-commands.d.ts +14 -87
- package/dist/cli/commands/qa-commands.js +17 -315
- package/dist/cli/commands/qa-context-prestep.d.ts +1 -0
- package/dist/cli/commands/qa-context-prestep.js +34 -0
- package/dist/cli/commands/qa-run-command.d.ts +3 -0
- package/dist/cli/commands/qa-run-command.js +105 -0
- package/dist/cli/commands/qa-run-options.d.ts +23 -0
- package/dist/cli/commands/qa-run-options.js +31 -0
- package/dist/cli/commands/qa-run-slice.d.ts +41 -0
- package/dist/cli/commands/qa-run-slice.js +145 -0
- package/dist/cli/commands/release-canary-command.d.ts +28 -0
- package/dist/cli/commands/release-canary-command.js +129 -0
- package/dist/cli/commands/release-command-shared.d.ts +13 -0
- package/dist/cli/commands/release-command-shared.js +18 -0
- package/dist/cli/commands/release-commands.d.ts +10 -18
- package/dist/cli/commands/release-commands.js +25 -298
- package/dist/cli/commands/release-done-command.d.ts +3 -0
- package/dist/cli/commands/release-done-command.js +64 -0
- package/dist/cli/commands/release-hotfix-command.d.ts +3 -0
- package/dist/cli/commands/release-hotfix-command.js +50 -0
- package/dist/cli/commands/release-plan-command.d.ts +3 -0
- package/dist/cli/commands/release-plan-command.js +33 -0
- package/dist/cli/commands/release-precheck-command.d.ts +3 -0
- package/dist/cli/commands/release-precheck-command.js +28 -0
- package/dist/cli/commands/release-promote-command.d.ts +3 -0
- package/dist/cli/commands/release-promote-command.js +34 -0
- package/dist/cli/commands/release-rollback-command.d.ts +3 -0
- package/dist/cli/commands/release-rollback-command.js +33 -0
- package/dist/cli/commands/release-watch-command.d.ts +3 -0
- package/dist/cli/commands/release-watch-command.js +44 -0
- package/dist/cli/commands/sediment-argv-flags.d.ts +54 -0
- package/dist/cli/commands/sediment-argv-flags.js +116 -0
- package/dist/cli/commands/sediment-command-shared.d.ts +15 -0
- package/dist/cli/commands/sediment-command-shared.js +5 -0
- package/dist/cli/commands/sediment-commands.d.ts +35 -59
- package/dist/cli/commands/sediment-commands.js +36 -590
- package/dist/cli/commands/sediment-pool-commands.d.ts +9 -0
- package/dist/cli/commands/sediment-pool-commands.js +185 -0
- package/dist/cli/commands/sediment-query-commands.d.ts +4 -0
- package/dist/cli/commands/sediment-query-commands.js +94 -0
- package/dist/cli/commands/sediment-release-commands.d.ts +8 -0
- package/dist/cli/commands/sediment-release-commands.js +232 -0
- package/dist/cli/commands/sop-advance-command.d.ts +3 -0
- package/dist/cli/commands/sop-advance-command.js +160 -0
- package/dist/cli/commands/sop-check-command.d.ts +3 -0
- package/dist/cli/commands/sop-check-command.js +44 -0
- package/dist/cli/commands/sop-command-shared.d.ts +23 -0
- package/dist/cli/commands/sop-command-shared.js +18 -0
- package/dist/cli/commands/sop-commands.d.ts +15 -1
- package/dist/cli/commands/sop-commands.js +26 -240
- package/dist/cli/commands/sop-init-command.d.ts +3 -0
- package/dist/cli/commands/sop-init-command.js +51 -0
- package/dist/cli/commands/sop-lint-command.d.ts +3 -0
- package/dist/cli/commands/sop-lint-command.js +64 -0
- package/dist/cli/commands/sop-register-command.d.ts +3 -0
- package/dist/cli/commands/sop-register-command.js +48 -0
- package/dist/cli/commands/sop-registry-command.d.ts +3 -0
- package/dist/cli/commands/sop-registry-command.js +30 -0
- package/dist/cli/commands/statusline-command-shared.d.ts +73 -0
- package/dist/cli/commands/statusline-command-shared.js +90 -0
- package/dist/cli/commands/statusline-commands.d.ts +1 -19
- package/dist/cli/commands/statusline-commands.js +48 -287
- package/dist/cli/commands/statusline-compact-command.d.ts +4 -0
- package/dist/cli/commands/statusline-compact-command.js +54 -0
- package/dist/cli/commands/statusline-install-command.d.ts +3 -0
- package/dist/cli/commands/statusline-install-command.js +48 -0
- package/dist/cli/commands/statusline-render-command.d.ts +9 -0
- package/dist/cli/commands/statusline-render-command.js +55 -0
- package/dist/cli/commands/statusline-status-command.d.ts +3 -0
- package/dist/cli/commands/statusline-status-command.js +23 -0
- package/dist/cli/commands/statusline-uninstall-command.d.ts +3 -0
- package/dist/cli/commands/statusline-uninstall-command.js +23 -0
- package/dist/cli/commands/test-command-run-helpers.d.ts +27 -0
- package/dist/cli/commands/test-command-run-helpers.js +73 -0
- package/dist/cli/commands/test-command-runner-resolution.d.ts +57 -0
- package/dist/cli/commands/test-command-runner-resolution.js +183 -0
- package/dist/cli/commands/test-commands.d.ts +8 -56
- package/dist/cli/commands/test-commands.js +26 -249
- package/dist/cli/commands/vm-command-shared.d.ts +23 -0
- package/dist/cli/commands/vm-command-shared.js +23 -0
- package/dist/cli/commands/vm-commands.d.ts +1 -28
- package/dist/cli/commands/vm-commands.js +36 -270
- package/dist/cli/commands/vm-hypervisor-runtime.d.ts +15 -0
- package/dist/cli/commands/vm-hypervisor-runtime.js +64 -0
- package/dist/cli/commands/vm-release-command.d.ts +5 -0
- package/dist/cli/commands/vm-release-command.js +101 -0
- package/dist/cli/commands/vm-spawn-command.d.ts +5 -0
- package/dist/cli/commands/vm-spawn-command.js +177 -0
- package/dist/cli/commands/web-command-shared.d.ts +12 -0
- package/dist/cli/commands/web-command-shared.js +30 -0
- package/dist/cli/commands/web-commands.d.ts +7 -14
- package/dist/cli/commands/web-commands.js +6 -314
- package/dist/cli/commands/web-install-command.d.ts +10 -0
- package/dist/cli/commands/web-install-command.js +116 -0
- package/dist/cli/commands/web-lifecycle-commands.d.ts +9 -30
- package/dist/cli/commands/web-lifecycle-commands.js +14 -322
- package/dist/cli/commands/web-login-command.d.ts +14 -0
- package/dist/cli/commands/web-login-command.js +189 -0
- package/dist/cli/commands/web-op-payload.d.ts +22 -0
- package/dist/cli/commands/web-op-payload.js +89 -0
- package/dist/cli/commands/web-op-refusals.d.ts +37 -0
- package/dist/cli/commands/web-op-refusals.js +73 -0
- package/dist/cli/commands/web-op-runner.d.ts +14 -0
- package/dist/cli/commands/web-op-runner.js +166 -0
- package/dist/cli/commands/web-status-command.d.ts +4 -0
- package/dist/cli/commands/web-status-command.js +32 -0
- package/dist/cli/commands/web-stop-command.d.ts +10 -0
- package/dist/cli/commands/web-stop-command.js +59 -0
- package/dist/cli/commands/web-verb-specs.d.ts +18 -0
- package/dist/cli/commands/web-verb-specs.js +66 -0
- package/dist/cli/commands/workflow-command-shared.d.ts +102 -0
- package/dist/cli/commands/workflow-command-shared.js +74 -0
- package/dist/cli/commands/workflow-graph-commands.d.ts +3 -0
- package/dist/cli/commands/workflow-graph-commands.js +73 -0
- package/dist/cli/commands/workflow-init-command.d.ts +3 -0
- package/dist/cli/commands/workflow-init-command.js +68 -0
- package/dist/cli/commands/workflow-lifecycle-commands.d.ts +9 -59
- package/dist/cli/commands/workflow-lifecycle-commands.js +14 -348
- package/dist/cli/commands/workflow-node-commands.d.ts +3 -0
- package/dist/cli/commands/workflow-node-commands.js +154 -0
- package/dist/cli/commands/workflow-terminalize-command.d.ts +3 -0
- package/dist/cli/commands/workflow-terminalize-command.js +56 -0
- package/dist/services/code/auto-compact-artifacts.d.ts +54 -0
- package/dist/services/code/auto-compact-artifacts.js +135 -0
- package/dist/services/code/auto-compact-attempt.d.ts +46 -0
- package/dist/services/code/auto-compact-attempt.js +88 -0
- package/dist/services/code/auto-compact-decision.d.ts +74 -0
- package/dist/services/code/auto-compact-decision.js +149 -0
- package/dist/services/code/auto-compact-dispatch-gate.d.ts +36 -0
- package/dist/services/code/auto-compact-dispatch-gate.js +86 -0
- package/dist/services/code/auto-compact-envelopes.d.ts +33 -0
- package/dist/services/code/auto-compact-envelopes.js +134 -0
- package/dist/services/code/auto-compact-history.d.ts +46 -0
- package/dist/services/code/auto-compact-history.js +17 -0
- package/dist/services/code/auto-compact-orchestrator.d.ts +11 -240
- package/dist/services/code/auto-compact-orchestrator.js +165 -686
- package/dist/services/code/auto-compact-run-types.d.ts +123 -0
- package/dist/services/code/auto-compact-run-types.js +1 -0
- package/dist/services/code/emit-handoff.d.ts +35 -1
- package/dist/services/code/emit-handoff.js +128 -7
- package/dist/services/code/step-08-gate.d.ts +28 -19
- package/dist/services/code/step-08-gate.js +92 -35
- package/dist/services/config/config-coercion.d.ts +7 -0
- package/dist/services/config/config-coercion.js +156 -0
- package/dist/services/config/config-file-io.d.ts +11 -0
- package/dist/services/config/config-file-io.js +61 -0
- package/dist/services/config/config-get.d.ts +2 -0
- package/dist/services/config/config-get.js +36 -0
- package/dist/services/config/config-global-loader.d.ts +15 -0
- package/dist/services/config/config-global-loader.js +111 -0
- package/dist/services/config/config-nested-path.d.ts +3 -0
- package/dist/services/config/config-nested-path.js +53 -0
- package/dist/services/config/config-primitives.d.ts +16 -0
- package/dist/services/config/config-primitives.js +24 -0
- package/dist/services/config/config-service.d.ts +9 -33
- package/dist/services/config/config-service.js +16 -665
- package/dist/services/config/config-validation.d.ts +19 -0
- package/dist/services/config/config-validation.js +152 -0
- package/dist/services/config/config-workspace.d.ts +10 -0
- package/dist/services/config/config-workspace.js +158 -0
- package/dist/services/skills/hooks-settings-deny-list.d.ts +61 -0
- package/dist/services/skills/hooks-settings-deny-list.js +173 -0
- package/dist/services/skills/hooks-settings-envelopes.d.ts +20 -0
- package/dist/services/skills/hooks-settings-envelopes.js +79 -0
- package/dist/services/skills/hooks-settings-file-shape.d.ts +43 -0
- package/dist/services/skills/hooks-settings-file-shape.js +207 -0
- package/dist/services/skills/hooks-settings-paths.d.ts +34 -0
- package/dist/services/skills/hooks-settings-paths.js +75 -0
- package/dist/services/skills/hooks-settings-read-installed.d.ts +39 -0
- package/dist/services/skills/hooks-settings-read-installed.js +60 -0
- package/dist/services/skills/hooks-settings-service.d.ts +12 -212
- package/dist/services/skills/hooks-settings-service.js +71 -657
- package/dist/services/skills/hooks-settings-types.d.ts +139 -0
- package/dist/services/skills/hooks-settings-types.js +1 -0
- package/dist/services/workspace/claude-settings-template-merge.d.ts +89 -0
- package/dist/services/workspace/claude-settings-template-merge.js +243 -0
- package/dist/services/workspace/claude-settings-template.d.ts +29 -87
- package/dist/services/workspace/claude-settings-template.js +81 -236
- package/package.json +5 -5
|
@@ -1,199 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { dirname } from 'node:path';
|
|
2
|
+
import { DEFAULT_CONFIG } from './config-types.js';
|
|
3
|
+
import { findProjectRoot, getProjectBootstrapConfigPath, getUserConfigPath, validateProjectBootstrapConfigPathForWrite, validateUserConfigPathForWrite, writeProjectConfigFile, writeUserConfigFile } from './config-safety.js';
|
|
4
|
+
import { getNestedPathParts, getNestedValue, setNestedValue } from './config-nested-path.js';
|
|
5
|
+
import { isRecord, omitProxy } from './config-primitives.js';
|
|
6
|
+
import { inferHumanLanguage, toModelProviderConfig, toPeaksConfig, toProviderModelConfig, toWorkspaceConfigs } from './config-coercion.js';
|
|
7
|
+
import { containsSensitiveConfigValue, getProxyUrlCandidate, isLegacyConfigKey, isProviderBaseUrlPath, isProviderConfigPath, isProxyConfigPath, isSensitiveConfigPath, redactConfigSecrets, validateModelProviderConfig, validateProviderBaseUrl, validateProviderConfig, validateProxyUrl, validateProxyConfig } from './config-validation.js';
|
|
8
|
+
import { ensureDir, getProjectWriteTarget, readExistingJsonFile, readJsonFile, readProjectJsonFile, readUserJsonFile, removeProjectSensitiveConfig } from './config-file-io.js';
|
|
8
9
|
// Re-export resolveProjectRootForConfig and resolveCanonicalProjectRoot for external consumers
|
|
9
10
|
export { resolveProjectRootForConfig, resolveCanonicalProjectRoot } from './config-safety.js';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* schema version — the caller is expected to run
|
|
17
|
-
* `peaks config migrate --apply` to bring it forward before
|
|
18
|
-
* continuing. This gate is intentional: a slim 2.0 reader must
|
|
19
|
-
* not silently pass through a 1.x shape, because every field it
|
|
20
|
-
* ignores is a field the caller is going to look for elsewhere
|
|
21
|
-
* (preferences.json, .bak, _state/).
|
|
22
|
-
*/
|
|
23
|
-
export function loadGlobalConfig() {
|
|
24
|
-
const path = globalConfigPath();
|
|
25
|
-
if (!existsSync(path))
|
|
26
|
-
return null;
|
|
27
|
-
const content = readConfigFileSafely(path, 'Global config path must stay inside the user root');
|
|
28
|
-
const raw = JSON.parse(content);
|
|
29
|
-
if (isConfigV2(raw)) {
|
|
30
|
-
if (hasLegacyGlobalFields(raw)) {
|
|
31
|
-
promoteLegacyGlobalFieldsToSidecars(raw);
|
|
32
|
-
rewriteSlimGlobalConfig();
|
|
33
|
-
}
|
|
34
|
-
return readSlimGlobalConfig();
|
|
35
|
-
}
|
|
36
|
-
const detected = typeof raw.version === 'string' ? raw.version : 'unknown';
|
|
37
|
-
throw new Error(`CONFIG_LEGACY_VERSION: ~/.peaks/config.json is at version "${detected}", expected ${CONFIG_SCHEMA_VERSION_V2}. Run \`peaks config migrate --apply\`.`);
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Slim 2.0 schema allows `version` + `ocr`. Any other top-level
|
|
41
|
-
* field is a legacy artifact that needs to be promoted to a
|
|
42
|
-
* sidecar file.
|
|
43
|
-
*/
|
|
44
|
-
function hasLegacyGlobalFields(raw) {
|
|
45
|
-
const allowed = new Set(['version', 'ocr']);
|
|
46
|
-
return Object.keys(raw).some((k) => !allowed.has(k));
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* One-shot promotion of legacy fields into their dedicated sidecar
|
|
50
|
-
* files. Idempotent: if the sidecar already has the field, the
|
|
51
|
-
* legacy value is dropped (sidecar is the new source of truth).
|
|
52
|
-
*/
|
|
53
|
-
function promoteLegacyGlobalFieldsToSidecars(raw) {
|
|
54
|
-
if (isRecord(raw.providers)) {
|
|
55
|
-
const existing = readSidecarJson(providersConfigPath(), {
|
|
56
|
-
version: SIDECAR_SCHEMA_VERSION,
|
|
57
|
-
providers: {}
|
|
58
|
-
});
|
|
59
|
-
const mergedProviders = {
|
|
60
|
-
...(existing.providers ?? {}),
|
|
61
|
-
...raw.providers
|
|
62
|
-
};
|
|
63
|
-
writeSidecarJson(providersConfigPath(), {
|
|
64
|
-
version: SIDECAR_SCHEMA_VERSION,
|
|
65
|
-
providers: mergedProviders
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
if (isRecord(raw.proxy) && typeof raw.proxy.httpProxy === 'string') {
|
|
69
|
-
const httpProxy = raw.proxy.httpProxy;
|
|
70
|
-
if (!sidecarExists(proxyConfigPath())) {
|
|
71
|
-
writeSidecarJson(proxyConfigPath(), { version: SIDECAR_SCHEMA_VERSION, httpProxy });
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if (Array.isArray(raw.workspaces) || typeof raw.currentWorkspace === 'string') {
|
|
75
|
-
if (!sidecarExists(workspacesConfigPath())) {
|
|
76
|
-
writeSidecarJson(workspacesConfigPath(), {
|
|
77
|
-
version: SIDECAR_SCHEMA_VERSION,
|
|
78
|
-
workspaces: Array.isArray(raw.workspaces) ? raw.workspaces : [],
|
|
79
|
-
currentWorkspace: typeof raw.currentWorkspace === 'string' ? raw.currentWorkspace : null
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
function readSlimGlobalConfig() {
|
|
85
|
-
const path = globalConfigPath();
|
|
86
|
-
if (!existsSync(path)) {
|
|
87
|
-
return { version: CONFIG_SCHEMA_VERSION_V2 };
|
|
88
|
-
}
|
|
89
|
-
const content = readConfigFileSafely(path, 'Global config path must stay inside the user root');
|
|
90
|
-
return JSON.parse(content);
|
|
91
|
-
}
|
|
92
|
-
function rewriteSlimGlobalConfig() {
|
|
93
|
-
const path = globalConfigPath();
|
|
94
|
-
const ocr = readOcrFromRawConfigFile();
|
|
95
|
-
const slim = { version: CONFIG_SCHEMA_VERSION_V2 };
|
|
96
|
-
if (ocr !== null)
|
|
97
|
-
slim['ocr'] = ocr;
|
|
98
|
-
writeUserConfigFile(path, JSON.stringify(slim, null, 2) + '\n');
|
|
99
|
-
}
|
|
100
|
-
function readOcrFromRawConfigFile() {
|
|
101
|
-
const path = globalConfigPath();
|
|
102
|
-
if (!existsSync(path))
|
|
103
|
-
return null;
|
|
104
|
-
const content = readConfigFileSafely(path, 'Global config path must stay inside the user root');
|
|
105
|
-
const raw = JSON.parse(content);
|
|
106
|
-
return isRecord(raw.ocr) ? raw.ocr : null;
|
|
107
|
-
}
|
|
108
|
-
function readJsonFile(path, validateBeforeRead, errorMessage = 'Config path must stay inside the config root') {
|
|
109
|
-
if (!path || !existsSync(path))
|
|
110
|
-
return null;
|
|
111
|
-
validateBeforeRead?.();
|
|
112
|
-
const content = readConfigFileSafely(path, errorMessage);
|
|
113
|
-
try {
|
|
114
|
-
return JSON.parse(content);
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
// TODO(g2): legacy silent catch — grace: 1 minor release (v2.14.0)
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
function readExistingJsonFile(path, errorMessage, validateBeforeRead) {
|
|
122
|
-
if (!existsSync(path))
|
|
123
|
-
return null;
|
|
124
|
-
validateBeforeRead?.();
|
|
125
|
-
try {
|
|
126
|
-
return JSON.parse(readConfigFileSafely(path, errorMessage));
|
|
127
|
-
}
|
|
128
|
-
catch {
|
|
129
|
-
throw new Error(errorMessage);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
function readUserJsonFile() {
|
|
133
|
-
const userPath = getUserConfigPath();
|
|
134
|
-
return readJsonFile(userPath, () => validateUserConfigPathForWrite(userPath), 'User config path must stay inside the user root');
|
|
135
|
-
}
|
|
136
|
-
function readProjectJsonFile(projectRoot) {
|
|
137
|
-
const projectPath = getProjectConfigPath(projectRoot);
|
|
138
|
-
return readJsonFile(projectPath, projectRoot && projectPath
|
|
139
|
-
? () => validateProjectBootstrapConfigPathForWrite(projectRoot, projectPath)
|
|
140
|
-
: undefined, 'Project config path must stay inside the project root');
|
|
141
|
-
}
|
|
142
|
-
function ensureDir(dirPath) {
|
|
143
|
-
if (!existsSync(dirPath)) {
|
|
144
|
-
mkdirSync(dirPath, { recursive: true });
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
const UNSAFE_NESTED_PATH_SEGMENTS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
148
|
-
function getNestedPathParts(path) {
|
|
149
|
-
return path
|
|
150
|
-
.replace(/\[(\d+)\]/g, '.$1')
|
|
151
|
-
.split('.')
|
|
152
|
-
.filter(Boolean);
|
|
153
|
-
}
|
|
154
|
-
function hasUnsafeNestedPathSegment(parts) {
|
|
155
|
-
return parts.some((part) => UNSAFE_NESTED_PATH_SEGMENTS.has(part));
|
|
156
|
-
}
|
|
157
|
-
function getNestedValue(obj, path) {
|
|
158
|
-
const parts = getNestedPathParts(path);
|
|
159
|
-
if (parts.length === 0 || hasUnsafeNestedPathSegment(parts)) {
|
|
160
|
-
return undefined;
|
|
161
|
-
}
|
|
162
|
-
let current = obj;
|
|
163
|
-
for (const part of parts) {
|
|
164
|
-
if (current === null ||
|
|
165
|
-
current === undefined ||
|
|
166
|
-
typeof current !== 'object' ||
|
|
167
|
-
!Object.prototype.hasOwnProperty.call(current, part)) {
|
|
168
|
-
return undefined;
|
|
169
|
-
}
|
|
170
|
-
current = current[part];
|
|
171
|
-
}
|
|
172
|
-
return current;
|
|
173
|
-
}
|
|
174
|
-
function setNestedValue(obj, path, value) {
|
|
175
|
-
const parts = getNestedPathParts(path);
|
|
176
|
-
if (parts.length === 0 || hasUnsafeNestedPathSegment(parts)) {
|
|
177
|
-
throw new Error('Unsafe config path');
|
|
178
|
-
}
|
|
179
|
-
let current = obj;
|
|
180
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
181
|
-
const part = parts[i];
|
|
182
|
-
if (!Object.prototype.hasOwnProperty.call(current, part) ||
|
|
183
|
-
typeof current[part] !== 'object' ||
|
|
184
|
-
current[part] === null ||
|
|
185
|
-
Array.isArray(current[part])) {
|
|
186
|
-
current[part] = {};
|
|
187
|
-
}
|
|
188
|
-
current = current[part];
|
|
189
|
-
}
|
|
190
|
-
const last = parts[parts.length - 1];
|
|
191
|
-
current[last] = value;
|
|
192
|
-
}
|
|
193
|
-
function removeProjectSensitiveConfig(config) {
|
|
194
|
-
const { providers, proxy, tokens, ...safeConfig } = config;
|
|
195
|
-
return Object.fromEntries(Object.entries(safeConfig).filter(([key, value]) => !isSecretKey(key) && !containsSensitiveConfigValue(value)));
|
|
196
|
-
}
|
|
11
|
+
// Every name below moved into a sibling module for the file-size cap; the
|
|
12
|
+
// declarations are unchanged, so importers of this path are unaffected.
|
|
13
|
+
export { getConfig } from './config-get.js';
|
|
14
|
+
export { loadGlobalConfig } from './config-global-loader.js';
|
|
15
|
+
export { addWorkspace, ensureWorkspaceConfigForCurrentPath, ensureWorkspaceConfigForPath, getCurrentWorkspaceConfig, getWorkspaceConfig, getWorkspaceConfigForCurrentPath, getWorkspaceConfigForPath, removeWorkspace, setCurrentWorkspace } from './config-workspace.js';
|
|
16
|
+
export { containsSensitiveConfigValue, isLegacyConfigKey, isSensitiveConfigPath, redactConfigSecrets };
|
|
197
17
|
export function isConfigLayer(value) {
|
|
198
18
|
return value === 'user' || value === 'project';
|
|
199
19
|
}
|
|
@@ -231,311 +51,6 @@ export function readContextWindowTokensOverride(projectRoot) {
|
|
|
231
51
|
return undefined;
|
|
232
52
|
}
|
|
233
53
|
}
|
|
234
|
-
export function isSensitiveConfigPath(path) {
|
|
235
|
-
const normalized = path.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
236
|
-
return (normalized.includes('apikey') ||
|
|
237
|
-
normalized.includes('accesskey') ||
|
|
238
|
-
normalized.includes('privatekey') ||
|
|
239
|
-
normalized.includes('token') ||
|
|
240
|
-
normalized.includes('secret') ||
|
|
241
|
-
normalized.includes('password') ||
|
|
242
|
-
normalized.includes('bearer') ||
|
|
243
|
-
normalized.includes('credential') ||
|
|
244
|
-
normalized.includes('auth'));
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* 2.0.1 slim-config contract: `~/.peaks/config.json` only stores
|
|
248
|
-
* `version` + `ocr.llm.*` placeholders. The 1.x → 2.0 migration
|
|
249
|
-
* moved per-project fields (`language`, `model`, `economyMode`,
|
|
250
|
-
* `swarmMode`) to `<project>/.peaks/preferences.json` (per spec
|
|
251
|
-
* §10.4). `setConfig` rejects writes to those keys and points the
|
|
252
|
-
* user to the preferences path; tokens / providers / proxy still
|
|
253
|
-
* live in `~/.peaks/config.json` (the loader is tolerant of them
|
|
254
|
-
* but does not synthesise defaults for them anymore).
|
|
255
|
-
*/
|
|
256
|
-
const LEGACY_CONFIG_KEYS = new Set([
|
|
257
|
-
'language',
|
|
258
|
-
'model',
|
|
259
|
-
'economyMode',
|
|
260
|
-
'swarmMode'
|
|
261
|
-
]);
|
|
262
|
-
export function isLegacyConfigKey(path) {
|
|
263
|
-
const topLevel = path.split(/[.[].*/, 1)[0] ?? '';
|
|
264
|
-
return LEGACY_CONFIG_KEYS.has(topLevel);
|
|
265
|
-
}
|
|
266
|
-
function isProviderConfigPath(path) {
|
|
267
|
-
return path === 'providers' || path.startsWith('providers.');
|
|
268
|
-
}
|
|
269
|
-
function isSecretKey(key) {
|
|
270
|
-
return isSensitiveConfigPath(key);
|
|
271
|
-
}
|
|
272
|
-
function sanitizeBaseUrlForDisplay(value) {
|
|
273
|
-
try {
|
|
274
|
-
const url = new URL(value);
|
|
275
|
-
url.username = '';
|
|
276
|
-
url.password = '';
|
|
277
|
-
url.search = '';
|
|
278
|
-
url.hash = '';
|
|
279
|
-
return url.toString();
|
|
280
|
-
}
|
|
281
|
-
catch {
|
|
282
|
-
return '[invalid-url-redacted]';
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
function isProviderBaseUrlPath(path) {
|
|
286
|
-
return /^providers\.[^.]+\.baseUrl$/.test(path);
|
|
287
|
-
}
|
|
288
|
-
function isValidProviderBaseUrl(value) {
|
|
289
|
-
try {
|
|
290
|
-
const url = new URL(value);
|
|
291
|
-
return (url.protocol === 'https:' &&
|
|
292
|
-
url.username.length === 0 &&
|
|
293
|
-
url.password.length === 0 &&
|
|
294
|
-
url.search.length === 0 &&
|
|
295
|
-
url.hash.length === 0);
|
|
296
|
-
}
|
|
297
|
-
catch {
|
|
298
|
-
return false;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
function validateProviderBaseUrl(value) {
|
|
302
|
-
if (value !== undefined && (typeof value !== 'string' || !isValidProviderBaseUrl(value))) {
|
|
303
|
-
throw new Error('Provider base URL must be HTTPS without embedded credentials, query, or fragment');
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
function getProxyUrlCandidate(key, value) {
|
|
307
|
-
if (key === 'proxy.httpProxy') {
|
|
308
|
-
return value;
|
|
309
|
-
}
|
|
310
|
-
if (key === 'proxy' && isRecord(value)) {
|
|
311
|
-
return value.httpProxy;
|
|
312
|
-
}
|
|
313
|
-
return undefined;
|
|
314
|
-
}
|
|
315
|
-
function isProxyConfigPath(path) {
|
|
316
|
-
return path === 'proxy' || path.startsWith('proxy.');
|
|
317
|
-
}
|
|
318
|
-
function validateModelProviderConfig(providers) {
|
|
319
|
-
for (const [providerId, provider] of Object.entries(providers)) {
|
|
320
|
-
validateProviderBaseUrl(provider?.baseUrl);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
function validateProviderConfig(partial) {
|
|
324
|
-
validateModelProviderConfig(partial.providers ?? {});
|
|
325
|
-
}
|
|
326
|
-
function isValidProxyUrl(value) {
|
|
327
|
-
try {
|
|
328
|
-
const url = new URL(value);
|
|
329
|
-
return ((url.protocol === 'http:' || url.protocol === 'https:') &&
|
|
330
|
-
url.username.length === 0 &&
|
|
331
|
-
url.password.length === 0 &&
|
|
332
|
-
url.pathname === '/' &&
|
|
333
|
-
url.search.length === 0 &&
|
|
334
|
-
url.hash.length === 0);
|
|
335
|
-
}
|
|
336
|
-
catch {
|
|
337
|
-
return false;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
function validateProxyUrl(value) {
|
|
341
|
-
if (value !== undefined && (typeof value !== 'string' || !isValidProxyUrl(value))) {
|
|
342
|
-
throw new Error('Proxy URL must be an HTTP or HTTPS URL without embedded credentials');
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
function validateProxyConfig(partial) {
|
|
346
|
-
validateProxyUrl(partial.proxy?.httpProxy);
|
|
347
|
-
}
|
|
348
|
-
function isRecord(value) {
|
|
349
|
-
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
350
|
-
}
|
|
351
|
-
function isSafeConfigSegment(value) {
|
|
352
|
-
return (/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(value) && !value.includes('..') && !value.endsWith('.'));
|
|
353
|
-
}
|
|
354
|
-
function toArtifactRemoteRepoConfig(value) {
|
|
355
|
-
if (!isRecord(value) ||
|
|
356
|
-
(value.provider !== 'github' && value.provider !== 'gitlab') ||
|
|
357
|
-
typeof value.owner !== 'string' ||
|
|
358
|
-
typeof value.name !== 'string') {
|
|
359
|
-
return null;
|
|
360
|
-
}
|
|
361
|
-
if (!isSafeConfigSegment(value.owner) || !isSafeConfigSegment(value.name)) {
|
|
362
|
-
return null;
|
|
363
|
-
}
|
|
364
|
-
return { provider: value.provider, owner: value.owner, name: value.name };
|
|
365
|
-
}
|
|
366
|
-
function toArtifactStorageConfig(value) {
|
|
367
|
-
if (!isRecord(value))
|
|
368
|
-
return null;
|
|
369
|
-
const localPath = typeof value.localPath === 'string' ? { localPath: value.localPath } : {};
|
|
370
|
-
if (value.mode === 'local') {
|
|
371
|
-
return { mode: 'local', ...localPath };
|
|
372
|
-
}
|
|
373
|
-
const remote = toArtifactRemoteRepoConfig(value.remote);
|
|
374
|
-
if (value.mode === 'local-with-remote-sync' && remote) {
|
|
375
|
-
return { mode: 'local-with-remote-sync', ...localPath, remote };
|
|
376
|
-
}
|
|
377
|
-
return null;
|
|
378
|
-
}
|
|
379
|
-
function toWorkspaceConfig(value) {
|
|
380
|
-
if (!isRecord(value))
|
|
381
|
-
return null;
|
|
382
|
-
const { workspaceId, name, rootPath, installedCapabilityIds } = value;
|
|
383
|
-
if (typeof workspaceId !== 'string' ||
|
|
384
|
-
!isSafeConfigSegment(workspaceId) ||
|
|
385
|
-
typeof name !== 'string' ||
|
|
386
|
-
typeof rootPath !== 'string' ||
|
|
387
|
-
!Array.isArray(installedCapabilityIds) ||
|
|
388
|
-
!installedCapabilityIds.every((id) => typeof id === 'string')) {
|
|
389
|
-
return null;
|
|
390
|
-
}
|
|
391
|
-
const artifactRepo = toArtifactRemoteRepoConfig(value.artifactRepo);
|
|
392
|
-
const artifactStorage = toArtifactStorageConfig(value.artifactStorage);
|
|
393
|
-
return {
|
|
394
|
-
workspaceId,
|
|
395
|
-
name,
|
|
396
|
-
rootPath,
|
|
397
|
-
installedCapabilityIds,
|
|
398
|
-
...(artifactRepo ? { artifactRepo } : {}),
|
|
399
|
-
...(artifactStorage ? { artifactStorage } : {})
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
function toWorkspaceConfigs(value) {
|
|
403
|
-
return Array.isArray(value)
|
|
404
|
-
? value
|
|
405
|
-
.map(toWorkspaceConfig)
|
|
406
|
-
.filter((workspace) => workspace !== null)
|
|
407
|
-
: [];
|
|
408
|
-
}
|
|
409
|
-
function toProviderModelConfig(value) {
|
|
410
|
-
if (!isRecord(value))
|
|
411
|
-
return {};
|
|
412
|
-
return {
|
|
413
|
-
...(typeof value.model === 'string' && value.model.trim().length > 0
|
|
414
|
-
? { model: value.model.trim() }
|
|
415
|
-
: {}),
|
|
416
|
-
...(typeof value.baseUrl === 'string' ? { baseUrl: value.baseUrl } : {}),
|
|
417
|
-
...(typeof value.apiKey === 'string' ? { apiKey: value.apiKey } : {})
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
const TOKEN_CONFIG_KEYS = new Set([
|
|
421
|
-
'AnthropicApiKey',
|
|
422
|
-
'OpenAiApiKey',
|
|
423
|
-
'GitHubToken',
|
|
424
|
-
'GitLabToken'
|
|
425
|
-
]);
|
|
426
|
-
function toTokenRef(value) {
|
|
427
|
-
if (!isRecord(value))
|
|
428
|
-
return null;
|
|
429
|
-
const env = typeof value.env === 'string' ? value.env.trim() : '';
|
|
430
|
-
const keychain = typeof value.keychain === 'string' ? value.keychain.trim() : '';
|
|
431
|
-
if (env.length > 0) {
|
|
432
|
-
return { env };
|
|
433
|
-
}
|
|
434
|
-
if (keychain.length > 0) {
|
|
435
|
-
return { keychain };
|
|
436
|
-
}
|
|
437
|
-
if (value.ghCli === true) {
|
|
438
|
-
return { ghCli: true };
|
|
439
|
-
}
|
|
440
|
-
return null;
|
|
441
|
-
}
|
|
442
|
-
function toTokenConfig(value) {
|
|
443
|
-
if (!isRecord(value))
|
|
444
|
-
return {};
|
|
445
|
-
const tokens = {};
|
|
446
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
447
|
-
if (!TOKEN_CONFIG_KEYS.has(key))
|
|
448
|
-
continue;
|
|
449
|
-
const tokenRef = toTokenRef(entry);
|
|
450
|
-
if (tokenRef) {
|
|
451
|
-
tokens[key] = tokenRef;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
return tokens;
|
|
455
|
-
}
|
|
456
|
-
function toModelProviderConfig(value) {
|
|
457
|
-
if (!isRecord(value))
|
|
458
|
-
return {};
|
|
459
|
-
return Object.fromEntries(Object.entries(value).map(([providerId, providerConfig]) => [
|
|
460
|
-
providerId,
|
|
461
|
-
toProviderModelConfig(providerConfig)
|
|
462
|
-
]));
|
|
463
|
-
}
|
|
464
|
-
function toProxyConfig(value) {
|
|
465
|
-
if (!isRecord(value))
|
|
466
|
-
return null;
|
|
467
|
-
return typeof value.httpProxy === 'string' && isValidProxyUrl(value.httpProxy)
|
|
468
|
-
? { httpProxy: value.httpProxy }
|
|
469
|
-
: null;
|
|
470
|
-
}
|
|
471
|
-
function getProjectWriteTarget() {
|
|
472
|
-
const projectRoot = findProjectRoot(process.cwd());
|
|
473
|
-
const configPath = getProjectConfigPath(projectRoot);
|
|
474
|
-
if (!projectRoot || !configPath) {
|
|
475
|
-
throw new Error('Project config not found');
|
|
476
|
-
}
|
|
477
|
-
return { projectRoot, configPath };
|
|
478
|
-
}
|
|
479
|
-
export function containsSensitiveConfigValue(value) {
|
|
480
|
-
if (Array.isArray(value)) {
|
|
481
|
-
return value.some(containsSensitiveConfigValue);
|
|
482
|
-
}
|
|
483
|
-
if (value === null || typeof value !== 'object') {
|
|
484
|
-
return false;
|
|
485
|
-
}
|
|
486
|
-
return Object.entries(value).some(([key, entry]) => isSecretKey(key) || containsSensitiveConfigValue(entry));
|
|
487
|
-
}
|
|
488
|
-
export function redactConfigSecrets(value, path = '') {
|
|
489
|
-
if (Array.isArray(value)) {
|
|
490
|
-
return value.map((item, index) => redactConfigSecrets(item, `${path}[${index}]`));
|
|
491
|
-
}
|
|
492
|
-
if (value === null || typeof value !== 'object') {
|
|
493
|
-
if (isProviderBaseUrlPath(path) && typeof value === 'string') {
|
|
494
|
-
return sanitizeBaseUrlForDisplay(value);
|
|
495
|
-
}
|
|
496
|
-
return value;
|
|
497
|
-
}
|
|
498
|
-
return Object.fromEntries(Object.entries(value).map(([key, entry]) => {
|
|
499
|
-
const nextPath = path ? `${path}.${key}` : key;
|
|
500
|
-
if (isSecretKey(key)) {
|
|
501
|
-
return [key, '***'];
|
|
502
|
-
}
|
|
503
|
-
if (isProviderBaseUrlPath(nextPath) && typeof entry === 'string') {
|
|
504
|
-
return [key, sanitizeBaseUrlForDisplay(entry)];
|
|
505
|
-
}
|
|
506
|
-
return [key, redactConfigSecrets(entry, nextPath)];
|
|
507
|
-
}));
|
|
508
|
-
}
|
|
509
|
-
function inferHumanLanguage(value) {
|
|
510
|
-
const normalized = value.trim();
|
|
511
|
-
if (!normalized) {
|
|
512
|
-
throw new Error('Language must be non-empty');
|
|
513
|
-
}
|
|
514
|
-
if (/^zh(?:-|$)/i.test(normalized) || /[㐀-鿿]/u.test(normalized)) {
|
|
515
|
-
return 'zh-CN';
|
|
516
|
-
}
|
|
517
|
-
if (/^en(?:-|$)/i.test(normalized)) {
|
|
518
|
-
return 'en';
|
|
519
|
-
}
|
|
520
|
-
return 'en';
|
|
521
|
-
}
|
|
522
|
-
function toPeaksConfig(value) {
|
|
523
|
-
if (!isRecord(value))
|
|
524
|
-
return {};
|
|
525
|
-
const proxy = toProxyConfig(value.proxy);
|
|
526
|
-
return {
|
|
527
|
-
...(typeof value.version === 'string' ? { version: value.version } : {}),
|
|
528
|
-
...(typeof value.language === 'string' ? { language: value.language } : {}),
|
|
529
|
-
...(typeof value.model === 'string' && ['haiku', 'sonnet', 'opus'].includes(value.model)
|
|
530
|
-
? { model: value.model }
|
|
531
|
-
: {}),
|
|
532
|
-
...(typeof value.economyMode === 'boolean' ? { economyMode: value.economyMode } : {}),
|
|
533
|
-
...(typeof value.swarmMode === 'boolean' ? { swarmMode: value.swarmMode } : {}),
|
|
534
|
-
...(isRecord(value.tokens) ? { tokens: toTokenConfig(value.tokens) } : {}),
|
|
535
|
-
...(isRecord(value.providers) ? { providers: toModelProviderConfig(value.providers) } : {}),
|
|
536
|
-
...(proxy ? { proxy } : {})
|
|
537
|
-
};
|
|
538
|
-
}
|
|
539
54
|
export function bootstrapProjectLanguageConfig(projectRoot, language) {
|
|
540
55
|
const inferredLanguage = inferHumanLanguage(language);
|
|
541
56
|
const projectPath = getProjectBootstrapConfigPath(projectRoot);
|
|
@@ -549,7 +64,7 @@ export function readConfig(projectRoot) {
|
|
|
549
64
|
const detectedRoot = projectRoot ?? findProjectRoot(process.cwd());
|
|
550
65
|
const userConfig = toPeaksConfig(readUserJsonFile());
|
|
551
66
|
const projectConfig = removeProjectSensitiveConfig(toPeaksConfig(readProjectJsonFile(detectedRoot)));
|
|
552
|
-
const
|
|
67
|
+
const projectConfigWithoutProxy = omitProxy(projectConfig);
|
|
553
68
|
return {
|
|
554
69
|
...DEFAULT_CONFIG,
|
|
555
70
|
...userConfig,
|
|
@@ -594,30 +109,6 @@ export function writeConfig(partial, layer = 'user') {
|
|
|
594
109
|
const merged = sanitizeWorkspacePartial({ ...existing, ...partial });
|
|
595
110
|
writeUserConfigFile(userPath, JSON.stringify(merged, null, 2));
|
|
596
111
|
}
|
|
597
|
-
export function getConfig(options = {}) {
|
|
598
|
-
const projectRoot = findProjectRoot(process.cwd());
|
|
599
|
-
const userConfig = readUserJsonFile() ?? {};
|
|
600
|
-
const projectConfig = removeProjectSensitiveConfig(readProjectJsonFile(projectRoot) ?? {});
|
|
601
|
-
const { proxy: projectProxy, ...projectConfigWithoutProxy } = projectConfig;
|
|
602
|
-
const source = options.layer === 'user'
|
|
603
|
-
? userConfig
|
|
604
|
-
: options.layer === 'project'
|
|
605
|
-
? projectConfig
|
|
606
|
-
: {
|
|
607
|
-
...userConfig,
|
|
608
|
-
...projectConfigWithoutProxy
|
|
609
|
-
};
|
|
610
|
-
const config = isRecord(source)
|
|
611
|
-
? {
|
|
612
|
-
...source,
|
|
613
|
-
...(source.tokens !== undefined ? { tokens: toTokenConfig(source.tokens) } : {})
|
|
614
|
-
}
|
|
615
|
-
: source;
|
|
616
|
-
if (options.key !== undefined) {
|
|
617
|
-
return getNestedValue(config, options.key);
|
|
618
|
-
}
|
|
619
|
-
return config;
|
|
620
|
-
}
|
|
621
112
|
export function setConfig(options) {
|
|
622
113
|
const layer = options.layer ?? 'user';
|
|
623
114
|
if (!isConfigLayer(layer)) {
|
|
@@ -663,145 +154,5 @@ export function setConfig(options) {
|
|
|
663
154
|
writeUserConfigFile(targetPath, content);
|
|
664
155
|
}
|
|
665
156
|
}
|
|
666
|
-
|
|
667
|
-
const config = getConfig({ layer });
|
|
668
|
-
return isRecord(config)
|
|
669
|
-
? {
|
|
670
|
-
currentWorkspace: typeof config.currentWorkspace === 'string' ? config.currentWorkspace : null,
|
|
671
|
-
workspaces: toWorkspaceConfigs(config.workspaces)
|
|
672
|
-
}
|
|
673
|
-
: { currentWorkspace: null, workspaces: [] };
|
|
674
|
-
}
|
|
675
|
-
function writeRawWorkspaceData(data, layer) {
|
|
676
|
-
const projectTarget = layer === 'project' ? getProjectWriteTarget() : null;
|
|
677
|
-
const targetPath = projectTarget?.configPath ?? getUserConfigPath();
|
|
678
|
-
ensureDir(dirname(targetPath));
|
|
679
|
-
const existing = projectTarget
|
|
680
|
-
? (readJsonFile(targetPath, () => validateProjectBootstrapConfigPathForWrite(projectTarget.projectRoot, targetPath)) ?? {})
|
|
681
|
-
: (readJsonFile(targetPath, () => validateUserConfigPathForWrite(targetPath)) ?? {});
|
|
682
|
-
const merged = { ...existing, ...data };
|
|
683
|
-
const content = JSON.stringify(merged, null, 2);
|
|
684
|
-
if (projectTarget) {
|
|
685
|
-
writeProjectConfigFile(projectTarget.projectRoot, targetPath, content);
|
|
686
|
-
}
|
|
687
|
-
else {
|
|
688
|
-
writeUserConfigFile(targetPath, content);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
function readAllWorkspaces() {
|
|
692
|
-
const userData = readRawWorkspaceData('user');
|
|
693
|
-
const projectData = readRawWorkspaceData('project');
|
|
694
|
-
const mergedWorkspaces = new Map();
|
|
695
|
-
for (const w of userData.workspaces)
|
|
696
|
-
mergedWorkspaces.set(w.workspaceId, w);
|
|
697
|
-
for (const w of projectData.workspaces)
|
|
698
|
-
mergedWorkspaces.set(w.workspaceId, w);
|
|
699
|
-
return {
|
|
700
|
-
currentWorkspace: projectData.currentWorkspace ?? userData.currentWorkspace,
|
|
701
|
-
workspaces: [...mergedWorkspaces.values()]
|
|
702
|
-
};
|
|
703
|
-
}
|
|
704
|
-
export function getWorkspaceConfig(workspaceId, _projectRoot) {
|
|
705
|
-
const { workspaces } = readAllWorkspaces();
|
|
706
|
-
return workspaces.find((w) => w.workspaceId === workspaceId) ?? null;
|
|
707
|
-
}
|
|
708
|
-
function readLayerConfig(layer) {
|
|
709
|
-
return readRawWorkspaceData(layer);
|
|
710
|
-
}
|
|
711
|
-
export function addWorkspace(workspace, layer = 'user') {
|
|
712
|
-
if (!isSafeConfigSegment(workspace.workspaceId)) {
|
|
713
|
-
throw new Error('Workspace id must only contain letters, numbers, dots, underscores, or hyphens and must not contain path traversal');
|
|
714
|
-
}
|
|
715
|
-
const config = readRawWorkspaceData(layer);
|
|
716
|
-
const workspaces = config.workspaces;
|
|
717
|
-
const existing = workspaces.findIndex((w) => w.workspaceId === workspace.workspaceId);
|
|
718
|
-
const updatedWorkspaces = existing >= 0
|
|
719
|
-
? workspaces.map((existingWorkspace) => existingWorkspace.workspaceId === workspace.workspaceId ? workspace : existingWorkspace)
|
|
720
|
-
: [...workspaces, workspace];
|
|
721
|
-
writeRawWorkspaceData({ workspaces: updatedWorkspaces }, layer);
|
|
722
|
-
}
|
|
723
|
-
export function removeWorkspace(workspaceId, layer = 'user') {
|
|
724
|
-
if (!isSafeConfigSegment(workspaceId))
|
|
725
|
-
return false;
|
|
726
|
-
const config = readRawWorkspaceData(layer);
|
|
727
|
-
const workspaces = config.workspaces;
|
|
728
|
-
const idx = workspaces.findIndex((w) => w.workspaceId === workspaceId);
|
|
729
|
-
if (idx < 0)
|
|
730
|
-
return false;
|
|
731
|
-
const updatedWorkspaces = workspaces.filter((w) => w.workspaceId !== workspaceId);
|
|
732
|
-
const currentWorkspace = config.currentWorkspace === workspaceId
|
|
733
|
-
? (updatedWorkspaces[0]?.workspaceId ?? null)
|
|
734
|
-
: (config.currentWorkspace ?? null);
|
|
735
|
-
writeRawWorkspaceData({ workspaces: updatedWorkspaces, currentWorkspace }, layer);
|
|
736
|
-
return true;
|
|
737
|
-
}
|
|
738
|
-
export function setCurrentWorkspace(workspaceId, layer = 'user') {
|
|
739
|
-
if (!isSafeConfigSegment(workspaceId))
|
|
740
|
-
return false;
|
|
741
|
-
const config = readRawWorkspaceData(layer);
|
|
742
|
-
const workspaces = config.workspaces;
|
|
743
|
-
const exists = workspaces.some((w) => w.workspaceId === workspaceId);
|
|
744
|
-
if (!exists)
|
|
745
|
-
return false;
|
|
746
|
-
writeRawWorkspaceData({ currentWorkspace: workspaceId }, layer);
|
|
747
|
-
return true;
|
|
748
|
-
}
|
|
749
|
-
export function getCurrentWorkspaceConfig() {
|
|
750
|
-
const { currentWorkspace, workspaces } = readAllWorkspaces();
|
|
751
|
-
if (!currentWorkspace)
|
|
752
|
-
return null;
|
|
753
|
-
return workspaces.find((w) => w.workspaceId === currentWorkspace) ?? null;
|
|
754
|
-
}
|
|
755
|
-
export function getWorkspaceConfigForPath(path = process.cwd()) {
|
|
756
|
-
const { workspaces } = readAllWorkspaces();
|
|
757
|
-
return findWorkspaceForPath(workspaces, path);
|
|
758
|
-
}
|
|
759
|
-
function findWorkspaceForPath(workspaces, path) {
|
|
760
|
-
const targetPath = stablePath(path);
|
|
761
|
-
const matches = workspaces.flatMap((workspace) => {
|
|
762
|
-
if (!isAbsolute(workspace.rootPath) || !existsSync(workspace.rootPath))
|
|
763
|
-
return [];
|
|
764
|
-
const rootPath = stablePath(workspace.rootPath);
|
|
765
|
-
return isInsidePath(targetPath, rootPath) ? [{ workspace, rootPath }] : [];
|
|
766
|
-
});
|
|
767
|
-
if (matches.length === 0)
|
|
768
|
-
return null;
|
|
769
|
-
return matches.reduce((best, match) => match.rootPath.length > best.rootPath.length ? match : best).workspace;
|
|
770
|
-
}
|
|
771
|
-
function getWorkspaceArtifactRoot(workspace) {
|
|
772
|
-
return workspace.artifactStorage?.localPath
|
|
773
|
-
? resolve(workspace.artifactStorage.localPath)
|
|
774
|
-
: resolve(workspace.rootPath, '.peaks', 'artifacts');
|
|
775
|
-
}
|
|
776
|
-
function ensureArtifactWorkspaceMarker(workspace) {
|
|
777
|
-
const artifactRoot = getWorkspaceArtifactRoot(workspace);
|
|
778
|
-
const peaksPath = resolve(artifactRoot, '.peaks');
|
|
779
|
-
const markerPath = resolve(peaksPath, 'config.json');
|
|
780
|
-
ensureDir(artifactRoot);
|
|
781
|
-
validateArtifactWorkspaceRoot(artifactRoot, workspace.rootPath);
|
|
782
|
-
ensureDir(peaksPath);
|
|
783
|
-
validateArtifactWorkspaceMarkerPath(artifactRoot, peaksPath, markerPath);
|
|
784
|
-
if (!existsSync(markerPath)) {
|
|
785
|
-
writeConfigFileSafely(markerPath, '{}\n', () => validateArtifactWorkspaceMarkerPath(artifactRoot, peaksPath, markerPath), 'Artifact workspace marker must stay inside the artifact workspace');
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
export function ensureWorkspaceConfigForPath(path = process.cwd()) {
|
|
789
|
-
const projectRoot = resolveProjectRootForConfig(path);
|
|
790
|
-
if (!isAbsolute(projectRoot) || !existsSync(projectRoot))
|
|
791
|
-
return null;
|
|
792
|
-
const config = readLayerConfig('user');
|
|
793
|
-
const existingWorkspace = findWorkspaceForPath(config.workspaces, path);
|
|
794
|
-
if (existingWorkspace) {
|
|
795
|
-
ensureArtifactWorkspaceMarker(existingWorkspace);
|
|
796
|
-
return existingWorkspace;
|
|
797
|
-
}
|
|
798
|
-
return null;
|
|
799
|
-
}
|
|
800
|
-
export function getWorkspaceConfigForCurrentPath() {
|
|
801
|
-
return getWorkspaceConfigForPath(process.cwd());
|
|
802
|
-
}
|
|
803
|
-
export function ensureWorkspaceConfigForCurrentPath() {
|
|
804
|
-
return ensureWorkspaceConfigForPath(process.cwd());
|
|
805
|
-
}
|
|
806
|
-
export { getUserConfigPath } from './config-safety.js';
|
|
157
|
+
export { getUserConfigPath };
|
|
807
158
|
export { globalConfigPath } from './config-migration.js';
|