create-principles-disciple 1.104.1 → 1.105.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.
Files changed (79) hide show
  1. package/console/dist/server/routes/update.js +17 -8
  2. package/console/dist/ui/i18n/en.json +3 -2
  3. package/console/dist/ui/i18n/zh-CN.json +3 -2
  4. package/console/dist/ui/pages/settings/UpdatePage.js +1 -1
  5. package/console/dist/ui/utils/validators.d.ts +2 -0
  6. package/console/dist/ui/utils/validators.js +3 -2
  7. package/console/dist/web/assets/app.css +7 -0
  8. package/console/dist/web/assets/app.js +18 -32
  9. package/core/dist/host/__tests__/host-adapter.test.js +12 -0
  10. package/core/dist/host/__tests__/host-adapter.test.js.map +1 -1
  11. package/core/dist/host/host-adapter.d.ts +4 -0
  12. package/core/dist/host/host-adapter.d.ts.map +1 -1
  13. package/core/dist/host/host-adapter.js +7 -0
  14. package/core/dist/host/host-adapter.js.map +1 -1
  15. package/core/dist/runtime-v2/__tests__/evidence-sanitizer.test.js +28 -0
  16. package/core/dist/runtime-v2/__tests__/evidence-sanitizer.test.js.map +1 -1
  17. package/core/dist/runtime-v2/__tests__/sqlite-connection-readonly.test.js +18 -0
  18. package/core/dist/runtime-v2/__tests__/sqlite-connection-readonly.test.js.map +1 -1
  19. package/core/dist/runtime-v2/evidence-sanitizer.d.ts.map +1 -1
  20. package/core/dist/runtime-v2/evidence-sanitizer.js +17 -1
  21. package/core/dist/runtime-v2/evidence-sanitizer.js.map +1 -1
  22. package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +15 -0
  23. package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
  24. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +1 -1
  25. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
  26. package/core/dist/runtime-v2/store/sqlite-connection.d.ts +3 -0
  27. package/core/dist/runtime-v2/store/sqlite-connection.d.ts.map +1 -1
  28. package/core/dist/runtime-v2/store/sqlite-connection.js +6 -3
  29. package/core/dist/runtime-v2/store/sqlite-connection.js.map +1 -1
  30. package/dist/installer.d.ts.map +1 -1
  31. package/dist/installer.js +52 -2
  32. package/dist/installer.js.map +1 -1
  33. package/dist/installers/codex-host-installer.d.ts +14 -0
  34. package/dist/installers/codex-host-installer.d.ts.map +1 -1
  35. package/dist/installers/codex-host-installer.js +53 -8
  36. package/dist/installers/codex-host-installer.js.map +1 -1
  37. package/dist/mvp-config.d.ts +20 -0
  38. package/dist/mvp-config.d.ts.map +1 -1
  39. package/dist/mvp-config.js +76 -0
  40. package/dist/mvp-config.js.map +1 -1
  41. package/dist/utils/config-file-io.d.ts +26 -0
  42. package/dist/utils/config-file-io.d.ts.map +1 -0
  43. package/dist/utils/config-file-io.js +128 -0
  44. package/dist/utils/config-file-io.js.map +1 -0
  45. package/host-runtime/dist/active-principle-prompt.d.ts +17 -0
  46. package/host-runtime/dist/active-principle-prompt.js +102 -0
  47. package/host-runtime/dist/index.d.ts +45 -0
  48. package/host-runtime/dist/index.js +148 -0
  49. package/host-runtime/dist/pd-config.d.ts +36 -0
  50. package/host-runtime/dist/pd-config.js +98 -0
  51. package/host-runtime/dist/production-pain-evidence.d.ts +24 -0
  52. package/host-runtime/dist/production-pain-evidence.js +293 -0
  53. package/host-runtime/dist/production-rulehost-gate.d.ts +23 -0
  54. package/host-runtime/dist/production-rulehost-gate.js +294 -0
  55. package/host-runtime/dist/rule-implementation-runtime.d.ts +25 -0
  56. package/host-runtime/dist/rule-implementation-runtime.js +114 -0
  57. package/host-runtime/package.json +37 -0
  58. package/package.json +2 -1
  59. package/pd-cli/dist/commands/health-codex.d.ts +7 -0
  60. package/pd-cli/dist/commands/health-codex.d.ts.map +1 -0
  61. package/pd-cli/dist/commands/health-codex.js +209 -0
  62. package/pd-cli/dist/commands/health-codex.js.map +1 -0
  63. package/pd-cli/dist/commands/health.d.ts +24 -0
  64. package/pd-cli/dist/commands/health.d.ts.map +1 -1
  65. package/pd-cli/dist/commands/health.js +48 -0
  66. package/pd-cli/dist/commands/health.js.map +1 -1
  67. package/pd-cli/dist/index.js +2 -9
  68. package/pd-cli/dist/index.js.map +1 -1
  69. package/pd-cli/package.json +2 -0
  70. package/plugin/dist/bundle.js +615 -533
  71. package/plugin/dist/core/pd-config-loader.d.ts +7 -78
  72. package/plugin/dist/hooks/after-tool-call-helpers.d.ts +6 -2
  73. package/plugin/dist/hooks/gate.d.ts +29 -0
  74. package/plugin/dist/hooks/pain.d.ts +22 -0
  75. package/plugin/dist/hooks/prompt.d.ts +12 -2
  76. package/plugin/dist/host-runtime/openclaw-host-runtime.d.ts +19 -0
  77. package/plugin/dist/index.d.ts +8 -0
  78. package/plugin/openclaw.plugin.json +1 -1
  79. package/plugin/package.json +2 -1
