dsh-packycode-api 1.3.2 → 1.3.4

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/lib/client.js CHANGED
@@ -122,6 +122,45 @@ window.__ModuleLoader__.load({
122
122
  groupsMiss: "不可用",
123
123
  groupsPartial: "部分",
124
124
  groupsStale: "分组为上次读取的结果",
125
+ keyClaudeCli: "Claude 经官方 CLI",
126
+ keyClaudeHttp: "Claude 经 HTTP",
127
+ keyClaudeCliHint: "分组 {groups} 只接受官方 Claude Code 客户端,这个 Key 的 Claude 请求由本机 Claude Code CLI 发出。",
128
+ keyClaudeHttpHint: "这个 Key 的 Claude 请求走插件内置的 HTTP 通道。",
129
+ keyClaudePinned: "(已在 Claude Code CLI 卡片中固定)",
130
+ cliTitle: "Claude Code CLI",
131
+ cliIntro: "cc 分组只接受官方 Claude Code 客户端,这些 Key 的 Claude 请求由本机的 Claude Code CLI 发出;cc-sale、cc-expensive、claude-officially 等分组继续走插件内置的 HTTP 通道。两种通道都由 DSH 执行工具、审批权限、计划模式、附件和历史,体验一致,CLI 只负责把请求发给 PackyCode。",
132
+ cliTransportTitle: "Claude 通道",
133
+ cliTransportAuto: "按分组自动",
134
+ cliTransportCli: "始终用 CLI",
135
+ cliTransportHttp: "始终用 HTTP",
136
+ cliTransportAutoHint: "推荐。Key 在 cc 分组时走 CLI,其它分组走 HTTP。",
137
+ cliTransportCliHint: "所有 Claude 请求都由 Claude Code CLI 发出,需要本机已安装 CLI。",
138
+ cliTransportHttpHint: "所有 Claude 请求都走 HTTP;cc 分组可能被网关识别为第三方客户端而拒绝。",
139
+ cliTransportNotWritable: "当前 profile 不允许写入设置,通道选择无法保存。",
140
+ cliTransportFailed: "保存 Claude 通道失败",
141
+ cliProcesses: "运行中的 CLI 会话 {live} 个 · 已启动 {opened} 次 · 续接 {continued} 次",
142
+ cliChecking: "正在检测本机的 Claude Code CLI…",
143
+ cliInstalled: "已安装",
144
+ cliVersion: "版本",
145
+ cliPath: "位置",
146
+ cliRecheck: "重新检测",
147
+ cliMissing: "未检测到 Claude Code CLI",
148
+ cliMissingHint: "cc 分组的 Key 需要它才能使用 Claude 模型(claude-opus-5-5、claude-sonnet-5-5、claude-haiku-5-5)。其它分组和其它模型不受影响。",
149
+ cliConfiguredMissing: "设置里指定的 CLI 路径不存在:{path}",
150
+ cliBroken: "找到了 CLI,但无法运行",
151
+ cliInstall: "安装 Claude Code CLI",
152
+ cliReinstall: "重新安装",
153
+ cliInstalling: "正在安装…(通常需要一两分钟,请勿关闭 DSH)",
154
+ cliInstallCommand: "将在本机执行:{command}(需要 Node.js 18 或更高版本)",
155
+ cliInstallSucceeded: "安装完成。",
156
+ cliInstallFailed: "安装失败",
157
+ cliNpmMissing: "没有找到 npm。请先从 https://nodejs.org 安装 Node.js(18 或更高版本),然后再点安装。",
158
+ cliPermission: "npm 没有权限写入全局目录。请在终端执行 sudo {command},或把 npm 的全局目录改到用户目录后重试。",
159
+ cliPermissionWindows: "npm 没有权限写入全局目录。请以管理员身份打开终端执行 {command},然后点「重新检测」。",
160
+ cliNetwork: "下载失败,请检查网络或 npm 镜像设置后重试。",
161
+ cliTimeout: "安装超时,请检查网络后重试。",
162
+ cliNotFoundAfterInstall: "npm 显示安装完成,但仍找不到 claude 命令。请在终端执行 claude --version 确认,然后点「重新检测」。",
163
+ cliWindowsNote: "Windows 上 Claude Code 还需要 Git for Windows(https://git-scm.com/downloads/win)。",
125
164
  modelsTitle: "显示的模型",
126
165
  modelsIntro: "切换模型时只显示已勾选的 PackyCode 模型,默认全选。修改后立即生效;已有会话仍可继续使用原模型。",
127
166
  modelsChecking: "正在读取模型设置…",
@@ -152,6 +191,8 @@ window.__ModuleLoader__.load({
152
191
  versionUpdate: "更新插件",
153
192
  versionUpdating: "正在更新…",
154
193
  versionUpdateFailed: "更新失败,请重试,或在插件页重新安装。",
194
+ versionCooling: "v{version} 发布不久,DSH 的 pnpm 要等新版本过了发布冷却期才会安装,请稍后再更新。",
195
+ versionCoolingUntil: "v{version} 发布不久,DSH 的 pnpm 要等新版本过了发布冷却期才会安装,{time} 之后可以更新。",
155
196
  versionUpdated: "已更新到 v{version}。",
156
197
  versionUpdatedHint: "新版本需要完全退出并重新打开桌面应用才会生效;只刷新页面不会重载 Host 里的插件。",
157
198
  versionRestart: "如何重启",
@@ -293,6 +334,45 @@ window.__ModuleLoader__.load({
293
334
  groupsMiss: "Not",
294
335
  groupsPartial: "partly",
295
336
  groupsStale: "groups from the last read",
337
+ keyClaudeCli: "Claude via official CLI",
338
+ keyClaudeHttp: "Claude via HTTP",
339
+ keyClaudeCliHint: "Group {groups} only serves the official Claude Code client, so this key's Claude requests are sent by this device's Claude Code CLI.",
340
+ keyClaudeHttpHint: "This key's Claude requests use the plugin's built-in HTTP route.",
341
+ keyClaudePinned: " (pinned in the Claude Code CLI card)",
342
+ cliTitle: "Claude Code CLI",
343
+ cliIntro: "The cc group only serves the official Claude Code client, so Claude requests on cc keys go through this device's Claude Code CLI; cc-sale, cc-expensive, claude-officially and other groups keep the built-in HTTP route. Either way DSH runs the tools, permissions, plan mode, attachments and history the same; the CLI only carries the request to PackyCode.",
344
+ cliTransportTitle: "Claude route",
345
+ cliTransportAuto: "By group",
346
+ cliTransportCli: "Always CLI",
347
+ cliTransportHttp: "Always HTTP",
348
+ cliTransportAutoHint: "Recommended. Keys in cc use the CLI; other groups use HTTP.",
349
+ cliTransportCliHint: "Every Claude request is sent by the Claude Code CLI, which must be installed.",
350
+ cliTransportHttpHint: "Every Claude request uses HTTP; the cc group may refuse it as a third-party client.",
351
+ cliTransportNotWritable: "This profile does not allow writing settings, so the route cannot be saved.",
352
+ cliTransportFailed: "Could not save the Claude route",
353
+ cliProcesses: "{live} CLI session(s) running · started {opened} · continued {continued}",
354
+ cliChecking: "Checking this device for the Claude Code CLI…",
355
+ cliInstalled: "Installed",
356
+ cliVersion: "Version",
357
+ cliPath: "Location",
358
+ cliRecheck: "Check again",
359
+ cliMissing: "Claude Code CLI not found",
360
+ cliMissingHint: "Keys in the cc group need it to use the Claude models (claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5). Other groups and models are unaffected.",
361
+ cliConfiguredMissing: "The CLI path set in settings does not exist: {path}",
362
+ cliBroken: "The CLI was found but could not run",
363
+ cliInstall: "Install Claude Code CLI",
364
+ cliReinstall: "Reinstall",
365
+ cliInstalling: "Installing… (usually a minute or two; keep DSH open)",
366
+ cliInstallCommand: "Runs on this device: {command} (requires Node.js 18 or later)",
367
+ cliInstallSucceeded: "Installed.",
368
+ cliInstallFailed: "Install failed",
369
+ cliNpmMissing: "npm was not found. Install Node.js 18 or later from https://nodejs.org, then click Install again.",
370
+ cliPermission: "npm cannot write its global directory. Run sudo {command} in a terminal, or point npm’s global prefix at a folder you own, then retry.",
371
+ cliPermissionWindows: "npm cannot write its global directory. Open a terminal as administrator, run {command}, then click Check again.",
372
+ cliNetwork: "The download failed. Check your network or npm registry settings and retry.",
373
+ cliTimeout: "The install timed out. Check your network and retry.",
374
+ cliNotFoundAfterInstall: "npm reported success, but the claude command still cannot be found. Run claude --version in a terminal, then click Check again.",
375
+ cliWindowsNote: "On Windows, Claude Code also needs Git for Windows (https://git-scm.com/downloads/win).",
296
376
  advanced: "Advanced: endpoints",
297
377
  apiHost: "Model endpoint",
298
378
  statusHost: "Balance endpoint",
@@ -315,6 +395,8 @@ window.__ModuleLoader__.load({
315
395
  versionUpdate: "Update plugin",
316
396
  versionUpdating: "Updating…",
317
397
  versionUpdateFailed: "The update failed. Try again, or reinstall from the Plugins page.",
398
+ versionCooling: "v{version} was published recently. DSH’s pnpm installs a new version only after its release cooldown; update again later.",
399
+ versionCoolingUntil: "v{version} was published recently. DSH’s pnpm installs a new version only after its release cooldown; update after {time}.",
318
400
  versionUpdated: "Updated to v{version}.",
319
401
  versionUpdatedHint: "Quit and reopen the desktop application. Refreshing the page does not reload the plugin inside the Host.",
320
402
  versionRestart: "How to restart",
@@ -1792,6 +1874,13 @@ window.__ModuleLoader__.load({
1792
1874
  const INVITE_URL = "https://www.packyapi.ai/register?aff=Im3l";
1793
1875
  /** How long after a search change the panel re-reads what DSH applied (the patch hot-reloads). */
1794
1876
  const SEARCH_SETTLE_MS = 1500;
1877
+ /** While the CLI installs, the panel polls its status this often. */
1878
+ const INSTALL_POLL_MS = 2e3;
1879
+ const CLAUDE_MODELS = [
1880
+ "claude-opus-5-5",
1881
+ "claude-sonnet-5-5",
1882
+ "claude-haiku-5-5"
1883
+ ];
1795
1884
  const OWN_SEARCH_IDS = {
1796
1885
  auto: "packycode-api-auto",
1797
1886
  packycode: "packycode-api"
@@ -1928,12 +2017,32 @@ window.__ModuleLoader__.load({
1928
2017
  ]
1929
2018
  }, family.name))
1930
2019
  }),
2020
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClaudeRoute, {
2021
+ group,
2022
+ t
2023
+ }),
1931
2024
  group.stale !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1932
2025
  className: "pkc-meta",
1933
2026
  children: t("groupsStale")
1934
2027
  })
1935
2028
  ] });
1936
2029
  }
