@mars-sea/dsh-commandcode-provider 0.10.0-alpha.4 → 0.10.0-alpha.6

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 CHANGED
@@ -4,6 +4,29 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [Unreleased]
8
+
9
+ ## [0.10.0-alpha.6] - 2026-09-03
10
+
11
+ > **Alpha channel for dsh 0.1.2-alpha.2.** This release requires **dsh 0.1.2-alpha.2 or later** and is published under the `alpha` npm tag, so `@latest` stays on 0.9.1 for older Harness releases. Install it explicitly with `@alpha`.
12
+
13
+ ### Added
14
+
15
+ - **Synced with the official command-code@1.44.0 CLI** (2026-09-02: 1.41.0 added Qwen 3.8 Max 0902, 1.42.0 added the free LongCat 2.0, 1.43.0 added Gemini 3.8 Flash, and 1.44.0 added Meta Muse Spark 1.3 + Contributor). `COMMAND_CODE_CLI_VERSION` is now `1.44.0`, and the model picker knows the five new models: Qwen 3.8 Max 0902 and LongCat 2.0 show under the Go tier, Gemini 3.8 Flash and Muse Spark 1.3 under GOAT, and Muse Spark 1.3 Contributor under Go. LongCat 2.0 also shows a `FREE` badge (100% off while it lasts, like Laguna S 2.1). Gemini 3.8 Flash, Qwen 3.8 Max 0902 and both Muse Spark 1.3 variants are Vision-capable and appear with the `Image` marker; LongCat 2.0 is text-only.
16
+
17
+ ### Fixed
18
+
19
+ - **Claude Fable 5.1 (`claude-fable-5-1`) is now correctly marked as a Provider/Max model.** The model, added upstream in command-code@1.40.0, was mis-synced in 0.10.0-alpha.5 as an Anthropic OAuth-only model outside the Provider API — but it IS served by the Provider API (it shows up in the live model catalog), and because it had no `KNOWN_PLANS` entry the picker's plan filter failed open and listed it for **every** subscription plan. It is now mapped to the Provider/Max tier (matching its official availability matrix and the CLI's plan-access map), so Go/GOAT/Pro accounts no longer see it in the picker; `resolveModel` still serves it and the server remains the final gate (`403 MODEL_NOT_IN_PLAN`). The snapshot now also carries its selectable reasoning efforts (`low`/`medium`/`high`/`xhigh`/`max`, same as `claude-fable-5`) and its Vision capability (official registry: "Text input, Vision, Reasoning").
20
+
21
+ ## [0.10.0-alpha.5] - 2026-09-02
22
+
23
+ > **Alpha channel for dsh 0.1.2-alpha.2.** This release requires **dsh 0.1.2-alpha.2 or later** and is published under the `alpha` npm tag, so `@latest` stays on 0.9.1 for older Harness releases. Install it explicitly with `@alpha`.
24
+
25
+ ### Changed
26
+
27
+ - **Kimi K3 now offers selectable reasoning efforts (`low`/`high`/`max`).** The model gained official effort levels in command-code@1.39.3 ("Add low, high, and max reasoning effort support for Kimi K3"), so the picker can now offer a reasoning-effort selector for it; it is no longer listed as an auto-thinking model.
28
+ - **Synced with the official command-code@1.40.1 CLI** (2026-09-02: 1.39.3 added Kimi K3 effort levels, 1.40.0 added Fable 5.1, and 1.40.1 is a ZDR feature-model filter). `COMMAND_CODE_CLI_VERSION` is now `1.40.1`. Re-verified against the official sources with no other changes: wire protocol, endpoints, auth flow, model catalog, subscription plan maps, deals, and peak/off-peak windows are all identical to 1.39.2. (Fable 5.1's plan-tier mapping was corrected in a follow-up — see [0.10.0-alpha.6].)
29
+
7
30
  ## [0.10.0-alpha.4] - 2026-09-01
8
31
 
9
32
  > **Alpha channel for dsh 0.1.2-alpha.2.** This release requires **dsh 0.1.2-alpha.2 or later** and is published under the `alpha` npm tag, so `@latest` stays on 0.9.1 for older Harness releases. Install it explicitly with `@alpha`.
package/lib/client.js CHANGED
@@ -454,11 +454,11 @@ window.__ModuleLoader__.load({
454
454
  ...this.addedAccounts.map((extra) => extra.ref)
455
455
  ]);
456
456
  let n = 2;
457
- while (used.has(`COMMANDCODE_API_KEY_${n}`)) n += 1;
457
+ while (used.has(`${this.credentialRef}_${n}`)) n += 1;
458
458
  const index = this.storedExtras().length + this.addedAccounts.length + 2;
459
459
  this.addedAccounts.push({
460
460
  label: `Account ${index}`,
461
- ref: `COMMANDCODE_API_KEY_${n}`
461
+ ref: `${this.credentialRef}_${n}`
462
462
  });
463
463
  this.failed = false;
464
464
  this.describeAll();
@@ -1379,39 +1379,125 @@ window.__ModuleLoader__.load({
1379
1379
  function sleep(ms) {
1380
1380
  return new Promise((resolve) => setTimeout(resolve, ms));
1381
1381
  }
1382
+ /**
1383
+ * The per-reason copy for a failed login attempt. Shared by the settings
1384
+ * page's login panel and the Models-page card's login row — the same reasons
1385
+ * can surface from either surface.
1386
+ */
1387
+ function loginFailureCopy(reason, t) {
1388
+ if (reason === "denied") return t("loginDenied");
1389
+ if (reason === "timeout") return t("loginTimeout");
1390
+ if (reason === "invalid-key") return t("loginInvalidKey");
1391
+ if (reason === "network") return t("loginNetwork");
1392
+ if (reason === "unavailable") return t("loginStoreFailed");
1393
+ if (reason === "cancelled") return t("loginCancelled");
1394
+ return t("loginFailedGeneric");
1395
+ }
1396
+ /**
1397
+ * The hint text + class for one login panel state, shared by the settings
1398
+ * page's `LoginPanel` and the Models-page card's login row so both surfaces
1399
+ * can never drift apart. Pure: no timers, no state — the components render it.
1400
+ */
1401
+ function loginHint(state, t) {
1402
+ if (state.phase === "starting" || state.phase === "waiting") return {
1403
+ text: t(state.phase === "starting" ? "loginStarting" : "loginWaiting"),
1404
+ className: "cc-hint",
1405
+ title: void 0
1406
+ };
1407
+ if (state.phase === "success") {
1408
+ const keyName = state.keyName !== void 0 && state.keyName !== "" ? ` · ${state.keyName}` : "";
1409
+ return {
1410
+ text: `${t("loginSuccess")} ${state.userName ?? ""}${keyName}`.trim(),
1411
+ className: "cc-loginDone",
1412
+ title: void 0
1413
+ };
1414
+ }
1415
+ if (state.phase === "failed") return {
1416
+ text: loginFailureCopy(state.reason, t),
1417
+ className: "cc-loginError",
1418
+ title: state.message
1419
+ };
1420
+ if (state.phase === "unavailable") return {
1421
+ text: `${t("loginUnavailable")} ${state.message ?? ""}`.trim(),
1422
+ className: "cc-loginError",
1423
+ title: void 0
1424
+ };
1425
+ return {
1426
+ text: t("loginHintIdle"),
1427
+ className: "cc-hint",
1428
+ title: void 0
1429
+ };
1430
+ }
1431
+ //#endregion
1432
+ //#region src/wire-shared.ts
1433
+ /** The npm package identity every contribution and descriptor claims. */
1434
+ const REMOTE_PACKAGE = "@mars-sea/dsh-commandcode-provider";
1435
+ /** The Cordis service key the Gateway resolves every Command Code Remote from. */
1436
+ const REMOTE_SERVICE = "commandcodeUsage";
1437
+ /** The wire namespace all Command Code endpoints share. */
1438
+ const REMOTE_NAMESPACE = "commandcode";
1439
+ /**
1440
+ * Build the validator helpers one endpoint uses Sequence. `prefix` names the
1441
+ * endpoint in the rejection message (e.g. `commandcode/report result:`), so
1442
+ * each wire file keeps its own diagnostic phrasing while sharing the helper
1443
+ * bodies.
1444
+ *
1445
+ * The helpers return the reject call directly in the failure branch: since
1446
+ * `reject` is typed `never`, the ternary's union collapses to the success type
1447
+ * without relying on TypeScript's control-flow analysis of a never-returning
1448
+ * call (which only recognizes function declarations, not the destructured
1449
+ * arrow `reject` callers receive from this factory).
1450
+ */
1451
+ function makeBoundaryValidator(prefix) {
1452
+ const reject = (field) => {
1453
+ throw new TypeError(`${prefix} invalid ${field}`);
1454
+ };
1455
+ const record = (value, field) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : reject(field);
1456
+ const stringField = (source, key, field) => typeof source[key] === "string" ? source[key] : reject(field);
1457
+ const numberField = (source, key, field) => typeof source[key] === "number" && Number.isFinite(source[key]) ? source[key] : reject(field);
1458
+ const booleanField = (source, key, field) => typeof source[key] === "boolean" ? source[key] : reject(field);
1459
+ return {
1460
+ reject,
1461
+ record,
1462
+ stringField,
1463
+ numberField,
1464
+ booleanField
1465
+ };
1466
+ }
1467
+ /**
1468
+ * Build one strict invocation descriptor. Every Command Code Remote shares the
1469
+ * `commandcode` namespace, the `commandcodeUsage` service, and a strict
1470
+ * `mode: 'strict'` result — only the endpoint, method, result type symbol, and
1471
+ * schema differ — so the boilerplate lives here once and each endpoint supplies
1472
+ * only its own facts.
1473
+ */
1474
+ function makeRemoteDescriptor(endpoint, method, typeSymbol, schema) {
1475
+ return {
1476
+ id: `${REMOTE_PACKAGE}#${endpoint}`,
1477
+ service: REMOTE_SERVICE,
1478
+ namespace: REMOTE_NAMESPACE,
1479
+ method,
1480
+ invocation: { kind: "direct" },
1481
+ parameters: [],
1482
+ result: {
1483
+ mode: "strict",
1484
+ typeSymbol,
1485
+ schema
1486
+ }
1487
+ };
1488
+ }
1382
1489
  //#endregion
1383
1490
  //#region src/usage-wire.ts
1384
1491
  /** The npm package identity both contribution registrations claim. */
1385
- const USAGE_REMOTE_PACKAGE = "@mars-sea/dsh-commandcode-provider";
1492
+ const USAGE_REMOTE_PACKAGE = REMOTE_PACKAGE;
1386
1493
  /** Canonical `<namespace>/<method>` endpoint of the usage report Remote. */
1387
1494
  const USAGE_REPORT_ENDPOINT = "commandcode/report";
1388
- /** Reject one boundary value with a field-naming error. */
1389
- function reject$1(field) {
1390
- throw new TypeError(`commandcode/report result: invalid ${field}`);
1391
- }
1392
- /** Read one required finite number field (`field` is the dotted error label). */
1393
- function numberField(source, key, field) {
1394
- const value = source[key];
1395
- if (typeof value !== "number" || !Number.isFinite(value)) reject$1(field);
1396
- return value;
1397
- }
1398
- /** Read one required string field (`field` is the dotted error label). */
1399
- function stringField(source, key, field) {
1400
- const value = source[key];
1401
- if (typeof value !== "string") reject$1(field);
1402
- return value;
1403
- }
1404
- /** Read one required boolean field (`field` is the dotted error label). */
1405
- function booleanField(source, key, field) {
1406
- const value = source[key];
1407
- if (typeof value !== "boolean") reject$1(field);
1408
- return value;
1409
- }
1410
- /** Narrow an unknown value to a plain record, or reject. */
1411
- function record(value, field) {
1412
- if (typeof value !== "object" || value === null || Array.isArray(value)) reject$1(field);
1413
- return value;
1414
- }
1495
+ /**
1496
+ * The shared read/validate helpers, prefixed with the report endpoint so
1497
+ * rejection messages name the offending boundary (the catalog endpoint below
1498
+ * shares this prefix, matching the historical behavior).
1499
+ */
1500
+ const { reject: reject$1, record, stringField, numberField, booleanField } = makeBoundaryValidator("commandcode/report result:");
1415
1501
  /** Validate one window-limit block (`fiveHour` / `weekly`). */
1416
1502
  function windowLimit(value, field) {
1417
1503
  const source = record(value, field);
@@ -1434,8 +1520,8 @@ window.__ModuleLoader__.load({
1434
1520
  const report = { failures };
1435
1521
  if (source.blocked !== void 0) {
1436
1522
  const blocked = source.blocked;
1437
- if (blocked !== "invalid-key" && blocked !== "service-unavailable" && blocked !== "network") reject$1("blocked");
1438
- report.blocked = blocked;
1523
+ if (blocked === "invalid-key" || blocked === "service-unavailable" || blocked === "network") report.blocked = blocked;
1524
+ else reject$1("blocked");
1439
1525
  }
1440
1526
  if (source.account !== void 0) {
1441
1527
  const account = record(source.account, "account");
@@ -1499,25 +1585,13 @@ window.__ModuleLoader__.load({
1499
1585
  /** Parse the wire result into a {@link CommandCodeAccountsReport}. */
1500
1586
  function parseAccountsReport(value) {
1501
1587
  const accounts = record(value, "result").accounts;
1502
- if (!Array.isArray(accounts)) reject$1("accounts");
1503
- return { accounts: accounts.map(parseAccountUsage) };
1588
+ if (Array.isArray(accounts)) return { accounts: accounts.map(parseAccountUsage) };
1589
+ return reject$1("accounts");
1504
1590
  }
1505
1591
  /** The Client-face contribution mounted on `ctx.remote`. */
1506
1592
  const USAGE_REMOTE_CONTRIBUTION = {
1507
1593
  package: USAGE_REMOTE_PACKAGE,
1508
- descriptors: [{
1509
- id: `${USAGE_REMOTE_PACKAGE}#${USAGE_REPORT_ENDPOINT}`,
1510
- service: "commandcodeUsage",
1511
- namespace: "commandcode",
1512
- method: "report",
1513
- invocation: { kind: "direct" },
1514
- parameters: [],
1515
- result: {
1516
- mode: "strict",
1517
- typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeAccountsReport`,
1518
- schema: { parse: parseAccountsReport }
1519
- }
1520
- }]
1594
+ descriptors: [makeRemoteDescriptor(USAGE_REPORT_ENDPOINT, "report", `${USAGE_REMOTE_PACKAGE}#CommandCodeAccountsReport`, { parse: parseAccountsReport })]
1521
1595
  };
1522
1596
  /** Canonical `<namespace>/<method>` endpoint of the model-catalog Remote. */
1523
1597
  const MODELS_ENDPOINT = "commandcode/models";
@@ -1532,25 +1606,13 @@ window.__ModuleLoader__.load({
1532
1606
  /** Parse the wire result into a {@link CommandCodeCatalog}. */
1533
1607
  function parseCatalog(value) {
1534
1608
  const models = record(value, "result").models;
1535
- if (!Array.isArray(models)) reject$1("models");
1536
- return { models: models.map(parseCatalogModel) };
1609
+ if (Array.isArray(models)) return { models: models.map(parseCatalogModel) };
1610
+ return reject$1("models");
1537
1611
  }
1538
1612
  /** The Client-face contribution for the model-catalog endpoint. */
1539
1613
  const MODELS_REMOTE_CONTRIBUTION = {
1540
1614
  package: USAGE_REMOTE_PACKAGE,
1541
- descriptors: [{
1542
- id: `${USAGE_REMOTE_PACKAGE}#${MODELS_ENDPOINT}`,
1543
- service: "commandcodeUsage",
1544
- namespace: "commandcode",
1545
- method: "models",
1546
- invocation: { kind: "direct" },
1547
- parameters: [],
1548
- result: {
1549
- mode: "strict",
1550
- typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeCatalog`,
1551
- schema: { parse: parseCatalog }
1552
- }
1553
- }]
1615
+ descriptors: [makeRemoteDescriptor(MODELS_ENDPOINT, "models", `${USAGE_REMOTE_PACKAGE}#CommandCodeCatalog`, { parse: parseCatalog })]
1554
1616
  };
1555
1617
  //#endregion
1556
1618
  //#region src/login-wire.ts
@@ -1567,7 +1629,12 @@ window.__ModuleLoader__.load({
1567
1629
  "cancelled",
1568
1630
  "error"
1569
1631
  ];
1570
- /** Reject one boundary value with a field-naming error. */
1632
+ /** The shared read/validate helpers, prefixed with the login endpoint so
1633
+ * rejection messages name the offending boundary. */
1634
+ /** Reject one boundary value with a field-naming error. A module-level
1635
+ * function declaration (not the factory's destructured arrow) so TypeScript's
1636
+ * control-flow analysis recognizes it as never-returning and narrows `state`
1637
+ * after the guard below. */
1571
1638
  function reject(field) {
1572
1639
  throw new TypeError(`commandcode/login result: invalid ${field}`);
1573
1640
  }
@@ -1608,23 +1675,11 @@ window.__ModuleLoader__.load({
1608
1675
  const loginStatusSchema = { parse: parseLoginStatus };
1609
1676
  /** Build one login invocation descriptor (uniform result, no parameters). */
1610
1677
  function loginDescriptor(endpoint, method) {
1611
- return {
1612
- id: `${USAGE_REMOTE_PACKAGE}#${endpoint}`,
1613
- service: "commandcodeUsage",
1614
- namespace: "commandcode",
1615
- method,
1616
- invocation: { kind: "direct" },
1617
- parameters: [],
1618
- result: {
1619
- mode: "strict",
1620
- typeSymbol: `${USAGE_REMOTE_PACKAGE}#CommandCodeLoginStatus`,
1621
- schema: loginStatusSchema
1622
- }
1623
- };
1678
+ return makeRemoteDescriptor(endpoint, method, `${REMOTE_PACKAGE}#CommandCodeLoginStatus`, loginStatusSchema);
1624
1679
  }
1625
1680
  /** The Client-face contribution fragment mounted on `ctx.remote`. */
1626
1681
  const LOGIN_REMOTE_CONTRIBUTION = {
1627
- package: USAGE_REMOTE_PACKAGE,
1682
+ package: REMOTE_PACKAGE,
1628
1683
  descriptors: [
1629
1684
  loginDescriptor(LOGIN_BEGIN_ENDPOINT, "loginBegin"),
1630
1685
  loginDescriptor(LOGIN_STATUS_ENDPOINT, "loginStatus"),
@@ -1632,8 +1687,56 @@ window.__ModuleLoader__.load({
1632
1687
  ]
1633
1688
  };
1634
1689
  //#endregion
1690
+ //#region src/client/login-row.tsx
1691
+ /** The sign-in alternative to pasting a key (settings page + Models card). */
1692
+ function LoginRow({ state, disabled, t, onBegin, onCancel }) {
1693
+ const busy = state.phase === "starting" || state.phase === "waiting";
1694
+ const hint = loginHint(state, t);
1695
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1696
+ className: "cc-field",
1697
+ children: [
1698
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1699
+ className: "cc-fieldHead",
1700
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1701
+ className: "cc-label",
1702
+ children: t("loginTitle")
1703
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1704
+ className: "cc-badges",
1705
+ children: busy ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1706
+ type: "button",
1707
+ className: "cc-reset",
1708
+ onClick: onCancel,
1709
+ children: t("loginCancel")
1710
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1711
+ type: "button",
1712
+ className: "cc-reset",
1713
+ disabled,
1714
+ onClick: onBegin,
1715
+ children: t("loginButton")
1716
+ })
1717
+ })]
1718
+ }),
1719
+ state.authUrl !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1720
+ className: "cc-hint",
1721
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1722
+ className: "cc-loginLink",
1723
+ href: state.authUrl,
1724
+ target: "_blank",
1725
+ rel: "noreferrer",
1726
+ children: t("loginOpenLink")
1727
+ })
1728
+ }) : null,
1729
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1730
+ className: hint.className,
1731
+ title: hint.title,
1732
+ children: hint.text
1733
+ })
1734
+ ]
1735
+ });
1736
+ }
1737
+ //#endregion
1635
1738
  //#region package.json
1636
- var version = "0.10.0-alpha.4";
1739
+ var version = "0.10.0-alpha.6";
1637
1740
  var repository = {
1638
1741
  "type": "git",
1639
1742
  "url": "git+https://github.com/Mars-Sea/dsh-commandcode-provider.git"
@@ -2101,82 +2204,6 @@ window.__ModuleLoader__.load({
2101
2204
  ]
2102
2205
  });
2103
2206
  }
2104
- /** The per-reason copy for a failed login attempt. */
2105
- function loginFailureCopy$1(reason, t) {
2106
- if (reason === "denied") return t("loginDenied");
2107
- if (reason === "timeout") return t("loginTimeout");
2108
- if (reason === "invalid-key") return t("loginInvalidKey");
2109
- if (reason === "network") return t("loginNetwork");
2110
- if (reason === "unavailable") return t("loginStoreFailed");
2111
- if (reason === "cancelled") return t("loginCancelled");
2112
- return t("loginFailedGeneric");
2113
- }
2114
- /**
2115
- * The sign-in alternative to pasting a key: one field row that starts the
2116
- * Host-side browser login, links to the Studio authorization page while the
2117
- * attempt is live, and reports the outcome. The key itself never crosses to
2118
- * the browser — only "who signed in" does.
2119
- */
2120
- function LoginPanel({ state, disabled, t, onBegin, onCancel }) {
2121
- const busy = state.phase === "starting" || state.phase === "waiting";
2122
- let hint = t("loginHintIdle");
2123
- let hintTitle;
2124
- let hintClass = "cc-hint";
2125
- if (state.phase === "starting" || state.phase === "waiting") hint = t(state.phase === "starting" ? "loginStarting" : "loginWaiting");
2126
- else if (state.phase === "success") {
2127
- const keyName = state.keyName !== void 0 && state.keyName !== "" ? ` · ${state.keyName}` : "";
2128
- hint = `${t("loginSuccess")} ${state.userName ?? ""}${keyName}`.trim();
2129
- hintClass = "cc-loginDone";
2130
- } else if (state.phase === "failed") {
2131
- hint = loginFailureCopy$1(state.reason, t);
2132
- hintClass = "cc-loginError";
2133
- if (state.message !== void 0) hintTitle = state.message;
2134
- } else if (state.phase === "unavailable") {
2135
- hint = `${t("loginUnavailable")} ${state.message ?? ""}`.trim();
2136
- hintClass = "cc-loginError";
2137
- }
2138
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2139
- className: "cc-field",
2140
- children: [
2141
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2142
- className: "cc-fieldHead",
2143
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
2144
- className: "cc-label",
2145
- children: t("loginTitle")
2146
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2147
- className: "cc-badges",
2148
- children: busy ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2149
- type: "button",
2150
- className: "cc-reset",
2151
- onClick: onCancel,
2152
- children: t("loginCancel")
2153
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2154
- type: "button",
2155
- className: "cc-reset",
2156
- disabled,
2157
- onClick: onBegin,
2158
- children: t("loginButton")
2159
- })
2160
- })]
2161
- }),
2162
- state.authUrl !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2163
- className: "cc-hint",
2164
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
2165
- className: "cc-loginLink",
2166
- href: state.authUrl,
2167
- target: "_blank",
2168
- rel: "noreferrer",
2169
- children: t("loginOpenLink")
2170
- })
2171
- }) : null,
2172
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2173
- className: hintClass,
2174
- title: hintTitle,
2175
- children: hint
2176
- })
2177
- ]
2178
- });
2179
- }
2180
2207
  /** One stat tile in the account card's summary grid. */
