create-principles-disciple 1.111.1 → 1.112.1
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/routes/update.js +105 -32
- package/console/dist/ui/i18n/en.json +1 -0
- package/console/dist/ui/i18n/zh-CN.json +1 -0
- package/console/dist/ui/pages/settings/UpdatePage.js +1 -1
- package/console/dist/ui/utils/validators.d.ts +4 -0
- package/console/dist/ui/utils/validators.js +6 -0
- package/console/dist/web/assets/app.js +10 -1
- package/package.json +4 -1
- package/pd-cli/dist/commands/legacy-cleanup.d.ts.map +1 -1
- package/pd-cli/dist/commands/legacy-cleanup.js +19 -2
- package/pd-cli/dist/commands/legacy-cleanup.js.map +1 -1
- package/pd-cli/dist/commands/pain-evidence.d.ts +3 -1
- package/pd-cli/dist/commands/pain-evidence.d.ts.map +1 -1
- package/pd-cli/dist/commands/pain-evidence.js +12 -3
- package/pd-cli/dist/commands/pain-evidence.js.map +1 -1
- package/pd-cli/dist/commands/rulecode.d.ts +13 -0
- package/pd-cli/dist/commands/rulecode.d.ts.map +1 -1
- package/pd-cli/dist/commands/rulecode.js +23 -2
- package/pd-cli/dist/commands/rulecode.js.map +1 -1
- package/pd-cli/dist/resolve-workspace.d.ts.map +1 -1
- package/pd-cli/dist/resolve-workspace.js +33 -12
- package/pd-cli/dist/resolve-workspace.js.map +1 -1
- package/pd-cli/dist/services/console-launcher.d.ts +8 -1
- package/pd-cli/dist/services/console-launcher.d.ts.map +1 -1
- package/pd-cli/dist/services/console-launcher.js +45 -3
- package/pd-cli/dist/services/console-launcher.js.map +1 -1
- package/pd-cli/dist/services/pd-config-loader.d.ts.map +1 -1
- package/pd-cli/dist/services/pd-config-loader.js +34 -1
- package/pd-cli/dist/services/pd-config-loader.js.map +1 -1
- package/pd-cli/dist/services/quality-scorecard/strong-model-gate.d.ts +19 -0
- package/pd-cli/dist/services/quality-scorecard/strong-model-gate.d.ts.map +1 -1
- package/pd-cli/dist/services/quality-scorecard/strong-model-gate.js +44 -2
- package/pd-cli/dist/services/quality-scorecard/strong-model-gate.js.map +1 -1
- package/pd-cli/dist/utils/path-security.d.ts +60 -0
- package/pd-cli/dist/utils/path-security.d.ts.map +1 -0
- package/pd-cli/dist/utils/path-security.js +90 -0
- package/pd-cli/dist/utils/path-security.js.map +1 -0
- package/plugin/dist/bundle.js +13 -11
- package/plugin/dist/constants/tools.d.ts +1 -1
- package/plugin/dist/hooks/prompt-helpers.d.ts +5 -5
- package/plugin/dist/templates/langs/en/core/AGENTS.md +40 -180
- package/plugin/dist/templates/langs/en/core/BOOT.md +19 -47
- package/plugin/dist/templates/langs/en/core/HEARTBEAT.md +26 -58
- package/plugin/dist/templates/langs/en/core/IDENTITY.md +15 -8
- package/plugin/dist/templates/langs/en/core/PRINCIPLES.md +6 -7
- package/plugin/dist/templates/langs/en/core/SOUL.md +10 -41
- package/plugin/dist/templates/langs/en/core/TOOLS.md +18 -10
- package/plugin/dist/templates/langs/en/core/USER.md +13 -8
- package/plugin/dist/templates/langs/en/skills/pd-auditor/SKILL.md +1 -1
- package/plugin/dist/templates/langs/en/skills/pd-explorer/SKILL.md +1 -1
- package/plugin/dist/templates/langs/en/skills/pd-implementer/SKILL.md +1 -1
- package/plugin/dist/templates/langs/en/skills/pd-mentor/SKILL.md +6 -30
- package/plugin/dist/templates/langs/en/skills/pd-planner/SKILL.md +1 -1
- package/plugin/dist/templates/langs/zh/core/AGENTS.md +38 -173
- package/plugin/dist/templates/langs/zh/core/BOOT.md +14 -46
- package/plugin/dist/templates/langs/zh/core/HEARTBEAT.md +20 -82
- package/plugin/dist/templates/langs/zh/core/IDENTITY.md +15 -8
- package/plugin/dist/templates/langs/zh/core/PRINCIPLES.md +7 -7
- package/plugin/dist/templates/langs/zh/core/SOUL.md +9 -41
- package/plugin/dist/templates/langs/zh/core/TOOLS.md +14 -10
- package/plugin/dist/templates/langs/zh/core/USER.md +12 -8
- package/plugin/dist/templates/langs/zh/skills/pd-auditor/SKILL.md +1 -1
- package/plugin/dist/templates/langs/zh/skills/pd-explorer/SKILL.md +1 -1
- package/plugin/dist/templates/langs/zh/skills/pd-implementer/SKILL.md +1 -1
- package/plugin/dist/templates/langs/zh/skills/pd-mentor/SKILL.md +6 -30
- package/plugin/dist/templates/langs/zh/skills/pd-planner/SKILL.md +1 -1
- package/plugin/openclaw.plugin.json +1 -1
- package/plugin/package.json +1 -2
- package/plugin/templates/langs/en/core/AGENTS.md +40 -180
- package/plugin/templates/langs/en/core/BOOT.md +19 -47
- package/plugin/templates/langs/en/core/HEARTBEAT.md +26 -58
- package/plugin/templates/langs/en/core/IDENTITY.md +15 -8
- package/plugin/templates/langs/en/core/PRINCIPLES.md +6 -7
- package/plugin/templates/langs/en/core/SOUL.md +10 -41
- package/plugin/templates/langs/en/core/TOOLS.md +18 -10
- package/plugin/templates/langs/en/core/USER.md +13 -8
- package/plugin/templates/langs/en/skills/pd-auditor/SKILL.md +1 -1
- package/plugin/templates/langs/en/skills/pd-explorer/SKILL.md +1 -1
- package/plugin/templates/langs/en/skills/pd-implementer/SKILL.md +1 -1
- package/plugin/templates/langs/en/skills/pd-mentor/SKILL.md +6 -30
- package/plugin/templates/langs/en/skills/pd-planner/SKILL.md +1 -1
- package/plugin/templates/langs/zh/core/AGENTS.md +38 -173
- package/plugin/templates/langs/zh/core/BOOT.md +14 -46
- package/plugin/templates/langs/zh/core/HEARTBEAT.md +20 -82
- package/plugin/templates/langs/zh/core/IDENTITY.md +15 -8
- package/plugin/templates/langs/zh/core/PRINCIPLES.md +7 -7
- package/plugin/templates/langs/zh/core/SOUL.md +9 -41
- package/plugin/templates/langs/zh/core/TOOLS.md +14 -10
- package/plugin/templates/langs/zh/core/USER.md +12 -8
- package/plugin/templates/langs/zh/skills/pd-auditor/SKILL.md +1 -1
- package/plugin/templates/langs/zh/skills/pd-explorer/SKILL.md +1 -1
- package/plugin/templates/langs/zh/skills/pd-implementer/SKILL.md +1 -1
- package/plugin/templates/langs/zh/skills/pd-mentor/SKILL.md +6 -30
- package/plugin/templates/langs/zh/skills/pd-planner/SKILL.md +1 -1
- package/plugin/dist/templates/langs/en/core/BOOTSTRAP.md +0 -259
- package/plugin/dist/templates/langs/en/skills/admin/SKILL.md +0 -39
- 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-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/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/BOOTSTRAP.md +0 -260
- package/plugin/dist/templates/langs/zh/skills/admin/SKILL.md +0 -41
- 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-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/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/scripts/acceptance-test.mjs +0 -257
- package/plugin/scripts/bootstrap-rules.mjs +0 -70
- package/plugin/scripts/compile-principles.mjs +0 -104
- package/plugin/scripts/install-dependencies.cjs +0 -47
- package/plugin/scripts/postinstall.cjs +0 -177
- package/plugin/scripts/sync-plugin.mjs +0 -1442
- package/plugin/scripts/verify-build.mjs +0 -120
- package/plugin/templates/langs/en/core/BOOTSTRAP.md +0 -259
- package/plugin/templates/langs/en/skills/admin/SKILL.md +0 -39
- package/plugin/templates/langs/en/skills/bootstrap-tools/SKILL.md +0 -53
- package/plugin/templates/langs/en/skills/deductive-audit/SKILL.md +0 -36
- package/plugin/templates/langs/en/skills/evolution-framework-update/SKILL.md +0 -31
- package/plugin/templates/langs/en/skills/evolve-task/SKILL.md +0 -83
- package/plugin/templates/langs/en/skills/feedback/SKILL.md +0 -51
- package/plugin/templates/langs/en/skills/init-strategy/SKILL.md +0 -54
- package/plugin/templates/langs/en/skills/inject-rule/SKILL.md +0 -19
- package/plugin/templates/langs/en/skills/profile/SKILL.md +0 -24
- package/plugin/templates/langs/en/skills/reflection/SKILL.md +0 -40
- package/plugin/templates/langs/en/skills/reflection-log/SKILL.md +0 -37
- package/plugin/templates/langs/en/skills/report/SKILL.md +0 -13
- package/plugin/templates/langs/en/skills/root-cause/SKILL.md +0 -33
- package/plugin/templates/langs/en/skills/triage/SKILL.md +0 -29
- package/plugin/templates/langs/en/skills/watch-evolution/SKILL.md +0 -33
- package/plugin/templates/langs/zh/core/BOOTSTRAP.md +0 -260
- package/plugin/templates/langs/zh/skills/admin/SKILL.md +0 -41
- package/plugin/templates/langs/zh/skills/bootstrap-tools/SKILL.md +0 -52
- package/plugin/templates/langs/zh/skills/deductive-audit/SKILL.md +0 -36
- package/plugin/templates/langs/zh/skills/evolution-framework-update/SKILL.md +0 -31
- package/plugin/templates/langs/zh/skills/evolve-task/SKILL.md +0 -83
- package/plugin/templates/langs/zh/skills/feedback/SKILL.md +0 -53
- package/plugin/templates/langs/zh/skills/init-strategy/SKILL.md +0 -54
- package/plugin/templates/langs/zh/skills/inject-rule/SKILL.md +0 -19
- package/plugin/templates/langs/zh/skills/profile/SKILL.md +0 -24
- package/plugin/templates/langs/zh/skills/reflection/SKILL.md +0 -40
- package/plugin/templates/langs/zh/skills/reflection-log/SKILL.md +0 -37
- package/plugin/templates/langs/zh/skills/report/SKILL.md +0 -13
- package/plugin/templates/langs/zh/skills/root-cause/SKILL.md +0 -33
- package/plugin/templates/langs/zh/skills/triage/SKILL.md +0 -29
- package/plugin/templates/langs/zh/skills/watch-evolution/SKILL.md +0 -33
|
@@ -14,6 +14,13 @@ import { migrateLegacyExtensionBackups, reservePdBackupDestination, resolvePdBac
|
|
|
14
14
|
// installer package (create-principles-disciple). These are independently
|
|
15
15
|
// versioned — comparing them caused a permanent false "update available".
|
|
16
16
|
const NPM_REGISTRY_LATEST = 'https://registry.npmjs.org/principles-disciple/latest';
|
|
17
|
+
// Full update installs the bundled plugin from the INSTALLER package. The
|
|
18
|
+
// installer captures the plugin version at build time (bundle-plugin.mjs
|
|
19
|
+
// records it as `pd.bundledPluginVersion`). `/check` must compare the
|
|
20
|
+
// installed version against what the installer can ACTUALLY deliver, not the
|
|
21
|
+
// raw plugin registry latest, otherwise it promises a version the full update
|
|
22
|
+
// can never install → permanent false "update available" and no-op updates.
|
|
23
|
+
const NPM_REGISTRY_INSTALLER = 'https://registry.npmjs.org/create-principles-disciple/latest';
|
|
17
24
|
const WORKSPACE_FILES = ['AGENTS.md', 'SOUL.md', 'USER.md', 'CLAUDE.md'];
|
|
18
25
|
// Directories to skip during backup and diff. node_modules contains native
|
|
19
26
|
// .node addons locked by the gateway/console processes (EPERM on copyfile),
|
|
@@ -287,45 +294,84 @@ function detectCodexInstall() {
|
|
|
287
294
|
const pdCodexDir = path.join(os.homedir(), '.pd', 'codex');
|
|
288
295
|
return fs.existsSync(codexHooks) || fs.existsSync(pdCodexDir);
|
|
289
296
|
}
|
|
297
|
+
/**
|
|
298
|
+
* Fetch a registry `/latest` document.
|
|
299
|
+
*
|
|
300
|
+
* Returns parsed fields with runtime guards (rc-1/rc-2): never trusts unknown
|
|
301
|
+
* JSON. `bundledPluginVersion` is read from `pd.bundledPluginVersion` and
|
|
302
|
+
* only returned when it is a valid semver string.
|
|
303
|
+
*/
|
|
304
|
+
async function fetchRegistryMetadata(url, label) {
|
|
305
|
+
const controller = new AbortController();
|
|
306
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
307
|
+
let response;
|
|
308
|
+
try {
|
|
309
|
+
response = await fetch(url, { signal: controller.signal });
|
|
310
|
+
if (!response.ok)
|
|
311
|
+
throw new Error(`${label}: HTTP ${response.status}`);
|
|
312
|
+
const rawData = await response.json();
|
|
313
|
+
if (!isRecord(rawData))
|
|
314
|
+
throw new Error(`Invalid registry response (${label})`);
|
|
315
|
+
if (typeof rawData.version !== 'string')
|
|
316
|
+
throw new Error(`Missing version (${label})`);
|
|
317
|
+
const out = { version: rawData.version };
|
|
318
|
+
if (isRecord(rawData.pd) && typeof rawData.pd.bundledPluginVersion === 'string') {
|
|
319
|
+
const bundled = rawData.pd.bundledPluginVersion;
|
|
320
|
+
if (semver.valid(bundled) !== null)
|
|
321
|
+
out.bundledPluginVersion = bundled;
|
|
322
|
+
}
|
|
323
|
+
return out;
|
|
324
|
+
}
|
|
325
|
+
finally {
|
|
326
|
+
clearTimeout(timeoutId);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
290
329
|
async function doCheckForUpdates(currentVersion) {
|
|
291
330
|
try {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
// Fetch release notes from GitHub
|
|
312
|
-
// non-blocking — if it fails, the UI still shows version info without notes).
|
|
331
|
+
// Fetch BOTH the plugin registry latest (for changelog + sync detection)
|
|
332
|
+
// and the installer's declared bundled plugin version (what a full update
|
|
333
|
+
// can actually deliver). rc-4: validate array/element shapes with guards.
|
|
334
|
+
const pluginResult = await fetchRegistryMetadata(NPM_REGISTRY_LATEST, 'Plugin registry check');
|
|
335
|
+
const pluginLatest = pluginResult.version;
|
|
336
|
+
const installerResult = await fetchRegistryMetadata(NPM_REGISTRY_INSTALLER, 'Installer registry check');
|
|
337
|
+
// The installer stamps the exact plugin version it bundles in
|
|
338
|
+
// `pd.bundledPluginVersion` (bundle-plugin.mjs). This is the version the
|
|
339
|
+
// full update ACTUALLY installs. Fall back to the plugin registry latest
|
|
340
|
+
// for old installers without the stamp.
|
|
341
|
+
const deliverableVersion = installerResult.bundledPluginVersion ?? pluginLatest;
|
|
342
|
+
// hasUpdate must compare against what we can actually install. If the
|
|
343
|
+
// installer is stale (its bundled plugin < plugin registry latest), we
|
|
344
|
+
// report the stale deliverable and surface the sync gap so the UI does
|
|
345
|
+
// not offer a version the update never installs.
|
|
346
|
+
const hasUpdate = semver.gt(deliverableVersion, currentVersion);
|
|
347
|
+
const syncPending = Boolean(pluginLatest) &&
|
|
348
|
+
Boolean(deliverableVersion) &&
|
|
349
|
+
semver.gt(pluginLatest, deliverableVersion);
|
|
350
|
+
// Fetch release notes from GitHub (best-effort, non-blocking).
|
|
313
351
|
let changelog = '';
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
if (
|
|
319
|
-
|
|
352
|
+
const notesVersion = syncPending ? pluginLatest : deliverableVersion;
|
|
353
|
+
if (notesVersion) {
|
|
354
|
+
try {
|
|
355
|
+
const ghResponse = await fetch(`https://api.github.com/repos/csuzngjh/principles/releases/tags/v${notesVersion}`, { signal: AbortSignal.timeout(5000), headers: { Accept: 'application/vnd.github.v3+json' } });
|
|
356
|
+
if (ghResponse.ok) {
|
|
357
|
+
const ghData = await ghResponse.json();
|
|
358
|
+
if (isRecord(ghData) && typeof ghData.body === 'string') {
|
|
359
|
+
changelog = ghData.body;
|
|
360
|
+
}
|
|
320
361
|
}
|
|
321
362
|
}
|
|
363
|
+
catch { /* best-effort — changelog is optional */ }
|
|
322
364
|
}
|
|
323
|
-
catch { /* best-effort — changelog is optional */ }
|
|
324
365
|
return {
|
|
325
|
-
hasUpdate
|
|
366
|
+
hasUpdate,
|
|
326
367
|
currentVersion,
|
|
327
|
-
latestVersion,
|
|
368
|
+
latestVersion: deliverableVersion,
|
|
328
369
|
changelog,
|
|
370
|
+
// Newer plugin is published but the installer has not been republished
|
|
371
|
+
// to bundle it. UI shows this as an honest "sync in progress" notice
|
|
372
|
+
// instead of offering an uninstallable version.
|
|
373
|
+
pluginLatestVersion: pluginLatest,
|
|
374
|
+
syncPending,
|
|
329
375
|
};
|
|
330
376
|
}
|
|
331
377
|
catch (error) {
|
|
@@ -560,7 +606,6 @@ async function doRollbackUpdate(options, workspaceDir) {
|
|
|
560
606
|
// pd-cli). We download it directly and copy the pre-built dist/ directories.
|
|
561
607
|
// This is seconds-fast (no npm install) and requires no CLI/npx — the entire
|
|
562
608
|
// operation happens inside the console HTTP handler.
|
|
563
|
-
const NPM_REGISTRY_INSTALLER = 'https://registry.npmjs.org/create-principles-disciple/latest';
|
|
564
609
|
/**
|
|
565
610
|
* Compare two dependency maps for meaningful differences.
|
|
566
611
|
* Ignores `@principles/core` (always `file:./core` in bundled packages).
|
|
@@ -680,8 +725,36 @@ async function doInlineFullUpdate(workspaceDir) {
|
|
|
680
725
|
if (tempDir && fs.existsSync(tempDir)) {
|
|
681
726
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
682
727
|
}
|
|
683
|
-
// 7.
|
|
728
|
+
// 7. Version-advance check (drift guard). The full update installs the
|
|
729
|
+
// plugin bundled inside the installer. If the installer is stale (its
|
|
730
|
+
// bundled plugin is NOT newer than what is installed), the "update" is a
|
|
731
|
+
// no-op that merely rewrites the same version — recording it as success
|
|
732
|
+
// produced the confusing `1.209.0 → 1.209.0` history and a permanent
|
|
733
|
+
// false "update available". Detect that and fail loud (rc-9) instead of
|
|
734
|
+
// reporting a false success.
|
|
684
735
|
const newVersion = readCurrentVersion(extDir) ?? toVersion ?? 'unknown';
|
|
736
|
+
const progressed = fromVersion !== 'unknown' &&
|
|
737
|
+
semver.valid(fromVersion) !== null &&
|
|
738
|
+
semver.valid(newVersion) !== null &&
|
|
739
|
+
semver.gt(newVersion, fromVersion);
|
|
740
|
+
if (!progressed) {
|
|
741
|
+
// Files were already rewritten to the same (or lower) version. Record a
|
|
742
|
+
// FAILED history entry so the operator sees why, and return a structured
|
|
743
|
+
// error with nextAction.
|
|
744
|
+
appendUpdateHistory(workspaceDir, {
|
|
745
|
+
fromVersion,
|
|
746
|
+
toVersion: newVersion,
|
|
747
|
+
success: false,
|
|
748
|
+
});
|
|
749
|
+
return {
|
|
750
|
+
success: false,
|
|
751
|
+
message: 'Installed version did not advance — the update source is stale (it bundles the same or an older plugin).',
|
|
752
|
+
reason: 'installer_bundle_stale',
|
|
753
|
+
nextAction: 'The published installer mirrors an older plugin. Contact the maintainer to republish the installer, or try again later when a newer installer is available.',
|
|
754
|
+
requiresRestart: false,
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
// 8. Record history (only for genuine version advancement)
|
|
685
758
|
appendUpdateHistory(workspaceDir, {
|
|
686
759
|
fromVersion,
|
|
687
760
|
toVersion: newVersion,
|
|
@@ -886,6 +886,7 @@
|
|
|
886
886
|
"version": "Version",
|
|
887
887
|
"failed": "Failed",
|
|
888
888
|
"checkError": "Check error",
|
|
889
|
+
"syncPending": "Version {{pluginVersion}} is published, but the installer is syncing (you can update to the version shown above for now). Please try again later.",
|
|
889
890
|
"loadError": "Unable to load update data. You can try refreshing the page.",
|
|
890
891
|
"checkFailed": "Update check failed. Please try again later.",
|
|
891
892
|
"applyUpdate": "Update Now",
|
|
@@ -197,7 +197,7 @@ export function UpdatePage() {
|
|
|
197
197
|
}
|
|
198
198
|
// ── Loaded state ─────────────────────────────────────────────────────────
|
|
199
199
|
const isUpToDate = statusData ? !statusData.hasUpdate : true;
|
|
200
|
-
return (_jsxs(PageShell, { children: [_jsxs("div", { className: "animate-[pdFadeIn_400ms_ease-out]", children: [_jsx("div", { className: "font-mono text-[12px] tracking-[0.14em] text-ink-3 uppercase mb-3", children: t("pages.update.eyebrow") }), _jsx("h1", { className: "text-[29px] font-semibold tracking-tight text-ink mb-2", children: t("pages.update.title") }), _jsx("p", { className: "text-ink-3 text-[14px] max-w-[760px] leading-relaxed mb-7", children: t("pages.update.subtitle") }), _jsxs("section", { className: "mb-8", "aria-labelledby": "section-update-status", children: [_jsx(SectionTitle, { id: "section-update-status", children: t("pages.update.currentVersion") }), _jsxs("div", { className: "bg-panel border border-line rounded-[6px] p-5", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-ink-3 text-[13px]", children: t("pages.update.currentVersion") }), _jsx("span", { className: "font-mono text-[13px] text-ink", children: statusData?.currentVersion ?? "—" })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-ink-3 text-[13px]", children: t("pages.update.latestVersion") }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-mono text-[13px] text-ink", children: statusData?.latestVersion ?? "—" }), isUpToDate ? (_jsx("span", { className: "inline-flex items-center border border-green/35 text-green rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.update.upToDate") })) : (_jsx("span", { className: "inline-flex items-center border border-amber/35 text-amber rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.update.updateAvailable") }))] })] })] }), statusData?.error && (_jsxs("div", { className: "mt-4 pt-3 border-t border-line text-[12px] text-ink-4 font-mono", children: [t("pages.update.checkError"), ": ", statusData.error] })), statusData?.codexInstalled && (_jsx("div", { className: "mt-4 p-3 rounded-[4px] border border-amber/30 bg-amber/5", children: _jsx("p", { className: "text-[12px] text-amber leading-relaxed", children: t("pages.update.codexWarning") }) })), statusData?.changelog && statusData.hasUpdate && (_jsxs("div", { className: "mt-4 p-4 rounded-[4px] border border-line bg-surface/50", children: [_jsx("p", { className: "text-[12px] font-mono text-ink-3 uppercase tracking-wide mb-2", children: t("pages.update.whatsNew") }), _jsx("div", { className: "text-[13px] text-ink-2 leading-relaxed max-h-[300px] overflow-y-auto whitespace-pre-wrap", children: statusData.changelog })] })), _jsxs("div", { className: "mt-5 pt-4 border-t border-line flex items-center gap-3 flex-wrap", children: [_jsx("button", { type: "button", onClick: handleCheckForUpdates, disabled: checking || fullUpdating, className: "border border-line bg-surface text-ink rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: checking ? t("pages.update.checking") : t("pages.update.checkForUpdates") }), !isUpToDate && (_jsx("button", { type: "button", onClick: () => setShowFullUpdateDialog(true), disabled: checking || fullUpdating, className: "bg-gov text-white rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-gov/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: fullUpdating ? (_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }), t("pages.update.updating")] })) : (t("pages.update.applyUpdate")) }))] }), updateResult && (_jsx("div", { className: `mt-4 p-4 rounded-[6px] border animate-[pdFadeIn_400ms_ease-out] ${updateResult.success ? 'bg-green/5 border-green/20' : 'bg-red/5 border-red/20'}`, children: _jsxs("div", { className: "flex items-start gap-3", children: [updateResult.success ? (_jsx(CheckCircle2, { className: "h-6 w-6 text-green shrink-0 mt-0.5 animate-[pdFadeIn_600ms_ease-out]", style: { transform: 'scale(1)', animationFillMode: 'both' } })) : (_jsx(XCircle, { className: "h-6 w-6 text-red shrink-0 mt-0.5" })), _jsxs("div", { className: "flex-1 min-w-0", children: [updateResult.success && updateResult.fromVersion && updateResult.newVersion && (_jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [_jsx("span", { className: "font-mono text-[13px] text-ink-3 line-through", children: updateResult.fromVersion }), _jsx(ArrowRight, { className: "h-3.5 w-3.5 text-green" }), _jsx("span", { className: "font-mono text-[13px] text-green font-medium", children: updateResult.newVersion })] })), _jsx("p", { className: `text-[13px] ${updateResult.success ? 'text-green' : 'text-red'}`, children: updateResult.message }), updateResult.success && updateResult.updatedFiles && updateResult.updatedFiles.length > 0 && (_jsx("p", { className: "mt-1 text-[12px] text-ink-4 font-mono", children: t("pages.update.filesUpdated", { count: updateResult.updatedFiles.length }) })), updateResult.success && !updateResult.requiresRestart && (_jsx("p", { className: "mt-2 text-[12px] font-mono text-ink-4", children: t("pages.update.restartHint") })), updateResult.success && updateResult.requiresRestart && (_jsx("p", { className: "mt-2 p-2 rounded-[3px] bg-amber/5 border border-amber/20 text-[12px] text-amber leading-relaxed", children: t("pages.update.fullUpdateRestartPrompt") })), updateResult.success && updateResult.partialUpdate && (_jsx("p", { className: "mt-1 text-[12px] text-amber leading-relaxed", children: t("pages.update.partialUpdateHint") })), !updateResult.success && updateResult.nextAction && (_jsx("p", { className: "mt-1 text-[12px] text-ink-4 font-mono leading-relaxed", children: updateResult.nextAction })), !updateResult.success && (_jsxs("div", { className: "mt-2 flex items-center gap-2", children: [/network|fetch|timeout|ECONNREFUSED|ENOTFOUND/i.test(updateResult.message) && (_jsx("p", { className: "text-[12px] text-ink-4 font-mono", children: t("pages.update.networkErrorHint") })), _jsx("button", { type: "button", onClick: handleApplyUpdate, disabled: updating, className: "text-[12px] text-red underline hover:text-red/80 disabled:opacity-50", children: t("pages.update.retry") })] }))] })] }) }))] })] }), _jsxs("section", { "aria-labelledby": "section-update-history", children: [_jsx(SectionTitle, { id: "section-update-history", children: t("pages.update.history") }), historyErrorReason ? (_jsxs("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: [t("pages.update.loadError"), " (", historyErrorReason, ")"] })) : historyData && historyData.updates.length > 0 ? (_jsx("div", { className: "space-y-[10px]", children: historyData.updates.map((entry) => (_jsx("article", { className: "bg-panel border border-line rounded-[6px] px-5 py-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "inline-flex items-center border border-line rounded-[2px] px-[7px] py-1 font-mono text-[11px] text-ink-3 bg-surface/80 uppercase", children: t("pages.update.version") }), _jsxs("span", { className: "font-mono text-[13px] text-ink", children: [entry.fromVersion, " \u2192 ", entry.toVersion] }), !entry.success && (_jsx("span", { className: "inline-flex items-center border border-red/35 text-red rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.update.failed") }))] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-ink-3 text-[13px]", children: formatDate(entry.timestamp, locale) }), entry.backupPath && (_jsxs("button", { type: "button", onClick: () => setShowRollbackDialog(entry.backupPath), disabled: rollingBack || updating, className: "flex items-center gap-1 border border-line bg-surface text-ink-3 rounded-[3px] px-[8px] py-[4px] text-[11px] hover:text-ink hover:border-line-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", title: t("pages.update.rollback"), children: [_jsx(RotateCcw, { className: "h-3 w-3" }), t("pages.update.rollback")] }))] })] }) }, entry.id))) })) : (_jsx("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: t("pages.update.noHistory") }))] })] }), _jsx(AlertDialog, { open: showFullUpdateDialog, onOpenChange: setShowFullUpdateDialog, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: t("pages.update.confirmFullUpdateTitle") }), _jsx(AlertDialogDescription, { children: t("pages.update.confirmFullUpdateDesc") })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: t("common.cancel") }), _jsx(AlertDialogAction, { onClick: handleApplyFullUpdate, children: t("pages.update.applyFullUpdate") })] })] }) }), _jsx(AlertDialog, { open: showRollbackDialog !== null, onOpenChange: (open) => { if (!open)
|
|
200
|
+
return (_jsxs(PageShell, { children: [_jsxs("div", { className: "animate-[pdFadeIn_400ms_ease-out]", children: [_jsx("div", { className: "font-mono text-[12px] tracking-[0.14em] text-ink-3 uppercase mb-3", children: t("pages.update.eyebrow") }), _jsx("h1", { className: "text-[29px] font-semibold tracking-tight text-ink mb-2", children: t("pages.update.title") }), _jsx("p", { className: "text-ink-3 text-[14px] max-w-[760px] leading-relaxed mb-7", children: t("pages.update.subtitle") }), _jsxs("section", { className: "mb-8", "aria-labelledby": "section-update-status", children: [_jsx(SectionTitle, { id: "section-update-status", children: t("pages.update.currentVersion") }), _jsxs("div", { className: "bg-panel border border-line rounded-[6px] p-5", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-ink-3 text-[13px]", children: t("pages.update.currentVersion") }), _jsx("span", { className: "font-mono text-[13px] text-ink", children: statusData?.currentVersion ?? "—" })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-ink-3 text-[13px]", children: t("pages.update.latestVersion") }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-mono text-[13px] text-ink", children: statusData?.latestVersion ?? "—" }), isUpToDate ? (_jsx("span", { className: "inline-flex items-center border border-green/35 text-green rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.update.upToDate") })) : (_jsx("span", { className: "inline-flex items-center border border-amber/35 text-amber rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.update.updateAvailable") }))] })] })] }), statusData?.error && (_jsxs("div", { className: "mt-4 pt-3 border-t border-line text-[12px] text-ink-4 font-mono", children: [t("pages.update.checkError"), ": ", statusData.error] })), statusData?.syncPending && (_jsx("div", { className: "mt-4 p-3 rounded-[4px] border border-amber/30 bg-amber/5", children: _jsx("p", { className: "text-[12px] text-amber leading-relaxed", children: t("pages.update.syncPending", { pluginVersion: statusData.pluginLatestVersion ?? "" }) }) })), statusData?.codexInstalled && (_jsx("div", { className: "mt-4 p-3 rounded-[4px] border border-amber/30 bg-amber/5", children: _jsx("p", { className: "text-[12px] text-amber leading-relaxed", children: t("pages.update.codexWarning") }) })), statusData?.changelog && statusData.hasUpdate && (_jsxs("div", { className: "mt-4 p-4 rounded-[4px] border border-line bg-surface/50", children: [_jsx("p", { className: "text-[12px] font-mono text-ink-3 uppercase tracking-wide mb-2", children: t("pages.update.whatsNew") }), _jsx("div", { className: "text-[13px] text-ink-2 leading-relaxed max-h-[300px] overflow-y-auto whitespace-pre-wrap", children: statusData.changelog })] })), _jsxs("div", { className: "mt-5 pt-4 border-t border-line flex items-center gap-3 flex-wrap", children: [_jsx("button", { type: "button", onClick: handleCheckForUpdates, disabled: checking || fullUpdating, className: "border border-line bg-surface text-ink rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:border-line-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: checking ? t("pages.update.checking") : t("pages.update.checkForUpdates") }), !isUpToDate && (_jsx("button", { type: "button", onClick: () => setShowFullUpdateDialog(true), disabled: checking || fullUpdating, className: "bg-gov text-white rounded-[3px] px-[14px] py-[6px] text-[12.5px] hover:bg-gov/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-2 focus-visible:outline-gov focus-visible:outline-offset-2", children: fullUpdating ? (_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }), t("pages.update.updating")] })) : (t("pages.update.applyUpdate")) }))] }), updateResult && (_jsx("div", { className: `mt-4 p-4 rounded-[6px] border animate-[pdFadeIn_400ms_ease-out] ${updateResult.success ? 'bg-green/5 border-green/20' : 'bg-red/5 border-red/20'}`, children: _jsxs("div", { className: "flex items-start gap-3", children: [updateResult.success ? (_jsx(CheckCircle2, { className: "h-6 w-6 text-green shrink-0 mt-0.5 animate-[pdFadeIn_600ms_ease-out]", style: { transform: 'scale(1)', animationFillMode: 'both' } })) : (_jsx(XCircle, { className: "h-6 w-6 text-red shrink-0 mt-0.5" })), _jsxs("div", { className: "flex-1 min-w-0", children: [updateResult.success && updateResult.fromVersion && updateResult.newVersion && (_jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [_jsx("span", { className: "font-mono text-[13px] text-ink-3 line-through", children: updateResult.fromVersion }), _jsx(ArrowRight, { className: "h-3.5 w-3.5 text-green" }), _jsx("span", { className: "font-mono text-[13px] text-green font-medium", children: updateResult.newVersion })] })), _jsx("p", { className: `text-[13px] ${updateResult.success ? 'text-green' : 'text-red'}`, children: updateResult.message }), updateResult.success && updateResult.updatedFiles && updateResult.updatedFiles.length > 0 && (_jsx("p", { className: "mt-1 text-[12px] text-ink-4 font-mono", children: t("pages.update.filesUpdated", { count: updateResult.updatedFiles.length }) })), updateResult.success && !updateResult.requiresRestart && (_jsx("p", { className: "mt-2 text-[12px] font-mono text-ink-4", children: t("pages.update.restartHint") })), updateResult.success && updateResult.requiresRestart && (_jsx("p", { className: "mt-2 p-2 rounded-[3px] bg-amber/5 border border-amber/20 text-[12px] text-amber leading-relaxed", children: t("pages.update.fullUpdateRestartPrompt") })), updateResult.success && updateResult.partialUpdate && (_jsx("p", { className: "mt-1 text-[12px] text-amber leading-relaxed", children: t("pages.update.partialUpdateHint") })), !updateResult.success && updateResult.nextAction && (_jsx("p", { className: "mt-1 text-[12px] text-ink-4 font-mono leading-relaxed", children: updateResult.nextAction })), !updateResult.success && (_jsxs("div", { className: "mt-2 flex items-center gap-2", children: [/network|fetch|timeout|ECONNREFUSED|ENOTFOUND/i.test(updateResult.message) && (_jsx("p", { className: "text-[12px] text-ink-4 font-mono", children: t("pages.update.networkErrorHint") })), _jsx("button", { type: "button", onClick: handleApplyUpdate, disabled: updating, className: "text-[12px] text-red underline hover:text-red/80 disabled:opacity-50", children: t("pages.update.retry") })] }))] })] }) }))] })] }), _jsxs("section", { "aria-labelledby": "section-update-history", children: [_jsx(SectionTitle, { id: "section-update-history", children: t("pages.update.history") }), historyErrorReason ? (_jsxs("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: [t("pages.update.loadError"), " (", historyErrorReason, ")"] })) : historyData && historyData.updates.length > 0 ? (_jsx("div", { className: "space-y-[10px]", children: historyData.updates.map((entry) => (_jsx("article", { className: "bg-panel border border-line rounded-[6px] px-5 py-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "inline-flex items-center border border-line rounded-[2px] px-[7px] py-1 font-mono text-[11px] text-ink-3 bg-surface/80 uppercase", children: t("pages.update.version") }), _jsxs("span", { className: "font-mono text-[13px] text-ink", children: [entry.fromVersion, " \u2192 ", entry.toVersion] }), !entry.success && (_jsx("span", { className: "inline-flex items-center border border-red/35 text-red rounded-[2px] px-[7px] py-1 font-mono text-[11px] uppercase", children: t("pages.update.failed") }))] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-ink-3 text-[13px]", children: formatDate(entry.timestamp, locale) }), entry.backupPath && (_jsxs("button", { type: "button", onClick: () => setShowRollbackDialog(entry.backupPath), disabled: rollingBack || updating, className: "flex items-center gap-1 border border-line bg-surface text-ink-3 rounded-[3px] px-[8px] py-[4px] text-[11px] hover:text-ink hover:border-line-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", title: t("pages.update.rollback"), children: [_jsx(RotateCcw, { className: "h-3 w-3" }), t("pages.update.rollback")] }))] })] }) }, entry.id))) })) : (_jsx("div", { className: "text-ink-3 text-[13px] leading-relaxed py-3", children: t("pages.update.noHistory") }))] })] }), _jsx(AlertDialog, { open: showFullUpdateDialog, onOpenChange: setShowFullUpdateDialog, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: t("pages.update.confirmFullUpdateTitle") }), _jsx(AlertDialogDescription, { children: t("pages.update.confirmFullUpdateDesc") })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: t("common.cancel") }), _jsx(AlertDialogAction, { onClick: handleApplyFullUpdate, children: t("pages.update.applyFullUpdate") })] })] }) }), _jsx(AlertDialog, { open: showRollbackDialog !== null, onOpenChange: (open) => { if (!open)
|
|
201
201
|
setShowRollbackDialog(null); }, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: t("pages.update.confirmRollbackTitle") }), _jsx(AlertDialogDescription, { children: t("pages.update.confirmRollbackDesc") })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: t("common.cancel") }), _jsx(AlertDialogAction, { onClick: () => { if (showRollbackDialog)
|
|
202
202
|
handleRollback(showRollbackDialog); }, children: t("pages.update.rollback") })] })] }) }), rollbackResult && (_jsxs("div", { className: `fixed bottom-4 right-4 max-w-md p-3 rounded-[4px] text-[13px] z-50 ${rollbackResult.success ? 'bg-green/10 border border-green/20 text-green' : 'bg-red/10 border border-red/20 text-red'}`, children: [_jsx("p", { children: rollbackResult.message }), rollbackResult.success && (_jsx("p", { className: "mt-1 text-[12px] font-mono opacity-80", children: t("pages.update.restartHintAfterRollback") }))] }))] }));
|
|
203
203
|
}
|
|
@@ -278,6 +278,10 @@ export interface UpdateStatusData {
|
|
|
278
278
|
codexInstalled?: boolean;
|
|
279
279
|
/** Release notes for the latest version (markdown, from GitHub Releases). */
|
|
280
280
|
changelog?: string;
|
|
281
|
+
/** Newest plugin version published to npm (may exceed what the installer can deliver). */
|
|
282
|
+
pluginLatestVersion?: string;
|
|
283
|
+
/** True when a newer plugin is published but the installer has not been republished to bundle it. */
|
|
284
|
+
syncPending?: boolean;
|
|
281
285
|
}
|
|
282
286
|
export declare function validateUpdateStatus(v: unknown): UpdateStatusData | null;
|
|
283
287
|
export interface UpdateHistoryEntryData {
|
|
@@ -759,6 +759,12 @@ export function validateUpdateStatus(v) {
|
|
|
759
759
|
if (Object.hasOwn(v, 'changelog') && isString(v.changelog)) {
|
|
760
760
|
result.changelog = v.changelog;
|
|
761
761
|
}
|
|
762
|
+
if (Object.hasOwn(v, 'pluginLatestVersion') && isString(v.pluginLatestVersion)) {
|
|
763
|
+
result.pluginLatestVersion = v.pluginLatestVersion;
|
|
764
|
+
}
|
|
765
|
+
if (Object.hasOwn(v, 'syncPending') && typeof v.syncPending === 'boolean') {
|
|
766
|
+
result.syncPending = v.syncPending;
|
|
767
|
+
}
|
|
762
768
|
return result;
|
|
763
769
|
}
|
|
764
770
|
export function validateUpdateHistoryEntry(v) {
|