2030
+ /** Which transport this key's Claude requests take, when the key reaches Claude. */
2031
+ function ClaudeRoute({ group, t }) {
2032
+ const route = group.claudeTransport;
2033
+ if (route === void 0 || !CLAUDE_MODELS.some((id) => group.coverage?.[id] === true)) return null;
2034
+ const pinned = route.reason === "preference" ? t("keyClaudePinned") : "";
2035
+ const hint = route.transport === "cli" ? `${fill(t("keyClaudeCliHint"), { groups: (route.groups ?? []).join(" / ") || "cc" })}${pinned}` : `${t("keyClaudeHttpHint")}${pinned}`;
2036
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2037
+ className: "pkc-groups",
2038
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2039
+ className: "pkc-chip",
2040
+ "data-tone": route.transport === "cli" ? "info" : "neutral",
2041
+ title: hint,
2042
+ children: route.transport === "cli" ? t("keyClaudeCli") : t("keyClaudeHttp")
2043
+ })
2044
+ });
2045
+ }
1937
2046
  function KeyRow({ entry, row, group, descriptions, groupsLoading, busy, rename, onAction, t }) {
1938
2047
  const editing = rename.renaming?.id === entry.id;
1939
2048
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -2475,12 +2584,235 @@ window.__ModuleLoader__.load({
2475
2584
  ]
2476
2585
  });
