@mars-sea/dsh-commandcode-provider 0.8.4 → 0.10.0-alpha.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/lib/index.d.ts CHANGED
@@ -24,7 +24,7 @@ declare const KNOWN_EFFORTS: Readonly<Record<string, readonly string[]>>;
24
24
  */
25
25
  declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
26
26
  /**
27
- * Models the official CLI's model table (command-code@1.36.0) marks
27
+ * Models the official CLI's model table (command-code@1.37.0) marks
28
28
  * `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
29
29
  * think automatically, with Command Code driving the depth. This is the
30
30
  * authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
@@ -32,11 +32,13 @@ declare const KNOWN_IMAGE_MODELS: ReadonlySet<string>;
32
32
  * effort levels, and this snapshot is not surfaced in the picker's compact
33
33
  * description — it exists for programmatic consumers.
34
34
  *
35
- * Source: the command-code@1.36.0 bundled model table (dist/cli.mjs),
35
+ * Source: the command-code@1.37.0 bundled model table (dist/cli.mjs),
36
36
  * cross-checked with https://commandcode.ai/docs/reference/cli/models.
37
37
  * (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it
38
38
  * selectable `['low', 'high', 'max']` efforts; the preview then ended in
39
- * 1.34.0, removing the model from the catalog entirely.)
39
+ * 1.34.0, removing the model from the catalog entirely. `tencent/hy4-preview`
40
+ * joined this set in command-code@1.37.0 — reasoning:!0, no efforts, 1M
41
+ * context, routed through OpenRouter.)
40
42
  * Keep in sync via the dsh-commandcode-upstream skill.
41
43
  */
42
44
  declare const KNOWN_THINKING_MODELS: ReadonlySet<string>;
@@ -187,7 +189,7 @@ declare function peakPricingState(modelId: string, now?: number): 'peak' | 'off-
187
189
  * for models without time-of-day pricing.
188
190
  */
189
191
  declare function peakPricingLabel(modelId: string, now?: number): string | undefined;
190
- declare const COMMAND_CODE_CLI_VERSION = "1.36.0";
192
+ declare const COMMAND_CODE_CLI_VERSION = "1.37.0";
191
193
  declare const DEFAULT_API_BASE = "https://api.commandcode.ai";
192
194
  declare const DEFAULT_GENERATE_MAX_TOKENS = 64000;
193
195
  declare const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
@@ -600,6 +602,23 @@ declare const USAGE_REPORT_ENDPOINT = "commandcode/report";
600
602
  */
601
603
  declare const usageReportSchema: TypertSchema<CommandCodeAccountsReport>;
602
604
  //#endregion
605
+ //#region src/command-locales.d.ts
606
+ /**
607
+ * Locale copy for the `/commandcode` usage command and the friendly
608
+ * image-gate error rewrite. Distinct from `./client/locales.ts` (the
609
+ * settings-page namespace `settings.commandcode`): the command runs on the
610
+ * Host and has no access to the client's `ctx.locale`, so the dictionaries
611
+ * are exposed as plain constants for direct lookup; the resolver lives in
612
+ * `pickCommandLocale()`. The image-gate wrapper also lives on the client
613
+ * but is reached from a non-React path that has no `t` in scope, so the
614
+ * same dictionaries serve both surfaces.
615
+ *
616
+ * zh is the source of truth for the key set; en must carry the exact same
617
+ * keys — a mismatch is a compile error at the lookup site.
618
+ */
619
+ /** Active locale id recognized by the command and the image-gate wrapper. */
620
+ type LocaleId = 'zh' | 'en';
621
+ //#endregion
603
622
  //#region src/commands.d.ts
604
623
  /** Everything the command needs beyond the adapter itself. */
605
624
  interface CommandCodeCommandDeps<C extends CommandCodeConnectionOptions = CommandCodeConnectionOptions> {
@@ -611,6 +630,14 @@ interface CommandCodeCommandDeps<C extends CommandCodeConnectionOptions = Comman
611
630
  * `adapter.getUsage()` report.
612
631
  */
613
632
  reports?: () => Promise<CommandCodeAccountsReport>;
633
+ /**
634
+ * Resolve the active locale for one command run. The plugin entry wires
635
+ * this from `Config.lang` and the shell's `LC_ALL`/`LANG`. Absent in
636
+ * programmatic setups (notably the existing test), the command renders
637
+ * with the default locale (`'zh'`) — historically the only language the
638
+ * command ever shipped in.
639
+ */
640
+ getLocale?: () => LocaleId;
614
641
  }