@@ -204,30 +204,39 @@ async function doCheckForUpdates(currentVersion) {
204
204
  if (!response.ok)
205
205
  throw new Error(`HTTP ${response.status}`);
206
206
  const rawData = await response.json();
207
- if (typeof rawData !== 'object' || rawData === null)
207
+ if (!isRecord(rawData))
208
208
  throw new Error('Invalid registry response');
209
- const data = rawData;
210
- if (typeof data.version !== 'string')
209
+ if (typeof rawData.version !== 'string')
211
210
  throw new Error('Invalid registry response: missing version');
212
- latestVersion = data.version;
211
+ latestVersion = rawData.version;
213
212
  }
214
213
  finally {
215
214
  clearTimeout(timeoutId);
216
215
  }
216
+ // Fetch release notes from GitHub for the latest version (best-effort,
217
+ // non-blocking — if it fails, the UI still shows version info without notes).
218
+ let changelog = '';
219
+ try {
220
+ const ghResponse = await fetch(`https://api.github.com/repos/csuzngjh/principles/releases/tags/v${latestVersion}`, { signal: AbortSignal.timeout(5000), headers: { Accept: 'application/vnd.github.v3+json' } });
221
+ if (ghResponse.ok) {
222
+ const ghData = await ghResponse.json();
223
+ if (isRecord(ghData) && typeof ghData.body === 'string') {
224
+ changelog = ghData.body;
225
+ }
226
+ }
227
+ }
228
+ catch { /* best-effort — changelog is optional */ }
217
229
  return {
218
230
  hasUpdate: semver.gt(latestVersion, currentVersion),
219
231
  currentVersion,
220
232
  latestVersion,
233
+ changelog,
221
234
  };
222
235
  }
223
236
  catch (error) {
224
237
  return {
225
238
  hasUpdate: false,
226
239
  currentVersion,
227
- // Contract with the UI (UpdatePage.tsx) requires latestVersion to be a
228
- // string. When the registry check fails we don't know the latest version,
229
- // so emit an empty string to keep the response shape stable and let the
230
- // UI surface `error` instead of crashing the whole page.
231
240
  latestVersion: '',
232
241
  error: error instanceof Error ? error.message : 'Unknown error',
233
242
  };
@@ -863,9 +863,10 @@
863
863
  "applyFullUpdate": "Full Update",
864
864
  "fullUpdating": "Full update in progress…",
865
865
  "fullUpdateSuccess": "Full update completed.",
866
- "confirmFullUpdateTitle": "Confirm Full Update",
866
+ "confirmFullUpdateTitle": "Confirm Update",
867
867
  "confirmFullUpdateDesc": "Downloads and updates all PD packages (plugin, console, core, CLI). Usually takes just a few seconds. Your custom files (AGENTS.md etc.) are not affected. You will need to restart the console after completion.",
868
- "fullUpdateRestartPrompt": "Full update complete. Please restart the console to load the new version: press Ctrl+C, then run pd console again."
868
+ "fullUpdateRestartPrompt": "Update complete. Please restart the console to load the new version: press Ctrl+C, then run pd console again.",
869
+ "whatsNew": "What's New"
869
870
  },