2477
2586
  }
2587
+ const INSTALL_FAILURES = {
2588
+ "npm-missing": () => "cliNpmMissing",
2589
+ permission: (cli) => cli.platform === "win32" ? "cliPermissionWindows" : "cliPermission",
2590
+ network: () => "cliNetwork",
2591
+ timeout: () => "cliTimeout",
2592
+ "not-found-after-install": () => "cliNotFoundAfterInstall"
2593
+ };
2594
+ /** The sentence explaining a failed install, by the code the host classified. */
2595
+ function installFailure(cli, t) {
2596
+ const key = INSTALL_FAILURES[cli.install?.code]?.(cli);
2597
+ return key === void 0 ? void 0 : fill(t(key), { command: cli.command ?? "" });
2598
+ }
2599
+ /**
2600
+ * Which route Claude requests take, whether this device has the Claude Code
2601
+ * CLI those on cc keys need, and — without one — an installer.
2602
+ */
2603
+ function ClaudeCliCard({ call, t }) {
2604
+ const [cli, setCli] = react.useState();
2605
+ const [checking, setChecking] = react.useState(false);
2606
+ const [saving, setSaving] = react.useState(false);
2607
+ const [error, setError] = react.useState();
2608
+ const check = react.useCallback((force = false) => {
2609
+ setChecking(true);
2610
+ setError(void 0);
2611
+ return call("claude-cli/status", { force }).then(setCli).catch((failure) => setError(clearMessage(failure))).finally(() => setChecking(false));
2612
+ }, [call]);
2613
+ react.useEffect(() => {
2614
+ check(false);
2615
+ }, [check]);
2616
+ const running = cli?.install?.state === "running";
2617
+ react.useEffect(() => {
2618
+ if (!running) return void 0;
2619
+ let live = true;
2620
+ const timer = window.setInterval(() => {
2621
+ call("claude-cli/status").then((value) => {
2622
+ if (live) setCli(value);
2623
+ }).catch(() => void 0);
2624
+ }, INSTALL_POLL_MS);
2625
+ return () => {
2626
+ live = false;
2627
+ window.clearInterval(timer);
2628
+ };
2629
+ }, [call, running]);
2630
+ const install = () => {
2631
+ setError(void 0);
2632
+ call("claude-cli/install").then(setCli).catch((failure) => setError(clearMessage(failure)));
2633
+ };
2634
+ const choose = (transport) => {
2635
+ setSaving(true);
2636
+ setError(void 0);
2637
+ call("claude-cli/update", { transport }).then(setCli).catch((failure) => setError(`${t("cliTransportFailed")}: ${clearMessage(failure)}`)).finally(() => setSaving(false));
2638
+ };
2639
+ const usable = cli?.installed === true && cli.version !== void 0;
2640
+ const failed = cli?.install?.state === "failed";
2641
+ const failure = cli === void 0 ? void 0 : installFailure(cli, t);
2642
+ const transport = cli?.transport ?? "auto";
2643
+ const processes = cli?.processes;
2644
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Card, {
2645
+ title: t("cliTitle"),
2646
+ aside: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
2647
+ disabled: checking || running,
2648
+ onClick: () => check(true),
2649
+ children: checking ? t("refreshing") : t("cliRecheck")
2650
+ }),
2651
+ children: [
2652
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2653
+ className: "pkc-note",
2654
+ children: t("cliIntro")
2655
+ }),
2656
+ cli !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2657
+ className: "pkc-setting",
2658
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2659
+ className: "pkc-label",
2660
+ children: t("cliTransportTitle")
2661
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
2662
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Segmented, {
2663
+ label: t("cliTransportTitle"),
2664
+ value: transport,
2665
+ disabled: saving || cli.writable !== true,
2666
+ onChange: choose,
2667
+ options: [
2668
+ {
2669
+ value: "auto",
2670
+ label: t("cliTransportAuto")
2671
+ },
2672
+ {
2673
+ value: "cli",
2674
+ label: t("cliTransportCli")
2675
+ },
2676
+ {
2677
+ value: "http",
2678
+ label: t("cliTransportHttp")
2679
+ }
2680
+ ]
2681
+ }),
2682
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2683
+ className: "pkc-note",
2684
+ children: t({
2685
+ auto: "cliTransportAutoHint",
2686
+ cli: "cliTransportCliHint",
2687
+ http: "cliTransportHttpHint"
2688
+ }[transport] ?? "cliTransportAutoHint")
2689
+ }),
2690
+ cli.writable !== true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2691
+ className: "pkc-note",
2692
+ children: t("cliTransportNotWritable")
2693
+ })
2694
+ ] })]
2695
+ }),
2696
+ cli === void 0 && error === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2697
+ className: "pkc-note",
2698
+ children: t("cliChecking")
2699
+ }),
2700
+ usable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
2701
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2702
+ className: "pkc-status",
2703
+ children: [
2704
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2705
+ className: "pkc-dot",
2706
+ "data-tone": "success"
2707
+ }),
2708
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("cliInstalled") }),
2709
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: `${t("cliVersion")} ${cli.version}` })
2710
+ ]
2711
+ }),
2712
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2713
+ className: "pkc-meta",
2714
+ children: [
2715
+ t("cliPath"),
2716
+ " ",
2717
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2718
+ className: "pkc-mono",
2719
+ children: cli.path
2720
+ })
2721
+ ]
2722
+ }),
2723
+ processes !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2724
+ className: "pkc-meta",
2725
+ children: fill(t("cliProcesses"), processes)
2726
+ }),
2727
+ cli.install?.state === "succeeded" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2728
+ className: "pkc-note",
2729
+ children: t("cliInstallSucceeded")
2730
+ })
2731
+ ] }),
2732
+ cli !== void 0 && !usable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2733
+ className: "pkc-callout",
2734
+ children: [
2735
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2736
+ className: "pkc-status",
2737
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2738
+ className: "pkc-dot",
2739
+ "data-tone": cli.installed ? "danger" : "warn"
2740
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: cli.installed ? t("cliBroken") : t("cliMissing") })]
2741
+ }),
2742
+ cli.installed && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2743
+ className: "pkc-meta",
2744
+ children: [
2745
+ t("cliPath"),
2746
+ " ",
2747
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2748
+ className: "pkc-mono",
2749
+ children: cli.path
2750
+ })
2751
+ ]
2752
+ }), cli.error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
2753
+ className: "pkc-detail",
2754
+ children: cli.error
2755
+ })] }),
2756
+ cli.configuredPath !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2757
+ className: "pkc-note",
2758
+ children: fill(t("cliConfiguredMissing"), { path: cli.configuredPath })
2759
+ }),
2760
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2761
+ className: "pkc-note",
2762
+ children: t("cliMissingHint")
2763
+ }),
2764
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2765
+ className: "pkc-split",
2766
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
2767
+ variant: "primary",
2768
+ size: "md",
2769
+ disabled: running || checking,
2770
+ onClick: install,
2771
+ children: running ? t("cliInstalling") : cli.installed ? t("cliReinstall") : t("cliInstall")
2772
+ })
2773
+ }),
2774
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
2775
+ className: "pkc-note",
2776
+ children: [fill(t("cliInstallCommand"), { command: cli.command ?? "" }), cli.platform === "win32" && ` ${t("cliWindowsNote")}`]
2777
+ })
2778
+ ]
2779
+ }),
2780
+ failed && !usable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2781
+ className: "pkc-error",
2782
+ children: failure === void 0 ? t("cliInstallFailed") : `${t("cliInstallFailed")} · ${failure}`
2783
+ }), cli.install.detail !== void 0 && cli.install.detail !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
2784
+ className: "pkc-detail",
2785
+ children: cli.install.detail
2786
+ })] }),
2787
+ error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2788
+ className: "pkc-error",
2789
+ role: "alert",
2790
+ children: `${t("error")}: ${error}`
2791
+ })
2792
+ ]
2793
+ });
2794
+ }
2795
+ /** A release-age wait can end tomorrow, so the date is part of the time. */
2796
+ function readDateTime(ms) {
2797
+ try {
2798
+ return new Date(ms).toLocaleString(void 0, {
2799
+ month: "numeric",
2800
+ day: "numeric",
2801
+ hour: "2-digit",
2802
+ minute: "2-digit"
2803
+ });
2804
+ } catch {
2805
+ return new Date(ms).toISOString().slice(0, 16).replace("T", " ");
2806
+ }
2807
+ }
2478
2808
  function VersionCard({ call, t }) {
2479
2809
  const [info, setInfo] = react.useState();
2480
2810
  const [loading, setLoading] = react.useState(true);
2481
2811
  const [error, setError] = react.useState(false);
2482
2812
  const [updating, setUpdating] = react.useState(false);
2483
2813
  const [updateFailed, setUpdateFailed] = react.useState(false);
2814
+ /** A version pnpm still holds back under the profile's release-age policy. */
2815
+ const [pending, setPending] = react.useState();
2484
2816
  const [updated, setUpdated] = react.useState();
2485
2817
  const [restartHint, setRestartHint] = react.useState(false);
2486
2818
  const generation = react.useRef(0);
@@ -2505,7 +2837,12 @@ window.__ModuleLoader__.load({
2505
2837
  const update = () => {
2506
2838
  setUpdating(true);
2507
2839
  setUpdateFailed(false);
2840
+ setPending(void 0);
2508
2841
  call("plugin/update").then((value) => {
2842
+ if (value?.pending === true) {
2843
+ setPending(value);
2844
+ return;
2845
+ }
2509
2846
  setUpdated(value);
2510
2847
  setRestartHint(false);
2511
2848
  }).catch(() => setUpdateFailed(true)).finally(() => setUpdating(false));
@@ -2567,6 +2904,14 @@ window.__ModuleLoader__.load({
2567
2904
  role: "alert",
2568
2905
  children: t("versionUpdateFailed")
2569
2906
  }),
2907
+ pending !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2908
+ className: "pkc-note",
2909
+ role: "status",
2910
+ children: typeof pending.availableAt === "number" ? fill(t("versionCoolingUntil"), {
2911
+ version: pending.version,
2912
+ time: readDateTime(pending.availableAt)
2913
+ }) : fill(t("versionCooling"), { version: pending.version })
2914
+ }),
2570
2915
  updated !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2571
2916
  className: "pkc-callout",
2572
2917
  "data-tone": "info",
@@ -2625,6 +2970,10 @@ window.__ModuleLoader__.load({
2625
2970
  call,
2626
2971
  t
2627
2972
  }),
2973
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClaudeCliCard, {
2974
+ call,
2975
+ t
2976
+ }),
2628
2977
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelsCard, {
2629
2978
  call,
2630
2979
  t