615
642
  /** The one registered `/commandcode` command. */
616
643
  declare function commandDefinition<C extends CommandCodeConnectionOptions>(deps: CommandCodeCommandDeps<C>): CommandDefinition;
@@ -906,6 +933,18 @@ interface Config {
906
933
  * rotation still applies). Unset means "first usable account".
907
934
  */
908
935
  activeAccount?: string;
936
+ /**
937
+ * Language override for the `/commandcode` Host-side command's user-facing
938
+ * copy. Host commands cannot read the client's `ctx.locale`, so this is
939
+ * the explicit knob: `'zh'` or `'en'`. Unset means the command reads
940
+ * `LC_ALL`/`LANG` from the launching shell, falling back to `'zh'`. The
941
+ * web settings page is unaffected — it follows the browser's language
942
+ * preference on its own. Two surfaces, two independent locales. The
943
+ * declared type is `string` (the schemastery `pattern` cannot narrow
944
+ * literal types); an unknown value is treated as "unset" by
945
+ * `pickCommandLocale`.
946
+ */
947
+ lang?: string;
909
948
  }
910
949
  declare const Config: z<Config>;
911
950
  /** One resolution's complete request facts: connection plus credential reference. */
package/lib/index.js CHANGED
@@ -2,10 +2,9 @@ import { homedir } from "node:os";
2
2
  import { dirname, join } from "node:path";
3
3
  import z from "@deepseek-ai/schemastery";
4
4
  import { MAX_TIMER_DELAY_MS } from "@deepseek-ai/dsh-timeout";
