create-principles-disciple 1.134.6 → 1.134.7

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 (51) hide show
  1. package/console/dist/server/routes/update.js +27 -15
  2. package/console/dist/server/utils/gateway.d.ts +4 -0
  3. package/console/dist/server/utils/gateway.js +24 -4
  4. package/console/dist/ui/pages/settings/UpdatePage.js +5 -3
  5. package/console/dist/ui/utils/validators.d.ts +2 -0
  6. package/console/dist/ui/utils/validators.js +3 -0
  7. package/console/dist/web/assets/app.js +11 -5
  8. package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.js +107 -1
  9. package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.js.map +1 -1
  10. package/core/dist/runtime-v2/index.d.ts +1 -1
  11. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  12. package/core/dist/runtime-v2/index.js +1 -1
  13. package/core/dist/runtime-v2/index.js.map +1 -1
  14. package/core/dist/runtime-v2/internalization/__tests__/candidate-lineage.pri717.test.d.ts +26 -0
  15. package/core/dist/runtime-v2/internalization/__tests__/candidate-lineage.pri717.test.d.ts.map +1 -0
  16. package/core/dist/runtime-v2/internalization/__tests__/candidate-lineage.pri717.test.js +420 -0
  17. package/core/dist/runtime-v2/internalization/__tests__/candidate-lineage.pri717.test.js.map +1 -0
  18. package/core/dist/runtime-v2/internalization/__tests__/candidate-lineage.property.test.js +6 -1
  19. package/core/dist/runtime-v2/internalization/__tests__/candidate-lineage.property.test.js.map +1 -1
  20. package/core/dist/runtime-v2/internalization/candidate-lineage.d.ts +50 -1
  21. package/core/dist/runtime-v2/internalization/candidate-lineage.d.ts.map +1 -1
  22. package/core/dist/runtime-v2/internalization/candidate-lineage.js +204 -77
  23. package/core/dist/runtime-v2/internalization/candidate-lineage.js.map +1 -1
  24. package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts +41 -1
  25. package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts.map +1 -1
  26. package/core/dist/runtime-v2/pain-signal-runtime-factory.js +59 -9
  27. package/core/dist/runtime-v2/pain-signal-runtime-factory.js.map +1 -1
  28. package/core/package.json +1 -1
  29. package/host-runtime/dist/internalization-consumer-cycle.js +71 -23
  30. package/host-runtime/package.json +1 -1
  31. package/package.json +1 -1
  32. package/pd-cli/dist/commands/runtime-internalization-run-once.d.ts.map +1 -1
  33. package/pd-cli/dist/commands/runtime-internalization-run-once.js +23 -7
  34. package/pd-cli/dist/commands/runtime-internalization-run-once.js.map +1 -1
  35. package/pd-cli/dist/services/__tests__/runtime-adapter-resolver.test.js +4 -1
  36. package/pd-cli/dist/services/__tests__/runtime-adapter-resolver.test.js.map +1 -1
  37. package/pd-cli/dist/services/resolve-runtime-from-pd-config.d.ts +28 -2
  38. package/pd-cli/dist/services/resolve-runtime-from-pd-config.d.ts.map +1 -1
  39. package/pd-cli/dist/services/resolve-runtime-from-pd-config.js +19 -6
  40. package/pd-cli/dist/services/resolve-runtime-from-pd-config.js.map +1 -1
  41. package/pd-cli/dist/services/rulehost-readiness.js +1 -1
  42. package/pd-cli/dist/services/rulehost-readiness.js.map +1 -1
  43. package/pd-cli/dist/services/runtime-adapter-resolver.d.ts +14 -1
  44. package/pd-cli/dist/services/runtime-adapter-resolver.d.ts.map +1 -1
  45. package/pd-cli/dist/services/runtime-adapter-resolver.js +4 -1
  46. package/pd-cli/dist/services/runtime-adapter-resolver.js.map +1 -1
  47. package/pd-cli/package.json +1 -1
  48. package/plugin/dist/bundle.js +515 -515
  49. package/plugin/dist/governance-audit.js +1 -1
  50. package/plugin/dist/rulehost-evidence.js +1 -1
  51. package/release-manager/package.json +1 -1
@@ -541,7 +541,21 @@ async function fetchWithRetry(url, label) {
541
541
  }
542
542
  throw new Error(`${label} failed after ${MAX_RETRIES + 1} attempts: ${lastError?.message ?? 'unknown'}`);
543
543
  }