2181
2208
  function UsageStat({ label, value, sub }) {
2182
2209
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -2988,7 +3015,7 @@ window.__ModuleLoader__.load({
2988
3015
  undoClearLabel: t("usageUndoKeyClear"),
2989
3016
  onEdit: (text) => props.edit("apiKey", text),
2990
3017
  onToggleClear: () => props.toggleKeyClear("default")
2991
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoginPanel, {
3018
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoginRow, {
2992
3019
  state: login,
2993
3020
  disabled: disabled || keyLocked,
2994
3021
  t,
@@ -3091,77 +3118,6 @@ window.__ModuleLoader__.load({
3091
3118
  children: ok ? okLabel : pendingLabel
3092
3119
  });
3093
3120
  }
3094
- /**
3095
- * The per-reason copy for a failed login attempt (mirrors the settings
3096
- * page's LoginPanel; the same reasons can surface from this card).
3097
- */
3098
- function loginFailureCopy(reason, t) {
3099
- if (reason === "denied") return t("loginDenied");
3100
- if (reason === "timeout") return t("loginTimeout");
3101
- if (reason === "invalid-key") return t("loginInvalidKey");
3102
- if (reason === "network") return t("loginNetwork");
3103
- if (reason === "unavailable") return t("loginStoreFailed");
3104
- if (reason === "cancelled") return t("loginCancelled");
3105
- return t("loginFailedGeneric");
3106
- }
3107
- /** The sign-in affordance row for the not-configured card (see LoginPanel). */
3108
- function CardLoginRow({ state, disabled, t, onBegin, onCancel }) {
3109
- const busy = state.phase === "starting" || state.phase === "waiting";
3110
- let hint = t("loginHintIdle");
3111
- let hintClass = "cc-hint";
3112
- if (state.phase === "starting" || state.phase === "waiting") hint = t(state.phase === "starting" ? "loginStarting" : "loginWaiting");
3113
- else if (state.phase === "success") {
3114
- const keyName = state.keyName !== void 0 && state.keyName !== "" ? ` · ${state.keyName}` : "";
3115
- hint = `${t("loginSuccess")} ${state.userName ?? ""}${keyName}`.trim();
3116
- hintClass = "cc-loginDone";
3117
- } else if (state.phase === "failed") {
3118
- hint = loginFailureCopy(state.reason, t);
3119
- hintClass = "cc-loginError";
3120
- } else if (state.phase === "unavailable") {
3121
- hint = `${t("loginUnavailable")} ${state.message ?? ""}`.trim();
3122
- hintClass = "cc-loginError";
3123
- }
3124
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3125
- className: "cc-field",
3126
- children: [
3127
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3128
- className: "cc-fieldHead",
3129
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3130
- className: "cc-label",
3131
- children: t("loginTitle")
3132
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3133
- className: "cc-badges",
3134
- children: busy ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3135
- type: "button",
3136
- className: "cc-reset",
3137
- onClick: onCancel,
3138
- children: t("loginCancel")
3139
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3140
- type: "button",
3141
- className: "cc-reset",
3142
- disabled,
3143
- onClick: onBegin,
3144
- children: t("loginButton")
3145
- })
3146
- })]
3147
- }),
3148
- state.authUrl !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3149
- className: "cc-hint",
3150
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
3151
- className: "cc-loginLink",
3152
- href: state.authUrl,
3153
- target: "_blank",
3154
- rel: "noreferrer",
3155
- children: t("loginOpenLink")
3156
- })
3157
- }) : null,
3158
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3159
- className: hintClass,
3160
- children: hint
3161
- })
3162
- ]
3163
- });
3164
- }
3165
3121
  /** Compact key field for the not-configured card. */
3166
3122
  function CardKeyField({ state, disabled, t, onEdit }) {
3167
3123
  const [visible, setVisible] = (0, react.useState)(false);
@@ -3295,7 +3251,7 @@ window.__ModuleLoader__.load({
3295
3251
  t,
3296
3252
  onEdit: (text) => props.edit("apiKey", text)
3297
3253
  }),
3298
- login !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardLoginRow, {
3254
+ login !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoginRow, {
3299
3255
  state: login,
3300
3256
  disabled,
3301
3257
  t,