870
871
  "intent": {
871
872
  "eyebrow": "Owner Intent",
@@ -863,9 +863,10 @@
863
863
  "applyFullUpdate": "全量更新",
864
864
  "fullUpdating": "全量更新中…",
865
865
  "fullUpdateSuccess": "全量更新完成。",
866
- "confirmFullUpdateTitle": "确认全量更新",
866
+ "confirmFullUpdateTitle": "确认更新",
867
867
  "confirmFullUpdateDesc": "将下载并更新全部 PD 代码包(插件、控制台、核心、CLI)。通常只需几秒钟。你自定义的文件(AGENTS.md 等)不受影响。更新完成后需要重启控制台。",
868
- "fullUpdateRestartPrompt": "全量更新已完成。请重启控制台以加载新版本:按 Ctrl+C 停止,然后重新运行 pd console。"
868
+ "fullUpdateRestartPrompt": "更新已完成。请重启控制台以加载新版本:按 Ctrl+C 停止,然后重新运行 pd console。",
869
+ "whatsNew": "更新内容"
869
870
  },
870
871
  "intent": {
871
872
  "eyebrow": "拥有者意图",
@@ -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") }) })), _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 || updating || 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: () => setShowUpdateDialog(true), disabled: updating || 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: updating ? (_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")) })), _jsx("button", { type: "button", onClick: () => setShowFullUpdateDialog(true), disabled: updating || 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: 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.fullUpdating")] })) : (t("pages.update.applyFullUpdate")) })] }), 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: showUpdateDialog, onOpenChange: setShowUpdateDialog, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: t("pages.update.confirmUpdateTitle") }), _jsx(AlertDialogDescription, { children: t("pages.update.confirmUpdateDesc", { version: statusData?.latestVersion ?? "latest" }) })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: t("common.cancel") }), _jsx(AlertDialogAction, { onClick: handleApplyUpdate, children: t("pages.update.applyUpdate") })] })] }) }), _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?.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
  }
@@ -254,6 +254,8 @@ export interface UpdateStatusData {
254
254
  error?: string;
255
255
  /** True when Codex host is also installed (triggers a warning banner). */
256
256
  codexInstalled?: boolean;
257
+ /** Release notes for the latest version (markdown, from GitHub Releases). */
258
+ changelog?: string;
257
259
  }
258
260
  export declare function validateUpdateStatus(v: unknown): UpdateStatusData | null;
259
261
  export interface UpdateHistoryEntryData {
@@ -684,14 +684,15 @@ export function validateUpdateStatus(v) {
684
684
  latestVersion: v.latestVersion,
685
685
  hasUpdate: v.hasUpdate,
686
686
  };
687
- // Optional error field (present when registry check fails)
688
687
  if (Object.hasOwn(v, 'error') && isString(v.error)) {
689
688
  result.error = v.error;
690
689
  }
691
- // Optional codexInstalled field (present when Codex host is detected)
692
690
  if (Object.hasOwn(v, 'codexInstalled') && typeof v.codexInstalled === 'boolean') {
693
691
  result.codexInstalled = v.codexInstalled;
694
692
  }
693
+ if (Object.hasOwn(v, 'changelog') && isString(v.changelog)) {
694
+ result.changelog = v.changelog;
695
+ }
695
696
  return result;
696
697
  }
697
698
  export function validateUpdateHistoryEntry(v) {
@@ -627,6 +627,9 @@
627
627
  .max-h-\[85vh\] {
628
628
  max-height: 85vh;
629
629
  }
630
+ .max-h-\[300px\] {
631
+ max-height: 300px;
632
+ }
630
633
  .max-h-\[400px\] {
631
634
  max-height: 400px;
632
635
  }
@@ -1953,6 +1956,10 @@
1953
1956
  --tw-tracking: var(--tracking-tight);
1954
1957
  letter-spacing: var(--tracking-tight);
1955
1958
  }
1959
+ .tracking-wide {
1960
+ --tw-tracking: var(--tracking-wide);
1961
+ letter-spacing: var(--tracking-wide);
1962
+ }
1956
1963
  .tracking-wider {
1957
1964
  --tw-tracking: var(--tracking-wider);
1958
1965
  letter-spacing: var(--tracking-wider);