create-principles-disciple 1.73.0 → 1.74.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/LICENSE +21 -21
- package/README.md +24 -0
- package/console/dist/server/index.js +13 -1
- package/console/dist/server/routes/agents.js +3 -118
- package/console/dist/server/routes/update-history.d.ts +12 -0
- package/console/dist/server/routes/update-history.js +52 -0
- package/console/dist/server/routes/update.d.ts +10 -0
- package/console/dist/server/routes/update.js +435 -0
- package/console/dist/ui/App.js +2 -1
- package/console/dist/ui/components/UpdateBanner.d.ts +1 -0
- package/console/dist/ui/components/UpdateBanner.js +41 -0
- package/console/dist/ui/components/UpdateProgressDialog.d.ts +12 -0
- package/console/dist/ui/components/UpdateProgressDialog.js +28 -0
- package/console/dist/ui/i18n/en.json +0 -1
- package/console/dist/ui/i18n/zh-CN.json +0 -1
- package/console/dist/ui/pages/AgentsPage.js +3 -17
- package/console/dist/ui/pages/TasksPage.js +0 -1
- package/console/dist/ui/pages/UpdatePage.d.ts +1 -0
- package/console/dist/ui/pages/UpdatePage.js +142 -0
- package/console/dist/web/assets/app.css +7 -0
- package/console/dist/web/assets/app.js +456 -173
- package/console/package.json +2 -0
- package/core/dist/runtime-v2/adapter/__tests__/schema-prompt-adapter.test.d.ts +2 -0
- package/core/dist/runtime-v2/adapter/__tests__/schema-prompt-adapter.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/adapter/__tests__/schema-prompt-adapter.test.js +270 -0
- package/core/dist/runtime-v2/adapter/__tests__/schema-prompt-adapter.test.js.map +1 -0
- package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.d.ts +1 -1
- package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.d.ts.map +1 -1
- package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js +4 -3
- package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js.map +1 -1
- package/core/dist/runtime-v2/adapter/schema-prompt-adapter.d.ts +13 -0
- package/core/dist/runtime-v2/adapter/schema-prompt-adapter.d.ts.map +1 -0
- package/core/dist/runtime-v2/adapter/schema-prompt-adapter.js +266 -0
- package/core/dist/runtime-v2/adapter/schema-prompt-adapter.js.map +1 -0
- package/core/dist/runtime-v2/adapter/tools/diagnostician-tool.d.ts +3 -7
- package/core/dist/runtime-v2/adapter/tools/diagnostician-tool.d.ts.map +1 -1
- package/core/dist/runtime-v2/adapter/tools/diagnostician-tool.js +7 -19
- package/core/dist/runtime-v2/adapter/tools/diagnostician-tool.js.map +1 -1
- package/core/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.test.js +97 -15
- package/core/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.test.js.map +1 -1
- package/core/dist/runtime-v2/diagnostician-output.d.ts +0 -10
- package/core/dist/runtime-v2/diagnostician-output.d.ts.map +1 -1
- package/core/dist/runtime-v2/diagnostician-output.js +5 -10
- package/core/dist/runtime-v2/diagnostician-output.js.map +1 -1
- package/core/dist/runtime-v2/diagnostician-prompt-builder.d.ts +6 -1
- package/core/dist/runtime-v2/diagnostician-prompt-builder.d.ts.map +1 -1
- package/core/dist/runtime-v2/diagnostician-prompt-builder.js +23 -15
- package/core/dist/runtime-v2/diagnostician-prompt-builder.js.map +1 -1
- package/dist/index.js +0 -0
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +67 -0
- package/dist/installer.js.map +1 -1
- package/dist/uninstaller.d.ts +0 -5
- package/dist/uninstaller.d.ts.map +1 -1
- package/dist/uninstaller.js +53 -8
- package/dist/uninstaller.js.map +1 -1
- package/dist/updater.d.ts +45 -0
- package/dist/updater.d.ts.map +1 -0
- package/dist/updater.js +333 -0
- package/dist/updater.js.map +1 -0
- package/dist/utils/env.d.ts +6 -0
- package/dist/utils/env.d.ts.map +1 -1
- package/dist/utils/env.js +54 -0
- package/dist/utils/env.js.map +1 -1
- package/package.json +6 -2
- package/pd-cli/dist/index.js +4 -1
- package/pd-cli/dist/index.js.map +1 -1
- package/pd-cli/package.json +2 -2
- package/plugin/templates/langs/en/skills/ai-sprint-orchestration/runtime/.gitignore +2 -2
- package/plugin/templates/langs/zh/skills/ai-sprint-orchestration/runtime/.gitignore +2 -2
- package/core/dist/runtime-v2/__tests__/nocturnal-compliance-trust-boundary.test.d.ts +0 -2
- package/core/dist/runtime-v2/__tests__/nocturnal-compliance-trust-boundary.test.d.ts.map +0 -1
- package/core/dist/runtime-v2/__tests__/nocturnal-compliance-trust-boundary.test.js +0 -215
- package/core/dist/runtime-v2/__tests__/nocturnal-compliance-trust-boundary.test.js.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-config-resolve.test.d.ts +0 -2
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-config-resolve.test.d.ts.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-config-resolve.test.js +0 -92
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-config-resolve.test.js.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-decision.test.d.ts +0 -2
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-decision.test.d.ts.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-decision.test.js +0 -134
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-decision.test.js.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-edge-cases.test.d.ts +0 -2
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-edge-cases.test.d.ts.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-edge-cases.test.js +0 -226
- package/core/dist/runtime-v2/idle-trigger/__tests__/idle-trigger-edge-cases.test.js.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-decision.d.ts +0 -3
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-decision.d.ts.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-decision.js +0 -5
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-decision.js.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-policy.d.ts +0 -4
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-policy.d.ts.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-policy.js +0 -81
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-policy.js.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-types.d.ts +0 -29
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-types.d.ts.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-types.js +0 -15
- package/core/dist/runtime-v2/idle-trigger/idle-trigger-types.js.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/index.d.ts +0 -5
- package/core/dist/runtime-v2/idle-trigger/index.d.ts.map +0 -1
- package/core/dist/runtime-v2/idle-trigger/index.js +0 -4
- package/core/dist/runtime-v2/idle-trigger/index.js.map +0 -1
- package/core/dist/runtime-v2/nocturnal/candidate-scoring.d.ts +0 -486
- package/core/dist/runtime-v2/nocturnal/candidate-scoring.d.ts.map +0 -1
- package/core/dist/runtime-v2/nocturnal/candidate-scoring.js +0 -493
- package/core/dist/runtime-v2/nocturnal/candidate-scoring.js.map +0 -1
- package/core/dist/runtime-v2/nocturnal/index.d.ts +0 -9
- package/core/dist/runtime-v2/nocturnal/index.d.ts.map +0 -1
- package/core/dist/runtime-v2/nocturnal/index.js +0 -5
- package/core/dist/runtime-v2/nocturnal/index.js.map +0 -1
- package/core/dist/runtime-v2/nocturnal/nocturnal-compliance.d.ts +0 -185
- package/core/dist/runtime-v2/nocturnal/nocturnal-compliance.d.ts.map +0 -1
- package/core/dist/runtime-v2/nocturnal/nocturnal-compliance.js +0 -912
- package/core/dist/runtime-v2/nocturnal/nocturnal-compliance.js.map +0 -1
- package/core/dist/runtime-v2/nocturnal/snapshot-contract.d.ts +0 -192
- package/core/dist/runtime-v2/nocturnal/snapshot-contract.d.ts.map +0 -1
- package/core/dist/runtime-v2/nocturnal/snapshot-contract.js +0 -185
- package/core/dist/runtime-v2/nocturnal/snapshot-contract.js.map +0 -1
- package/core/dist/runtime-v2/nocturnal/trinity-types.d.ts +0 -421
- package/core/dist/runtime-v2/nocturnal/trinity-types.d.ts.map +0 -1
- package/core/dist/runtime-v2/nocturnal/trinity-types.js +0 -182
- package/core/dist/runtime-v2/nocturnal/trinity-types.js.map +0 -1
- package/pd-cli/dist/commands/runtime-idle-trigger.d.ts +0 -12
- package/pd-cli/dist/commands/runtime-idle-trigger.d.ts.map +0 -1
- package/pd-cli/dist/commands/runtime-idle-trigger.js +0 -102
- package/pd-cli/dist/commands/runtime-idle-trigger.js.map +0 -1
- package/plugin/dist/bundle.js +0 -2424
- package/plugin/dist/core/trajectory/index.js +0 -1804
- package/plugin/dist/openclaw.plugin.json +0 -65
- package/plugin/dist/templates/langs/en/core/AGENTS.md +0 -205
- package/plugin/dist/templates/langs/en/core/BOOT.md +0 -60
- package/plugin/dist/templates/langs/en/core/BOOTSTRAP.md +0 -273
- package/plugin/dist/templates/langs/en/core/HEARTBEAT.md +0 -74
- package/plugin/dist/templates/langs/en/core/IDENTITY.md +0 -8
- package/plugin/dist/templates/langs/en/core/PRINCIPLES.md +0 -10
- package/plugin/dist/templates/langs/en/core/SOUL.md +0 -46
- package/plugin/dist/templates/langs/en/core/TOOLS.md +0 -15
- package/plugin/dist/templates/langs/en/core/USER.md +0 -10
- package/plugin/dist/templates/langs/en/pain/00_seed_samples.md +0 -23
- package/plugin/dist/templates/langs/en/pain_dictionary.json +0 -22
- package/plugin/dist/templates/langs/en/principles/THINKING_OS.md +0 -64
- package/plugin/dist/templates/langs/en/skills/admin/SKILL.md +0 -39
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/EXAMPLES.md +0 -63
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/REFERENCE.md +0 -136
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/SKILL.md +0 -67
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/references/agent-registry.json +0 -143
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +0 -107
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +0 -107
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +0 -95
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +0 -98
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +0 -58
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +0 -190
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/runtime/.gitignore +0 -2
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +0 -310
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +0 -683
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +0 -604
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +0 -32
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +0 -707
- package/plugin/dist/templates/langs/en/skills/ai-sprint-orchestration/scripts/run.mjs +0 -3455
- package/plugin/dist/templates/langs/en/skills/bootstrap-tools/SKILL.md +0 -53
- package/plugin/dist/templates/langs/en/skills/deductive-audit/SKILL.md +0 -36
- package/plugin/dist/templates/langs/en/skills/evolution-framework-update/SKILL.md +0 -31
- package/plugin/dist/templates/langs/en/skills/evolve-system/SKILL.md +0 -46
- package/plugin/dist/templates/langs/en/skills/evolve-task/SKILL.md +0 -83
- package/plugin/dist/templates/langs/en/skills/feedback/SKILL.md +0 -51
- package/plugin/dist/templates/langs/en/skills/init-strategy/SKILL.md +0 -54
- package/plugin/dist/templates/langs/en/skills/inject-rule/SKILL.md +0 -19
- package/plugin/dist/templates/langs/en/skills/manage-okr/SKILL.md +0 -96
- package/plugin/dist/templates/langs/en/skills/pd-auditor/SKILL.md +0 -61
- package/plugin/dist/templates/langs/en/skills/pd-cli-operator/SKILL.md +0 -67
- package/plugin/dist/templates/langs/en/skills/pd-daily/SKILL.md +0 -199
- package/plugin/dist/templates/langs/en/skills/pd-diagnostician/SKILL.md +0 -466
- package/plugin/dist/templates/langs/en/skills/pd-explorer/SKILL.md +0 -65
- package/plugin/dist/templates/langs/en/skills/pd-grooming/SKILL.md +0 -46
- package/plugin/dist/templates/langs/en/skills/pd-implementer/SKILL.md +0 -68
- package/plugin/dist/templates/langs/en/skills/pd-mentor/SKILL.md +0 -230
- package/plugin/dist/templates/langs/en/skills/pd-pain-signal/SKILL.md +0 -30
- package/plugin/dist/templates/langs/en/skills/pd-planner/SKILL.md +0 -65
- package/plugin/dist/templates/langs/en/skills/pd-runtime-v2/SKILL.md +0 -61
- package/plugin/dist/templates/langs/en/skills/plan-script/SKILL.md +0 -32
- package/plugin/dist/templates/langs/en/skills/profile/SKILL.md +0 -24
- package/plugin/dist/templates/langs/en/skills/reflection/SKILL.md +0 -40
- package/plugin/dist/templates/langs/en/skills/reflection-log/SKILL.md +0 -37
- package/plugin/dist/templates/langs/en/skills/report/SKILL.md +0 -13
- package/plugin/dist/templates/langs/en/skills/root-cause/SKILL.md +0 -33
- package/plugin/dist/templates/langs/en/skills/triage/SKILL.md +0 -29
- package/plugin/dist/templates/langs/en/skills/watch-evolution/SKILL.md +0 -33
- package/plugin/dist/templates/langs/zh/core/AGENTS.md +0 -197
- package/plugin/dist/templates/langs/zh/core/BOOT.md +0 -60
- package/plugin/dist/templates/langs/zh/core/BOOTSTRAP.md +0 -273
- package/plugin/dist/templates/langs/zh/core/HEARTBEAT.md +0 -98
- package/plugin/dist/templates/langs/zh/core/IDENTITY.md +0 -8
- package/plugin/dist/templates/langs/zh/core/PRINCIPLES.md +0 -7
- package/plugin/dist/templates/langs/zh/core/SOUL.md +0 -46
- package/plugin/dist/templates/langs/zh/core/TOOLS.md +0 -15
- package/plugin/dist/templates/langs/zh/core/USER.md +0 -10
- package/plugin/dist/templates/langs/zh/pain/00_seed_samples.md +0 -24
- package/plugin/dist/templates/langs/zh/pain_dictionary.json +0 -18
- package/plugin/dist/templates/langs/zh/principles/THINKING_OS.md +0 -64
- package/plugin/dist/templates/langs/zh/skills/admin/SKILL.md +0 -41
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/EXAMPLES.md +0 -63
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/REFERENCE.md +0 -136
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/SKILL.md +0 -67
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/references/agent-registry.json +0 -143
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +0 -107
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +0 -107
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/nocturnal-trinity-quality-enhancement.json +0 -111
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +0 -95
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +0 -98
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +0 -58
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +0 -190
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/runtime/.gitignore +0 -2
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +0 -310
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +0 -683
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +0 -604
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +0 -32
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +0 -707
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +0 -3455
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/test/archive.test.mjs +0 -230
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/test/contract-enforcement.test.mjs +0 -672
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/test/decision.test.mjs +0 -1321
- package/plugin/dist/templates/langs/zh/skills/ai-sprint-orchestration/test/run.test.mjs +0 -1435
- package/plugin/dist/templates/langs/zh/skills/bootstrap-tools/SKILL.md +0 -52
- package/plugin/dist/templates/langs/zh/skills/deductive-audit/SKILL.md +0 -36
- package/plugin/dist/templates/langs/zh/skills/evolution-framework-update/SKILL.md +0 -31
- package/plugin/dist/templates/langs/zh/skills/evolve-system/SKILL.md +0 -46
- package/plugin/dist/templates/langs/zh/skills/evolve-task/SKILL.md +0 -83
- package/plugin/dist/templates/langs/zh/skills/feedback/SKILL.md +0 -53
- package/plugin/dist/templates/langs/zh/skills/init-strategy/SKILL.md +0 -54
- package/plugin/dist/templates/langs/zh/skills/inject-rule/SKILL.md +0 -19
- package/plugin/dist/templates/langs/zh/skills/manage-okr/SKILL.md +0 -109
- package/plugin/dist/templates/langs/zh/skills/pd-auditor/SKILL.md +0 -61
- package/plugin/dist/templates/langs/zh/skills/pd-cli-operator/SKILL.md +0 -67
- package/plugin/dist/templates/langs/zh/skills/pd-daily/SKILL.md +0 -283
- package/plugin/dist/templates/langs/zh/skills/pd-diagnostician/SKILL.md +0 -391
- package/plugin/dist/templates/langs/zh/skills/pd-explorer/SKILL.md +0 -65
- package/plugin/dist/templates/langs/zh/skills/pd-grooming/SKILL.md +0 -46
- package/plugin/dist/templates/langs/zh/skills/pd-implementer/SKILL.md +0 -68
- package/plugin/dist/templates/langs/zh/skills/pd-mentor/SKILL.md +0 -230
- package/plugin/dist/templates/langs/zh/skills/pd-pain-signal/SKILL.md +0 -30
- package/plugin/dist/templates/langs/zh/skills/pd-planner/SKILL.md +0 -65
- package/plugin/dist/templates/langs/zh/skills/pd-runtime-v2/SKILL.md +0 -61
- package/plugin/dist/templates/langs/zh/skills/plan-script/SKILL.md +0 -32
- package/plugin/dist/templates/langs/zh/skills/profile/SKILL.md +0 -24
- package/plugin/dist/templates/langs/zh/skills/reflection/SKILL.md +0 -40
- package/plugin/dist/templates/langs/zh/skills/reflection-log/SKILL.md +0 -37
- package/plugin/dist/templates/langs/zh/skills/report/SKILL.md +0 -13
- package/plugin/dist/templates/langs/zh/skills/root-cause/SKILL.md +0 -33
- package/plugin/dist/templates/langs/zh/skills/triage/SKILL.md +0 -29
- package/plugin/dist/templates/langs/zh/skills/watch-evolution/SKILL.md +0 -33
- package/plugin/dist/templates/pain_dictionary.json +0 -36
- package/plugin/dist/templates/pain_settings.json +0 -103
- package/plugin/dist/templates/workspace/.principles/DECISION_POLICY.json +0 -44
- package/plugin/dist/templates/workspace/.principles/PRINCIPLES.md +0 -20
- package/plugin/dist/templates/workspace/.principles/PROFILE.json +0 -54
- package/plugin/dist/templates/workspace/.principles/PROFILE.schema.json +0 -56
- package/plugin/dist/templates/workspace/.principles/THINKING_OS.md +0 -64
- package/plugin/dist/templates/workspace/.principles/THINKING_OS_ARCHIVE.md +0 -7
- package/plugin/dist/templates/workspace/.principles/THINKING_OS_CANDIDATES.md +0 -9
- package/plugin/dist/templates/workspace/.principles/models/_INDEX.md +0 -27
- package/plugin/dist/templates/workspace/.principles/models/first_principles.md +0 -62
- package/plugin/dist/templates/workspace/.principles/models/marketing_4p.md +0 -52
- package/plugin/dist/templates/workspace/.principles/models/porter_five.md +0 -63
- package/plugin/dist/templates/workspace/.principles/models/swot.md +0 -60
- package/plugin/dist/templates/workspace/.principles/models/user_story_map.md +0 -63
- package/plugin/dist/templates/workspace/.state/WORKBOARD.json +0 -4
- package/plugin/dist/templates/workspace/AUDIT.md +0 -15
- package/plugin/dist/templates/workspace/PLAN.md +0 -2
- package/plugin/dist/templates/workspace/okr/CURRENT_FOCUS.md +0 -57
- package/plugin/dist/templates/workspace/okr/RECOVERY_PROTOCOL.md +0 -56
- package/plugin/dist/templates/workspace/okr/TASK_CHANGES.jsonl +0 -6
- package/plugin/dist/templates/workspace/okr/WEEK_TASKS.json +0 -6
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import { execSync } from 'child_process';
|
|
5
|
+
import semver from 'semver';
|
|
6
|
+
import { sendSuccess, sendError, sendMethodNotAllowed, sendBadRequest, sendNotFound, } from '../utils/response.js';
|
|
7
|
+
import { appendUpdateHistory } from './update-history.js';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Constants
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
const NPM_REGISTRY_LATEST = 'https://registry.npmjs.org/create-principles-disciple/latest';
|
|
12
|
+
const WORKSPACE_FILES = ['AGENTS.md', 'SOUL.md', 'USER.md', 'CLAUDE.md'];
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Helpers
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
function resolvePluginDir(workspaceDir) {
|
|
17
|
+
return path.join(path.dirname(workspaceDir), 'extensions', 'principles-disciple');
|
|
18
|
+
}
|
|
19
|
+
function readCurrentVersion(pluginDir) {
|
|
20
|
+
const pkgPath = path.join(pluginDir, 'package.json');
|
|
21
|
+
try {
|
|
22
|
+
if (!fs.existsSync(pkgPath))
|
|
23
|
+
return undefined;
|
|
24
|
+
const raw = fs.readFileSync(pkgPath, 'utf-8');
|
|
25
|
+
const parsed = JSON.parse(raw);
|
|
26
|
+
if (typeof parsed === 'object' && parsed !== null && Object.hasOwn(parsed, 'version')) {
|
|
27
|
+
const { version } = parsed;
|
|
28
|
+
if (typeof version === 'string')
|
|
29
|
+
return version;
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function readJsonBody(req) {
|
|
38
|
+
let body = '';
|
|
39
|
+
req.on('data', (chunk) => { body += chunk.toString(); });
|
|
40
|
+
await new Promise((resolve) => { req.on('end', resolve); });
|
|
41
|
+
return JSON.parse(body);
|
|
42
|
+
}
|
|
43
|
+
function isString(value) {
|
|
44
|
+
return typeof value === 'string';
|
|
45
|
+
}
|
|
46
|
+
function isValidMergeStrategy(value) {
|
|
47
|
+
return typeof value === 'string' && (value === 'smart' || value === 'overwrite' || value === 'keep');
|
|
48
|
+
}
|
|
49
|
+
function validatePathInWorkspace(target, workspaceDir) {
|
|
50
|
+
const resolved = path.resolve(target);
|
|
51
|
+
const resolvedWorkspace = path.resolve(workspaceDir);
|
|
52
|
+
// Allow paths within workspace or within the extensions directory
|
|
53
|
+
const extensionsDir = path.resolve(path.join(path.dirname(workspaceDir), 'extensions'));
|
|
54
|
+
return resolved.startsWith(resolvedWorkspace + path.sep) || resolved === resolvedWorkspace
|
|
55
|
+
|| resolved.startsWith(extensionsDir + path.sep) || resolved === extensionsDir;
|
|
56
|
+
}
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Core update operations (inline to avoid cross-package import)
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
function copyDirRecursive(src, dest) {
|
|
61
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
62
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
63
|
+
for (const entry of entries) {
|
|
64
|
+
const srcPath = path.join(src, entry.name);
|
|
65
|
+
const destPath = path.join(dest, entry.name);
|
|
66
|
+
if (entry.isDirectory()) {
|
|
67
|
+
copyDirRecursive(srcPath, destPath);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
fs.copyFileSync(srcPath, destPath);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function isWorkspaceFile(filePath) {
|
|
75
|
+
return WORKSPACE_FILES.some(f => filePath.endsWith(f));
|
|
76
|
+
}
|
|
77
|
+
function copyFileTo(src, dest) {
|
|
78
|
+
const dir = path.dirname(dest);
|
|
79
|
+
if (!fs.existsSync(dir))
|
|
80
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
81
|
+
fs.copyFileSync(src, dest);
|
|
82
|
+
}
|
|
83
|
+
function getAllFilesLocal(dir) {
|
|
84
|
+
const result = [];
|
|
85
|
+
try {
|
|
86
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
87
|
+
for (const entry of entries) {
|
|
88
|
+
const fullPath = path.join(dir, entry.name);
|
|
89
|
+
if (entry.isDirectory()) {
|
|
90
|
+
const subFiles = getAllFilesLocal(fullPath);
|
|
91
|
+
result.push(...subFiles.map(f => path.join(entry.name, f)));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
result.push(entry.name);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch { /* ignore */ }
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
function computeDiffLocal(currentDir, newDir) {
|
|
102
|
+
const modified = [];
|
|
103
|
+
const added = [];
|
|
104
|
+
const deleted = [];
|
|
105
|
+
const currentFiles = getAllFilesLocal(currentDir);
|
|
106
|
+
const newFiles = getAllFilesLocal(newDir);
|
|
107
|
+
const currentSet = new Set(currentFiles);
|
|
108
|
+
const newSet = new Set(newFiles);
|
|
109
|
+
for (const file of currentFiles) {
|
|
110
|
+
if (newSet.has(file)) {
|
|
111
|
+
try {
|
|
112
|
+
const cur = fs.readFileSync(path.join(currentDir, file), 'utf-8');
|
|
113
|
+
const nw = fs.readFileSync(path.join(newDir, file), 'utf-8');
|
|
114
|
+
if (cur !== nw)
|
|
115
|
+
modified.push(file);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
modified.push(file);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
deleted.push(file);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
for (const file of newFiles) {
|
|
126
|
+
if (!currentSet.has(file))
|
|
127
|
+
added.push(file);
|
|
128
|
+
}
|
|
129
|
+
return { modified, added, deleted };
|
|
130
|
+
}
|
|
131
|
+
async function doCheckForUpdates(currentVersion) {
|
|
132
|
+
try {
|
|
133
|
+
const controller = new AbortController();
|
|
134
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
135
|
+
let latestVersion = '';
|
|
136
|
+
try {
|
|
137
|
+
const response = await fetch(NPM_REGISTRY_LATEST, {
|
|
138
|
+
signal: controller.signal,
|
|
139
|
+
});
|
|
140
|
+
if (!response.ok)
|
|
141
|
+
throw new Error(`HTTP ${response.status}`);
|
|
142
|
+
const rawData = await response.json();
|
|
143
|
+
if (typeof rawData !== 'object' || rawData === null)
|
|
144
|
+
throw new Error('Invalid registry response');
|
|
145
|
+
const data = rawData;
|
|
146
|
+
if (typeof data.version !== 'string')
|
|
147
|
+
throw new Error('Invalid registry response: missing version');
|
|
148
|
+
latestVersion = data.version;
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
clearTimeout(timeoutId);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
hasUpdate: semver.gt(latestVersion, currentVersion),
|
|
155
|
+
currentVersion,
|
|
156
|
+
latestVersion,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
return {
|
|
161
|
+
hasUpdate: false,
|
|
162
|
+
currentVersion,
|
|
163
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async function doApplyUpdate(options, workspaceDir) {
|
|
168
|
+
const { targetDir, mergeStrategy, createBackup } = options;
|
|
169
|
+
try {
|
|
170
|
+
// 0. Save current version BEFORE any changes
|
|
171
|
+
const fromVersion = readCurrentVersion(targetDir) ?? 'unknown';
|
|
172
|
+
// 1. Fetch latest package info
|
|
173
|
+
const response = await fetch(NPM_REGISTRY_LATEST);
|
|
174
|
+
if (!response.ok)
|
|
175
|
+
return { success: false, message: `Failed to fetch package info: HTTP ${response.status}` };
|
|
176
|
+
const rawData = await response.json();
|
|
177
|
+
if (typeof rawData !== 'object' || rawData === null)
|
|
178
|
+
return { success: false, message: 'Invalid registry response' };
|
|
179
|
+
const data = rawData;
|
|
180
|
+
const toVersion = typeof data.version === 'string' ? data.version : undefined;
|
|
181
|
+
if (!toVersion)
|
|
182
|
+
return { success: false, message: 'Missing version in registry response' };
|
|
183
|
+
const dist = typeof data.dist === 'object' && data.dist !== null ? data.dist : null;
|
|
184
|
+
const tarball = dist && typeof dist.tarball === 'string' ? dist.tarball : undefined;
|
|
185
|
+
if (!tarball)
|
|
186
|
+
return { success: false, message: 'Missing tarball URL in registry response' };
|
|
187
|
+
// 2. Create backup if requested
|
|
188
|
+
let backupPath = undefined;
|
|
189
|
+
if (createBackup) {
|
|
190
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
191
|
+
backupPath = path.join(path.dirname(targetDir), `.pd-backup-${timestamp}`);
|
|
192
|
+
copyDirRecursive(targetDir, backupPath);
|
|
193
|
+
}
|
|
194
|
+
// 3. Download and extract new version
|
|
195
|
+
const tempDir = path.join(os.tmpdir(), `pd-update-${Date.now()}`);
|
|
196
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
197
|
+
try {
|
|
198
|
+
const dlResponse = await fetch(tarball);
|
|
199
|
+
if (!dlResponse.ok)
|
|
200
|
+
throw new Error(`Download failed: HTTP ${dlResponse.status}`);
|
|
201
|
+
const buffer = Buffer.from(await dlResponse.arrayBuffer());
|
|
202
|
+
const tarballPath = path.join(tempDir, 'package.tgz');
|
|
203
|
+
fs.writeFileSync(tarballPath, buffer);
|
|
204
|
+
execSync(`tar xzf "${tarballPath}" -C "${tempDir}" --strip-components=1`, { stdio: 'pipe' });
|
|
205
|
+
fs.unlinkSync(tarballPath);
|
|
206
|
+
}
|
|
207
|
+
catch (dlError) {
|
|
208
|
+
// Clean up temp dir on download failure
|
|
209
|
+
if (fs.existsSync(tempDir))
|
|
210
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
211
|
+
throw dlError;
|
|
212
|
+
}
|
|
213
|
+
// 4. Compute diff and apply
|
|
214
|
+
const diff = computeDiffLocal(targetDir, tempDir);
|
|
215
|
+
const updatedFiles = [];
|
|
216
|
+
for (const file of diff.modified) {
|
|
217
|
+
if (isWorkspaceFile(file)) {
|
|
218
|
+
switch (mergeStrategy) {
|
|
219
|
+
case 'smart': {
|
|
220
|
+
const content = fs.readFileSync(path.join(tempDir, file), 'utf-8');
|
|
221
|
+
fs.writeFileSync(path.join(targetDir, `${file}.update`), content);
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
case 'overwrite':
|
|
225
|
+
copyFileTo(path.join(tempDir, file), path.join(targetDir, file));
|
|
226
|
+
updatedFiles.push(file);
|
|
227
|
+
break;
|
|
228
|
+
case 'keep':
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
copyFileTo(path.join(tempDir, file), path.join(targetDir, file));
|
|
234
|
+
updatedFiles.push(file);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
for (const file of diff.added) {
|
|
238
|
+
copyFileTo(path.join(tempDir, file), path.join(targetDir, file));
|
|
239
|
+
updatedFiles.push(file);
|
|
240
|
+
}
|
|
241
|
+
for (const file of diff.deleted) {
|
|
242
|
+
// Only delete non-workspace files, or workspace files when strategy is overwrite
|
|
243
|
+
if (isWorkspaceFile(file) && mergeStrategy !== 'overwrite') {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
const filePath = path.join(targetDir, file);
|
|
247
|
+
if (fs.existsSync(filePath))
|
|
248
|
+
fs.unlinkSync(filePath);
|
|
249
|
+
updatedFiles.push(file);
|
|
250
|
+
}
|
|
251
|
+
// 5. Update package.json version
|
|
252
|
+
const pkgPath = path.join(targetDir, 'package.json');
|
|
253
|
+
if (fs.existsSync(pkgPath)) {
|
|
254
|
+
const rawPkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
255
|
+
if (typeof rawPkg === 'object' && rawPkg !== null) {
|
|
256
|
+
const pkg = { ...rawPkg, version: toVersion };
|
|
257
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// 6. Cleanup temp dir
|
|
261
|
+
if (fs.existsSync(tempDir))
|
|
262
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
263
|
+
// 7. Record update history (fromVersion is the OLD version saved before changes)
|
|
264
|
+
appendUpdateHistory(workspaceDir, {
|
|
265
|
+
fromVersion,
|
|
266
|
+
toVersion,
|
|
267
|
+
success: true,
|
|
268
|
+
backupPath,
|
|
269
|
+
});
|
|
270
|
+
return {
|
|
271
|
+
success: true,
|
|
272
|
+
message: 'Update applied successfully',
|
|
273
|
+
updatedFiles,
|
|
274
|
+
backupPath,
|
|
275
|
+
newVersion: toVersion,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
return {
|
|
280
|
+
success: false,
|
|
281
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async function doRollbackUpdate(options, workspaceDir) {
|
|
286
|
+
const { targetDir, backupDir } = options;
|
|
287
|
+
try {
|
|
288
|
+
if (!fs.existsSync(backupDir)) {
|
|
289
|
+
return { success: false, message: 'Backup not found' };
|
|
290
|
+
}
|
|
291
|
+
if (fs.existsSync(targetDir)) {
|
|
292
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
293
|
+
}
|
|
294
|
+
copyDirRecursive(backupDir, targetDir);
|
|
295
|
+
// Record rollback history
|
|
296
|
+
appendUpdateHistory(workspaceDir, {
|
|
297
|
+
fromVersion: 'rolled-back',
|
|
298
|
+
toVersion: readCurrentVersion(targetDir) ?? 'unknown',
|
|
299
|
+
success: true,
|
|
300
|
+
backupPath: backupDir,
|
|
301
|
+
});
|
|
302
|
+
return { success: true, message: 'Rollback completed successfully' };
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
return {
|
|
306
|
+
success: false,
|
|
307
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// ---------------------------------------------------------------------------
|
|
312
|
+
// Route handler
|
|
313
|
+
// ---------------------------------------------------------------------------
|
|
314
|
+
export async function handleUpdateRoute(req, res, workspaceDir, subPath) {
|
|
315
|
+
const pluginDir = resolvePluginDir(workspaceDir);
|
|
316
|
+
// GET /check
|
|
317
|
+
if (subPath === '/check') {
|
|
318
|
+
if (req.method !== 'GET') {
|
|
319
|
+
sendMethodNotAllowed(res);
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
try {
|
|
323
|
+
const currentVersion = readCurrentVersion(pluginDir);
|
|
324
|
+
if (!currentVersion) {
|
|
325
|
+
sendError(res, 500, 'version_not_found', 'Could not determine current version');
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const result = await doCheckForUpdates(currentVersion);
|
|
329
|
+
sendSuccess(res, result);
|
|
330
|
+
}
|
|
331
|
+
catch (err) {
|
|
332
|
+
sendError(res, 500, 'update_check_error', err instanceof Error ? err.message : 'Unknown error');
|
|
333
|
+
}
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
// POST /apply
|
|
337
|
+
if (subPath === '/apply') {
|
|
338
|
+
if (req.method !== 'POST') {
|
|
339
|
+
sendMethodNotAllowed(res);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
try {
|
|
343
|
+
const rawBody = await readJsonBody(req);
|
|
344
|
+
if (typeof rawBody !== 'object' || rawBody === null) {
|
|
345
|
+
sendBadRequest(res, 'Request body must be a JSON object');
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
const body = rawBody;
|
|
349
|
+
// targetDir is optional — if not provided, resolve from workspaceDir
|
|
350
|
+
const targetDir = isString(body.targetDir) && body.targetDir.length > 0
|
|
351
|
+
? body.targetDir
|
|
352
|
+
: pluginDir;
|
|
353
|
+
const { mergeStrategy } = body;
|
|
354
|
+
if (!isValidMergeStrategy(mergeStrategy)) {
|
|
355
|
+
sendBadRequest(res, 'Missing or invalid field: mergeStrategy');
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
// createBackup is a boolean (default false)
|
|
359
|
+
const createBackup = typeof body.createBackup === 'boolean' ? body.createBackup : false;
|
|
360
|
+
// Path traversal validation
|
|
361
|
+
if (!validatePathInWorkspace(targetDir, workspaceDir)) {
|
|
362
|
+
sendBadRequest(res, 'targetDir must be within workspace or extensions directory');
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
const result = await doApplyUpdate({
|
|
366
|
+
targetDir,
|
|
367
|
+
mergeStrategy,
|
|
368
|
+
createBackup,
|
|
369
|
+
}, workspaceDir);
|
|
370
|
+
sendSuccess(res, result);
|
|
371
|
+
}
|
|
372
|
+
catch (err) {
|
|
373
|
+
if (err instanceof SyntaxError) {
|
|
374
|
+
sendBadRequest(res, 'Invalid JSON body');
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
sendError(res, 500, 'update_apply_error', err instanceof Error ? err.message : 'Unknown error');
|
|
378
|
+
}
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
// GET /status
|
|
382
|
+
if (subPath === '/status') {
|
|
383
|
+
if (req.method !== 'GET') {
|
|
384
|
+
sendMethodNotAllowed(res);
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
const currentVersion = readCurrentVersion(pluginDir) ?? 'unknown';
|
|
388
|
+
sendSuccess(res, { checking: false, updating: false, currentVersion });
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
// POST /rollback
|
|
392
|
+
if (subPath === '/rollback') {
|
|
393
|
+
if (req.method !== 'POST') {
|
|
394
|
+
sendMethodNotAllowed(res);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
try {
|
|
398
|
+
const rawBody = await readJsonBody(req);
|
|
399
|
+
if (typeof rawBody !== 'object' || rawBody === null) {
|
|
400
|
+
sendBadRequest(res, 'Request body must be a JSON object');
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
const body = rawBody;
|
|
404
|
+
// targetDir is optional — if not provided, resolve from workspaceDir
|
|
405
|
+
const targetDir = isString(body.targetDir) && body.targetDir.length > 0
|
|
406
|
+
? body.targetDir
|
|
407
|
+
: pluginDir;
|
|
408
|
+
const { backupDir } = body;
|
|
409
|
+
if (!isString(backupDir) || backupDir.length === 0) {
|
|
410
|
+
sendBadRequest(res, 'Missing or invalid field: backupDir');
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
// Path traversal validation
|
|
414
|
+
if (!validatePathInWorkspace(targetDir, workspaceDir)) {
|
|
415
|
+
sendBadRequest(res, 'targetDir must be within workspace or extensions directory');
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (!validatePathInWorkspace(backupDir, workspaceDir)) {
|
|
419
|
+
sendBadRequest(res, 'backupDir must be within workspace or extensions directory');
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
const result = await doRollbackUpdate({ targetDir, backupDir }, workspaceDir);
|
|
423
|
+
sendSuccess(res, result);
|
|
424
|
+
}
|
|
425
|
+
catch (err) {
|
|
426
|
+
if (err instanceof SyntaxError) {
|
|
427
|
+
sendBadRequest(res, 'Invalid JSON body');
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
sendError(res, 500, 'update_rollback_error', err instanceof Error ? err.message : 'Unknown error');
|
|
431
|
+
}
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
sendNotFound(res, `Update route not found: ${subPath}`);
|
|
435
|
+
}
|
package/console/dist/ui/App.js
CHANGED
|
@@ -25,6 +25,7 @@ import { PrinciplesPage } from "./pages/PrinciplesPage.js";
|
|
|
25
25
|
import { PrincipleDetailPage } from "./pages/PrincipleDetailPage.js";
|
|
26
26
|
import { AgentsPage } from "./pages/AgentsPage.js";
|
|
27
27
|
import { LoginPage } from "./pages/LoginPage.js";
|
|
28
|
+
import { UpdatePage } from "./pages/UpdatePage.js";
|
|
28
29
|
import { ErrorBoundary } from "./components/error-boundary.js";
|
|
29
30
|
import { getToken, clearToken, checkAuth } from "./api.js";
|
|
30
31
|
export function App() {
|
|
@@ -48,5 +49,5 @@ export function App() {
|
|
|
48
49
|
clearToken();
|
|
49
50
|
setAuthed(false);
|
|
50
51
|
};
|
|
51
|
-
return (_jsx(ThemeProvider, { children: _jsx(I18nextProvider, { i18n: i18n, children: _jsx(HashRouter, { children: _jsxs("div", { className: "min-h-screen bg-background text-foreground", children: [_jsx("a", { href: "#main-content", className: "sr-only focus:not-sr-only focus:absolute focus:z-50 focus:p-4 focus:bg-background focus:text-foreground", children: "Skip to main content" }), _jsx(AppSidebar, { collapsed: sidebarCollapsed, onCollapsedChange: setSidebarCollapsed }), _jsxs("div", { className: `transition-[margin] duration-300 motion-reduce:transition-none flex flex-col min-h-screen ${sidebarCollapsed ? "ml-16" : "ml-56"}`, children: [_jsx("header", { className: "sticky top-0 z-40 border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60", children: _jsxs("div", { className: "flex items-center justify-between px-6 py-3", children: [_jsx("div", { className: "flex items-center gap-4", children: _jsx("span", { className: "text-sm font-medium text-muted-foreground", children: "PD Console v0.2" }) }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(LanguageSwitcher, {}), _jsx(ThemeToggle, {}), getToken() && (_jsx(Button, { variant: "ghost", size: "sm", onClick: handleSignOut, children: t("common:logout") }))] })] }) }), _jsx("main", { id: "main-content", className: "flex-1 p-6 overflow-y-auto", children: _jsx(ErrorBoundary, { children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(PainPage, {}) }), _jsx(Route, { path: "/pain", element: _jsx(PainPage, {}) }), _jsx(Route, { path: "/approvals", element: _jsx(ApprovalsPage, {}) }), _jsx(Route, { path: "/overview", element: _jsx(OverviewPage, {}) }), _jsx(Route, { path: "/central", element: _jsx(CentralPage, {}) }), _jsx(Route, { path: "/tasks", element: _jsx(TasksPage, {}) }), _jsx(Route, { path: "/feedback", element: _jsx(FeedbackPage, {}) }), _jsx(Route, { path: "/gates", element: _jsx(GatesPage, {}) }), _jsx(Route, { path: "/samples", element: _jsx(SamplesPage, {}) }), _jsx(Route, { path: "/evolution", element: _jsx(EvolutionPage, {}) }), _jsx(Route, { path: "/principles", element: _jsx(PrinciplesPage, {}) }), _jsx(Route, { path: "/principles/:id", element: _jsx(PrincipleDetailPage, {}) }), _jsx(Route, { path: "/agents", element: _jsx(AgentsPage, {}) }), _jsx(Route, { path: "/data-flow", element: _jsx(DataFlowPage, {}) }), _jsx(Route, { path: "/event-log", element: _jsx(EventLogPage, {}) }), _jsx(Route, { path: "/thinking-models", element: _jsx(ThinkingModelsPage, {}) }), _jsx(Route, { path: "/settings", element: _jsx(SettingsPage, {}) })] }) }) })] })] }) }) }) }));
|
|
52
|
+
return (_jsx(ThemeProvider, { children: _jsx(I18nextProvider, { i18n: i18n, children: _jsx(HashRouter, { children: _jsxs("div", { className: "min-h-screen bg-background text-foreground", children: [_jsx("a", { href: "#main-content", className: "sr-only focus:not-sr-only focus:absolute focus:z-50 focus:p-4 focus:bg-background focus:text-foreground", children: "Skip to main content" }), _jsx(AppSidebar, { collapsed: sidebarCollapsed, onCollapsedChange: setSidebarCollapsed }), _jsxs("div", { className: `transition-[margin] duration-300 motion-reduce:transition-none flex flex-col min-h-screen ${sidebarCollapsed ? "ml-16" : "ml-56"}`, children: [_jsx("header", { className: "sticky top-0 z-40 border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60", children: _jsxs("div", { className: "flex items-center justify-between px-6 py-3", children: [_jsx("div", { className: "flex items-center gap-4", children: _jsx("span", { className: "text-sm font-medium text-muted-foreground", children: "PD Console v0.2" }) }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(LanguageSwitcher, {}), _jsx(ThemeToggle, {}), getToken() && (_jsx(Button, { variant: "ghost", size: "sm", onClick: handleSignOut, children: t("common:logout") }))] })] }) }), _jsx("main", { id: "main-content", className: "flex-1 p-6 overflow-y-auto", children: _jsx(ErrorBoundary, { children: _jsxs(Routes, { children: [_jsx(Route, { path: "/", element: _jsx(PainPage, {}) }), _jsx(Route, { path: "/pain", element: _jsx(PainPage, {}) }), _jsx(Route, { path: "/approvals", element: _jsx(ApprovalsPage, {}) }), _jsx(Route, { path: "/overview", element: _jsx(OverviewPage, {}) }), _jsx(Route, { path: "/central", element: _jsx(CentralPage, {}) }), _jsx(Route, { path: "/tasks", element: _jsx(TasksPage, {}) }), _jsx(Route, { path: "/feedback", element: _jsx(FeedbackPage, {}) }), _jsx(Route, { path: "/gates", element: _jsx(GatesPage, {}) }), _jsx(Route, { path: "/samples", element: _jsx(SamplesPage, {}) }), _jsx(Route, { path: "/evolution", element: _jsx(EvolutionPage, {}) }), _jsx(Route, { path: "/principles", element: _jsx(PrinciplesPage, {}) }), _jsx(Route, { path: "/principles/:id", element: _jsx(PrincipleDetailPage, {}) }), _jsx(Route, { path: "/agents", element: _jsx(AgentsPage, {}) }), _jsx(Route, { path: "/data-flow", element: _jsx(DataFlowPage, {}) }), _jsx(Route, { path: "/event-log", element: _jsx(EventLogPage, {}) }), _jsx(Route, { path: "/thinking-models", element: _jsx(ThinkingModelsPage, {}) }), _jsx(Route, { path: "/settings", element: _jsx(SettingsPage, {}) }), _jsx(Route, { path: "/settings/update", element: _jsx(UpdatePage, {}) })] }) }) })] })] }) }) }) }));
|
|
52
53
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function UpdateBanner(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { Badge } from "./ui/badge.js";
|
|
5
|
+
import { RefreshCw, X } from "lucide-react";
|
|
6
|
+
export function UpdateBanner() {
|
|
7
|
+
const { t } = useTranslation();
|
|
8
|
+
const [updateInfo, setUpdateInfo] = useState(null);
|
|
9
|
+
const [dismissed, setDismissed] = useState(false);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
async function check() {
|
|
12
|
+
try {
|
|
13
|
+
const response = await fetch("/api/update/check");
|
|
14
|
+
const result = await response.json();
|
|
15
|
+
if (typeof result === "object" && result !== null &&
|
|
16
|
+
Object.hasOwn(result, "success") && result.success === true) {
|
|
17
|
+
const data = result.data;
|
|
18
|
+
if (typeof data === "object" && data !== null &&
|
|
19
|
+
typeof data.hasUpdate === "boolean" &&
|
|
20
|
+
typeof data.currentVersion === "string") {
|
|
21
|
+
setUpdateInfo(data);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
console.error("[UpdateBanner] Invalid data shape from /api/update/check:", data);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
console.error("[UpdateBanner] Failed to check for updates:", err);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
check();
|
|
33
|
+
}, []);
|
|
34
|
+
if (!updateInfo?.hasUpdate || dismissed) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return (_jsx("div", { className: "bg-primary/5 border-b border-primary/20 px-4 py-2", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(RefreshCw, { className: "h-4 w-4 text-primary animate-spin", style: { animationDuration: "3s" } }), _jsx("span", { className: "text-sm", children: t("components:updateBanner.newVersion", {
|
|
38
|
+
version: updateInfo.latestVersion,
|
|
39
|
+
defaultValue: `PD ${updateInfo.latestVersion} 可用`,
|
|
40
|
+
}) }), _jsxs(Badge, { variant: "outline", className: "text-xs", children: [updateInfo.currentVersion, " \u2192 ", updateInfo.latestVersion] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("a", { href: "#/settings/update", className: "text-sm font-medium text-primary hover:underline", children: t("components:updateBanner.updateNow", { defaultValue: "立即更新" }) }), _jsx("button", { onClick: () => setDismissed(true), className: "p-1 text-muted-foreground hover:text-foreground", "aria-label": t("common:dismiss", { defaultValue: "关闭" }), children: _jsx(X, { className: "h-3 w-3" }) })] })] }) }));
|
|
41
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type UpdateStatus = "checking" | "downloading" | "applying" | "completed" | "failed";
|
|
2
|
+
interface UpdateProgressDialogProps {
|
|
3
|
+
open: boolean;
|
|
4
|
+
onOpenChange: (open: boolean) => void;
|
|
5
|
+
status: UpdateStatus;
|
|
6
|
+
currentVersion: string;
|
|
7
|
+
targetVersion: string;
|
|
8
|
+
errorMessage?: string;
|
|
9
|
+
onRollback?: () => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function UpdateProgressDialog({ open, onOpenChange, status, currentVersion, targetVersion, errorMessage, onRollback, }: UpdateProgressDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from "./ui/dialog.js";
|
|
4
|
+
import { Button } from "./ui/button.js";
|
|
5
|
+
import { Loader2, CheckCircle2, XCircle } from "lucide-react";
|
|
6
|
+
const STATUS_ICONS = {
|
|
7
|
+
checking: _jsx(Loader2, { className: "h-5 w-5 animate-spin text-primary" }),
|
|
8
|
+
downloading: _jsx(Loader2, { className: "h-5 w-5 animate-spin text-primary" }),
|
|
9
|
+
applying: _jsx(Loader2, { className: "h-5 w-5 animate-spin text-primary" }),
|
|
10
|
+
completed: _jsx(CheckCircle2, { className: "h-5 w-5 text-green-600" }),
|
|
11
|
+
failed: _jsx(XCircle, { className: "h-5 w-5 text-destructive" }),
|
|
12
|
+
};
|
|
13
|
+
export function UpdateProgressDialog({ open, onOpenChange, status, currentVersion, targetVersion, errorMessage, onRollback, }) {
|
|
14
|
+
const { t } = useTranslation();
|
|
15
|
+
const isActive = status === "checking" || status === "downloading" || status === "applying";
|
|
16
|
+
const isDone = status === "completed" || status === "failed";
|
|
17
|
+
const statusLabels = {
|
|
18
|
+
checking: t("components:updateProgress.checking", { defaultValue: "正在检查更新..." }),
|
|
19
|
+
downloading: t("components:updateProgress.downloading", { defaultValue: "正在下载更新包..." }),
|
|
20
|
+
applying: t("components:updateProgress.applying", { defaultValue: "正在应用更新..." }),
|
|
21
|
+
completed: t("components:updateProgress.completed", { defaultValue: "更新完成!" }),
|
|
22
|
+
failed: t("components:updateProgress.failed", { defaultValue: "更新失败" }),
|
|
23
|
+
};
|
|
24
|
+
return (_jsx(Dialog, { open: open, onOpenChange: isDone ? onOpenChange : undefined, children: _jsxs(DialogContent, { className: "max-w-md", onPointerDownOutside: (e) => { if (isActive)
|
|
25
|
+
e.preventDefault(); }, children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { className: "flex items-center gap-2", children: [STATUS_ICONS[status], statusLabels[status]] }), _jsx(DialogDescription, { children: _jsxs("span", { className: "font-mono text-sm", children: ["v", currentVersion, " \u2192 v", targetVersion] }) })] }), status === "failed" && errorMessage && (_jsx("div", { className: "rounded-md bg-destructive/10 p-3 text-sm text-destructive", children: errorMessage })), isActive && (_jsx("div", { className: "space-y-2", children: _jsx("div", { className: "h-2 rounded-full bg-muted overflow-hidden", children: _jsx("div", { className: "h-full bg-primary rounded-full transition-all duration-500", style: {
|
|
26
|
+
width: status === "checking" ? "30%" : status === "downloading" ? "60%" : "85%",
|
|
27
|
+
} }) }) })), _jsxs(DialogFooter, { children: [status === "failed" && onRollback && (_jsx(Button, { variant: "outline", onClick: onRollback, children: t("components:updateProgress.rollback", { defaultValue: "回滚" }) })), isDone && (_jsx(Button, { onClick: () => onOpenChange(false), children: t("common:close", { defaultValue: "关闭" }) }))] })] }) }));
|
|
28
|
+
}
|
|
@@ -99,7 +99,6 @@
|
|
|
99
99
|
"noToken": "No authentication token configured",
|
|
100
100
|
"checkingAuth": "Checking authentication…",
|
|
101
101
|
"agentDiagnostician": "Diagnostician",
|
|
102
|
-
"agentNocturnalReflection": "Nocturnal Reflection",
|
|
103
102
|
"agentCorrectionObserver": "Correction Observer",
|
|
104
103
|
"secondsAgo": "{{count}}s ago",
|
|
105
104
|
"minutesAgo": "{{count}}m ago",
|
|
@@ -40,20 +40,12 @@ const FLOW_NODES = [
|
|
|
40
40
|
{ id: "pain-diagnostic-gate", x: 280, y: 40, w: 170, h: 52, nameZh: "PainDiagnosticGate", icon: "SearchCheck" },
|
|
41
41
|
{ id: "diagnostician", x: 520, y: 40, w: 150, h: 52, nameZh: "诊断者", icon: "Stethoscope" },
|
|
42
42
|
{ id: "evolution-worker", x: 60, y: 180, w: 170, h: 52, nameZh: "Evolution Worker", icon: "Cpu" },
|
|
43
|
-
{ id: "
|
|
44
|
-
{ id: "
|
|
45
|
-
{ id: "trinity-philosopher", x: 560, y: 192, w: 130, h: 44, nameZh: "Philosopher", icon: "Scale", small: true },
|
|
46
|
-
{ id: "trinity-scribe", x: 560, y: 244, w: 130, h: 44, nameZh: "Scribe", icon: "PenTool", small: true },
|
|
47
|
-
{ id: "correction-observer", x: 310, y: 320, w: 170, h: 52, nameZh: "纠正观察者", icon: "SearchCheck" },
|
|
48
|
-
{ id: "detection-funnel", x: 60, y: 320, w: 150, h: 44, nameZh: "Detection Funnel", icon: "Cpu", small: true },
|
|
43
|
+
{ id: "correction-observer", x: 310, y: 180, w: 170, h: 52, nameZh: "纠正观察者", icon: "SearchCheck" },
|
|
44
|
+
{ id: "detection-funnel", x: 560, y: 180, w: 150, h: 44, nameZh: "Detection Funnel", icon: "Cpu", small: true },
|
|
49
45
|
];
|
|
50
46
|
const FLOW_EDGES = [
|
|
51
47
|
{ from: "after_tool_call", to: "pain-diagnostic-gate" },
|
|
52
48
|
{ from: "pain-diagnostic-gate", to: "diagnostician" },
|
|
53
|
-
{ from: "evolution-worker", to: "nocturnal-reflection" },
|
|
54
|
-
{ from: "nocturnal-reflection", to: "trinity-dreamer" },
|
|
55
|
-
{ from: "nocturnal-reflection", to: "trinity-philosopher" },
|
|
56
|
-
{ from: "nocturnal-reflection", to: "trinity-scribe" },
|
|
57
49
|
{ from: "evolution-worker", to: "correction-observer" },
|
|
58
50
|
{ from: "evolution-worker", to: "detection-funnel" },
|
|
59
51
|
];
|
|
@@ -77,12 +69,6 @@ function AgentNode({ node, agent, selected, onClick, }) {
|
|
|
77
69
|
const status = agent?.status ?? "unknown";
|
|
78
70
|
return (_jsxs("g", { onClick: onClick, style: { cursor: "pointer" }, children: [_jsx("rect", { x: node.x, y: node.y, width: node.w, height: node.h, rx: node.small ? 6 : 10, fill: "var(--color-card, hsl(0 0% 100%))", stroke: selected ? "var(--color-primary, hsl(220 90% 56%))" : "var(--color-border, hsl(220 14% 78%))", strokeWidth: selected ? 2.5 : 1.5, className: "transition-all duration-200" }), _jsx("foreignObject", { x: node.x + 6, y: node.y + (node.small ? 4 : 6), width: node.small ? 16 : 22, height: node.small ? 16 : 22, children: _jsx("div", { className: node.small ? "w-3.5 h-3.5 text-muted-foreground" : "w-4.5 h-4.5 text-muted-foreground", children: _jsx(Icon, { className: "w-full h-full" }) }) }), _jsx("text", { x: node.x + 34, y: node.y + node.h / 2 + 1, dominantBaseline: "middle", fontSize: node.small ? 11 : 13, fontWeight: 500, fill: "var(--color-foreground, hsl(0 0% 9%))", children: node.nameZh }), _jsx("circle", { cx: node.x + node.w - 14, cy: node.y + node.h / 2, r: 5, fill: STATUS_COLORS[status], className: "transition-colors duration-300" }), agent?.cooldownRemaining && (_jsx("text", { x: node.x + node.w - 14, y: node.y + 6, textAnchor: "middle", fontSize: 8, fill: "hsl(45 93% 47%)", children: "\u23F3" }))] }));
|
|
79
71
|
}
|
|
80
|
-
function TrinityGroup() {
|
|
81
|
-
const dreamer = FLOW_NODES.find((n) => n.id === "trinity-dreamer");
|
|
82
|
-
const scribe = FLOW_NODES.find((n) => n.id === "trinity-scribe");
|
|
83
|
-
const pad = 12;
|
|
84
|
-
return (_jsx("rect", { x: dreamer.x - pad, y: dreamer.y - pad, width: dreamer.w + pad * 2, height: scribe.y + scribe.h - dreamer.y + pad * 2, rx: 8, fill: "none", stroke: "var(--color-border, hsl(220 14% 78%))", strokeWidth: 1, strokeDasharray: "6 3" }));
|
|
85
|
-
}
|
|
86
72
|
function FlowEdgeLine({ from, to }) {
|
|
87
73
|
const d = getEdgePath(from, to);
|
|
88
74
|
return (_jsxs("g", { children: [_jsx("defs", { children: _jsx("marker", { id: `arrow-${from.id}-${to.id}`, viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "6", markerHeight: "6", orient: "auto-start-reverse", children: _jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: "var(--color-accent, hsl(180 70% 50%))" }) }) }), _jsx("path", { d: d, fill: "none", stroke: "var(--color-accent, hsl(180 70% 50%))", strokeWidth: 1.8, markerEnd: `url(#arrow-${from.id}-${to.id})`, className: "opacity-70" })] }));
|
|
@@ -97,7 +83,7 @@ function AgentFlowMap({ agents, selectedId, onSelect, }) {
|
|
|
97
83
|
const fromNode = FLOW_NODES.find((n) => n.id === edge.from);
|
|
98
84
|
const toNode = FLOW_NODES.find((n) => n.id === edge.to);
|
|
99
85
|
return _jsx(FlowEdgeLine, { from: fromNode, to: toNode }, `${edge.from}-${edge.to}`);
|
|
100
|
-
}),
|
|
86
|
+
}), FLOW_NODES.map((node) => (_jsx(AgentNode, { node: node, agent: agentMap.get(node.id), selected: selectedId === node.id, onClick: () => onSelect(node.id) }, node.id)))] }) }) }));
|
|
101
87
|
}
|
|
102
88
|
function CollapsibleSection({ title, defaultOpen = false, children, }) {
|
|
103
89
|
const [open, setOpen] = useState(defaultOpen);
|
|
@@ -19,7 +19,6 @@ const ZONE_CONFIG = [
|
|
|
19
19
|
];
|
|
20
20
|
const TASK_KIND_AGENT = {
|
|
21
21
|
diagnostician: { id: 'diagnostician', i18nKey: 'pages:tasks.agentDiagnostician' },
|
|
22
|
-
sleep_reflection: { id: 'nocturnal-reflection', i18nKey: 'pages:tasks.agentNocturnalReflection' },
|
|
23
22
|
keyword_optimization: { id: 'correction-observer', i18nKey: 'pages:tasks.agentCorrectionObserver' },
|
|
24
23
|
principle_candidate_intake: { id: 'diagnostician', i18nKey: 'pages:tasks.agentDiagnostician' },
|
|
25
24
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function UpdatePage(): import("react/jsx-runtime").JSX.Element;
|