544
- async function doApplyUpdate(options, workspaceDir) {
544
+ function stopGatewayForUpdate(flow) {
545
+ const stopRes = stopOpenClawGateway();
546
+ if (stopRes.ok)
547
+ return true;
548
+ flow.notice = `OpenClaw gateway stop failed — the gateway kept running during the update (${stopRes.error}). Restart the gateway afterwards so it loads the updated plugin.`;
549
+ return false;
550
+ }
551
+ function restartGatewayAfterUpdate(flow) {
552
+ const restartRes = restartOpenClawGateway();
553
+ if (restartRes.ok)
554
+ return;
555
+ const message = `OpenClaw gateway was stopped for the update but failed to restart (${restartRes.error}). Run \`openclaw gateway start\` to restore it.`;
556
+ flow.notice = flow.notice ? `${flow.notice} ${message}` : message;
557
+ }
558
+ async function doApplyUpdate(options, workspaceDir, gatewayFlow = {}) {
545
559
  const { targetDir, mergeStrategy, createBackup } = options;
546
560
  let backupPath = undefined;
547
561
  let appliedChanges = false;
@@ -564,13 +578,11 @@ async function doApplyUpdate(options, workspaceDir) {
564
578
  // the gateway isn't running, we proceed (dist/*.js files are not locked).
565
579
  const gatewayStatus = await checkOpenClawGateway();
566
580
  if (gatewayStatus.isRunning) {
567
- const stopRes = stopOpenClawGateway();
568
- if (stopRes.ok) {
569
- gatewayWasStopped = true;
570
- }
581
+ gatewayWasStopped = stopGatewayForUpdate(gatewayFlow);
571
582
  // If stop failed, proceed anyway — the file operations below don't touch
572
583
  // node_modules (excluded from backup and diff), so locks on native modules
573
584
  // don't matter. dist/*.js files are read-once by Node, never locked.
585
+ // The failure itself reaches the Owner via gatewayFlow.notice (PRI-723).
574
586
  }
575
587
  try {
576
588
  // 0. Save current version BEFORE any changes
@@ -791,7 +803,7 @@ async function doApplyUpdate(options, workspaceDir) {
791
803
  // Fix 5: restart the gateway if we stopped it (even on failure), so the
792
804
  // user is never left without a running gateway. Mirrors installer.ts behavior.
793
805
  if (gatewayWasStopped) {
794
- restartOpenClawGateway();
806
+ restartGatewayAfterUpdate(gatewayFlow);
795
807
  }
796
808
  }
797
809
  }
@@ -1136,7 +1148,7 @@ function ensureRuntimeResolutionLinks(layout, tempDir) {
1136
1148
  }
1137
1149
  return { quarantined };
1138
1150
  }
1139
- async function doInlineFullUpdate(workspaceDir) {
1151
+ async function doInlineFullUpdate(workspaceDir, gatewayFlow = {}) {
1140
1152
  const layout = resolveUpdateLayout();
1141
1153
  if (!layout) {
1142
1154
  return {
@@ -1292,9 +1304,7 @@ async function doInlineFullUpdate(workspaceDir) {
1292
1304
  ? await checkOpenClawGateway()
1293
1305
  : { isRunning: false };
1294
1306
  if (gatewayStatus.isRunning) {
1295
- const stopRes = stopOpenClawGateway();
1296
- if (stopRes.ok)
1297
- gatewayWasStopped = true;
1307
+ gatewayWasStopped = stopGatewayForUpdate(gatewayFlow);
1298
1308
  }
1299
1309
  // Heal legacy installs only after candidate verification. This writes
1300
1310
  // outside the release tree, so it must not happen for a refused release.
@@ -1597,7 +1607,7 @@ async function doInlineFullUpdate(workspaceDir) {
1597
1607
  finally {
1598
1608
  // 8. Restart gateway regardless of success/failure
1599
1609
  if (gatewayWasStopped) {
1600
- restartOpenClawGateway();
1610
+ restartGatewayAfterUpdate(gatewayFlow);
1601
1611
  }
1602
1612
  }
1603
1613
  }
@@ -1717,10 +1727,11 @@ function legacyApplyMutation(req, res, ctx) {
1717
1727
  // ADR-0024 D-2 (PRI-709 P0-3): every runtime mutation is journaled.
1718
1728
  // `planned` lands after all request validation, so a rejected request
1719
1729
  // leaves no transaction behind.
1720
- const { result, journal } = await runLegacyJournaledMutation({ kind: 'apply', pdHome, pluginDir }, () => doApplyUpdate({ targetDir, mergeStrategy, createBackup }, ctx.workspaceDir));
1730
+ const gatewayFlow = {};
1731
+ const { result, journal } = await runLegacyJournaledMutation({ kind: 'apply', pdHome, pluginDir }, () => doApplyUpdate({ targetDir, mergeStrategy, createBackup }, ctx.workspaceDir, gatewayFlow));
1721
1732
  if (!journal.journaled)
1722
1733
  logLegacyJournalGap('apply', journal.reason);
1723
- sendSuccess(res, result);
1734
+ sendSuccess(res, gatewayFlow.notice ? { ...result, gatewayNotice: gatewayFlow.notice } : result);
1724
1735
  }
1725
1736
  catch (err) {
1726
1737
  if (err instanceof SyntaxError) {
@@ -1790,10 +1801,11 @@ function legacyApplyFullMutation(req, res, ctx) {
1790
1801
  }
1791
1802
  const pluginDir = resolvePluginDir(ctx.workspaceDir);
1792
1803
  try {
1793
- const { result, journal } = await runLegacyJournaledMutation({ kind: 'apply-full', pdHome, pluginDir }, () => doInlineFullUpdate(ctx.workspaceDir));
1804
+ const gatewayFlow = {};
1805
+ const { result, journal } = await runLegacyJournaledMutation({ kind: 'apply-full', pdHome, pluginDir }, () => doInlineFullUpdate(ctx.workspaceDir, gatewayFlow));
1794
1806
  if (!journal.journaled)
1795
1807
  logLegacyJournalGap('apply-full', journal.reason);
1796
- sendSuccess(res, result);
1808
+ sendSuccess(res, gatewayFlow.notice ? { ...result, gatewayNotice: gatewayFlow.notice } : result);
1797
1809
  }
1798
1810
  catch (err) {
1799
1811
  sendError(res, 500, 'update_apply_full_error', err instanceof Error ? err.message : 'Unknown error');
@@ -16,6 +16,10 @@ export declare function checkOpenClawGateway(): Promise<OpenClawGatewayStatus>;
16
16
  /**
17
17
  * Stop the OpenClaw gateway service. Call before mutating the plugin ext dir
18
18
  * to release file locks held on native modules (EPERM on backup copyfile).
19
+ *
20
+ * Tries a plain stop first, then `--force`: recent OpenClaw builds refuse an
21
+ * operator-gateway stop without the flag, while older builds reject the
22
+ * unknown option instead — only trying one shape breaks the other generation.
19
23
  */
20
24
  export declare function stopOpenClawGateway(): GatewayControlResult;
21
25
  /**
@@ -110,10 +110,20 @@ export async function checkOpenClawGateway() {
110
110
  * rc-9: never throws — returns {ok:false, error} so the caller can degrade
111
111
  * with a structured reason + nextAction instead of crashing mid-update.
112
112
  */
113
- function runGatewayServiceCommand(subcommand) {
113
+ function runGatewayServiceCommand(subcommand, extraArgs = []) {
114
114
  try {
115
- // EP-08: argv array + typed subcommand union — no shell interpolation.
116
- execFileSync('openclaw', ['gateway', subcommand], { stdio: 'pipe', encoding: 'utf-8', timeout: 15000 });
115
+ // EP-08: argv array + typed subcommand union — every argv is a constant
116
+ // literal, so no external input can reach the command line. shell:true is
117
+ // required on Windows: the npm-global `openclaw` resolves to a .cmd shim,
118
+ // and Node's CVE-2024-27980 hardening refuses to spawn .cmd targets
119
+ // without a shell (observed 2026-09-10 as a silent ENOENT that skipped
120
+ // every gateway stop/restart during console updates — PRI-723).
121
+ execFileSync('openclaw', ['gateway', subcommand, ...extraArgs], {
122
+ stdio: 'pipe',
123
+ encoding: 'utf-8',
124
+ timeout: 15000,
125
+ shell: process.platform === 'win32',
126
+ });
117
127
  return { ok: true };
118
128
  }
119
129
  catch (e) {
@@ -124,9 +134,19 @@ function runGatewayServiceCommand(subcommand) {
124
134
  /**
125
135
  * Stop the OpenClaw gateway service. Call before mutating the plugin ext dir
126
136
  * to release file locks held on native modules (EPERM on backup copyfile).
137
+ *
138
+ * Tries a plain stop first, then `--force`: recent OpenClaw builds refuse an
139
+ * operator-gateway stop without the flag, while older builds reject the
140
+ * unknown option instead — only trying one shape breaks the other generation.
127
141
  */
128
142
  export function stopOpenClawGateway() {
129
- return runGatewayServiceCommand('stop');
143
+ const plain = runGatewayServiceCommand('stop');
144
+ if (plain.ok)
145
+ return plain;
146
+ const forced = runGatewayServiceCommand('stop', ['--force']);
147
+ if (forced.ok)
148
+ return forced;
149
+ return { ok: false, error: `${plain.error}; forced retry: ${forced.error}` };
130
150
  }
131
151
  /**
132
152
  * Start the OpenClaw gateway service (inverse of stopOpenClawGateway).
@@ -111,12 +111,13 @@ export function UpdatePage() {
111
111
  updatedFiles: data.updatedFiles,
112
112
  fromVersion: statusData?.currentVersion,
113
113
  partialUpdate: data.partialUpdate,
114
+ gatewayNotice: data.gatewayNotice,
114
115
  });
115
116
  toast.success(t('pages.update.updateSuccess', { version: data.newVersion ?? 'latest' }));
116
117
  await loadData();
117
118
  }
118
119
  else {
119
- setUpdateResult({ success: false, message: data.message, reason: data.reason, nextAction: data.nextAction });
120
+ setUpdateResult({ success: false, message: data.message, reason: data.reason, nextAction: data.nextAction, gatewayNotice: data.gatewayNotice });
120
121
  toast.error(t('pages.update.updateFailed', { message: data.message }));
121
122
  }
122
123
  }, [t, loadData]);
@@ -140,12 +141,13 @@ export function UpdatePage() {
140
141
  fromVersion: statusData?.currentVersion,
141
142
  requiresRestart: data.requiresRestart,
142
143
  partialUpdate: data.partialUpdate,
144
+ gatewayNotice: data.gatewayNotice,
143
145
  });
144
146
  toast.success(t('pages.update.fullUpdateSuccess'));
145
147
  await loadData();
146
148
  }
147
149
  else {
148
- setUpdateResult({ success: false, message: data.message, reason: data.reason, nextAction: data.nextAction });
150
+ setUpdateResult({ success: false, message: data.message, reason: data.reason, nextAction: data.nextAction, gatewayNotice: data.gatewayNotice });
149
151
  toast.error(t('pages.update.updateFailed', { message: data.message }));
150
152
  }
151
153
  }, [t, loadData, statusData?.currentVersion]);
@@ -180,7 +182,7 @@ export function UpdatePage() {
180
182
  }
181
183
  // ── Loaded state ─────────────────────────────────────────────────────────
182
184
  const isUpToDate = statusData ? !statusData.hasUpdate : true;
183
- 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", children: _jsx(MarkdownRenderer, { content: 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) => (_jsxs("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 === "failed" ? "—" : entry.toVersion] }), entry.kind !== "failure" && (_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.historyKind.${entry.kind}`) })), !entry.success && entry.kind !== 'refusal' && (_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, i18n.language, {
185
+ 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", children: _jsx(MarkdownRenderer, { content: 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.gatewayNotice && (_jsx("p", { className: "mt-2 p-2 rounded-[3px] bg-amber/5 border border-amber/20 text-[12px] text-amber leading-relaxed font-mono", children: updateResult.gatewayNotice })), !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) => (_jsxs("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 === "failed" ? "—" : entry.toVersion] }), entry.kind !== "failure" && (_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.historyKind.${entry.kind}`) })), !entry.success && entry.kind !== 'refusal' && (_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, i18n.language, {
184
186
  year: "numeric",
185
187
  month: "short",
186
188
  day: "numeric",
@@ -695,6 +695,8 @@ export interface ApplyUpdateResultData {
695
695
  reason?: string;
696
696
  /** Suggested next action when the update fails. */
697
697
  nextAction?: string;
698
+ /** Present when the OpenClaw gateway could not be stopped/restarted around the update (PRI-723). */
699
+ gatewayNotice?: string;
698
700
  }
699
701
  export declare function validateApplyUpdateResult(v: unknown): ApplyUpdateResultData | null;
700
702
  export interface RollbackResultData {
@@ -1971,6 +1971,9 @@ export function validateApplyUpdateResult(v) {
1971
1971
  if (Object.hasOwn(v, 'nextAction') && isString(v.nextAction)) {
1972
1972
  result.nextAction = v.nextAction;
1973
1973
  }
1974
+ if (Object.hasOwn(v, 'gatewayNotice') && isString(v.gatewayNotice)) {
1975
+ result.gatewayNotice = v.gatewayNotice;
1976
+ }
1974
1977
  return result;
1975
1978
  }
1976
1979
  export function validateRollbackResult(v) {