create-principles-disciple 1.82.0 → 1.83.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/console/dist/server/config/pd-config-store.d.ts +135 -0
- package/console/dist/server/config/pd-config-store.js +660 -0
- package/console/dist/server/index.js +40 -389
- package/console/dist/server/models/ActivationsConsoleModel.d.ts +33 -0
- package/console/dist/server/models/ActivationsConsoleModel.js +112 -0
- package/console/dist/server/models/ApprovalsConsoleModel.d.ts +5 -0
- package/console/dist/server/models/ApprovalsConsoleModel.js +14 -0
- package/console/dist/server/models/ApprovalsGroupedConsoleModel.d.ts +25 -0
- package/console/dist/server/models/ApprovalsGroupedConsoleModel.js +126 -0
- package/console/dist/server/models/ConsoleLifecycleDatasource.d.ts +13 -0
- package/console/dist/server/models/ConsoleLifecycleDatasource.js +73 -0
- package/console/dist/server/models/EvidenceChainConsoleModel.d.ts +58 -0
- package/console/dist/server/models/EvidenceChainConsoleModel.js +493 -0
- package/console/dist/server/models/GovernanceConsoleModel.d.ts +74 -0
- package/console/dist/server/models/GovernanceConsoleModel.js +246 -0
- package/console/dist/server/models/HealthCheckModel.d.ts +0 -4
- package/console/dist/server/models/HealthCheckModel.js +49 -80
- package/console/dist/server/models/LifecycleConsoleModel.d.ts +19 -0
- package/console/dist/server/models/LifecycleConsoleModel.js +55 -0
- package/console/dist/server/models/PrincipleClassifier.d.ts +41 -0
- package/console/dist/server/models/PrincipleClassifier.js +100 -0
- package/console/dist/server/models/PrinciplesConsoleModel.d.ts +12 -1
- package/console/dist/server/models/PrinciplesConsoleModel.js +53 -6
- package/console/dist/server/models/WorkspaceService.d.ts +2 -1
- package/console/dist/server/models/WorkspaceService.js +51 -23
- package/console/dist/server/routes/activations.d.ts +3 -0
- package/console/dist/server/routes/activations.js +111 -0
- package/console/dist/server/routes/approvals-grouped.d.ts +3 -0
- package/console/dist/server/routes/approvals-grouped.js +32 -0
- package/console/dist/server/routes/approvals.js +28 -4
- package/console/dist/server/routes/config.d.ts +27 -0
- package/console/dist/server/routes/config.js +213 -0
- package/console/dist/server/routes/evidence-chain.d.ts +9 -0
- package/console/dist/server/routes/evidence-chain.js +32 -0
- package/console/dist/server/routes/governance.d.ts +3 -0
- package/console/dist/server/routes/governance.js +32 -0
- package/console/dist/server/routes/{evolution.d.ts → lifecycle.d.ts} +2 -2
- package/console/dist/server/routes/lifecycle.js +48 -0
- package/console/dist/server/routes/principles.js +74 -1
- package/console/dist/server/routes/workspaces.js +8 -1
- package/console/dist/server/utils/response.d.ts +1 -1
- package/console/dist/server/utils/response.js +6 -2
- package/console/dist/types.d.ts +1 -0
- package/console/dist/ui/App.js +116 -40
- package/console/dist/ui/api.d.ts +88 -501
- package/console/dist/ui/api.js +139 -162
- package/console/dist/ui/components/approval-card.js +1 -1
- package/console/dist/ui/components/approval-detail-dialog.js +1 -1
- package/console/dist/ui/components/auth/login-form.d.ts +3 -0
- package/console/dist/ui/components/auth/login-form.js +36 -0
- package/console/dist/ui/components/auth/splash-screen.d.ts +8 -0
- package/console/dist/ui/components/auth/splash-screen.js +22 -0
- package/console/dist/ui/components/layout/app-sidebar.d.ts +1 -0
- package/console/dist/ui/components/layout/app-sidebar.js +56 -0
- package/console/dist/ui/components/layout/page-shell.d.ts +11 -0
- package/console/dist/ui/components/layout/page-shell.js +10 -0
- package/console/dist/ui/components/layout/section-title.d.ts +10 -0
- package/console/dist/ui/components/layout/section-title.js +9 -0
- package/console/dist/ui/components/theme-provider.d.ts +1 -1
- package/console/dist/ui/components/theme-provider.js +13 -8
- package/console/dist/ui/components/theme-toggle.js +2 -21
- package/console/dist/ui/components/ui/badge.d.ts +1 -1
- package/console/dist/ui/components/ui/badge.js +7 -5
- package/console/dist/ui/components/ui/button.d.ts +2 -2
- package/console/dist/ui/components/ui/button.js +12 -11
- package/console/dist/ui/components/ui/card.js +6 -6
- package/console/dist/ui/components/ui/sheet.d.ts +1 -1
- package/console/dist/ui/i18n/en.json +401 -343
- package/console/dist/ui/i18n/index.js +2 -2
- package/console/dist/ui/i18n/zh-CN.json +406 -348
- package/console/dist/ui/main.d.ts +1 -1
- package/console/dist/ui/main.js +1 -0
- package/console/dist/ui/pages/activation/ActivationPage.d.ts +1 -0
- package/console/dist/ui/pages/activation/ActivationPage.js +150 -0
- package/console/dist/ui/pages/activation/ActivationValidators.d.ts +20 -0
- package/console/dist/ui/pages/activation/ActivationValidators.js +156 -0
- package/console/dist/ui/pages/control-center/ControlCenterPage.d.ts +1 -0
- package/console/dist/ui/pages/control-center/ControlCenterPage.js +447 -0
- package/console/dist/ui/pages/debt/DebtPage.d.ts +1 -0
- package/console/dist/ui/pages/debt/DebtPage.js +5 -0
- package/console/dist/ui/pages/design-system/DesignSystemPage.d.ts +1 -0
- package/console/dist/ui/pages/design-system/DesignSystemPage.js +30 -0
- package/console/dist/ui/pages/focus/FocusPage.d.ts +1 -0
- package/console/dist/ui/pages/focus/FocusPage.js +265 -0
- package/console/dist/ui/pages/pain/PainEvidenceValidators.d.ts +59 -0
- package/console/dist/ui/pages/pain/PainEvidenceValidators.js +125 -0
- package/console/dist/ui/pages/pain/PainPage.js +136 -0
- package/console/dist/ui/pages/principles/PrincipleDetailPage.js +264 -0
- package/console/dist/ui/pages/principles/PrinciplesPage.js +244 -0
- package/console/dist/ui/pages/report-problem/ReportProblemPage.js +245 -0
- package/console/dist/ui/pages/settings/SettingsPage.d.ts +4 -0
- package/console/dist/ui/pages/settings/SettingsPage.js +202 -0
- package/console/dist/ui/pages/settings/UpdatePage.d.ts +5 -0
- package/console/dist/ui/pages/settings/UpdatePage.js +168 -0
- package/console/dist/ui/utils/control-center-helpers.d.ts +58 -0
- package/console/dist/ui/utils/control-center-helpers.js +152 -0
- package/console/dist/ui/utils/validators.d.ts +350 -0
- package/console/dist/ui/utils/validators.js +995 -0
- package/console/dist/web/assets/app.css +672 -902
- package/console/dist/web/assets/app.js +6404 -15347
- package/console/dist/web/assets/jetbrains-mono-cyrillic-400-normal-C5JECUCT.woff2 +0 -0
- package/console/dist/web/assets/jetbrains-mono-cyrillic-400-normal-FGCZYWMY.woff +0 -0
- package/console/dist/web/assets/jetbrains-mono-cyrillic-ext-400-normal-C7IFWGF6.woff2 +0 -0
- package/console/dist/web/assets/jetbrains-mono-cyrillic-ext-400-normal-PWXUA557.woff +0 -0
- package/console/dist/web/assets/jetbrains-mono-greek-400-normal-JJNQZMPZ.woff +0 -0
- package/console/dist/web/assets/jetbrains-mono-greek-400-normal-O7JTTR3P.woff2 +0 -0
- package/console/dist/web/assets/jetbrains-mono-latin-400-normal-3OOWLGQ2.woff2 +0 -0
- package/console/dist/web/assets/jetbrains-mono-latin-400-normal-WDD34GPP.woff +0 -0
- package/console/dist/web/assets/jetbrains-mono-latin-ext-400-normal-55RNMRQS.woff +0 -0
- package/console/dist/web/assets/jetbrains-mono-latin-ext-400-normal-JVR3IR4Z.woff2 +0 -0
- package/console/dist/web/assets/jetbrains-mono-vietnamese-400-normal-7ULXAK72.woff +0 -0
- package/console/dist/web/assets/jetbrains-mono-vietnamese-400-normal-KU7YLUPA.woff2 +0 -0
- package/console/package.json +2 -1
- package/core/dist/runtime-v2/__tests__/admission-gate.test.js +49 -0
- package/core/dist/runtime-v2/__tests__/admission-gate.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +16 -1
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/evidence-sanitizer.test.d.ts +21 -0
- package/core/dist/runtime-v2/__tests__/evidence-sanitizer.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/evidence-sanitizer.test.js +354 -0
- package/core/dist/runtime-v2/__tests__/evidence-sanitizer.test.js.map +1 -0
- package/core/dist/runtime-v2/__tests__/language-directive.test.d.ts +12 -0
- package/core/dist/runtime-v2/__tests__/language-directive.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/language-directive.test.js +162 -0
- package/core/dist/runtime-v2/__tests__/language-directive.test.js.map +1 -0
- package/core/dist/runtime-v2/__tests__/pain-signal-observability.test.js +23 -1
- package/core/dist/runtime-v2/__tests__/pain-signal-observability.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/pain-to-principle-service.test.js +48 -3
- package/core/dist/runtime-v2/__tests__/pain-to-principle-service.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/proven-channel-baseline.test.js +13 -1
- package/core/dist/runtime-v2/__tests__/proven-channel-baseline.test.js.map +1 -1
- package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.d.ts +12 -0
- package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.js +194 -0
- package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.js.map +1 -0
- package/core/dist/runtime-v2/__tests__/runtime-config-boundary.test.js +5 -3
- package/core/dist/runtime-v2/__tests__/runtime-config-boundary.test.js.map +1 -1
- package/core/dist/runtime-v2/activation/__tests__/activation-dispatcher.test.js +1 -0
- package/core/dist/runtime-v2/activation/__tests__/activation-dispatcher.test.js.map +1 -1
- package/core/dist/runtime-v2/activation/__tests__/approval-queue.test.js +54 -0
- package/core/dist/runtime-v2/activation/__tests__/approval-queue.test.js.map +1 -1
- package/core/dist/runtime-v2/activation/__tests__/memory-activation-state-store.test.js +15 -2
- package/core/dist/runtime-v2/activation/__tests__/memory-activation-state-store.test.js.map +1 -1
- package/core/dist/runtime-v2/activation/__tests__/prompt-activation-reader-contract.test.js +10 -0
- package/core/dist/runtime-v2/activation/__tests__/prompt-activation-reader-contract.test.js.map +1 -1
- package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store.test.js +17 -2
- package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store.test.js.map +1 -1
- package/core/dist/runtime-v2/activation/__tests__/sqlite-approval-store.test.js +36 -0
- package/core/dist/runtime-v2/activation/__tests__/sqlite-approval-store.test.js.map +1 -1
- package/core/dist/runtime-v2/activation/activation-dispatcher.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/activation-dispatcher.js +1 -1
- package/core/dist/runtime-v2/activation/activation-dispatcher.js.map +1 -1
- package/core/dist/runtime-v2/activation/activation-types.d.ts +10 -0
- package/core/dist/runtime-v2/activation/activation-types.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/activation-types.js.map +1 -1
- package/core/dist/runtime-v2/activation/approval-queue.d.ts +6 -0
- package/core/dist/runtime-v2/activation/approval-queue.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/approval-queue.js +3 -0
- package/core/dist/runtime-v2/activation/approval-queue.js.map +1 -1
- package/core/dist/runtime-v2/activation/memory-activation-state-store.d.ts +2 -0
- package/core/dist/runtime-v2/activation/memory-activation-state-store.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/memory-activation-state-store.js +17 -1
- package/core/dist/runtime-v2/activation/memory-activation-state-store.js.map +1 -1
- package/core/dist/runtime-v2/activation/memory-approval-store.d.ts +6 -0
- package/core/dist/runtime-v2/activation/memory-approval-store.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/memory-approval-store.js +16 -0
- package/core/dist/runtime-v2/activation/memory-approval-store.js.map +1 -1
- package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.js +1 -1
- package/core/dist/runtime-v2/activation/prompt-activation-reader-contract.js.map +1 -1
- package/core/dist/runtime-v2/activation/sqlite-activation-state-store.d.ts +2 -0
- package/core/dist/runtime-v2/activation/sqlite-activation-state-store.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/sqlite-activation-state-store.js +34 -6
- package/core/dist/runtime-v2/activation/sqlite-activation-state-store.js.map +1 -1
- package/core/dist/runtime-v2/activation/sqlite-approval-store.d.ts +6 -0
- package/core/dist/runtime-v2/activation/sqlite-approval-store.d.ts.map +1 -1
- package/core/dist/runtime-v2/activation/sqlite-approval-store.js +10 -0
- package/core/dist/runtime-v2/activation/sqlite-approval-store.js.map +1 -1
- package/core/dist/runtime-v2/adapter/__tests__/json-extractor.test.js +51 -1
- package/core/dist/runtime-v2/adapter/__tests__/json-extractor.test.js.map +1 -1
- package/core/dist/runtime-v2/adapter/__tests__/openclaw-cli-runtime-adapter.test.js +145 -0
- package/core/dist/runtime-v2/adapter/__tests__/openclaw-cli-runtime-adapter.test.js.map +1 -1
- package/core/dist/runtime-v2/adapter/json-extractor.d.ts +13 -0
- package/core/dist/runtime-v2/adapter/json-extractor.d.ts.map +1 -1
- package/core/dist/runtime-v2/adapter/json-extractor.js +103 -0
- package/core/dist/runtime-v2/adapter/json-extractor.js.map +1 -1
- package/core/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.d.ts +4 -2
- package/core/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.d.ts.map +1 -1
- package/core/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.js +57 -5
- package/core/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.js.map +1 -1
- package/core/dist/runtime-v2/config/__tests__/pd-config-agent-binding.test.d.ts +18 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-agent-binding.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-agent-binding.test.js +633 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-agent-binding.test.js.map +1 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-validation-edge-cases.test.js +92 -0
- package/core/dist/runtime-v2/config/__tests__/pd-config-validation-edge-cases.test.js.map +1 -1
- package/core/dist/runtime-v2/config/index.d.ts +3 -1
- package/core/dist/runtime-v2/config/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/index.js +1 -0
- package/core/dist/runtime-v2/config/index.js.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-agent-binding.d.ts +93 -0
- package/core/dist/runtime-v2/config/pd-config-agent-binding.d.ts.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-agent-binding.js +184 -0
- package/core/dist/runtime-v2/config/pd-config-agent-binding.js.map +1 -0
- package/core/dist/runtime-v2/config/pd-config-defaults.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-defaults.js +2 -0
- package/core/dist/runtime-v2/config/pd-config-defaults.js.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-effective.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-effective.js +3 -0
- package/core/dist/runtime-v2/config/pd-config-effective.js.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-types.d.ts +8 -0
- package/core/dist/runtime-v2/config/pd-config-types.d.ts.map +1 -1
- package/core/dist/runtime-v2/config/pd-config-types.js.map +1 -1
- package/core/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.d.ts +13 -0
- package/core/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.js +97 -0
- package/core/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.js.map +1 -0
- package/core/dist/runtime-v2/diagnostician-prompt-builder.d.ts +3 -2
- package/core/dist/runtime-v2/diagnostician-prompt-builder.d.ts.map +1 -1
- package/core/dist/runtime-v2/diagnostician-prompt-builder.js +6 -4
- package/core/dist/runtime-v2/diagnostician-prompt-builder.js.map +1 -1
- package/core/dist/runtime-v2/evidence-sanitizer.d.ts +57 -0
- package/core/dist/runtime-v2/evidence-sanitizer.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-sanitizer.js +213 -0
- package/core/dist/runtime-v2/evidence-sanitizer.js.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/admission-events.test.d.ts +7 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/admission-events.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/admission-events.test.js +170 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/admission-events.test.js.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/source-descriptors.test.d.ts +18 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/source-descriptors.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/source-descriptors.test.js +277 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/source-descriptors.test.js.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/triage-policy.test.d.ts +13 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/triage-policy.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/triage-policy.test.js +264 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/triage-policy.test.js.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/trigger-controller.test.d.ts +16 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/trigger-controller.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/trigger-controller.test.js +316 -0
- package/core/dist/runtime-v2/evidence-triage/__tests__/trigger-controller.test.js.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/admission-events.d.ts +126 -0
- package/core/dist/runtime-v2/evidence-triage/admission-events.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/admission-events.js +159 -0
- package/core/dist/runtime-v2/evidence-triage/admission-events.js.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/index.d.ts +16 -0
- package/core/dist/runtime-v2/evidence-triage/index.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/index.js +13 -0
- package/core/dist/runtime-v2/evidence-triage/index.js.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/source-descriptors.d.ts +48 -0
- package/core/dist/runtime-v2/evidence-triage/source-descriptors.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/source-descriptors.js +131 -0
- package/core/dist/runtime-v2/evidence-triage/source-descriptors.js.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/triage-policy.d.ts +32 -0
- package/core/dist/runtime-v2/evidence-triage/triage-policy.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/triage-policy.js +95 -0
- package/core/dist/runtime-v2/evidence-triage/triage-policy.js.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/trigger-controller.d.ts +116 -0
- package/core/dist/runtime-v2/evidence-triage/trigger-controller.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/trigger-controller.js +218 -0
- package/core/dist/runtime-v2/evidence-triage/trigger-controller.js.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/types.d.ts +65 -0
- package/core/dist/runtime-v2/evidence-triage/types.d.ts.map +1 -0
- package/core/dist/runtime-v2/evidence-triage/types.js +38 -0
- package/core/dist/runtime-v2/evidence-triage/types.js.map +1 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +10 -0
- package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +1 -0
- package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
- package/core/dist/runtime-v2/index.d.ts +8 -1
- package/core/dist/runtime-v2/index.d.ts.map +1 -1
- package/core/dist/runtime-v2/index.js +7 -1
- package/core/dist/runtime-v2/index.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/scribe-prompt-language.test.d.ts +12 -0
- package/core/dist/runtime-v2/internalization/__tests__/scribe-prompt-language.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/internalization/__tests__/scribe-prompt-language.test.js +83 -0
- package/core/dist/runtime-v2/internalization/__tests__/scribe-prompt-language.test.js.map +1 -0
- package/core/dist/runtime-v2/internalization/scribe-prompt-builder.d.ts +10 -0
- package/core/dist/runtime-v2/internalization/scribe-prompt-builder.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-prompt-builder.js +13 -1
- package/core/dist/runtime-v2/internalization/scribe-prompt-builder.js.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-runner.d.ts +3 -0
- package/core/dist/runtime-v2/internalization/scribe-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/scribe-runner.js +2 -0
- package/core/dist/runtime-v2/internalization/scribe-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization-chain-integrity-read-model.js +1 -1
- package/core/dist/runtime-v2/internalization-chain-integrity-read-model.js.map +1 -1
- package/core/dist/runtime-v2/language-directive.d.ts +80 -0
- package/core/dist/runtime-v2/language-directive.d.ts.map +1 -0
- package/core/dist/runtime-v2/language-directive.js +108 -0
- package/core/dist/runtime-v2/language-directive.js.map +1 -0
- package/core/dist/runtime-v2/pain-signal-observability.d.ts.map +1 -1
- package/core/dist/runtime-v2/pain-signal-observability.js +24 -11
- package/core/dist/runtime-v2/pain-signal-observability.js.map +1 -1
- package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts +16 -0
- package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts.map +1 -1
- package/core/dist/runtime-v2/pain-signal-runtime-factory.js +97 -6
- package/core/dist/runtime-v2/pain-signal-runtime-factory.js.map +1 -1
- package/core/dist/runtime-v2/pain-to-principle-service.d.ts +7 -0
- package/core/dist/runtime-v2/pain-to-principle-service.d.ts.map +1 -1
- package/core/dist/runtime-v2/pain-to-principle-service.js +2 -0
- package/core/dist/runtime-v2/pain-to-principle-service.js.map +1 -1
- package/core/dist/runtime-v2/proven-channel-baseline.d.ts.map +1 -1
- package/core/dist/runtime-v2/proven-channel-baseline.js +14 -0
- package/core/dist/runtime-v2/proven-channel-baseline.js.map +1 -1
- package/core/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.js +40 -0
- package/core/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.js.map +1 -1
- package/core/dist/runtime-v2/runner/base-peer-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/runner/base-peer-runner.js +1 -0
- package/core/dist/runtime-v2/runner/base-peer-runner.js.map +1 -1
- package/core/dist/runtime-v2/runner/diagnostician-runner-options.d.ts +10 -0
- package/core/dist/runtime-v2/runner/diagnostician-runner-options.d.ts.map +1 -1
- package/core/dist/runtime-v2/runner/diagnostician-runner-options.js +1 -0
- package/core/dist/runtime-v2/runner/diagnostician-runner-options.js.map +1 -1
- package/core/dist/runtime-v2/runner/diagnostician-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/runner/diagnostician-runner.js +28 -4
- package/core/dist/runtime-v2/runner/diagnostician-runner.js.map +1 -1
- package/core/dist/runtime-v2/runner/peer-runner-types.d.ts +9 -0
- package/core/dist/runtime-v2/runner/peer-runner-types.d.ts.map +1 -1
- package/core/dist/runtime-v2/store/runtime-state-manager.d.ts.map +1 -1
- package/core/dist/runtime-v2/store/runtime-state-manager.integration.test.js +34 -1
- package/core/dist/runtime-v2/store/runtime-state-manager.integration.test.js.map +1 -1
- package/core/dist/runtime-v2/store/runtime-state-manager.js +1 -0
- package/core/dist/runtime-v2/store/runtime-state-manager.js.map +1 -1
- package/core/dist/runtime-v2/store/sqlite-connection.d.ts.map +1 -1
- package/core/dist/runtime-v2/store/sqlite-connection.js +9 -1
- package/core/dist/runtime-v2/store/sqlite-connection.js.map +1 -1
- package/core/dist/runtime-v2/store/task/sqlite-task-store.js +1 -1
- package/core/dist/runtime-v2/store/task/sqlite-task-store.js.map +1 -1
- package/core/dist/runtime-v2/task-status.d.ts +4 -4
- package/core/dist/runtime-v2/task-status.d.ts.map +1 -1
- package/core/dist/runtime-v2/task-status.js +2 -2
- package/core/dist/runtime-v2/task-status.js.map +1 -1
- package/core/package.json +1 -1
- package/package.json +2 -2
- package/pd-cli/dist/commands/console.d.ts +2 -0
- package/pd-cli/dist/commands/console.d.ts.map +1 -1
- package/pd-cli/dist/commands/console.js +6 -1
- package/pd-cli/dist/commands/console.js.map +1 -1
- package/pd-cli/dist/commands/diagnose.d.ts.map +1 -1
- package/pd-cli/dist/commands/diagnose.js +18 -1
- package/pd-cli/dist/commands/diagnose.js.map +1 -1
- package/pd-cli/dist/commands/pain-evidence.d.ts +41 -0
- package/pd-cli/dist/commands/pain-evidence.d.ts.map +1 -0
- package/pd-cli/dist/commands/pain-evidence.js +177 -0
- package/pd-cli/dist/commands/pain-evidence.js.map +1 -0
- package/pd-cli/dist/commands/pain-record.d.ts.map +1 -1
- package/pd-cli/dist/commands/pain-record.js +24 -9
- package/pd-cli/dist/commands/pain-record.js.map +1 -1
- package/pd-cli/dist/commands/pain-retry.d.ts +19 -0
- package/pd-cli/dist/commands/pain-retry.d.ts.map +1 -0
- package/pd-cli/dist/commands/pain-retry.js +485 -0
- package/pd-cli/dist/commands/pain-retry.js.map +1 -0
- package/pd-cli/dist/commands/runtime-internalization-run-once.d.ts.map +1 -1
- package/pd-cli/dist/commands/runtime-internalization-run-once.js +59 -9
- package/pd-cli/dist/commands/runtime-internalization-run-once.js.map +1 -1
- package/pd-cli/dist/commands/runtime-uat.d.ts +1 -0
- package/pd-cli/dist/commands/runtime-uat.d.ts.map +1 -1
- package/pd-cli/dist/commands/runtime-uat.guard.test.d.ts +2 -0
- package/pd-cli/dist/commands/runtime-uat.guard.test.d.ts.map +1 -0
- package/pd-cli/dist/commands/runtime-uat.guard.test.js +155 -0
- package/pd-cli/dist/commands/runtime-uat.guard.test.js.map +1 -0
- package/pd-cli/dist/commands/runtime-uat.js +29 -3
- package/pd-cli/dist/commands/runtime-uat.js.map +1 -1
- package/pd-cli/dist/config-reader.d.ts +25 -0
- package/pd-cli/dist/config-reader.d.ts.map +1 -0
- package/pd-cli/dist/config-reader.js +109 -0
- package/pd-cli/dist/config-reader.js.map +1 -0
- package/pd-cli/dist/index.js +40 -5
- package/pd-cli/dist/index.js.map +1 -1
- package/pd-cli/dist/services/console-launcher.d.ts.map +1 -1
- package/pd-cli/dist/services/console-launcher.js +29 -15
- package/pd-cli/dist/services/console-launcher.js.map +1 -1
- package/pd-cli/dist/services/demo-story-a-runner.d.ts.map +1 -1
- package/pd-cli/dist/services/demo-story-a-runner.js +1 -0
- package/pd-cli/dist/services/demo-story-a-runner.js.map +1 -1
- package/pd-cli/dist/utils/production-workspace-guard.d.ts +77 -0
- package/pd-cli/dist/utils/production-workspace-guard.d.ts.map +1 -0
- package/pd-cli/dist/utils/production-workspace-guard.js +170 -0
- package/pd-cli/dist/utils/production-workspace-guard.js.map +1 -0
- package/pd-cli/dist/utils/production-workspace-guard.test.d.ts +2 -0
- package/pd-cli/dist/utils/production-workspace-guard.test.d.ts.map +1 -0
- package/pd-cli/dist/utils/production-workspace-guard.test.js +95 -0
- package/pd-cli/dist/utils/production-workspace-guard.test.js.map +1 -0
- package/pd-cli/package.json +1 -1
- package/plugin/dist/commands/pain.js +27 -2
- package/plugin/dist/core/pain-diagnostic-gate.d.ts +6 -0
- package/plugin/dist/core/pain-diagnostic-gate.js +9 -0
- package/plugin/dist/hooks/after-tool-call-helpers.d.ts +90 -0
- package/plugin/dist/hooks/after-tool-call-helpers.js +486 -0
- package/plugin/dist/hooks/after-tool-call-types.d.ts +92 -0
- package/plugin/dist/hooks/after-tool-call-types.js +13 -0
- package/plugin/dist/hooks/gate-block-helper.js +73 -29
- package/plugin/dist/hooks/llm.js +49 -29
- package/plugin/dist/hooks/message-sanitize.d.ts +21 -0
- package/plugin/dist/hooks/message-sanitize.js +30 -0
- package/plugin/dist/hooks/pain.d.ts +26 -3
- package/plugin/dist/hooks/pain.js +165 -425
- package/plugin/dist/hooks/prompt.js +3 -2
- package/plugin/dist/hooks/trajectory-evidence.d.ts +11 -0
- package/plugin/dist/hooks/trajectory-evidence.js +65 -0
- package/plugin/dist/hooks/triage-adapter.d.ts +82 -0
- package/plugin/dist/hooks/triage-adapter.js +121 -0
- package/console/dist/server/models/EventLogReadModel.d.ts +0 -33
- package/console/dist/server/models/EventLogReadModel.js +0 -218
- package/console/dist/server/models/EvolutionConsoleModel.d.ts +0 -79
- package/console/dist/server/models/EvolutionConsoleModel.js +0 -179
- package/console/dist/server/models/FeedbackConsoleModel.d.ts +0 -38
- package/console/dist/server/models/FeedbackConsoleModel.js +0 -129
- package/console/dist/server/models/GateConsoleModel.d.ts +0 -50
- package/console/dist/server/models/GateConsoleModel.js +0 -151
- package/console/dist/server/models/OverviewConsoleModel.d.ts +0 -22
- package/console/dist/server/models/OverviewConsoleModel.js +0 -202
- package/console/dist/server/models/PipelineStatsModel.d.ts +0 -35
- package/console/dist/server/models/PipelineStatsModel.js +0 -129
- package/console/dist/server/models/SampleConsoleModel.d.ts +0 -21
- package/console/dist/server/models/SampleConsoleModel.js +0 -188
- package/console/dist/server/models/ThinkingModelsConsoleModel.d.ts +0 -22
- package/console/dist/server/models/ThinkingModelsConsoleModel.js +0 -75
- package/console/dist/server/routes/agents.d.ts +0 -3
- package/console/dist/server/routes/agents.js +0 -442
- package/console/dist/server/routes/central.d.ts +0 -5
- package/console/dist/server/routes/central.js +0 -31
- package/console/dist/server/routes/events.d.ts +0 -10
- package/console/dist/server/routes/events.js +0 -99
- package/console/dist/server/routes/evolution.js +0 -73
- package/console/dist/server/routes/feedback.d.ts +0 -3
- package/console/dist/server/routes/feedback.js +0 -65
- package/console/dist/server/routes/gates.d.ts +0 -3
- package/console/dist/server/routes/gates.js +0 -52
- package/console/dist/server/routes/overview.d.ts +0 -3
- package/console/dist/server/routes/overview.js +0 -49
- package/console/dist/server/routes/pipeline.d.ts +0 -3
- package/console/dist/server/routes/pipeline.js +0 -33
- package/console/dist/server/routes/samples.d.ts +0 -3
- package/console/dist/server/routes/samples.js +0 -101
- package/console/dist/server/routes/thinking-models.d.ts +0 -3
- package/console/dist/server/routes/thinking-models.js +0 -54
- package/console/dist/ui/components/app-sidebar.d.ts +0 -7
- package/console/dist/ui/components/app-sidebar.js +0 -75
- package/console/dist/ui/components/compare-view.d.ts +0 -7
- package/console/dist/ui/components/compare-view.js +0 -32
- package/console/dist/ui/components/data-freshness-indicator.d.ts +0 -10
- package/console/dist/ui/components/data-freshness-indicator.js +0 -63
- package/console/dist/ui/components/health-diagnostic-card.d.ts +0 -15
- package/console/dist/ui/components/health-diagnostic-card.js +0 -42
- package/console/dist/ui/components/page-header.d.ts +0 -10
- package/console/dist/ui/components/page-header.js +0 -37
- package/console/dist/ui/hooks/useAutoRefresh.d.ts +0 -13
- package/console/dist/ui/hooks/useAutoRefresh.js +0 -64
- package/console/dist/ui/hooks/useBookmarks.d.ts +0 -6
- package/console/dist/ui/hooks/useBookmarks.js +0 -43
- package/console/dist/ui/hooks/useDebounce.d.ts +0 -2
- package/console/dist/ui/hooks/useDebounce.js +0 -32
- package/console/dist/ui/hooks/useKeyboardNavigation.d.ts +0 -14
- package/console/dist/ui/hooks/useKeyboardNavigation.js +0 -75
- package/console/dist/ui/pages/AgentsPage.d.ts +0 -1
- package/console/dist/ui/pages/AgentsPage.js +0 -167
- package/console/dist/ui/pages/ApprovalsPage.d.ts +0 -1
- package/console/dist/ui/pages/ApprovalsPage.js +0 -123
- package/console/dist/ui/pages/CentralPage.d.ts +0 -1
- package/console/dist/ui/pages/CentralPage.js +0 -57
- package/console/dist/ui/pages/DataFlowPage.d.ts +0 -1
- package/console/dist/ui/pages/DataFlowPage.js +0 -158
- package/console/dist/ui/pages/EventLogPage.d.ts +0 -1
- package/console/dist/ui/pages/EventLogPage.js +0 -176
- package/console/dist/ui/pages/EvolutionPage.d.ts +0 -1
- package/console/dist/ui/pages/EvolutionPage.js +0 -118
- package/console/dist/ui/pages/FeedbackPage.d.ts +0 -1
- package/console/dist/ui/pages/FeedbackPage.js +0 -46
- package/console/dist/ui/pages/GatesPage.d.ts +0 -1
- package/console/dist/ui/pages/GatesPage.js +0 -31
- package/console/dist/ui/pages/LoginPage.d.ts +0 -5
- package/console/dist/ui/pages/LoginPage.js +0 -39
- package/console/dist/ui/pages/OverviewPage.d.ts +0 -1
- package/console/dist/ui/pages/OverviewPage.js +0 -50
- package/console/dist/ui/pages/PainPage.js +0 -50
- package/console/dist/ui/pages/PrincipleDetailPage.js +0 -145
- package/console/dist/ui/pages/PrinciplesPage.js +0 -322
- package/console/dist/ui/pages/ReportProblemPage.js +0 -186
- package/console/dist/ui/pages/SamplesPage.d.ts +0 -1
- package/console/dist/ui/pages/SamplesPage.js +0 -105
- package/console/dist/ui/pages/SettingsPage.d.ts +0 -1
- package/console/dist/ui/pages/SettingsPage.js +0 -86
- package/console/dist/ui/pages/TasksPage.d.ts +0 -1
- package/console/dist/ui/pages/TasksPage.js +0 -373
- package/console/dist/ui/pages/ThinkingModelsPage.d.ts +0 -1
- package/console/dist/ui/pages/ThinkingModelsPage.js +0 -32
- package/console/dist/ui/pages/UpdatePage.d.ts +0 -1
- package/console/dist/ui/pages/UpdatePage.js +0 -142
- /package/console/dist/ui/pages/{PainPage.d.ts → pain/PainPage.d.ts} +0 -0
- /package/console/dist/ui/pages/{PrincipleDetailPage.d.ts → principles/PrincipleDetailPage.d.ts} +0 -0
- /package/console/dist/ui/pages/{PrinciplesPage.d.ts → principles/PrinciplesPage.d.ts} +0 -0
- /package/console/dist/ui/pages/{ReportProblemPage.d.ts → report-problem/ReportProblemPage.d.ts} +0 -0
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PD Config Store — PRI-309
|
|
3
|
+
*
|
|
4
|
+
* I/O boundary for reading and writing `.pd/config.yaml`.
|
|
5
|
+
* Uses core validation and effective config computation.
|
|
6
|
+
* Safe partial writes: validate before write, preserve unrelated sections,
|
|
7
|
+
* reject malformed existing file.
|
|
8
|
+
*
|
|
9
|
+
* ERR entries:
|
|
10
|
+
* - ERR-001/ERR-005: No `as` bypasses on untrusted parsed YAML
|
|
11
|
+
* - ERR-002: Graceful degradation includes reason
|
|
12
|
+
* - ERR-009/ERR-010: Required fields fail loud
|
|
13
|
+
* - ERR-013: Object.hasOwn() for untrusted keys
|
|
14
|
+
* - ERR-045: ANY-segment redaction for sensitive keys
|
|
15
|
+
*/
|
|
16
|
+
import * as fs from 'fs';
|
|
17
|
+
import * as path from 'path';
|
|
18
|
+
import yaml from 'js-yaml';
|
|
19
|
+
import { validatePdConfig, computeEffectivePdConfig, redactPdConfig, checkAgentRuntimeReadiness, resolveAgentRuntimeBinding, INTERNAL_AGENT_NAMES, } from '@principles/core/runtime-v2';
|
|
20
|
+
// ── Constants ────────────────────────────────────────────────────────────────
|
|
21
|
+
const PD_CONFIG_DIR = '.pd';
|
|
22
|
+
const PD_CONFIG_FILENAME = 'config.yaml';
|
|
23
|
+
/** Allowed top-level keys in PATCH /agents/:name/binding payload */
|
|
24
|
+
const ALLOWED_PAYLOAD_KEYS = new Set(['runtimeProfile', 'enabled']);
|
|
25
|
+
/** Secret-like key segments for ANY-segment detection (ERR-045) */
|
|
26
|
+
const SECRET_KEY_SEGMENTS = [
|
|
27
|
+
'apikey', 'api_key', 'key', 'token', 'secret', 'password', 'auth',
|
|
28
|
+
'credential', 'gatewaytoken', 'gateway_token', 'accesstoken', 'access_token',
|
|
29
|
+
];
|
|
30
|
+
// ── Private Helpers (defined before public functions) ────────────────────────
|
|
31
|
+
function buildProfileLabel(_id, profile) {
|
|
32
|
+
if (profile.type === 'openclaw') {
|
|
33
|
+
const parts = ['openclaw'];
|
|
34
|
+
if (profile.provider)
|
|
35
|
+
parts.push(profile.provider);
|
|
36
|
+
if (profile.model)
|
|
37
|
+
parts.push(profile.model);
|
|
38
|
+
if (profile.source && !profile.provider && !profile.model)
|
|
39
|
+
parts.push(profile.source);
|
|
40
|
+
return parts.join(': ');
|
|
41
|
+
}
|
|
42
|
+
return `pi-ai: ${profile.provider}/${profile.model}`;
|
|
43
|
+
}
|
|
44
|
+
function writeConfigAtomic(configPath, config) {
|
|
45
|
+
// Ensure directory exists
|
|
46
|
+
const dir = path.dirname(configPath);
|
|
47
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
48
|
+
// Serialize to YAML
|
|
49
|
+
const content = yaml.dump(config, {
|
|
50
|
+
lineWidth: 120,
|
|
51
|
+
noRefs: true,
|
|
52
|
+
sortKeys: false,
|
|
53
|
+
});
|
|
54
|
+
// Atomic write: tmp → rename
|
|
55
|
+
const tmpPath = configPath + '.tmp';
|
|
56
|
+
fs.writeFileSync(tmpPath, content, 'utf8');
|
|
57
|
+
fs.renameSync(tmpPath, configPath);
|
|
58
|
+
}
|
|
59
|
+
function isValidAgentName(name) {
|
|
60
|
+
return INTERNAL_AGENT_NAMES.includes(name);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Type guard: is `value` a plain Record<string, unknown>?
|
|
64
|
+
* Replaces `payload as Record<string, unknown>` (ERR-001/ERR-005).
|
|
65
|
+
*/
|
|
66
|
+
function isRecord(value) {
|
|
67
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* ANY-segment secret key detection (ERR-045).
|
|
71
|
+
* Checks if any segment of a dotted key path matches a secret-like pattern.
|
|
72
|
+
* E.g. "provider.api_key" → detected; "runtimeProfile" → not detected.
|
|
73
|
+
*/
|
|
74
|
+
function containsSecretSegment(key) {
|
|
75
|
+
const lower = key.toLowerCase();
|
|
76
|
+
const segments = lower.split(/[._-]/);
|
|
77
|
+
return segments.some(seg => SECRET_KEY_SEGMENTS.includes(seg));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Recursively scan an object for secret-like keys at any depth (ERR-045).
|
|
81
|
+
*/
|
|
82
|
+
function hasSecretLikeKeyDeep(obj, prefix = '') {
|
|
83
|
+
for (const key of Object.keys(obj)) {
|
|
84
|
+
const fullPath = prefix ? `${prefix}.${key}` : key;
|
|
85
|
+
if (containsSecretSegment(key)) {
|
|
86
|
+
return fullPath;
|
|
87
|
+
}
|
|
88
|
+
const val = obj[key];
|
|
89
|
+
if (isRecord(val)) {
|
|
90
|
+
const nested = hasSecretLikeKeyDeep(val, fullPath);
|
|
91
|
+
if (nested)
|
|
92
|
+
return nested;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
export function validateBindingPayload(payload) {
|
|
98
|
+
// Use isRecord() type guard instead of `as` (ERR-001/ERR-005)
|
|
99
|
+
if (!isRecord(payload)) {
|
|
100
|
+
return { ok: false, error: 'bad_request', message: 'Payload must be a JSON object with runtimeProfile and enabled fields' };
|
|
101
|
+
}
|
|
102
|
+
// Strict whitelist: reject unknown top-level keys
|
|
103
|
+
const payloadKeys = Object.keys(payload);
|
|
104
|
+
for (const key of payloadKeys) {
|
|
105
|
+
if (!ALLOWED_PAYLOAD_KEYS.has(key)) {
|
|
106
|
+
return { ok: false, error: 'bad_request', message: `Payload contains unknown field '${key}'. Only 'runtimeProfile' and 'enabled' are allowed.` };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// ANY-segment secret key detection on nested values (ERR-045)
|
|
110
|
+
for (const key of payloadKeys) {
|
|
111
|
+
const val = payload[key];
|
|
112
|
+
if (isRecord(val)) {
|
|
113
|
+
const secretPath = hasSecretLikeKeyDeep(val, key);
|
|
114
|
+
if (secretPath) {
|
|
115
|
+
return { ok: false, error: 'bad_request', message: `Payload contains secret-like field '${secretPath}'. Remove secret fields from the request.` };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const runtimeProfileRaw = Object.hasOwn(payload, 'runtimeProfile') ? payload.runtimeProfile : undefined;
|
|
120
|
+
if (runtimeProfileRaw === undefined) {
|
|
121
|
+
return { ok: false, error: 'bad_request', message: 'Missing required field: runtimeProfile' };
|
|
122
|
+
}
|
|
123
|
+
if (typeof runtimeProfileRaw !== 'string' || runtimeProfileRaw.length === 0) {
|
|
124
|
+
return { ok: false, error: 'bad_request', message: 'runtimeProfile must be a non-empty string' };
|
|
125
|
+
}
|
|
126
|
+
const enabledRaw = Object.hasOwn(payload, 'enabled') ? payload.enabled : undefined;
|
|
127
|
+
if (enabledRaw === undefined) {
|
|
128
|
+
return { ok: false, error: 'bad_request', message: 'Missing required field: enabled' };
|
|
129
|
+
}
|
|
130
|
+
if (typeof enabledRaw !== 'boolean') {
|
|
131
|
+
return { ok: false, error: 'bad_request', message: 'enabled must be a boolean' };
|
|
132
|
+
}
|
|
133
|
+
return { ok: true, value: { runtimeProfile: runtimeProfileRaw, enabled: enabledRaw } };
|
|
134
|
+
}
|
|
135
|
+
// ── Config Path ──────────────────────────────────────────────────────────────
|
|
136
|
+
export function getPdConfigPath(workspaceDir) {
|
|
137
|
+
return path.join(workspaceDir, PD_CONFIG_DIR, PD_CONFIG_FILENAME);
|
|
138
|
+
}
|
|
139
|
+
// ── Load Config ──────────────────────────────────────────────────────────────
|
|
140
|
+
export function loadPdConfig(workspaceDir) {
|
|
141
|
+
const configPath = getPdConfigPath(workspaceDir);
|
|
142
|
+
// Missing file → defaults
|
|
143
|
+
if (!fs.existsSync(configPath)) {
|
|
144
|
+
const effective = computeEffectivePdConfig(null);
|
|
145
|
+
return {
|
|
146
|
+
ok: true,
|
|
147
|
+
effective,
|
|
148
|
+
source: 'defaults',
|
|
149
|
+
configPath,
|
|
150
|
+
warnings: effective.warnings,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// Read
|
|
154
|
+
let raw;
|
|
155
|
+
try {
|
|
156
|
+
raw = fs.readFileSync(configPath, 'utf8');
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
160
|
+
const defaults = computeEffectivePdConfig(null);
|
|
161
|
+
return {
|
|
162
|
+
ok: false,
|
|
163
|
+
source: 'malformed',
|
|
164
|
+
configPath,
|
|
165
|
+
errors: [{ path: '', reason: `Failed to read .pd/config.yaml: ${message}`, nextAction: 'Check file permissions for .pd/config.yaml' }],
|
|
166
|
+
defaults,
|
|
167
|
+
warnings: [],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
// Parse YAML — treat as unknown (ERR-001)
|
|
171
|
+
let parsed;
|
|
172
|
+
try {
|
|
173
|
+
parsed = yaml.load(raw, { schema: yaml.JSON_SCHEMA });
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
177
|
+
const defaults = computeEffectivePdConfig(null);
|
|
178
|
+
return {
|
|
179
|
+
ok: false,
|
|
180
|
+
source: 'malformed',
|
|
181
|
+
configPath,
|
|
182
|
+
errors: [{ path: '', reason: `YAML parse error: ${message}`, nextAction: 'Fix YAML syntax in .pd/config.yaml' }],
|
|
183
|
+
defaults,
|
|
184
|
+
warnings: [],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// Validate via core (ERR-001, ERR-005)
|
|
188
|
+
const validationResult = validatePdConfig(parsed);
|
|
189
|
+
if (!validationResult.ok) {
|
|
190
|
+
const defaults = computeEffectivePdConfig(null);
|
|
191
|
+
return {
|
|
192
|
+
ok: false,
|
|
193
|
+
source: 'malformed',
|
|
194
|
+
configPath,
|
|
195
|
+
errors: validationResult.errors.map(e => ({
|
|
196
|
+
path: e.path,
|
|
197
|
+
reason: e.reason,
|
|
198
|
+
nextAction: e.nextAction,
|
|
199
|
+
})),
|
|
200
|
+
defaults,
|
|
201
|
+
warnings: [],
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// Compute effective config
|
|
205
|
+
const effective = computeEffectivePdConfig(validationResult.value);
|
|
206
|
+
return {
|
|
207
|
+
ok: true,
|
|
208
|
+
effective,
|
|
209
|
+
source: 'user_config',
|
|
210
|
+
configPath,
|
|
211
|
+
warnings: effective.warnings,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
// ── Get Redacted Summary ─────────────────────────────────────────────────────
|
|
215
|
+
export function getConfigSummary(workspaceDir) {
|
|
216
|
+
const result = loadPdConfig(workspaceDir);
|
|
217
|
+
const effective = result.ok ? result.effective : result.defaults;
|
|
218
|
+
const summary = redactPdConfig(effective);
|
|
219
|
+
if (!result.ok) {
|
|
220
|
+
return { summary, errors: result.errors };
|
|
221
|
+
}
|
|
222
|
+
return { summary };
|
|
223
|
+
}
|
|
224
|
+
// ── Get Catalog ──────────────────────────────────────────────────────────────
|
|
225
|
+
export function getConfigCatalog(workspaceDir) {
|
|
226
|
+
const result = loadPdConfig(workspaceDir);
|
|
227
|
+
if (!result.ok) {
|
|
228
|
+
// Surface malformed config errors instead of silently using defaults
|
|
229
|
+
return {
|
|
230
|
+
profiles: [],
|
|
231
|
+
errors: result.errors,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const summary = redactPdConfig(result.effective);
|
|
235
|
+
return { profiles: summary.runtimeProfiles };
|
|
236
|
+
}
|
|
237
|
+
// ── Update Agent Binding ─────────────────────────────────────────────────────
|
|
238
|
+
export function updateAgentBinding(workspaceDir, agentName, payload) {
|
|
239
|
+
// 1. Validate agent name
|
|
240
|
+
if (!isValidAgentName(agentName)) {
|
|
241
|
+
return {
|
|
242
|
+
ok: false,
|
|
243
|
+
statusCode: 400,
|
|
244
|
+
error: 'bad_request',
|
|
245
|
+
message: `Unknown agent name '${agentName}'. Valid agents: ${INTERNAL_AGENT_NAMES.join(', ')}`,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
// 2. Validate payload
|
|
249
|
+
const payloadResult = validateBindingPayload(payload);
|
|
250
|
+
if (!payloadResult.ok) {
|
|
251
|
+
return { ok: false, statusCode: 400, error: payloadResult.error, message: payloadResult.message };
|
|
252
|
+
}
|
|
253
|
+
const { runtimeProfile, enabled } = payloadResult.value;
|
|
254
|
+
// 3. Load existing config
|
|
255
|
+
const loadResult = loadPdConfig(workspaceDir);
|
|
256
|
+
// 4. If malformed, refuse to write (AC: malformed existing config 拒绝写入)
|
|
257
|
+
if (!loadResult.ok) {
|
|
258
|
+
return {
|
|
259
|
+
ok: false,
|
|
260
|
+
statusCode: 409,
|
|
261
|
+
error: 'conflict',
|
|
262
|
+
message: `Cannot update agent binding: existing .pd/config.yaml is malformed. Fix config errors first. Errors: ${loadResult.errors.map(e => e.reason).join('; ')}`,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
const { effective } = loadResult;
|
|
266
|
+
// 5. Validate runtime profile reference exists
|
|
267
|
+
if (!Object.hasOwn(effective.config.runtimeProfiles, runtimeProfile)) {
|
|
268
|
+
return {
|
|
269
|
+
ok: false,
|
|
270
|
+
statusCode: 400,
|
|
271
|
+
error: 'bad_request',
|
|
272
|
+
message: `Runtime profile '${runtimeProfile}' does not exist. Available profiles: ${Object.keys(effective.config.runtimeProfiles).join(', ')}`,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
// 6. Build updated config — read original file to preserve unknown root entries
|
|
276
|
+
const configPath = getPdConfigPath(workspaceDir);
|
|
277
|
+
let rawConfig;
|
|
278
|
+
if (fs.existsSync(configPath)) {
|
|
279
|
+
const rawContent = fs.readFileSync(configPath, 'utf8');
|
|
280
|
+
const rawParsed = yaml.load(rawContent, { schema: yaml.JSON_SCHEMA });
|
|
281
|
+
if (isRecord(rawParsed)) {
|
|
282
|
+
rawConfig = { ...rawParsed };
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
rawConfig = {};
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
rawConfig = {};
|
|
290
|
+
}
|
|
291
|
+
// Update only the agent binding section
|
|
292
|
+
const agentsMap = {};
|
|
293
|
+
for (const name of INTERNAL_AGENT_NAMES) {
|
|
294
|
+
const existing = effective.config.internalAgents.agents[name];
|
|
295
|
+
if (name === agentName) {
|
|
296
|
+
agentsMap[name] = { enabled, runtimeProfile };
|
|
297
|
+
}
|
|
298
|
+
else if (existing) {
|
|
299
|
+
agentsMap[name] = {
|
|
300
|
+
enabled: existing.enabled,
|
|
301
|
+
...(existing.runtimeProfile ? { runtimeProfile: existing.runtimeProfile } : {}),
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// Merge: start from raw config, overlay known sections, update internalAgents.agents
|
|
306
|
+
const updatedConfig = {
|
|
307
|
+
...rawConfig,
|
|
308
|
+
version: effective.config.version,
|
|
309
|
+
features: { ...effective.config.features },
|
|
310
|
+
runtimeProfiles: { ...effective.config.runtimeProfiles },
|
|
311
|
+
internalAgents: {
|
|
312
|
+
defaultRuntime: effective.config.internalAgents.defaultRuntime,
|
|
313
|
+
agents: agentsMap,
|
|
314
|
+
},
|
|
315
|
+
ui: { ...effective.config.ui },
|
|
316
|
+
};
|
|
317
|
+
// 7. Validate the updated config before writing
|
|
318
|
+
const validation = validatePdConfig(updatedConfig);
|
|
319
|
+
if (!validation.ok) {
|
|
320
|
+
return {
|
|
321
|
+
ok: false,
|
|
322
|
+
statusCode: 400,
|
|
323
|
+
error: 'bad_request',
|
|
324
|
+
message: `Updated config would be invalid: ${validation.errors.map(e => e.reason).join('; ')}`,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
// 8. Write to disk (atomic: write to tmp, then rename)
|
|
328
|
+
writeConfigAtomic(configPath, updatedConfig);
|
|
329
|
+
return {
|
|
330
|
+
ok: true,
|
|
331
|
+
agent: agentName,
|
|
332
|
+
runtimeProfile,
|
|
333
|
+
enabled,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
export function updateDefaultRuntime(workspaceDir, payload) {
|
|
337
|
+
// 1. Validate payload
|
|
338
|
+
if (!isRecord(payload)) {
|
|
339
|
+
return { ok: false, statusCode: 400, error: 'bad_request', message: 'Payload must be a JSON object with a defaultRuntime field' };
|
|
340
|
+
}
|
|
341
|
+
const defaultRuntimeRaw = Object.hasOwn(payload, 'defaultRuntime') ? payload.defaultRuntime : undefined;
|
|
342
|
+
if (defaultRuntimeRaw === undefined) {
|
|
343
|
+
return { ok: false, statusCode: 400, error: 'bad_request', message: 'Missing required field: defaultRuntime' };
|
|
344
|
+
}
|
|
345
|
+
if (typeof defaultRuntimeRaw !== 'string' || defaultRuntimeRaw.length === 0) {
|
|
346
|
+
return { ok: false, statusCode: 400, error: 'bad_request', message: 'defaultRuntime must be a non-empty string' };
|
|
347
|
+
}
|
|
348
|
+
// ANY-segment secret key detection (ERR-045)
|
|
349
|
+
const secretPath = hasSecretLikeKeyDeep(payload);
|
|
350
|
+
if (secretPath) {
|
|
351
|
+
return { ok: false, statusCode: 400, error: 'bad_request', message: `Payload contains secret-like field '${secretPath}'. Remove secret fields from the request.` };
|
|
352
|
+
}
|
|
353
|
+
// 2. Load existing config
|
|
354
|
+
const loadResult = loadPdConfig(workspaceDir);
|
|
355
|
+
// 3. If malformed, refuse to write
|
|
356
|
+
if (!loadResult.ok) {
|
|
357
|
+
return {
|
|
358
|
+
ok: false,
|
|
359
|
+
statusCode: 409,
|
|
360
|
+
error: 'conflict',
|
|
361
|
+
message: `Cannot update default runtime: existing .pd/config.yaml is malformed. Fix config errors first. Errors: ${loadResult.errors.map(e => e.reason).join('; ')}`,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
const { effective } = loadResult;
|
|
365
|
+
// 4. Validate runtime profile reference exists
|
|
366
|
+
if (!Object.hasOwn(effective.config.runtimeProfiles, defaultRuntimeRaw)) {
|
|
367
|
+
return {
|
|
368
|
+
ok: false,
|
|
369
|
+
statusCode: 400,
|
|
370
|
+
error: 'bad_request',
|
|
371
|
+
message: `Runtime profile '${defaultRuntimeRaw}' does not exist. Available profiles: ${Object.keys(effective.config.runtimeProfiles).join(', ')}`,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
// 5. Build updated config — read original file to preserve unknown root entries
|
|
375
|
+
// and preserve agent inheritance (agents without explicit runtimeProfile
|
|
376
|
+
// should NOT get one written back — they inherit defaultRuntime)
|
|
377
|
+
const configPath = getPdConfigPath(workspaceDir);
|
|
378
|
+
let rawConfig;
|
|
379
|
+
let rawAgentsMap;
|
|
380
|
+
if (fs.existsSync(configPath)) {
|
|
381
|
+
const rawContent = fs.readFileSync(configPath, 'utf8');
|
|
382
|
+
const rawParsed = yaml.load(rawContent, { schema: yaml.JSON_SCHEMA });
|
|
383
|
+
if (isRecord(rawParsed)) {
|
|
384
|
+
rawConfig = { ...rawParsed };
|
|
385
|
+
// Extract the raw agents map from the file to preserve inheritance
|
|
386
|
+
const rawInternalAgents = rawParsed.internalAgents;
|
|
387
|
+
if (isRecord(rawInternalAgents) && Object.hasOwn(rawInternalAgents, 'agents')) {
|
|
388
|
+
const rawAgents = rawInternalAgents.agents;
|
|
389
|
+
if (isRecord(rawAgents)) {
|
|
390
|
+
rawAgentsMap = rawAgents;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
rawConfig = {};
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
rawConfig = {};
|
|
400
|
+
}
|
|
401
|
+
// Build agents map preserving ONLY explicit overrides from the original file.
|
|
402
|
+
// Agents that omit runtimeProfile in the file should continue to inherit
|
|
403
|
+
// defaultRuntime — we must NOT write back the effective (resolved) value.
|
|
404
|
+
// Only write agents that already exist in the file — do not add new ones.
|
|
405
|
+
const agentsMap = {};
|
|
406
|
+
if (rawAgentsMap) {
|
|
407
|
+
for (const name of Object.keys(rawAgentsMap)) {
|
|
408
|
+
const rawEntry = rawAgentsMap[name];
|
|
409
|
+
if (!isRecord(rawEntry))
|
|
410
|
+
continue;
|
|
411
|
+
// Preserve enabled if present, default to true
|
|
412
|
+
const enabledRaw = Object.hasOwn(rawEntry, 'enabled') ? rawEntry.enabled : undefined;
|
|
413
|
+
const enabled = typeof enabledRaw === 'boolean' ? enabledRaw : true;
|
|
414
|
+
// Only include runtimeProfile if the original file had an explicit one
|
|
415
|
+
const hasExplicitProfile = Object.hasOwn(rawEntry, 'runtimeProfile')
|
|
416
|
+
&& typeof rawEntry.runtimeProfile === 'string'
|
|
417
|
+
&& (rawEntry.runtimeProfile).length > 0;
|
|
418
|
+
agentsMap[name] = {
|
|
419
|
+
enabled,
|
|
420
|
+
...(hasExplicitProfile ? { runtimeProfile: rawEntry.runtimeProfile } : {}),
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
// No agents in file — write nothing (all agents inherit default)
|
|
426
|
+
}
|
|
427
|
+
// Merge: update only defaultRuntime, preserve agent overrides
|
|
428
|
+
const updatedConfig = {
|
|
429
|
+
...rawConfig,
|
|
430
|
+
version: effective.config.version,
|
|
431
|
+
features: { ...effective.config.features },
|
|
432
|
+
runtimeProfiles: { ...effective.config.runtimeProfiles },
|
|
433
|
+
internalAgents: {
|
|
434
|
+
defaultRuntime: defaultRuntimeRaw,
|
|
435
|
+
agents: agentsMap,
|
|
436
|
+
},
|
|
437
|
+
ui: { ...effective.config.ui },
|
|
438
|
+
};
|
|
439
|
+
// 6. Validate the updated config before writing
|
|
440
|
+
const validation = validatePdConfig(updatedConfig);
|
|
441
|
+
if (!validation.ok) {
|
|
442
|
+
return {
|
|
443
|
+
ok: false,
|
|
444
|
+
statusCode: 400,
|
|
445
|
+
error: 'bad_request',
|
|
446
|
+
message: `Updated config would be invalid: ${validation.errors.map(e => e.reason).join('; ')}`,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
// 7. Write to disk (atomic)
|
|
450
|
+
writeConfigAtomic(configPath, updatedConfig);
|
|
451
|
+
return {
|
|
452
|
+
ok: true,
|
|
453
|
+
defaultRuntime: defaultRuntimeRaw,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
// ── Principles Output Language (PRI-332 P1-1) ─────────────────────────────
|
|
457
|
+
/** Valid values for principles.outputLanguage in config.yaml */
|
|
458
|
+
export const VALID_OUTPUT_LANGUAGES = ['zh-CN', 'en'];
|
|
459
|
+
function isValidOutputLanguage(value) {
|
|
460
|
+
return typeof value === 'string' && VALID_OUTPUT_LANGUAGES.includes(value);
|
|
461
|
+
}
|
|
462
|
+
/** Default output language when not configured. */
|
|
463
|
+
const DEFAULT_OUTPUT_LANGUAGE = 'zh-CN';
|
|
464
|
+
/**
|
|
465
|
+
* Read principles.outputLanguage from config.yaml.
|
|
466
|
+
* Returns default ('zh-CN') when not set.
|
|
467
|
+
* Fail loud if set to an invalid value (ERR-009).
|
|
468
|
+
*/
|
|
469
|
+
export function getPrinciplesOutputLanguage(workspaceDir) {
|
|
470
|
+
const configPath = getPdConfigPath(workspaceDir);
|
|
471
|
+
if (!fs.existsSync(configPath)) {
|
|
472
|
+
return { ok: true, outputLanguage: DEFAULT_OUTPUT_LANGUAGE, source: 'default' };
|
|
473
|
+
}
|
|
474
|
+
let raw;
|
|
475
|
+
try {
|
|
476
|
+
raw = fs.readFileSync(configPath, 'utf8');
|
|
477
|
+
}
|
|
478
|
+
catch (err) {
|
|
479
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
480
|
+
return { ok: false, error: 'read_error', statusCode: 500, message: `Failed to read config: ${message}`, nextAction: 'Check file permissions for .pd/config.yaml' };
|
|
481
|
+
}
|
|
482
|
+
let parsed;
|
|
483
|
+
try {
|
|
484
|
+
parsed = yaml.load(raw, { schema: yaml.JSON_SCHEMA });
|
|
485
|
+
}
|
|
486
|
+
catch (err) {
|
|
487
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
488
|
+
return { ok: false, error: 'yaml_error', statusCode: 500, message: `YAML parse error: ${message}`, nextAction: 'Fix YAML syntax in .pd/config.yaml' };
|
|
489
|
+
}
|
|
490
|
+
if (!isRecord(parsed)) {
|
|
491
|
+
return { ok: true, outputLanguage: DEFAULT_OUTPUT_LANGUAGE, source: 'default' };
|
|
492
|
+
}
|
|
493
|
+
// Extract principles section — unknown-first, no `as` bypass (ERR-001)
|
|
494
|
+
const principlesRaw = Object.hasOwn(parsed, 'principles') ? parsed.principles : undefined;
|
|
495
|
+
if (principlesRaw === undefined) {
|
|
496
|
+
return { ok: true, outputLanguage: DEFAULT_OUTPUT_LANGUAGE, source: 'default' };
|
|
497
|
+
}
|
|
498
|
+
if (!isRecord(principlesRaw)) {
|
|
499
|
+
return {
|
|
500
|
+
ok: false,
|
|
501
|
+
error: 'invalid_config',
|
|
502
|
+
statusCode: 500,
|
|
503
|
+
message: 'principles section must be a mapping',
|
|
504
|
+
nextAction: 'Fix principles section in .pd/config.yaml to be a YAML mapping',
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
const outputLangRaw = Object.hasOwn(principlesRaw, 'outputLanguage') ? principlesRaw.outputLanguage : undefined;
|
|
508
|
+
if (outputLangRaw === undefined) {
|
|
509
|
+
return { ok: true, outputLanguage: DEFAULT_OUTPUT_LANGUAGE, source: 'default' };
|
|
510
|
+
}
|
|
511
|
+
if (!isValidOutputLanguage(outputLangRaw)) {
|
|
512
|
+
return {
|
|
513
|
+
ok: false,
|
|
514
|
+
error: 'invalid_output_language',
|
|
515
|
+
statusCode: 500,
|
|
516
|
+
message: `principles.outputLanguage must be one of: ${VALID_OUTPUT_LANGUAGES.join(', ')}. Got: ${String(outputLangRaw)}`,
|
|
517
|
+
nextAction: `Set principles.outputLanguage to one of: ${VALID_OUTPUT_LANGUAGES.join(', ')}`,
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
return { ok: true, outputLanguage: outputLangRaw, source: 'user_config' };
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Update principles.outputLanguage in config.yaml.
|
|
524
|
+
* Safe partial write: preserves unknown sections, validates before write.
|
|
525
|
+
*/
|
|
526
|
+
export function updatePrinciplesOutputLanguage(workspaceDir, payload) {
|
|
527
|
+
// 1. Validate payload
|
|
528
|
+
if (!isRecord(payload)) {
|
|
529
|
+
return { ok: false, error: 'bad_request', statusCode: 400, message: 'Payload must be a JSON object with an outputLanguage field', nextAction: 'Send { outputLanguage: "zh-CN" } or { outputLanguage: "en" }' };
|
|
530
|
+
}
|
|
531
|
+
const outputLangRaw = Object.hasOwn(payload, 'outputLanguage') ? payload.outputLanguage : undefined;
|
|
532
|
+
if (outputLangRaw === undefined) {
|
|
533
|
+
return { ok: false, error: 'bad_request', statusCode: 400, message: 'Missing required field: outputLanguage', nextAction: `Send { outputLanguage: "${DEFAULT_OUTPUT_LANGUAGE}" }` };
|
|
534
|
+
}
|
|
535
|
+
if (!isValidOutputLanguage(outputLangRaw)) {
|
|
536
|
+
return {
|
|
537
|
+
ok: false,
|
|
538
|
+
error: 'bad_request',
|
|
539
|
+
statusCode: 400,
|
|
540
|
+
message: `outputLanguage must be one of: ${VALID_OUTPUT_LANGUAGES.join(', ')}. Got: ${String(outputLangRaw)}`,
|
|
541
|
+
nextAction: `Set outputLanguage to one of: ${VALID_OUTPUT_LANGUAGES.join(', ')}`,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
// 2. Read raw config to preserve unknown sections
|
|
545
|
+
const configPath = getPdConfigPath(workspaceDir);
|
|
546
|
+
let rawConfig;
|
|
547
|
+
if (fs.existsSync(configPath)) {
|
|
548
|
+
let rawContent;
|
|
549
|
+
try {
|
|
550
|
+
rawContent = fs.readFileSync(configPath, 'utf8');
|
|
551
|
+
}
|
|
552
|
+
catch (err) {
|
|
553
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
554
|
+
return { ok: false, error: 'read_error', statusCode: 500, message: `Failed to read config for update: ${message}`, nextAction: 'Check file permissions for .pd/config.yaml' };
|
|
555
|
+
}
|
|
556
|
+
let rawParsed;
|
|
557
|
+
try {
|
|
558
|
+
rawParsed = yaml.load(rawContent, { schema: yaml.JSON_SCHEMA });
|
|
559
|
+
}
|
|
560
|
+
catch (err) {
|
|
561
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
562
|
+
return { ok: false, error: 'yaml_error', statusCode: 500, message: `YAML parse error during update: ${message}`, nextAction: 'Fix YAML syntax in .pd/config.yaml' };
|
|
563
|
+
}
|
|
564
|
+
if (isRecord(rawParsed)) {
|
|
565
|
+
rawConfig = { ...rawParsed };
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
rawConfig = {};
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
rawConfig = {};
|
|
573
|
+
}
|
|
574
|
+
// 3. Update principles.outputLanguage
|
|
575
|
+
const existingPrinciples = isRecord(rawConfig.principles) ? { ...rawConfig.principles } : {};
|
|
576
|
+
existingPrinciples.outputLanguage = outputLangRaw;
|
|
577
|
+
rawConfig.principles = existingPrinciples;
|
|
578
|
+
// 4. Validate via core (principles is an unknown section — safe to pass through)
|
|
579
|
+
const validation = validatePdConfig(rawConfig);
|
|
580
|
+
if (!validation.ok) {
|
|
581
|
+
return {
|
|
582
|
+
ok: false,
|
|
583
|
+
error: 'validation_error',
|
|
584
|
+
statusCode: 500,
|
|
585
|
+
message: `Updated config would be invalid: ${validation.errors.map(e => e.reason).join('; ')}`,
|
|
586
|
+
nextAction: 'Fix config validation errors before retrying',
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
// 5. Atomic write
|
|
590
|
+
try {
|
|
591
|
+
writeConfigAtomic(configPath, rawConfig);
|
|
592
|
+
}
|
|
593
|
+
catch (err) {
|
|
594
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
595
|
+
return { ok: false, error: 'write_error', statusCode: 500, message: `Failed to write config: ${message}`, nextAction: 'Check disk space and file permissions for .pd/config.yaml' };
|
|
596
|
+
}
|
|
597
|
+
return { ok: true, outputLanguage: outputLangRaw, source: 'user_config' };
|
|
598
|
+
}
|
|
599
|
+
// ── Check Readiness ──────────────────────────────────────────────────────────
|
|
600
|
+
export function checkReadiness(workspaceDir, agentName, getEnvVar = (name) => process.env[name]) {
|
|
601
|
+
// 1. Validate agent name
|
|
602
|
+
if (!isValidAgentName(agentName)) {
|
|
603
|
+
return {
|
|
604
|
+
ok: false,
|
|
605
|
+
statusCode: 404,
|
|
606
|
+
error: 'not_found',
|
|
607
|
+
message: `Unknown agent name '${agentName}'. Valid agents: ${INTERNAL_AGENT_NAMES.join(', ')}`,
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
// 2. Load config — if malformed, return unknown (not defaults pretending normal)
|
|
611
|
+
const loadResult = loadPdConfig(workspaceDir);
|
|
612
|
+
if (!loadResult.ok) {
|
|
613
|
+
return {
|
|
614
|
+
ok: true,
|
|
615
|
+
agent: agentName,
|
|
616
|
+
readiness: 'unknown',
|
|
617
|
+
profileId: '',
|
|
618
|
+
profileLabel: '',
|
|
619
|
+
reason: `Config file is malformed: ${loadResult.errors[0]?.reason ?? 'unknown error'}`,
|
|
620
|
+
nextAction: 'Fix .pd/config.yaml errors before checking readiness',
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
const { effective } = loadResult;
|
|
624
|
+
// 3. Resolve agent binding
|
|
625
|
+
const bindingResult = resolveAgentRuntimeBinding(effective, agentName);
|
|
626
|
+
if (!bindingResult.ok) {
|
|
627
|
+
// Agent is disabled or profile not found
|
|
628
|
+
// Use the agent's override profile id if present, otherwise default
|
|
629
|
+
const unresolvedProfileId = effective.config.internalAgents.agents[agentName]?.runtimeProfile
|
|
630
|
+
?? effective.config.internalAgents.defaultRuntime;
|
|
631
|
+
const resolvedProfileId = bindingResult.readiness === 'disabled'
|
|
632
|
+
? effective.config.internalAgents.defaultRuntime
|
|
633
|
+
: unresolvedProfileId;
|
|
634
|
+
const resolvedProfile = effective.config.runtimeProfiles[resolvedProfileId];
|
|
635
|
+
// If profile not found, label must clearly indicate the missing profile
|
|
636
|
+
const profileLabel = resolvedProfile
|
|
637
|
+
? buildProfileLabel(resolvedProfileId, resolvedProfile)
|
|
638
|
+
: `unknown:${resolvedProfileId}`;
|
|
639
|
+
return {
|
|
640
|
+
ok: true,
|
|
641
|
+
agent: agentName,
|
|
642
|
+
readiness: bindingResult.readiness,
|
|
643
|
+
profileId: resolvedProfileId,
|
|
644
|
+
profileLabel,
|
|
645
|
+
reason: bindingResult.reason,
|
|
646
|
+
nextAction: bindingResult.nextAction,
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
// 4. Check runtime readiness
|
|
650
|
+
const readinessResult = checkAgentRuntimeReadiness(bindingResult.profile, getEnvVar);
|
|
651
|
+
return {
|
|
652
|
+
ok: true,
|
|
653
|
+
agent: agentName,
|
|
654
|
+
readiness: readinessResult.readiness,
|
|
655
|
+
profileId: bindingResult.profileId,
|
|
656
|
+
profileLabel: buildProfileLabel(bindingResult.profileId, bindingResult.profile),
|
|
657
|
+
reason: readinessResult.reason,
|
|
658
|
+
nextAction: readinessResult.nextAction,
|
|
659
|
+
};
|
|
660
|
+
}
|