@mars-sea/dsh-commandcode-provider 0.11.10 → 0.11.12

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
@@ -625,7 +625,6 @@ window.__ModuleLoader__.load({
625
625
  listeners = /* @__PURE__ */ new Set();
626
626
  disposers = [];
627
627
  disposed = false;
628
- defaultWorkingDir;
629
628
  /** The credential reference the default account resolves. */
630
629
  credentialRef = DEFAULT_API_KEY_REF;
631
630
  /** Host-reported configured/writable state per credential reference. */
@@ -669,10 +668,8 @@ window.__ModuleLoader__.load({
669
668
  /**
670
669
  * @param scope - bound scope for the `llm-commandcode` namespace.
671
670
  * @param api - credentials wire face.
672
- * @param hostDescription - the Host-description observable whose `cwd` is
673
- * shown as the placeholder a blank `workingDir` field resolves to.
674
671
  */
675
- constructor(scope, api, hostDescription) {
672
+ constructor(scope, api) {
676
673
  this.scope = scope;
677
674
  this.api = api;
678
675
  this.disposers.push(scope.subscribe(() => {
@@ -680,17 +677,6 @@ window.__ModuleLoader__.load({
680
677
  this.describeAll();
681
678
  this.publish();
682
679
  }));
683
- if (hostDescription !== void 0) {
684
- this.defaultWorkingDir = hostDescription.getSnapshot()?.cwd;
685
- this.disposers.push(hostDescription.subscribe(() => {
686
- if (this.disposed) return;
687
- const cwd = hostDescription.getSnapshot()?.cwd;
688
- if (cwd !== this.defaultWorkingDir) {
689
- this.defaultWorkingDir = cwd;
690
- this.publish();
691
- }
692
- }));
693
- }
694
680
  this.recomputeCredentialRef();
695
681
  this.describeAll();
696
682
  this.refreshCatalog();
@@ -743,7 +729,6 @@ window.__ModuleLoader__.load({
743
729
  apiKeyClearStaged: this.keyClears.has(this.credentialRef),
744
730
  apiBase: this.field("apiBase"),
745
731
  workingDir: this.field("workingDir"),
746
- defaultWorkingDir: this.defaultWorkingDir,
747
732
  requestTimeoutMs: this.field("requestTimeoutMs"),
748
733
  streamIdleTimeoutMs: this.field("streamIdleTimeoutMs"),
749
734
  transportMaxRetries: this.field("transportMaxRetries"),
@@ -1483,47 +1468,6 @@ window.__ModuleLoader__.load({
1483
1468
  }
1484
1469
  };
1485
1470
  //#endregion
1486
- //#region src/client/legacy-credentials.ts
1487
- /** Convert a legacy credentials ApiProxy into the current settings-page face. */
1488
- function adaptLegacyCredentials(legacy) {
1489
- if (legacy === void 0) return void 0;
1490
- return { credentials: {
1491
- describe: async (refs) => {
1492
- const response = await legacy.describe({ refs });
1493
- return response.result.ok ? {
1494
- ok: true,
1495
- value: response.result.value.credentials
1496
- } : {
1497
- ok: false,
1498
- error: response.result.error
1499
- };
1500
- },
1501
- set: async (ref, value) => {
1502
- const response = await legacy.set({
1503
- ref,
1504
- value
1505
- });
1506
- return response.result.ok ? {
1507
- ok: true,
1508
- value: void 0
1509
- } : {
1510
- ok: false,
1511
- error: response.result.error
1512
- };
1513
- },
1514
- unset: async (ref) => {
1515
- const response = await legacy.unset({ ref });
1516
- return response.result.ok ? {
1517
- ok: true,
1518
- value: void 0
1519
- } : {
1520
- ok: false,
1521
- error: response.result.error
1522
- };
1523
- }
1524
- } };
1525
- }
1526
- //#endregion
1527
1471
  //#region src/client/usage.ts
1528
1472
  const IDLE$1 = {
1529
1473
  status: "idle",
@@ -1803,6 +1747,21 @@ window.__ModuleLoader__.load({
1803
1747
  };
1804
1748
  //#endregion
1805
1749
  //#region src/client/login.ts
1750
+ /** Keep one account's login status out of every other account's row. */
1751
+ function loginStateForTarget(state, targetRef) {
1752
+ if (state.targetRef === targetRef) return {
1753
+ visible: state,
1754
+ busyElsewhere: false
1755
+ };
1756
+ return {
1757
+ visible: {
1758
+ ...state,
1759
+ phase: "idle",
1760
+ authUrl: void 0
1761
+ },
1762
+ busyElsewhere: state.phase === "starting" || state.phase === "waiting"
1763
+ };
1764
+ }
1806
1765
  /** How often a live attempt is polled. */
1807
1766
  const POLL_INTERVAL_MS = 1e3;
1808
1767
  /**
@@ -1817,6 +1776,7 @@ window.__ModuleLoader__.load({
1817
1776
  generation = 0;
1818
1777
  disposed = false;
1819
1778
  phase = "idle";
1779
+ targetRef;
1820
1780
  authUrl;
1821
1781
  userName;
1822
1782
  keyName;
@@ -1835,6 +1795,7 @@ window.__ModuleLoader__.load({
1835
1795
  state() {
1836
1796
  return {
1837
1797
  phase: this.phase,
1798
+ ...this.targetRef === void 0 ? {} : { targetRef: this.targetRef },
1838
1799
  authUrl: this.authUrl,
1839
1800
  userName: this.userName,
1840
1801
  keyName: this.keyName,
@@ -1843,9 +1804,10 @@ window.__ModuleLoader__.load({
1843
1804
  };
1844
1805
  }
1845
1806
  /** Start (or rejoin) a login attempt and begin polling its status. */
1846
- async begin() {
1807
+ async begin(targetRef) {
1847
1808
  if (this.disposed || this.phase === "starting" || this.phase === "waiting") return;
1848
1809
  const generation = ++this.generation;
1810
+ this.targetRef = targetRef;
1849
1811
  this.set({
1850
1812
  phase: "starting",
1851
1813
  authUrl: void 0,
@@ -1868,7 +1830,7 @@ window.__ModuleLoader__.load({
1868
1830
  }
1869
1831
  let result;
1870
1832
  try {
1871
- result = await remote.loginBegin();
1833
+ result = await remote.loginBegin(targetRef);
1872
1834
  } catch (error) {
1873
1835
  result = {
1874
1836
  ok: false,
@@ -2106,6 +2068,14 @@ window.__ModuleLoader__.load({
2106
2068
  booleanField
2107
2069
  };
2108
2070
  }
2071
+ /** Use the same strict-codec shape for invocation parameters and results. */
2072
+ function makeStrictCodec(typeSymbol, schema) {
2073
+ return {
2074
+ mode: "strict",
2075
+ typeSymbol,
2076
+ create: () => schema
2077
+ };
2078
+ }
2109
2079
  /**
2110
2080
  * Build one strict invocation descriptor. Every Command Code Remote shares the
2111
2081
  * `commandcode` namespace, the `commandcodeUsage` service, and a strict
@@ -2114,12 +2084,6 @@ window.__ModuleLoader__.load({
2114
2084
  * only its own facts.
2115
2085
  */
2116
2086
  function makeRemoteDescriptor(endpoint, method, typeSymbol, schema) {
2117
- const result = {
2118
- mode: "strict",
2119
- typeSymbol,
2120
- schema,
2121
- create: () => schema
2122
- };
2123
2087
  return {
2124
2088
  id: `${REMOTE_PACKAGE}#${endpoint}`,
2125
2089
  service: REMOTE_SERVICE,
@@ -2127,7 +2091,7 @@ window.__ModuleLoader__.load({
2127
2091
  method,
2128
2092
  invocation: { kind: "direct" },
2129
2093
  parameters: [],
2130
- result
2094
+ result: makeStrictCodec(typeSymbol, schema)
2131
2095
  };
2132
2096
  }
2133
2097
  //#endregion
@@ -2172,7 +2136,7 @@ window.__ModuleLoader__.load({
2172
2136
  const report = { failures };
2173
2137
  if (source.blocked !== void 0) {
2174
2138
  const blocked = source.blocked;
2175
- if (blocked === "invalid-key" || blocked === "service-unavailable" || blocked === "network") report.blocked = blocked;
2139
+ if (blocked === "invalid-key" || blocked === "service-unavailable" || blocked === "invalid-response" || blocked === "network") report.blocked = blocked;
2176
2140
  else reject$1("blocked");
2177
2141
  }
2178
2142
  if (source.account !== void 0) {
@@ -2388,9 +2352,24 @@ window.__ModuleLoader__.load({
2388
2352
  }
2389
2353
  /** The strict result codec shared by all three login endpoints. */
2390
2354
  const loginStatusSchema = { parse: parseLoginStatus };
2391
- /** Build one login invocation descriptor (uniform result, no parameters). */
2355
+ /** Optional account target; the Host still checks it against saved slots. */
2356
+ const loginTargetSchema = { parse(value) {
2357
+ if (value === void 0 || typeof value === "string") return value;
2358
+ return reject("targetRef");
2359
+ } };
2360
+ /** Build one login invocation descriptor. Only begin accepts an account ref. */
2392
2361
  function loginDescriptor(endpoint, method) {
2393
- return makeRemoteDescriptor(endpoint, method, `${REMOTE_PACKAGE}#CommandCodeLoginStatus`, loginStatusSchema);
2362
+ const descriptor = makeRemoteDescriptor(endpoint, method, `${REMOTE_PACKAGE}#CommandCodeLoginStatus`, loginStatusSchema);
2363
+ return method === "loginBegin" ? {
2364
+ ...descriptor,
2365
+ parameters: [{
2366
+ name: "targetRef",
2367
+ wire: "targetRef",
2368
+ source: "json",
2369
+ codec: makeStrictCodec(`${REMOTE_PACKAGE}#CommandCodeLoginTargetRef`, loginTargetSchema),
2370
+ acceptsUndefined: true
2371
+ }]
2372
+ } : descriptor;
2394
2373
  }
2395
2374
  /** The Client-face contribution fragment mounted on `ctx.remote`. */
2396
2375
  const LOGIN_REMOTE_CONTRIBUTION = {
@@ -2404,9 +2383,10 @@ window.__ModuleLoader__.load({
2404
2383
  //#endregion
2405
2384
  //#region src/client/login-row.tsx
2406
2385
  /** The sign-in alternative to pasting a key (settings page + Models card). */
2407
- function LoginRow({ state, disabled, t, onBegin, onCancel }) {
2408
- const busy = state.phase === "starting" || state.phase === "waiting";
2409
- const hint = loginHint(state, t);
2386
+ function LoginRow({ state, targetRef, disabled, disabledHint, t, onBegin, onCancel }) {
2387
+ const { visible: visibleState, busyElsewhere } = loginStateForTarget(state, targetRef);
2388
+ const busy = visibleState.phase === "starting" || visibleState.phase === "waiting";
2389
+ const hint = loginHint(visibleState, t);
2410
2390
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2411
2391
  className: "cc-field",
2412
2392
  children: [
@@ -2425,17 +2405,17 @@ window.__ModuleLoader__.load({
2425
2405
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2426
2406
  type: "button",
2427
2407
  className: "cc-reset",
2428
- disabled,
2408
+ disabled: disabled || busyElsewhere,
2429
2409
  onClick: onBegin,
2430
2410
  children: t("loginButton")
2431
2411
  })
2432
2412
  })]
2433
2413
  }),
2434
- state.authUrl !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2414
+ visibleState.authUrl !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2435
2415
  className: "cc-hint",
2436
2416
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
2437
2417
  className: "cc-loginLink",
2438
- href: state.authUrl,
2418
+ href: visibleState.authUrl,
2439
2419
  target: "_blank",
2440
2420
  rel: "noreferrer",
2441
2421
  children: t("loginOpenLink")
@@ -2444,7 +2424,7 @@ window.__ModuleLoader__.load({
2444
2424
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2445
2425
  className: hint.className,
2446
2426
  title: hint.title,
2447
- children: hint.text
2427
+ children: disabled && !busy && disabledHint !== void 0 ? disabledHint : hint.text
2448
2428
  })
2449
2429
  ]
2450
2430
  });
@@ -2593,7 +2573,7 @@ window.__ModuleLoader__.load({
2593
2573
  }
2594
2574
  //#endregion
2595
2575
  //#region package.json
2596
- var version = "0.11.10";
2576
+ var version = "0.11.12";
2597
2577
  var repository = {
2598
2578
  "type": "git",
2599
2579
  "url": "git+https://github.com/Mars-Sea/dsh-commandcode-provider.git"
@@ -2915,7 +2895,6 @@ window.__ModuleLoader__.load({
2915
2895
  hint: t("workingDirHint"),
2916
2896
  state: state.workingDir,
2917
2897
  disabled,
2918
- placeholder: state.defaultWorkingDir,
2919
2898
  onEdit: (text) => onEdit("workingDir", text),
2920
2899
  onReset: () => onReset("workingDir"),
2921
2900
  t
@@ -3398,12 +3377,14 @@ window.__ModuleLoader__.load({
3398
3377
  function blockedTitle(reason, t) {
3399
3378
  if (reason === "invalid-key") return t("usageKeyInvalid");
3400
3379
  if (reason === "service-unavailable") return t("usageServiceUnavailable");
3380
+ if (reason === "invalid-response") return t("usageInvalidResponse");
3401
3381
  return t("usageNetworkError");
3402
3382
  }
3403
3383
  /** The actionable hint under a blocked report's headline. */
3404
3384
  function blockedHint(reason, t) {
3405
3385
  if (reason === "invalid-key") return t("usageKeyInvalidHint");
3406
3386
  if (reason === "service-unavailable") return t("usageServiceUnavailableHint");
3387
+ if (reason === "invalid-response") return t("usageInvalidResponseHint");
3407
3388
  return t("usageNetworkHint");
3408
3389
  }
3409
3390
  /** The status dot on an account tab: cooling/invalid warn, everything else ok. */
@@ -3594,7 +3575,7 @@ window.__ModuleLoader__.load({
3594
3575
  });
3595
3576
  }
3596
3577
  /** The multi-account card: the active-account selector + extra accounts in rotation order + add button. */
3597
- function AccountsCard({ t, state, disabled, onAdd, onRemove, onLabel, onKey, onToggleClear, onActive, onActiveReset }) {
3578
+ function AccountsCard({ t, state, login, disabled, onAdd, onRemove, onLabel, onKey, onToggleClear, onActive, onActiveReset, onBeginLogin, onCancelLogin }) {
3598
3579
  const active = state.activeAccount;
3599
3580
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3600
3581
  className: "cc-card",
@@ -3672,14 +3653,31 @@ window.__ModuleLoader__.load({
3672
3653
  })
3673
3654
  ]
3674
3655
  }),
3675
- state.accounts.map((account) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountRow, {
3676
- account,
3677
- disabled,
3678
- t,
3679
- onLabel: (text) => onLabel(account.id, text),
3680
- onKey: (text) => onKey(account.id, text),
3681
- onToggleClear: () => onToggleClear(account.id),
3682
- onRemove: () => onRemove(account.id)
3656
+ state.accounts.map((account) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3657
+ className: "cc-accountEditor",
3658
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountRow, {
3659
+ account,
3660
+ disabled: disabled || login.targetRef === account.ref && (login.phase === "starting" || login.phase === "waiting"),
3661
+ t,
3662
+ onLabel: (text) => onLabel(account.id, text),
3663
+ onKey: (text) => onKey(account.id, text),
3664
+ onToggleClear: () => onToggleClear(account.id),
3665
+ onRemove: () => onRemove(account.id)
3666
+ }), account.added ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3667
+ className: "cc-accountLoginHint",
3668
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3669
+ className: "cc-hint",
3670
+ children: t("accountLoginAfterSave")
3671
+ })
3672
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoginRow, {
3673
+ state: login,
3674
+ targetRef: account.ref,
3675
+ disabled: disabled || !account.writable || state.dirty,
3676
+ disabledHint: state.dirty ? t("loginSaveBefore") : void 0,
3677
+ t,
3678
+ onBegin: () => onBeginLogin(account.ref),
3679
+ onCancel: onCancelLogin
3680
+ })]
3683
3681
  }, account.id))
3684
3682
  ]
3685
3683
  });
@@ -3991,6 +3989,8 @@ window.__ModuleLoader__.load({
3991
3989
  /** The settings page body: connection facts for the Command Code provider. */
3992
3990
  function CommandCodeSettingsPage(props) {
3993
3991
  const { t } = props;
3992
+ const footerMarker = (0, react.useRef)(null);
3993
+ const [footerFloating, setFooterFloating] = (0, react.useState)(false);
3994
3994
  const state = props.useCommandCodeSettings((snapshot) => snapshot);
3995
3995
  const usage = props.useCommandCodeUsage((snapshot) => snapshot);
3996
3996
  const login = props.useCommandCodeLogin((snapshot) => snapshot);
@@ -3998,6 +3998,15 @@ window.__ModuleLoader__.load({
3998
3998
  const keyLocked = !state.apiKeyWritable;
3999
3999
  const savedVisible = useSavedFlash(state.savedCount);
4000
4000
  const updateVersion = usePluginUpdate();
4001
+ (0, react.useEffect)(() => {
4002
+ const marker = footerMarker.current;
4003
+ if (!marker || typeof IntersectionObserver === "undefined") return;
4004
+ const observer = new IntersectionObserver(([entry]) => {
4005
+ if (entry) setFooterFloating(!entry.isIntersecting);
4006
+ });
4007
+ observer.observe(marker);
4008
+ return () => observer.disconnect();
4009
+ }, []);
4001
4010
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
4002
4011
  className: "cc-section",
4003
4012
  "aria-label": t("title"),
@@ -4027,6 +4036,7 @@ window.__ModuleLoader__.load({
4027
4036
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountsCard, {
4028
4037
  t,
4029
4038
  state,
4039
+ login,
4030
4040
  disabled,
4031
4041
  onAdd: props.addAccount,
4032
4042
  onRemove: props.removeAccount,
@@ -4034,7 +4044,9 @@ window.__ModuleLoader__.load({
4034
4044
  onKey: props.editAccountKey,
4035
4045
  onToggleClear: (id) => props.toggleKeyClear(id),
4036
4046
  onActive: (text) => props.edit("activeAccount", text),
4037
- onActiveReset: () => props.resetField("activeAccount")
4047
+ onActiveReset: () => props.resetField("activeAccount"),
4048
+ onBeginLogin: props.beginLogin,
4049
+ onCancelLogin: props.cancelLogin
4038
4050
  }),
4039
4051
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RulesCard, {
4040
4052
  t,
@@ -4058,7 +4070,7 @@ window.__ModuleLoader__.load({
4058
4070
  label: t("apiKey"),
4059
4071
  hint: keyLocked ? t("apiKeyLocked") : t("apiKeyHint"),
4060
4072
  state: state.apiKey,
4061
- disabled: disabled || keyLocked,
4073
+ disabled: disabled || keyLocked || login.targetRef === void 0 && (login.phase === "starting" || login.phase === "waiting"),
4062
4074
  configured: state.apiKeyConfigured,
4063
4075
  configuredLabel: t("apiKeySet"),
4064
4076
  unconfiguredLabel: t("apiKeyUnset"),
@@ -4072,7 +4084,8 @@ window.__ModuleLoader__.load({
4072
4084
  onToggleClear: () => props.toggleKeyClear("default")
4073
4085
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoginRow, {
4074
4086
  state: login,
4075
- disabled: disabled || keyLocked,
4087
+ disabled: disabled || keyLocked || state.dirty,
4088
+ disabledHint: state.dirty ? t("loginSaveBefore") : void 0,
4076
4089
  t,
4077
4090
  onBegin: props.beginLogin,
4078
4091
  onCancel: props.cancelLogin
@@ -4085,34 +4098,42 @@ window.__ModuleLoader__.load({
4085
4098
  onEdit: props.edit,
4086
4099
  onReset: props.resetField
4087
4100
  }),
4088
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4089
- className: "cc-footer",
4090
- children: [
4091
- state.failed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4092
- className: "cc-failed",
4093
- role: "status",
4094
- children: t("saveFailed")
4095
- }) : null,
4096
- savedVisible ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4097
- className: "cc-saved",
4098
- role: "status",
4099
- children: t("saved")
4100
- }) : null,
4101
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
4102
- variant: "ghost",
4103
- size: "sm",
4104
- disabled: !state.dirty || state.saving,
4105
- onClick: props.discard,
4106
- children: t("discard")
4107
- }),
4108
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
4109
- variant: "primary",
4110
- size: "sm",
4111
- disabled: !state.dirty || state.invalid || state.saving,
4112
- onClick: props.save,
4113
- children: t(state.saving ? "saving" : "save")
4114
- })
4115
- ]
4101
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4102
+ ref: footerMarker,
4103
+ className: "cc-footerMarker",
4104
+ "aria-hidden": "true"
4105
+ }),
4106
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4107
+ className: `cc-footer cc-footerSticky${footerFloating ? " cc-footerFloating" : ""}`,
4108
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4109
+ className: "cc-footerActions",
4110
+ children: [
4111
+ state.failed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4112
+ className: "cc-failed",
4113
+ role: "status",
4114
+ children: t("saveFailed")
4115
+ }) : null,
4116
+ savedVisible ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
4117
+ className: "cc-saved",
4118
+ role: "status",
4119
+ children: t("saved")
4120
+ }) : null,
4121
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
4122
+ variant: "ghost",
4123
+ size: "sm",
4124
+ disabled: !state.dirty || state.saving,
4125
+ onClick: props.discard,
4126
+ children: t("discard")
4127
+ }),
4128
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
4129
+ variant: "primary",
4130
+ size: "sm",
4131
+ disabled: !state.dirty || state.invalid || state.saving,
4132
+ onClick: props.save,
4133
+ children: t(state.saving ? "saving" : "save")
4134
+ })
4135
+ ]
4136
+ })
4116
4137
  }),
4117
4138
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
4118
4139
  className: "cc-version",
@@ -4399,6 +4420,8 @@ window.__ModuleLoader__.load({
4399
4420
  errorServiceUnavailableHint: "服务端返回错误(5xx),请稍后点击刷新重试。",
4400
4421
  errorNetwork: "无法连接 Command Code 服务",
4401
4422
  errorNetworkHint: "所有请求都没有到达服务端。请检查网络连接或 API 地址设置。",
4423
+ errorInvalidResponse: "Command Code 响应无法读取",
4424
+ errorInvalidResponseHint: "请求已收到响应,但内容无法解析。请检查宿主的 HTTP 代理或响应解压配置。",
4402
4425
  errorGeneric: "用量获取失败"
4403
4426
  };
4404
4427
  /** The panel's English string table (must mirror {@link PANEL_COPY_ZH}). */
@@ -4451,6 +4474,8 @@ window.__ModuleLoader__.load({
4451
4474
  errorServiceUnavailableHint: "The server returned errors (5xx). Try Refresh again in a moment.",
4452
4475
  errorNetwork: "Could not reach the Command Code service",
4453
4476
  errorNetworkHint: "No request reached the server. Check your network connection or the API base setting.",
4477
+ errorInvalidResponse: "Could not read the Command Code response",
4478
+ errorInvalidResponseHint: "The requests received responses, but their bodies could not be parsed. Check the host HTTP proxy or response decoding.",
4454
4479
  errorGeneric: "Could not fetch account usage"
4455
4480
  };
4456
4481
  /** Every panel key, in the English table's declaration order. */
@@ -4631,6 +4656,11 @@ window.__ModuleLoader__.load({
4631
4656
  hint: "errorNetworkHint",
4632
4657
  detail
4633
4658
  };
4659
+ if (blocked === "invalid-response") return {
4660
+ title: "errorInvalidResponse",
4661
+ hint: "errorInvalidResponseHint",
4662
+ detail
4663
+ };
4634
4664
  if (state.status === "error" && state.report === void 0) return {
4635
4665
  title: "errorGeneric",
4636
4666
  hint: "errorGeneric",
@@ -5701,15 +5731,15 @@ window.__ModuleLoader__.load({
5701
5731
  /**
5702
5732
  * The shipped composer stats row (dsh-client-ui-chat `StatsPills`).
5703
5733
  *
5704
- * A PREFERENCE, not a requirement: 0.1.6-alpha.2 dropped this attribute from the
5705
- * row's root while leaving the rest of the markup identical, so a lookup that
5706
- * insisted on it would silently stop finding the row on that engine. When it is
5707
- * absent the search falls back to the dock OUTLET — deliberately the outlet and
5708
- * never the outlet's parent, because from 0.1.6-alpha.2 the parent is the new
5709
- * composer footer, which holds the `ContextMeter` as well, and that meter's
5710
- * trigger is itself a `button[aria-haspopup="dialog"]` rendered AFTER the dock.
5711
- * A parent-scoped "last trigger wins" would therefore append the cost to the
5712
- * context ring instead of the token pill.
5734
+ * A PREFERENCE, not a requirement: the attribute has already been dropped once
5735
+ * upstream (0.1.6-alpha.2) while the rest of the row's markup stayed identical,
5736
+ * so a lookup that insisted on it would silently stop finding the row. When it
5737
+ * is absent the search falls back to the dock OUTLET — deliberately the outlet
5738
+ * and never the outlet's parent, because the parent is the composer footer,
5739
+ * which holds the `ContextMeter` as well, and that meter's trigger is itself a
5740
+ * `button[aria-haspopup="dialog"]` rendered AFTER the dock. A parent-scoped
5741
+ * "last trigger wins" would therefore append the cost to the context ring
5742
+ * instead of the token pill.
5713
5743
  */
5714
5744
  const STATS_ROOT = "[data-composer-stats]";
5715
5745
  /**
@@ -5846,14 +5876,14 @@ window.__ModuleLoader__.load({
5846
5876
  *
5847
5877
  * The scope is the dock OUTLET (`display: contents`, one per slot), which holds
5848
5878
  * exactly that slot's entries — the shipped `stats` cell and ours, in their
5849
- * registration order. {@link STATS_ROOT} narrows that to the stats row on the
5850
- * engines that still mark it; on the engines that do not, the outlet is
5851
- * already the narrowest correct container, because the composer footer's
5852
- * `ContextMeter` sits BESIDE the outlet rather than inside it.
5879
+ * registration order. {@link STATS_ROOT} narrows that to the stats row where
5880
+ * the markup marks it; where it does not, the outlet is already the narrowest
5881
+ * correct container, because the composer footer's `ContextMeter` sits BESIDE
5882
+ * the outlet rather than inside it.
5853
5883
  *
5854
5884
  * A missing scope is "no pill", never a document-wide search: the outlet is
5855
5885
  * what makes this lookup per-composer, and a second composer can be live at
5856
- * once (0.1.6-alpha.2 mounts an embedded Conversation in the sidebar).
5886
+ * once (the sidebar can mount an embedded Conversation).
5857
5887
  */
5858
5888
  resolvePillButton() {
5859
5889
  const scope = this.scope();
@@ -6203,9 +6233,18 @@ window.__ModuleLoader__.load({
6203
6233
  .cc-ruleCaret{flex-shrink:0;border-right:1.5px solid var(--dsw-alias-label-tertiary);border-bottom:1.5px solid var(--dsw-alias-label-tertiary);width:6px;height:6px;margin-right:4px;margin-bottom:2px;transform:rotate(45deg)}
6204
6234
  .cc-checkRow{align-items:center;gap:8px;display:inline-flex;min-width:0}
6205
6235
  .cc-checkRow:hover{cursor:pointer}
6206
- .cc-check{appearance:none;flex-shrink:0;width:15px;height:15px;margin:0;border:1px solid var(--dsw-alias-border-l2);border-radius:4px;background:var(--dsw-alias-bg-layer-1);position:relative}
6236
+ /* A hand-drawn box rather than the platform's accent-color checkbox: the
6237
+ * native control's colours come from color-scheme, which the theme sets once
6238
+ * at BOOT (it is not re-applied when the theme is switched in-session), so a
6239
+ * native box can paint light-chrome white on a dark page. Drawn from tokens it
6240
+ * cannot. The mark rides a brand-primary fill, so it takes the theme's brand
6241
+ * foreground — the platform's pairing for anything painted on that fill, and
6242
+ * the only one that survives the dark mode's near-white brand. The box
6243
+ * outline is a border-l3 hairline: border-l2 (#ffffff1f in dark) leaves an
6244
+ * unchecked box all but invisible against the menu surface. */
6245
+ .cc-check{box-sizing:border-box;appearance:none;flex-shrink:0;width:16px;height:16px;margin:0;border:1px solid var(--dsw-alias-border-l3);border-radius:4px;background:0 0;position:relative}
6207
6246
  .cc-check:checked{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}
6208
- .cc-check:checked::after{content:'';position:absolute;top:2px;left:5px;width:3px;height:7px;border:solid #fff;border-width:0 1.5px 1.5px 0;transform:rotate(45deg)}
6247
+ .cc-check:checked::after{content:'';position:absolute;top:3px;left:5px;width:3px;height:7px;border:solid var(--dsw-alias-label-primary-foreground,#fff);border-width:0 1.5px 1.5px 0;transform:rotate(45deg)}
6209
6248
  .cc-checkName{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
6210
6249
  /* The model multi-select search box: stacked under the trigger while the
6211
6250
  * dropdown is open, same input sizing so the pair reads as one control. The
@@ -6235,12 +6274,38 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6235
6274
  .cc-advancedBody>.cc-field:first-of-type{border-top:1px solid var(--dsw-alias-border-l2)}
6236
6275
  .cc-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}
6237
6276
  .cc-footer{justify-content:flex-end;align-items:center;gap:8px;display:flex}
6277
+ /* Keep the original footer in flow and inside the settings scrollport. */
6278
+ .cc-footerMarker{height:1px;margin:-6px 0 -7px;pointer-events:none}
6279
+ .cc-footerSticky{position:sticky;bottom:0;z-index:2;flex-shrink:0;min-height:48px;pointer-events:none}
6280
+ .cc-footerActions{align-items:center;gap:8px;display:flex;pointer-events:auto}
6281
+ .cc-footerFloating .cc-footerActions{padding:6px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-bg-layer-2));box-shadow:0 8px 24px rgba(0,0,0,.12)}
6282
+ .cc-accountEditor{border-top:1px solid var(--dsw-alias-border-l2)}
6283
+ .cc-accountLoginHint{padding:0 0 12px}
6238
6284
  .cc-toggleRow{align-items:center;gap:8px;cursor:pointer;display:flex}
6239
6285
  .cc-toggleRow:has(.cc-toggle:disabled){cursor:default}
6240
- .cc-toggle{appearance:none;flex-shrink:0;background:var(--dsw-alias-border-l2);border-radius:999px;width:30px;height:18px;margin:0;cursor:pointer;position:relative;transition:background .15s ease}
6286
+ /* Modelled on the platform's own Switch primitive (ui-primitives
6287
+ * Switch.module.css, dsh 0.1.6+): a 36x20 capsule that pads its track by 2px
6288
+ * and slides a 16px thumb across the 32px content box, so the control is the
6289
+ * same shape, size and motion as every other switch in the app.
6290
+ *
6291
+ * Three things are load-bearing. (1) corner-shape:round on BOTH the track and
6292
+ * the thumb: the theme sets a global superellipse corner shape on every
6293
+ * element, and a superellipse capsule squares its ends off around a round
6294
+ * thumb (the primitive's own comment is about exactly this).
6295
+ * (2) No literal colours. --dsw-alias-brand-primary INVERTS between the two
6296
+ * modes (near-black in light, near-white in dark, on every engine generation
6297
+ * this plugin supports), so the old hardcoded white thumb vanished on the
6298
+ * checked track in dark mode; the brand foreground is the token the platform
6299
+ * paints on that fill, so it contrasts in both modes and in any brand pack.
6300
+ * (3) --dsw-alias-border-l3 as the off track: --dsw-alias-border-l2
6301
+ * (#ffffff1f in dark) left the unchecked track indistinguishable from the card
6302
+ * — the dark-mode half of the same report. */
6303
+ .cc-toggle{box-sizing:border-box;appearance:none;flex-shrink:0;width:36px;height:20px;margin:0;padding:2px;border:0;border-radius:10px;corner-shape:round;background:var(--dsw-alias-border-l3);cursor:pointer;position:relative}
6241
6304
  .cc-toggle:checked{background:var(--dsw-alias-brand-primary)}
6242
- .cc-toggle::after{content:'';background:#fff;border-radius:50%;width:14px;height:14px;position:absolute;top:2px;left:2px;transition:left .15s ease}
6243
- .cc-toggle:checked::after{left:14px}
6305
+ .cc-toggle::after{content:'';display:block;width:16px;height:16px;border-radius:50%;corner-shape:round;background:var(--dsw-alias-label-primary-foreground);box-shadow:0 0 0 .5px var(--dsw-alias-border-l2);transition:transform .12s ease}
6306
+ /* 32px content box minus the 16px thumb. */
6307
+ .cc-toggle:checked::after{transform:translateX(16px)}
6308
+ .cc-toggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}
6244
6309
  .cc-toggle:disabled{cursor:default;opacity:.5}
6245
6310
  .cc-failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}
6246
6311
  .cc-usageCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:14px 16px;flex-direction:column;gap:12px;display:flex}
@@ -6268,7 +6333,7 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6268
6333
  .cc-usageBar{overflow:hidden;background:var(--dsw-alias-bg-layer-1);border-radius:999px;height:6px}
6269
6334
  .cc-usageBarFill{background:var(--dsw-alias-brand-primary);border-radius:999px;height:100%;transition:width .3s ease}
6270
6335
  .cc-usageBarFillWarn{background:var(--dsw-alias-label-error)}
6271
- @media (prefers-reduced-motion:reduce){.cc-chevron,.cc-toggle,.cc-toggle::after,.cc-usageBarFill{transition:none}}.cc-usageWindowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:1.5}
6336
+ @media (prefers-reduced-motion:reduce){.cc-chevron,.cc-toggle::after,.cc-usageBarFill{transition:none}}.cc-usageWindowReset{color:var(--dsw-alias-label-tertiary);margin:0;font-size:11px;line-height:1.5}
6272
6337
  .cc-usageMeta{align-items:center;gap:8px;display:flex}
6273
6338
  .cc-accountReport{flex-direction:column;gap:12px;display:flex}
6274
6339
  .cc-tabs{flex-wrap:wrap;gap:6px;display:flex}
@@ -6526,6 +6591,7 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6526
6591
  accountLabel: "账户备注名",
6527
6592
  accountKey: "API 密钥",
6528
6593
  accountKeyHint: "该账户的 API 密钥。留空保存不会覆盖已存储的密钥。",
6594
+ accountLoginAfterSave: "先点击页面底部的「保存」,再点击该账户的「登录 Command Code」通过网页获取密钥。",
6529
6595
  accountDefault: "默认账户",
6530
6596
  activeAccount: "当前使用账户",
6531
6597
  activeAccountAuto: "自动(第一个可用账户)",
@@ -6596,6 +6662,8 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6596
6662
  usageServiceUnavailableHint: "服务端返回了错误(5xx),稍后点击刷新重试。",
6597
6663
  usageNetworkError: "无法连接 Command Code 服务",
6598
6664
  usageNetworkHint: "所有请求都没有到达服务端。请检查网络连接或 API 地址设置。",
6665
+ usageInvalidResponse: "Command Code 响应无法读取",
6666
+ usageInvalidResponseHint: "请求已收到响应,但内容无法解析。请检查宿主的 HTTP 代理或响应解压配置。",
6599
6667
  usageUpdated: "更新于",
6600
6668
  usagePeriodEnd: "账期截止",
6601
6669
  usageActive: "当前使用",
@@ -6606,6 +6674,7 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6606
6674
  updateHint: "已发布新版本,点击查看发布说明;更新插件后刷新本页,提示会自动消失。",
6607
6675
  loginTitle: "通过官方登录获取密钥",
6608
6676
  loginHintIdle: "不想手动创建密钥?点击登录后浏览器会打开 commandcode.ai 授权页,完成后密钥自动写入本机凭据服务,下次请求即生效。",
6677
+ loginSaveBefore: "请先保存本页更改,再通过网页登录此账户。",
6609
6678
  loginButton: "登录 Command Code",
6610
6679
  loginStarting: "正在启动本地回调服务…",
6611
6680
  loginWaiting: "等待在浏览器中完成授权…",
@@ -6623,7 +6692,7 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6623
6692
  cardTitle: "Command Code",
6624
6693
  cardRouteActive: "已启用",
6625
6694
  cardLoadingHint: "正在读取 Command Code 配置…",
6626
- cardRegistrationHint: "此卡片随 Command Code 插件注册,需要较新版本的 DeepSeek Harness 才会显示完整内容。"
6695
+ cardRegistrationHint: "此卡片由 Command Code 插件提供,正在等待设置页装配,稍后即可显示完整内容。"
6627
6696
  };
6628
6697
  const en = {
6629
6698
  nav: "Command Code",
@@ -6670,6 +6739,7 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6670
6739
  accountLabel: "Account label",
6671
6740
  accountKey: "API key",
6672
6741
  accountKeyHint: "This account’s API key. Saving with the field blank keeps the stored key.",
6742
+ accountLoginAfterSave: "Use Save at the bottom of the page, then sign in to this account in your browser to obtain a key.",
6673
6743
  accountDefault: "Default account",
6674
6744
  activeAccount: "Active account",
6675
6745
  activeAccountAuto: "Auto (first usable account)",
@@ -6740,6 +6810,8 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6740
6810
  usageServiceUnavailableHint: "The server returned errors (5xx); try Refresh again later.",
6741
6811
  usageNetworkError: "Could not reach the Command Code service",
6742
6812
  usageNetworkHint: "No request reached the server. Check your network connection or the API base setting.",
6813
+ usageInvalidResponse: "Could not read the Command Code response",
6814
+ usageInvalidResponseHint: "The requests received responses, but their bodies could not be parsed. Check the host HTTP proxy or response decoding.",
6743
6815
  usageUpdated: "Updated",
6744
6816
  usagePeriodEnd: "Period ends",
6745
6817
  usageActive: "Active",
@@ -6750,6 +6822,7 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6750
6822
  updateHint: "A newer version has been published; click for release notes. The notice disappears once the plugin is updated.",
6751
6823
  loginTitle: "Sign in to fetch a key",
6752
6824
  loginHintIdle: "Rather not create a key by hand? Sign in and your browser opens the commandcode.ai authorization page; the approved key is stored in the local credential service and applies to the next request.",
6825
+ loginSaveBefore: "Save page changes before signing in to this account.",
6753
6826
  loginButton: "Sign in to Command Code",
6754
6827
  loginStarting: "Starting the local callback server…",
6755
6828
  loginWaiting: "Waiting for authorization in your browser…",
@@ -6767,7 +6840,7 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6767
6840
  cardTitle: "Command Code",
6768
6841
  cardRouteActive: "Active",
6769
6842
  cardLoadingHint: "Loading the Command Code configuration…",
6770
- cardRegistrationHint: "This card is contributed by the Command Code plugin; a newer DeepSeek Harness is needed to show the full controls."
6843
+ cardRegistrationHint: "This card is contributed by the Command Code plugin and is waiting for the settings page to finish assembling."
6771
6844
  };
6772
6845
  //#endregion
6773
6846
  //#region src/client/index.ts
@@ -6807,15 +6880,6 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6807
6880
  */
6808
6881
  const PANEL_ID = "commandcode-panel";
6809
6882
  /**
6810
- * ui-conversation's reserved `main` key, used only as the exit fallback for a
6811
- * layout whose `selectPanel` predates the `null` "show the Conversation"
6812
- * selection (see `close` in {@link applyClientSurfaces}). Declared locally for
6813
- * the same reason as {@link PANEL_ID}: ui-conversation is not a dependency of
6814
- * this bundle, and the key is a published contract of the layout (its README
6815
- * names `conversation` as reserved for the Conversation).
6816
- */
6817
- const CONVERSATION_PANEL_ID = "conversation";
6818
- /**
6819
6883
  * The composer figure's entry id in `conversation.composer.dock`. Its own id,
6820
6884
  * not the shipped `stats` cell's: reusing `stats` would REPLACE the tokens /
6821
6885
  * cache-hit / throughput readout rather than inject into it, and that readout
@@ -6823,12 +6887,10 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6823
6887
  */
6824
6888
  const SESSION_COST_ID = "commandcode-session-cost";
6825
6889
  /**
6826
- * Client plugin body. Gates on the services shared by both client generations
6827
- * (`slots`, `locale`, `connection`, `remote`) — never on `settingsScope`,
6828
- * which 0.1.7 removed and which the settings scope here replaces for every
6829
- * generation. Current clients mount the page after `remote.credentials`
6830
- * appears; legacy clients mount it from the connection ApiProxy credential
6831
- * face.
6890
+ * Client plugin body. Gates on `slots`, `locale` and `remote` — never on
6891
+ * `settingsScope`, whose wrapper service the 0.1.7 settings rewrite removed
6892
+ * (the settings scope here speaks the `remote.settings` wire directly). The
6893
+ * page mounts once `remote.credentials` appears.
6832
6894
  */
6833
6895
  function apply(ctx) {
6834
6896
  injectPageCss();
@@ -6840,19 +6902,13 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6840
6902
  zh: PANEL_COPY_ZH,
6841
6903
  en: PANEL_COPY_EN
6842
6904
  }), "dsh-commandcode-provider: panel copy");
6843
- const connection = ctx.get("connection");
6844
- const legacyApi = adaptLegacyCredentials(connection?.api?.credentials);
6845
- if (legacyApi !== void 0) {
6846
- applyClientSurfaces(ctx, legacyApi, connection?.hostDescription);
6847
- return;
6848
- }
6849
6905
  ctx.inject(["remote.credentials"], (remoteCtx) => {
6850
6906
  const credentials = remoteCtx.remote.credentials;
6851
6907
  applyClientSurfaces(remoteCtx, { credentials });
6852
6908
  });
6853
6909
  }
6854
- /** Mount the one shared UI implementation over either credential transport. */
6855
- function applyClientSurfaces(ctx, api, hostDescription) {
6910
+ /** Mount the one shared UI implementation. */
6911
+ function applyClientSurfaces(ctx, api) {
6856
6912
  let settingsNamespace;
6857
6913
  const scope = createSettingsScope(ctx, COMMANDCODE_NS, () => settingsNamespace);
6858
6914
  ctx.effect(() => () => {
@@ -6872,7 +6928,7 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6872
6928
  ok: false,
6873
6929
  error: { message: "commandcode/models remote is not mounted" }
6874
6930
  })
6875
- }, hostDescription);
6931
+ });
6876
6932
  ctx.effect(() => () => controller.dispose(), "dsh-commandcode-provider: settings controller");
6877
6933
  const store = createSnapshotStore(controller.state());
6878
6934
  controller.subscribe(() => store.set(controller.state()));
@@ -6964,12 +7020,12 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
6964
7020
  const pricesStore = createSnapshotStore(pricesController.state());
6965
7021
  pricesController.subscribe(() => pricesStore.set(pricesController.state()));
6966
7022
  const loginRemote = {
6967
- loginBegin: async () => {
7023
+ loginBegin: async (targetRef) => {
6968
7024
  if (usageNamespace === void 0) return {
6969
7025
  ok: false,
6970
7026
  error: { message: usageMountError ?? "commandcode remote is not mounted" }
6971
7027
  };
6972
- return usageNamespace.loginBegin();
7028
+ return usageNamespace.loginBegin(targetRef);
6973
7029
  },
6974
7030
  loginStatus: async () => {
6975
7031
  if (usageNamespace === void 0) return {
@@ -7013,7 +7069,7 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
7013
7069
  }),
7014
7070
  discard: () => controller.discard(),
7015
7071
  refreshUsage: () => void usageController.refresh(),
7016
- beginLogin: () => void loginController.begin(),
7072
+ beginLogin: (targetRef) => void loginController.begin(targetRef),
7017
7073
  cancelLogin: () => void loginController.cancel(),
7018
7074
  addAccount: () => controller.addAccount(),
7019
7075
  removeAccount: (id) => controller.removeAccount(id),
@@ -7065,21 +7121,10 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
7065
7121
  },
7066
7122
  startAutoRefresh: () => startPanelAutoRefresh(usageController, () => true),
7067
7123
  open: () => {
7068
- const layout = ctx.get("layout");
7069
- if (typeof layout?.selectPanel === "function") layout.selectPanel(PANEL_ID);
7124
+ ctx.get("layout")?.selectPanel(PANEL_ID);
7070
7125
  },
7071
7126
  close: () => {
7072
- const layout = ctx.get("layout");
7073
- if (typeof layout?.selectPanel !== "function") return;
7074
- try {
7075
- layout.selectPanel(null);
7076
- } catch {
7077
- try {
7078
- layout.selectPanel(CONVERSATION_PANEL_ID);
7079
- } catch (error) {
7080
- console.error("[dsh-commandcode-provider] could not close the plans & quota panel:", error);
7081
- }
7082
- }
7127
+ ctx.get("layout")?.selectPanel(null);
7083
7128
  }
7084
7129
  });
7085
7130
  ctx.effect(() => injectPanelCss(), "dsh-commandcode-provider: panel styles");
@@ -7094,7 +7139,6 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
7094
7139
  console.error("[dsh-commandcode-provider] could not register the plans & quota panel:", error);
7095
7140
  }
7096
7141
  ctx.inject(["layout"], (layoutCtx) => {
7097
- if (typeof layoutCtx.get("layout")?.selectPanel !== "function") return;
7098
7142
  try {
7099
7143
  layoutCtx.slots.inject("sidebar.footer.action", () => layoutCtx.slots.register({
7100
7144
  name: "sidebar.footer.action",
@@ -7121,7 +7165,6 @@ select.cc-input{appearance:none;-webkit-appearance:none;-moz-appearance:none;box
7121
7165
  const inject = [
7122
7166
  "slots",
7123
7167
  "locale",
7124
- "connection",
7125
7168
  "remote"
7126
7169
  ];
7127
7170
  //#endregion