@mars-sea/dsh-commandcode-provider 0.8.4 → 0.9.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/CHANGELOG.md +23 -0
- package/README.md +3 -0
- package/README.zh-CN.md +3 -0
- package/lib/client.js +563 -91
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +43 -4
- package/lib/index.js +130 -30
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
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.
|
|
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.
|
|
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.
|
|
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
|
@@ -216,7 +216,7 @@ var CommandCodeAccountPool = class {
|
|
|
216
216
|
* and API key or subscription, and Command Code's terms apply.
|
|
217
217
|
*
|
|
218
218
|
* Wire protocol (reverse-engineered by the pi plugin, command-code@1.28.4;
|
|
219
|
-
* re-verified against command-code@1.
|
|
219
|
+
* re-verified against command-code@1.37.0 — endpoints, request shape, and
|
|
220
220
|
* stream events unchanged):
|
|
221
221
|
* POST {apiBase}/alpha/generate
|
|
222
222
|
* body: { config, memory, taste, skills, params: { model, messages, tools,
|
|
@@ -444,7 +444,7 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
444
444
|
"z-ai/glm-5.3-flash"
|
|
445
445
|
]);
|
|
446
446
|
/**
|
|
447
|
-
* Models the official CLI's model table (command-code@1.
|
|
447
|
+
* Models the official CLI's model table (command-code@1.37.0) marks
|
|
448
448
|
* `reasoning:!0` but defines no selectable `reasoning_effort` levels — they
|
|
449
449
|
* think automatically, with Command Code driving the depth. This is the
|
|
450
450
|
* authoritative "thinks, effort not adjustable" set: `KNOWN_EFFORTS` (which
|
|
@@ -452,11 +452,13 @@ const KNOWN_IMAGE_MODELS = /* @__PURE__ */ new Set([
|
|
|
452
452
|
* effort levels, and this snapshot is not surfaced in the picker's compact
|
|
453
453
|
* description — it exists for programmatic consumers.
|
|
454
454
|
*
|
|
455
|
-
* Source: the command-code@1.
|
|
455
|
+
* Source: the command-code@1.37.0 bundled model table (dist/cli.mjs),
|
|
456
456
|
* cross-checked with https://commandcode.ai/docs/reference/cli/models.
|
|
457
457
|
* (`stealth/ox-alpha` left this set in command-code@1.32.1, which gave it
|
|
458
458
|
* selectable `['low', 'high', 'max']` efforts; the preview then ended in
|
|
459
|
-
* 1.34.0, removing the model from the catalog entirely.
|
|
459
|
+
* 1.34.0, removing the model from the catalog entirely. `tencent/hy4-preview`
|
|
460
|
+
* joined this set in command-code@1.37.0 — reasoning:!0, no efforts, 1M
|
|
461
|
+
* context, routed through OpenRouter.)
|
|
460
462
|
* Keep in sync via the dsh-commandcode-upstream skill.
|
|
461
463
|
*/
|
|
462
464
|
const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
|
|
@@ -473,6 +475,7 @@ const KNOWN_THINKING_MODELS = /* @__PURE__ */ new Set([
|
|
|
473
475
|
"stepfun/Step-3.5-Flash",
|
|
474
476
|
"stepfun/Step-3.7-Flash",
|
|
475
477
|
"tencent/hy3-paid",
|
|
478
|
+
"tencent/hy4-preview",
|
|
476
479
|
"nvidia/nemotron-3-ultra-550b-a55b",
|
|
477
480
|
"thinkingmachines/inkling",
|
|
478
481
|
"thinkingmachines/inkling-small",
|
|
@@ -525,6 +528,7 @@ const KNOWN_PLANS = {
|
|
|
525
528
|
"stepfun/Step-3.5-Flash": "go",
|
|
526
529
|
"stepfun/Step-3.7-Flash": "go",
|
|
527
530
|
"tencent/hy3-paid": "go",
|
|
531
|
+
"tencent/hy4-preview": "go",
|
|
528
532
|
"thinkingmachines/inkling": "go",
|
|
529
533
|
"thinkingmachines/inkling-small": "go",
|
|
530
534
|
"xai/grok-4.5": "go",
|
|
@@ -759,7 +763,7 @@ function peakPricingLabel(modelId, now = Date.now()) {
|
|
|
759
763
|
if (state === void 0) return void 0;
|
|
760
764
|
return state === "peak" ? "Peak" : "Half";
|
|
761
765
|
}
|
|
762
|
-
const COMMAND_CODE_CLI_VERSION = "1.
|
|
766
|
+
const COMMAND_CODE_CLI_VERSION = "1.37.0";
|
|
763
767
|
const DEFAULT_API_BASE = "https://api.commandcode.ai";
|
|
764
768
|
const DEFAULT_GENERATE_MAX_TOKENS = 64e3;
|
|
765
769
|
const DEFAULT_MAX_OUTPUT_TOKENS = 65536;
|
|
@@ -1790,6 +1794,97 @@ function mapFinishReason(reason) {
|
|
|
1790
1794
|
return { kind: "stop" };
|
|
1791
1795
|
}
|
|
1792
1796
|
//#endregion
|
|
1797
|
+
//#region src/command-locales.ts
|
|
1798
|
+
const commandcodeCommand = {
|
|
1799
|
+
zh: {
|
|
1800
|
+
title: "📊 Command Code 用量{account}",
|
|
1801
|
+
accountTitle: "📊 {label}{badges}",
|
|
1802
|
+
accountSeparator: "────────────────────",
|
|
1803
|
+
activeBadge: " ✅ 当前使用",
|
|
1804
|
+
invalidCredentialBadge: " ⛔ 密钥无效",
|
|
1805
|
+
cooldownBadge: " ⏳ 限额冷却中,重置 {when}",
|
|
1806
|
+
rateLimitBadge: " ⏳ 已达限额(等待窗口探测)",
|
|
1807
|
+
unconfigured: " (未配置 API 密钥)",
|
|
1808
|
+
blockedInvalidKey: "⛔ API 密钥无效或已过期 — 服务端拒绝了全部请求(401),请检查该账户的密钥配置",
|
|
1809
|
+
blockedServiceUnavailable: "⚠️ Command Code 服务暂时不可用(5xx),稍后重试",
|
|
1810
|
+
blockedNetwork: "⚠️ 无法连接 Command Code 服务 — 请检查网络或 API 地址",
|
|
1811
|
+
planLine: " 📦 套餐 {name}{status}{period}",
|
|
1812
|
+
planPeriodSuffix: " · 账期截止 {date}",
|
|
1813
|
+
usageHeader: "── 请求 ──────────────────────────────",
|
|
1814
|
+
requestsLine: " 💬 请求 {n} 次 / 失败 {f} 成功率 {r}%",
|
|
1815
|
+
costLine: " 💰 花费 {money} ({credits} credits)",
|
|
1816
|
+
tokensLine: " 🔤 Token {in} 入 / {out} 出",
|
|
1817
|
+
creditsHeader: "── 信用 ──────────────────────────────",
|
|
1818
|
+
monthlyLine: " 💳 月额度 {monthly} (已购 {purchased} / 赠送 {free})",
|
|
1819
|
+
barLine: " └ {bar} {pct}%",
|
|
1820
|
+
windowsHeader: "── 窗口用量 ──────────────────────────",
|
|
1821
|
+
fiveHourLine: " ⏱ 5 小时 {used} / {cap}{warn}",
|
|
1822
|
+
weeklyLine: " 📅 每周 {used} / {cap}{warn}",
|
|
1823
|
+
windowBarLine: " └ {bar} 重置 {when}",
|
|
1824
|
+
exceededWarning: " ⚠️ 超限!",
|
|
1825
|
+
resetSuffix: "重置 {when}",
|
|
1826
|
+
partialFailures: "⚠️ 部分端点失败: {list}",
|
|
1827
|
+
noData: "(no data — check your API key)",
|
|
1828
|
+
errorText: "Could not fetch Command Code usage: {message}",
|
|
1829
|
+
imageGate: "当前会话已包含图片,而模型 {model} 不支持图片输入;请选择支持图片的模型,或先移除会话中的图片。"
|
|
1830
|
+
},
|
|
1831
|
+
en: {
|
|
1832
|
+
title: "📊 Command Code usage{account}",
|
|
1833
|
+
accountTitle: "📊 {label}{badges}",
|
|
1834
|
+
accountSeparator: "────────────────────",
|
|
1835
|
+
activeBadge: " ✅ active",
|
|
1836
|
+
invalidCredentialBadge: " ⛔ invalid key",
|
|
1837
|
+
cooldownBadge: " ⏳ cooling down, resets {when}",
|
|
1838
|
+
rateLimitBadge: " ⏳ rate-limited (waiting for window probe)",
|
|
1839
|
+
unconfigured: " (no API key configured)",
|
|
1840
|
+
blockedInvalidKey: "⛔ API key invalid or expired — the server rejected every request (401); check the key configured for this account",
|
|
1841
|
+
blockedServiceUnavailable: "⚠️ Command Code service temporarily unavailable (5xx); try again later",
|
|
1842
|
+
blockedNetwork: "⚠️ could not reach the Command Code service — check your network or the API base setting",
|
|
1843
|
+
planLine: " 📦 Plan {name}{status}{period}",
|
|
1844
|
+
planPeriodSuffix: " · period ends {date}",
|
|
1845
|
+
usageHeader: "── Requests ──────────────────────────",
|
|
1846
|
+
requestsLine: " 💬 Requests {n} / failed {f} success rate {r}%",
|
|
1847
|
+
costLine: " 💰 Spend {money} ({credits} credits)",
|
|
1848
|
+
tokensLine: " 🔤 Tokens {in} in / {out} out",
|
|
1849
|
+
creditsHeader: "── Credits ───────────────────────────",
|
|
1850
|
+
monthlyLine: " 💳 Monthly {monthly} (purchased {purchased} / free {free})",
|
|
1851
|
+
barLine: " └ {bar} {pct}%",
|
|
1852
|
+
windowsHeader: "── Window usage ──────────────────────",
|
|
1853
|
+
fiveHourLine: " ⏱ 5-hour {used} / {cap}{warn}",
|
|
1854
|
+
weeklyLine: " 📅 Weekly {used} / {cap}{warn}",
|
|
1855
|
+
windowBarLine: " └ {bar} resets {when}",
|
|
1856
|
+
exceededWarning: " ⚠️ exceeded!",
|
|
1857
|
+
resetSuffix: "resets {when}",
|
|
1858
|
+
partialFailures: "⚠️ some endpoints failed: {list}",
|
|
1859
|
+
noData: "(no data — check your API key)",
|
|
1860
|
+
errorText: "Could not fetch Command Code usage: {message}",
|
|
1861
|
+
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."
|
|
1862
|
+
}
|
|
1863
|
+
};
|
|
1864
|
+
/**
|
|
1865
|
+
* Resolve the active locale for a Host-side command run.
|
|
1866
|
+
*
|
|
1867
|
+
* Priority: explicit `override` (from `Config.lang`) → `LC_ALL` → `LANG` →
|
|
1868
|
+
* the conventional fallback (`'zh'`, matching the existing single-language
|
|
1869
|
+
* behavior so unconfigured deployments keep their current output).
|
|
1870
|
+
*
|
|
1871
|
+
* The values are matched on the leading tag only — `zh_CN.UTF-8`,
|
|
1872
|
+
* `zh-Hans`, `zh` all map to `'zh'`; everything starting with `en` maps to
|
|
1873
|
+
* `'en'`; anything else falls back to `'zh'` (a non-`en` shell that
|
|
1874
|
+
* already has Chinese in the terminal is the closest sensible default;
|
|
1875
|
+
* a Western shell that happens to be neither keeps the existing Chinese
|
|
1876
|
+
* output rather than swapping to half-translated English).
|
|
1877
|
+
*/
|
|
1878
|
+
function pickCommandLocale(override, env = process.env) {
|
|
1879
|
+
if (override === "zh" || override === "en") return override;
|
|
1880
|
+
if (((env.LC_ALL ?? env.LANG ?? "").toLowerCase().split(/[._-]/)[0] ?? "") === "en") return "en";
|
|
1881
|
+
return "zh";
|
|
1882
|
+
}
|
|
1883
|
+
/** Look up a key in the active locale, with an internal en fallback. */
|
|
1884
|
+
function commandCopy(locale, key) {
|
|
1885
|
+
return commandcodeCommand[locale][key] ?? commandcodeCommand.en[key] ?? key;
|
|
1886
|
+
}
|
|
1887
|
+
//#endregion
|
|
1793
1888
|
//#region src/commands.ts
|
|
1794
1889
|
/** Format a dollar amount. */
|
|
1795
1890
|
function money(value) {
|
|
@@ -1806,7 +1901,7 @@ function tokensCompact(value) {
|
|
|
1806
1901
|
if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
|
|
1807
1902
|
return String(value);
|
|
1808
1903
|
}
|
|
1809
|
-
/** Format a millis timestamp as a local date. */
|
|
1904
|
+
/** Format a millis timestamp as a local date; `n/a` when unset. */
|
|
1810
1905
|
function resetLabel(ms) {
|
|
1811
1906
|
if (ms <= 0) return "n/a";
|
|
1812
1907
|
return new Date(ms).toLocaleString();
|
|
@@ -1822,37 +1917,37 @@ function bar(used, cap) {
|
|
|
1822
1917
|
return "█".repeat(filled) + "░".repeat(10 - filled);
|
|
1823
1918
|
}
|
|
1824
1919
|
/** 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
|
|
1828
|
-
if (entry.mark === "rate-limit") return
|
|
1920
|
+
function markLabel(entry, locale) {
|
|
1921
|
+
if (entry.mark === "invalid-credential") return commandCopy(locale, "invalidCredentialBadge");
|
|
1922
|
+
if (entry.cooldownUntil > 0) return commandCopy(locale, "cooldownBadge").replace("{when}", resetLabel(entry.cooldownUntil));
|
|
1923
|
+
if (entry.mark === "rate-limit") return commandCopy(locale, "rateLimitBadge");
|
|
1829
1924
|
return "";
|
|
1830
1925
|
}
|
|
1831
1926
|
/** Render the usage report as a structured, aligned, bar-chart text view. */
|
|
1832
|
-
function renderReport(report, title) {
|
|
1927
|
+
function renderReport(report, locale, title) {
|
|
1833
1928
|
const lines = [];
|
|
1834
1929
|
const account = report.account ? ` (${report.account.userName || report.account.name})` : "";
|
|
1835
|
-
lines.push(title ??
|
|
1836
|
-
if (report.blocked === "invalid-key") lines.push(
|
|
1837
|
-
else if (report.blocked === "service-unavailable") lines.push(
|
|
1838
|
-
else if (report.blocked === "network") lines.push(
|
|
1930
|
+
lines.push(title ?? commandCopy(locale, "title").replace("{account}", account), "");
|
|
1931
|
+
if (report.blocked === "invalid-key") lines.push(commandCopy(locale, "blockedInvalidKey"), "");
|
|
1932
|
+
else if (report.blocked === "service-unavailable") lines.push(commandCopy(locale, "blockedServiceUnavailable"), "");
|
|
1933
|
+
else if (report.blocked === "network") lines.push(commandCopy(locale, "blockedNetwork"), "");
|
|
1839
1934
|
if (report.plan && report.plan.name !== "") {
|
|
1840
1935
|
const p = report.plan;
|
|
1841
1936
|
const status = p.status !== "" && p.status !== "active" ? ` (${p.status})` : "";
|
|
1842
|
-
const period = p.currentPeriodEnd > 0 ?
|
|
1843
|
-
lines.push(
|
|
1937
|
+
const period = p.currentPeriodEnd > 0 ? commandCopy(locale, "planPeriodSuffix").replace("{date}", new Date(p.currentPeriodEnd).toLocaleDateString()) : "";
|
|
1938
|
+
lines.push(commandCopy(locale, "planLine").replace("{name}", p.name).replace("{status}", status).replace("{period}", period), "");
|
|
1844
1939
|
}
|
|
1845
1940
|
if (report.usage) {
|
|
1846
1941
|
const u = report.usage;
|
|
1847
|
-
lines.push("
|
|
1942
|
+
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
1943
|
}
|
|
1849
1944
|
if (report.credits) {
|
|
1850
1945
|
const c = report.credits;
|
|
1851
1946
|
const monthlyPct = c.monthlyCredits > 0 ? `${(c.monthlyCredits / (c.monthlyCredits + c.purchasedCredits) * 100).toFixed(0)}%` : "—";
|
|
1852
|
-
lines.push("
|
|
1947
|
+
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
1948
|
}
|
|
1854
|
-
if (report.failures.length > 0) lines.push(
|
|
1855
|
-
if (!report.account && !report.usage && !report.credits) lines.push(
|
|
1949
|
+
if (report.failures.length > 0) lines.push(commandCopy(locale, "partialFailures").replace("{list}", report.failures.join("; ")), "");
|
|
1950
|
+
if (!report.account && !report.usage && !report.credits) lines.push(commandCopy(locale, "noData"), "");
|
|
1856
1951
|
return lines.join("\n").trimEnd();
|
|
1857
1952
|
}
|
|
1858
1953
|
/** The one registered `/commandcode` command. */
|
|
@@ -1863,27 +1958,29 @@ function commandDefinition(deps) {
|
|
|
1863
1958
|
description: "Command Code account usage dashboard",
|
|
1864
1959
|
input: { hint: "[status]" },
|
|
1865
1960
|
handler: async () => {
|
|
1961
|
+
const locale = deps.getLocale?.() ?? "zh";
|
|
1866
1962
|
try {
|
|
1867
1963
|
if (deps.reports !== void 0) {
|
|
1868
1964
|
const { accounts } = await deps.reports();
|
|
1869
1965
|
return {
|
|
1870
1966
|
kind: "success",
|
|
1871
1967
|
text: accounts.map((entry) => {
|
|
1872
|
-
const badges = `${entry.active ?
|
|
1873
|
-
const title =
|
|
1874
|
-
if (!entry.configured) return `${title}\n\n
|
|
1875
|
-
return renderReport(entry.report, title);
|
|
1876
|
-
}).join(
|
|
1968
|
+
const badges = `${entry.active ? commandCopy(locale, "activeBadge") : ""}${markLabel(entry, locale)}`;
|
|
1969
|
+
const title = commandCopy(locale, "accountTitle").replace("{label}", entry.label).replace("{badges}", badges);
|
|
1970
|
+
if (!entry.configured) return `${title}\n\n${commandCopy(locale, "unconfigured")}`;
|
|
1971
|
+
return renderReport(entry.report, locale, title);
|
|
1972
|
+
}).join(`\n\n${commandCopy(locale, "accountSeparator")}\n\n`)
|
|
1877
1973
|
};
|
|
1878
1974
|
}
|
|
1879
1975
|
return {
|
|
1880
1976
|
kind: "success",
|
|
1881
|
-
text: renderReport(await adapter.getUsage())
|
|
1977
|
+
text: renderReport(await adapter.getUsage(), locale)
|
|
1882
1978
|
};
|
|
1883
1979
|
} catch (error) {
|
|
1980
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1884
1981
|
return {
|
|
1885
1982
|
kind: "error",
|
|
1886
|
-
text:
|
|
1983
|
+
text: commandCopy(locale, "errorText").replace("{message}", message)
|
|
1887
1984
|
};
|
|
1888
1985
|
}
|
|
1889
1986
|
}
|
|
@@ -2623,7 +2720,8 @@ const Config = z.object({
|
|
|
2623
2720
|
apiKeyEnv: z.string().role("credential-ref"),
|
|
2624
2721
|
apiKey: z.string()
|
|
2625
2722
|
})),
|
|
2626
|
-
activeAccount: z.string()
|
|
2723
|
+
activeAccount: z.string(),
|
|
2724
|
+
lang: z.string().pattern(/^(zh|en)$/).default("zh")
|
|
2627
2725
|
});
|
|
2628
2726
|
/**
|
|
2629
2727
|
* The one explicit resolve step from raw config to validated connection
|
|
@@ -2747,10 +2845,12 @@ function apply(ctx, config) {
|
|
|
2747
2845
|
};
|
|
2748
2846
|
})) };
|
|
2749
2847
|
};
|
|
2848
|
+
const commandLocale = () => pickCommandLocale(current().lang);
|
|
2750
2849
|
ctx.inject(["commands"], (commandCtx) => {
|
|
2751
2850
|
applyCommands(commandCtx, {
|
|
2752
2851
|
adapter,
|
|
2753
|
-
reports: usageReports
|
|
2852
|
+
reports: usageReports,
|
|
2853
|
+
getLocale: commandLocale
|
|
2754
2854
|
});
|
|
2755
2855
|
});
|
|
2756
2856
|
const loginFlow = new CommandCodeLoginFlow({
|