5
- import { CallId, LlmAdapter, LlmError, ReasoningEffortId, assertUsableApiKey, attributionHeaders, errorChain, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
5
+ import { LlmAdapter, LlmError, ReasoningEffortId, ToolCallId, assertUsableApiKey, attributionHeaders, errorChain, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
6
6
  import { credentialRef } from "@deepseek-ai/dsh-credentials";
7
7
  import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
8
- import { installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
9
8
  import { existsSync, readFileSync } from "node:fs";
10
9
  import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
11
10
  import { randomBytes, randomUUID } from "node:crypto";
@@ -216,7 +215,7 @@ var CommandCodeAccountPool = class {
216
215
  * and API key or subscription, and Command Code's terms apply.
217
216
  *
218
217
  * Wire protocol (reverse-engineered by the pi plugin, command-code@1.28.4;
219
- * re-verified against command-code@1.36.0 — endpoints, request shape, and
218
+ * re-verified against command-code@1.37.0 — endpoints, request shape, and
220
219
  * stream events unchanged):
221
220
  * POST {apiBase}/alpha/generate
222
221
  * body: { config, memory, taste, skills, params: { model, messages, tools,
@@ -444,7 +443,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
444
443
  "z-ai/glm-5.3-flash"
445
444
  ]);
446
445
  /**
447
- * Models the official CLI's model table (command-code@1.36.0) marks
446
+ * Models the official CLI's model table (command-code@1.37.0) marks
448
447
  * `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
449
448
  * think automatically, with Command Code driving the depth. This is the
450
449
  * authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
@@ -452,11 +451,13 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
452
451
  * effort levels, and this snapshot is not surfaced in the picker's compact
453
452
  * description — it exists for programmatic consumers.
454
453
  *
455
- * Source: the command-code@1.36.0 bundled model table (dist/cli.mjs),
454
+ * Source: the command-code@1.37.0 bundled model table (dist/cli.mjs),
456
455
  * cross-checked with https://commandcode.ai/docs/reference/cli/models.
457
456
  * (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it
458
457
  * selectable `['low', 'high', 'max']` efforts; the preview then ended in
459
- * 1.34.0, removing the model from the catalog entirely.)
458
+ * 1.34.0, removing the model from the catalog entirely. `tencent/hy4-preview`
459
+ * joined this set in command-code@1.37.0 — reasoning:!0, no efforts, 1M
460
+ * context, routed through OpenRouter.)
460
461
  * Keep in sync via the dsh-commandcode-upstream skill.
461
462
  */
462
463
  const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
@@ -473,6 +474,7 @@ const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
473
474
  "stepfun/Step-3.5-Flash",
474
475
  "stepfun/Step-3.7-Flash",
475
476
  "tencent/hy3-paid",
477
+ "tencent/hy4-preview",
476
478
  "nvidia/nemotron-3-ultra-550b-a55b",
477
479
  "thinkingmachines/inkling",
478
480
  "thinkingmachines/inkling-small",
@@ -525,6 +527,7 @@ const KNOWN_PLANS = {
525
527
  "stepfun/Step-3.5-Flash": "go",
526
528
  "stepfun/Step-3.7-Flash": "go",
527
529
  "tencent/hy3-paid": "go",
530
+ "tencent/hy4-preview": "go",
528
531
  "thinkingmachines/inkling": "go",
529
532
  "thinkingmachines/inkling-small": "go",
530
533
  "xai/grok-4.5": "go",
@@ -759,7 +762,7 @@ function peakPricingLabel(modelId, now = Date.now()) {
759
762
  if (state === void 0) return void 0;
760
763
  return state === "peak" ? "Peak" : "Half";
761
764
  }
762
- const COMMAND_CODE_CLI_VERSION = "1.36.0";
765
+ const COMMAND_CODE_CLI_VERSION = "1.37.0";
763
766
  const DEFAULT_API_BASE = "https://api.commandcode.ai";
764
767
  const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
765
768
  const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
@@ -1638,7 +1641,7 @@ var CommandCodeAdapter = class extends LlmAdapter {
1638
1641
  }, {
1639
1642
  type: "tool-call-delta",
1640
1643
  index,
1641
- id: CallId(id),
1644
+ id: ToolCallId(id),
1642
1645
  name,
1643
1646
  argumentsDelta: args
1644
1647
  }, {
@@ -1646,7 +1649,7 @@ var CommandCodeAdapter = class extends LlmAdapter {
1646
1649
  index,
1647
1650
  block: {
1648
1651
  type: "tool-call",
1649
- id: CallId(id),
1652
+ id: ToolCallId(id),
1650
1653
  name,
1651
1654
  arguments: args
1652
1655
  }
@@ -1790,6 +1793,97 @@ function mapFinishReason(reason) {
1790
1793
  return { kind: "stop" };
1791
1794
  }
1792
1795
  //#endregion
1796
+ //#region src/command-locales.ts
1797
+ const commandcodeCommand = {
1798
+ zh: {
1799
+ title: "📊 Command Code 用量{account}",
1800
+ accountTitle: "📊 {label}{badges}",
1801
+ accountSeparator: "────────────────────",
1802
+ activeBadge: " ✅ 当前使用",
1803
+ invalidCredentialBadge: " ⛔ 密钥无效",
1804
+ cooldownBadge: " ⏳ 限额冷却中,重置 {when}",
1805
+ rateLimitBadge: " ⏳ 已达限额(等待窗口探测)",
1806
+ unconfigured: " (未配置 API 密钥)",
1807
+ blockedInvalidKey: "⛔ API 密钥无效或已过期 — 服务端拒绝了全部请求(401),请检查该账户的密钥配置",
1808
+ blockedServiceUnavailable: "⚠️ Command Code 服务暂时不可用(5xx),稍后重试",
1809
+ blockedNetwork: "⚠️ 无法连接 Command Code 服务 — 请检查网络或 API 地址",
1810
+ planLine: " 📦 套餐 {name}{status}{period}",
1811
+ planPeriodSuffix: " · 账期截止 {date}",
1812
+ usageHeader: "── 请求 ──────────────────────────────",
1813
+ requestsLine: " 💬 请求 {n} 次 / 失败 {f} 成功率 {r}%",
1814
+ costLine: " 💰 花费 {money} ({credits} credits)",
1815
+ tokensLine: " 🔤 Token {in} 入 / {out} 出",
1816
+ creditsHeader: "── 信用 ──────────────────────────────",
1817
+ monthlyLine: " 💳 月额度 {monthly} (已购 {purchased} / 赠送 {free})",
1818
+ barLine: " └ {bar} {pct}%",
1819
+ windowsHeader: "── 窗口用量 ──────────────────────────",
1820
+ fiveHourLine: " ⏱ 5 小时 {used} / {cap}{warn}",
1821
+ weeklyLine: " 📅 每周 {used} / {cap}{warn}",
1822
+ windowBarLine: " └ {bar} 重置 {when}",
1823
+ exceededWarning: " ⚠️ 超限!",
1824
+ resetSuffix: "重置 {when}",
1825
+ partialFailures: "⚠️ 部分端点失败: {list}",
1826
+ noData: "(no data — check your API key)",
1827
+ errorText: "Could not fetch Command Code usage: {message}",
1828
+ imageGate: "当前会话已包含图片,而模型 {model} 不支持图片输入;请选择支持图片的模型,或先移除会话中的图片。"
1829
+ },
1830
+ en: {
1831
+ title: "📊 Command Code usage{account}",
1832
+ accountTitle: "📊 {label}{badges}",
1833
+ accountSeparator: "────────────────────",
1834
+ activeBadge: " ✅ active",
1835
+ invalidCredentialBadge: " ⛔ invalid key",
1836
+ cooldownBadge: " ⏳ cooling down, resets {when}",
1837
+ rateLimitBadge: " ⏳ rate-limited (waiting for window probe)",
1838
+ unconfigured: " (no API key configured)",
1839
+ blockedInvalidKey: "⛔ API key invalid or expired — the server rejected every request (401); check the key configured for this account",
1840
+ blockedServiceUnavailable: "⚠️ Command Code service temporarily unavailable (5xx); try again later",
1841
+ blockedNetwork: "⚠️ could not reach the Command Code service — check your network or the API base setting",
1842
+ planLine: " 📦 Plan {name}{status}{period}",
1843
+ planPeriodSuffix: " · period ends {date}",
1844
+ usageHeader: "── Requests ──────────────────────────",
1845
+ requestsLine: " 💬 Requests {n} / failed {f} success rate {r}%",
1846
+ costLine: " 💰 Spend {money} ({credits} credits)",
1847
+ tokensLine: " 🔤 Tokens {in} in / {out} out",
1848
+ creditsHeader: "── Credits ───────────────────────────",
1849
+ monthlyLine: " 💳 Monthly {monthly} (purchased {purchased} / free {free})",
1850
+ barLine: " └ {bar} {pct}%",
1851
+ windowsHeader: "── Window usage ──────────────────────",
1852
+ fiveHourLine: " ⏱ 5-hour {used} / {cap}{warn}",
1853
+ weeklyLine: " 📅 Weekly {used} / {cap}{warn}",
1854
+ windowBarLine: " └ {bar} resets {when}",
1855
+ exceededWarning: " ⚠️ exceeded!",
1856
+ resetSuffix: "resets {when}",
1857
+ partialFailures: "⚠️ some endpoints failed: {list}",
1858
+ noData: "(no data — check your API key)",
1859
+ errorText: "Could not fetch Command Code usage: {message}",
1860
+ imageGate: "This session already contains images, and model {model} does not accept image input; please select an image-capable model, or remove the images from the session first."
1861
+ }
1862
+ };
1863
+ /**
1864
+ * Resolve the active locale for a Host-side command run.
1865
+ *
1866
+ * Priority: explicit `override` (from `Config.lang`) → `LC_ALL` → `LANG` →
1867
+ * the conventional fallback (`'zh'`, matching the existing single-language
1868
+ * behavior so unconfigured deployments keep their current output).
1869
+ *
1870
+ * The values are matched on the leading tag only — `zh_CN.UTF-8`,
1871
+ * `zh-Hans`, `zh` all map to `'zh'`; everything starting with `en` maps to
1872
+ * `'en'`; anything else falls back to `'zh'` (a non-`en` shell that
1873
+ * already has Chinese in the terminal is the closest sensible default;
1874
+ * a Western shell that happens to be neither keeps the existing Chinese
1875
+ * output rather than swapping to half-translated English).
1876
+ */
1877
+ function pickCommandLocale(override, env = process.env) {
1878
+ if (override === "zh" || override === "en") return override;
1879
+ if (((env.LC_ALL ?? env.LANG ?? "").toLowerCase().split(/[._-]/)[0] ?? "") === "en") return "en";
1880
+ return "zh";
1881
+ }
1882
+ /** Look up a key in the active locale, with an internal en fallback. */
1883
+ function commandCopy(locale, key) {
1884
+ return commandcodeCommand[locale][key] ?? commandcodeCommand.en[key] ?? key;
1885
+ }
1886
+ //#endregion
1793
1887
  //#region src/commands.ts
1794
1888
  /** Format a dollar amount. */
1795
1889
  function money(value) {
@@ -1806,7 +1900,7 @@ function tokensCompact(value) {
1806
1900
  if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
1807
1901
  return String(value);
1808
1902
  }
1809
- /** Format a millis timestamp as a local date. */
1903
+ /** Format a millis timestamp as a local date; `n/a` when unset. */
1810
1904
  function resetLabel(ms) {
1811
1905
  if (ms <= 0) return "n/a";
1812
1906
  return new Date(ms).toLocaleString();
@@ -1822,37 +1916,37 @@ function bar(used, cap) {
1822
1916
  return "█".repeat(filled) + "░".repeat(10 - filled);
1823
1917
  }
1824
1918
  /** Render one account's rotation mark / cooldown as a short badge. */
1825
- function markLabel(entry) {
1826
- if (entry.mark === "invalid-credential") return " ⛔ 密钥无效";
1827
- if (entry.cooldownUntil > 0) return ` ⏳ 限额冷却中,重置 ${resetLabel(entry.cooldownUntil)}`;
1828
- if (entry.mark === "rate-limit") return " ⏳ 已达限额(等待窗口探测)";
1919
+ function markLabel(entry, locale) {
1920
+ if (entry.mark === "invalid-credential") return commandCopy(locale, "invalidCredentialBadge");
1921
+ if (entry.cooldownUntil > 0) return commandCopy(locale, "cooldownBadge").replace("{when}", resetLabel(entry.cooldownUntil));
1922
+ if (entry.mark === "rate-limit") return commandCopy(locale, "rateLimitBadge");
1829
1923
  return "";
1830
1924
  }
1831
1925
  /** Render the usage report as a structured, aligned, bar-chart text view. */
1832
- function renderReport(report, title) {
1926
+ function renderReport(report, locale, title) {
1833
1927
  const lines = [];
1834
1928
  const account = report.account ? ` (${report.account.userName || report.account.name})` : "";
1835
- lines.push(title ?? `📊 Command Code 用量${account}`, "");
1836
- if (report.blocked === "invalid-key") lines.push("⛔ API 密钥无效或已过期 — 服务端拒绝了全部请求(401),请检查该账户的密钥配置", "");
1837
- else if (report.blocked === "service-unavailable") lines.push("⚠️ Command Code 服务暂时不可用(5xx),稍后重试", "");
1838
- else if (report.blocked === "network") lines.push("⚠️ 无法连接 Command Code 服务 — 请检查网络或 API 地址", "");
1929
+ lines.push(title ?? commandCopy(locale, "title").replace("{account}", account), "");
1930
+ if (report.blocked === "invalid-key") lines.push(commandCopy(locale, "blockedInvalidKey"), "");
1931
+ else if (report.blocked === "service-unavailable") lines.push(commandCopy(locale, "blockedServiceUnavailable"), "");
1932
+ else if (report.blocked === "network") lines.push(commandCopy(locale, "blockedNetwork"), "");
1839
1933
  if (report.plan && report.plan.name !== "") {
1840
1934
  const p = report.plan;
1841
1935
  const status = p.status !== "" && p.status !== "active" ? ` (${p.status})` : "";
1842
- const period = p.currentPeriodEnd > 0 ? ` · 账期截止 ${new Date(p.currentPeriodEnd).toLocaleDateString()}` : "";
1843
- lines.push(` 📦 套餐 ${p.name}${status}${period}`, "");
1936
+ const period = p.currentPeriodEnd > 0 ? commandCopy(locale, "planPeriodSuffix").replace("{date}", new Date(p.currentPeriodEnd).toLocaleDateString()) : "";
1937
+ lines.push(commandCopy(locale, "planLine").replace("{name}", p.name).replace("{status}", status).replace("{period}", period), "");
1844
1938
  }
1845
1939
  if (report.usage) {
1846
1940
  const u = report.usage;
1847
- lines.push("── 请求 ──────────────────────────────", ` 💬 请求 ${u.completedCount} 次 / 失败 ${u.failedCount} 成功率 ${u.successRate}%`, ` 💰 花费 ${money(u.totalCost)} (${moneyShort(u.totalCredits)} credits)`, ` 🔤 Token ${tokensCompact(u.totalTokensIn)} 入 / ${tokensCompact(u.totalTokensOut)} 出`, "");
1941
+ lines.push(commandCopy(locale, "usageHeader"), commandCopy(locale, "requestsLine").replace("{n}", String(u.completedCount)).replace("{f}", String(u.failedCount)).replace("{r}", String(u.successRate)), commandCopy(locale, "costLine").replace("{money}", money(u.totalCost)).replace("{credits}", moneyShort(u.totalCredits)), commandCopy(locale, "tokensLine").replace("{in}", tokensCompact(u.totalTokensIn)).replace("{out}", tokensCompact(u.totalTokensOut)), "");
1848
1942
  }
1849
1943
  if (report.credits) {
1850
1944
  const c = report.credits;
1851
1945
  const monthlyPct = c.monthlyCredits > 0 ? `${(c.monthlyCredits / (c.monthlyCredits + c.purchasedCredits) * 100).toFixed(0)}%` : "—";
1852
- lines.push("── 信用 ──────────────────────────────", ` 💳 月额度 ${moneyShort(c.monthlyCredits)} (已购 ${moneyShort(c.purchasedCredits)} / 赠送 ${moneyShort(c.freeCredits)})`, ` └ ${bar(c.monthlyCredits, c.monthlyCredits + c.purchasedCredits)} ${monthlyPct}`, "", "── 窗口用量 ──────────────────────────", ` ⏱ 5 小时 ${moneyShort(c.fiveHour.used)} / ${moneyShort(c.fiveHour.cap)}${c.fiveHour.exceeded ? " ⚠️ 超限!" : ""}`, ` └ ${bar(c.fiveHour.used, c.fiveHour.cap)} 重置 ${resetLabel(c.fiveHour.resetAt)}`, ` 📅 每周 ${moneyShort(c.weekly.used)} / ${moneyShort(c.weekly.cap)}${c.weekly.exceeded ? " ⚠️ 超限!" : ""}`, ` └ ${bar(c.weekly.used, c.weekly.cap)} 重置 ${resetLabel(c.weekly.resetAt)}`, "");
1946
+ lines.push(commandCopy(locale, "creditsHeader"), commandCopy(locale, "monthlyLine").replace("{monthly}", moneyShort(c.monthlyCredits)).replace("{purchased}", moneyShort(c.purchasedCredits)).replace("{free}", moneyShort(c.freeCredits)), commandCopy(locale, "barLine").replace("{bar}", bar(c.monthlyCredits, c.monthlyCredits + c.purchasedCredits)).replace("{pct}", monthlyPct), "", commandCopy(locale, "windowsHeader"), commandCopy(locale, "fiveHourLine").replace("{used}", moneyShort(c.fiveHour.used)).replace("{cap}", moneyShort(c.fiveHour.cap)).replace("{warn}", c.fiveHour.exceeded ? commandCopy(locale, "exceededWarning") : ""), commandCopy(locale, "windowBarLine").replace("{bar}", bar(c.fiveHour.used, c.fiveHour.cap)).replace("{when}", resetLabel(c.fiveHour.resetAt)), commandCopy(locale, "weeklyLine").replace("{used}", moneyShort(c.weekly.used)).replace("{cap}", moneyShort(c.weekly.cap)).replace("{warn}", c.weekly.exceeded ? commandCopy(locale, "exceededWarning") : ""), commandCopy(locale, "windowBarLine").replace("{bar}", bar(c.weekly.used, c.weekly.cap)).replace("{when}", resetLabel(c.weekly.resetAt)), "");
1853
1947
  }
1854
- if (report.failures.length > 0) lines.push(`⚠️ 部分端点失败: ${report.failures.join("; ")}`, "");
1855
- if (!report.account && !report.usage && !report.credits) lines.push("(no data — check your API key)", "");
1948
+ if (report.failures.length > 0) lines.push(commandCopy(locale, "partialFailures").replace("{list}", report.failures.join("; ")), "");
1949
+ if (!report.account && !report.usage && !report.credits) lines.push(commandCopy(locale, "noData"), "");
1856
1950
  return lines.join("\n").trimEnd();
1857
1951
  }
1858
1952
  /** The one registered `/commandcode` command. */
@@ -1863,27 +1957,29 @@ function commandDefinition(deps) {
1863
1957
  description: "Command Code account usage dashboard",
1864
1958
  input: { hint: "[status]" },
1865
1959
  handler: async () => {
1960
+ const locale = deps.getLocale?.() ?? "zh";
1866
1961
  try {
1867
1962
  if (deps.reports !== void 0) {
1868
1963
  const { accounts } = await deps.reports();
1869
1964
  return {
1870
1965
  kind: "success",
1871
1966
  text: accounts.map((entry) => {
1872
- const badges = `${entry.active ? " ✅ 当前使用" : ""}${markLabel(entry)}`;
1873
- const title = `📊 ${entry.label}${badges}`;
1874
- if (!entry.configured) return `${title}\n\n (未配置 API 密钥)`;
1875
- return renderReport(entry.report, title);
1876
- }).join("\n\n────────────────────\n\n")
1967
+ const badges = `${entry.active ? commandCopy(locale, "activeBadge") : ""}${markLabel(entry, locale)}`;
1968
+ const title = commandCopy(locale, "accountTitle").replace("{label}", entry.label).replace("{badges}", badges);
1969
+ if (!entry.configured) return `${title}\n\n${commandCopy(locale, "unconfigured")}`;
1970
+ return renderReport(entry.report, locale, title);
1971
+ }).join(`\n\n${commandCopy(locale, "accountSeparator")}\n\n`)
1877
1972
  };
1878
1973
  }
1879
1974
  return {
1880
1975
  kind: "success",
1881
- text: renderReport(await adapter.getUsage())
1976
+ text: renderReport(await adapter.getUsage(), locale)
1882
1977
  };
1883
1978
  } catch (error) {
1979
+ const message = error instanceof Error ? error.message : String(error);
1884
1980
  return {
1885
1981
  kind: "error",
1886
- text: `Could not fetch Command Code usage: ${error instanceof Error ? error.message : String(error)}`
1982
+ text: commandCopy(locale, "errorText").replace("{message}", message)
1887
1983
  };
1888
1984
  }
1889
1985
  }
@@ -2027,6 +2123,11 @@ const USAGE_HOST_CONTRIBUTION = {
2027
2123
  package: USAGE_REMOTE_PACKAGE,
2028
2124
  face: "host",
2029
2125
  schemas: [],
2126
+ model: {
2127
+ services: [],
2128
+ events: [],
2129
+ objects: []
2130
+ },
2030
2131
  invocations: [{
2031
2132
  id: `${USAGE_REMOTE_PACKAGE}#${USAGE_REPORT_ENDPOINT}`,
2032
2133
  service: "commandcodeUsage",
@@ -2603,7 +2704,7 @@ function corsOrigin(origin) {
2603
2704
  */
2604
2705
  const name = "llm-commandcode";
2605
2706
  const inject = ["llm"];
2606
- const NS = settingsNamespace("llm-commandcode");
2707
+ const NS = "llm-commandcode";
2607
2708
  const DEFAULT_API_KEY_ENV = "COMMANDCODE_API_KEY";
2608
2709
  /** The single provider route this plugin owns. */
2609
2710
  const PROVIDER = "commandcode";
@@ -2623,7 +2724,8 @@ const Config = z.object({
2623
2724
  apiKeyEnv: z.string().role("credential-ref"),
2624
2725
  apiKey: z.string()
2625
2726
  })),
2626
- activeAccount: z.string()
2727
+ activeAccount: z.string(),
2728
+ lang: z.string().pattern(/^(zh|en)$/).default("zh")
2627
2729
  });
2628
2730
  /**
2629
2731
  * The one explicit resolve step from raw config to validated connection
@@ -2747,10 +2849,12 @@ function apply(ctx, config) {
2747
2849
  };
2748
2850
  })) };
2749
2851
  };
2852
+ const commandLocale = () => pickCommandLocale(current().lang);
2750
2853
  ctx.inject(["commands"], (commandCtx) => {
2751
2854
  applyCommands(commandCtx, {
2752
2855
  adapter,
2753
- reports: usageReports
2856
+ reports: usageReports,
2857
+ getLocale: commandLocale
2754
2858
  });
2755
2859
  });
2756
2860
  const loginFlow = new CommandCodeLoginFlow({
@@ -2768,11 +2872,13 @@ function apply(ctx, config) {
2768
2872
  reports: usageReports,
2769
2873
  login: loginFlow
2770
2874
  });
2771
- installSettingsSection(ctx, NS, Config, config, {
2772
- setSource: (source) => {
2773
- current = source;
2774
- },
2775
- onChange: () => {}
2875
+ ctx.inject(["settings"], (settingsCtx) => {
2876
+ settingsCtx.settings.installSection(ctx, NS, Config, config, {
2877
+ setSource: (source) => {
2878
+ current = source;
2879
+ },
2880
+ onChange: () => {}
2881
+ });
2776
2882
  });
2777
2883
  }
2778
2884
  //#endregion