@codexhost/cli-darwin-x64 0.13.3 → 0.14.0

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.
@@ -14768,10 +14768,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14768
14768
  var project = external_exports.string().min(1).max(4096);
14769
14769
  var usageStatisticsParamsSchema = external_exports.strictObject({
14770
14770
  range: external_exports.enum(USAGE_STATISTICS_RANGES),
14771
+ /** Display timezone for ranges, dates and hourly buckets; omitted means the Host's local zone. */
14772
+ timeZone: external_exports.string().min(1).max(128).refine((value) => {
14773
+ try {
14774
+ new Intl.DateTimeFormat("en", { timeZone: value });
14775
+ return true;
14776
+ } catch {
14777
+ return false;
14778
+ }
14779
+ }, "Unsupported usage statistics timezone").optional(),
14771
14780
  harness: harness.optional(),
14772
14781
  model: model.nullable().optional(),
14773
14782
  project: project.nullable().optional(),
14774
- /** One local date inside the range. */
14783
+ /** One date in the query timezone inside the range. */
14775
14784
  date: localDate.optional()
14776
14785
  });
14777
14786
  var usageStatisticsTotalsSchema = external_exports.strictObject({
@@ -14807,7 +14816,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14807
14816
  });
14808
14817
  var usageStatisticsResultSchema = external_exports.strictObject({
14809
14818
  range: external_exports.enum(USAGE_STATISTICS_RANGES),
14810
- /** First local date of the range; null for all time. */
14819
+ /** First date in the query timezone (Host local when omitted); null for all time. */
14811
14820
  from: localDate.nullable(),
14812
14821
  to: localDate,
14813
14822
  /** The filters these figures apply, echoed so a late answer to older filters is recognised. */
@@ -14847,7 +14856,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14847
14856
  totals: usageStatisticsTotalsSchema,
14848
14857
  /** Each date and Harness of the range: every filter except the day. */
14849
14858
  daily: external_exports.array(external_exports.strictObject({ date: localDate, harness, ...totals })).max(2e5),
14850
- /** Local weekday (0 = Sunday) and hour, all filters applied. */
14859
+ /** Weekday (0 = Sunday) and hour in the query timezone, all filters applied. */
14851
14860
  hourly: external_exports.array(external_exports.strictObject({
14852
14861
  weekday: external_exports.number().int().min(0).max(6),
14853
14862
  hour: external_exports.number().int().min(0).max(23),
@@ -14908,6 +14917,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14908
14917
  "codexhost/harness/display-settings/set",
14909
14918
  "codexhost/harness/inspect",
14910
14919
  "codexhost/harness/installation",
14920
+ "codexhost/harness/installation/start",
14921
+ "codexhost/harness/installation/status",
14911
14922
  "codexhost/harness/launch-settings/get",
14912
14923
  "codexhost/harness/launch-settings/set",
14913
14924
  "codexhost/harness/web-ui/open",
@@ -14985,7 +14996,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14985
14996
  var nonNegativeSafeIntegerSchema = external_exports.number().int().safe().nonnegative();
14986
14997
  var finiteNonNegativeNumberSchema = external_exports.number().finite().nonnegative();
14987
14998
  var cacheHitRatePercentSchema = external_exports.number().finite().min(0).max(100);
14999
+ var indicatorTextSchema = (maximum) => harnessLocalizedTextSchema.refine((entries) => Object.values(entries).every((text) => text.length <= maximum));
15000
+ var composerIndicatorsSchema = external_exports.array(external_exports.object({
15001
+ kind: external_exports.literal("countdown"),
15002
+ id: external_exports.string().min(1).max(64),
15003
+ expiresAtUnix: nonNegativeSafeIntegerSchema,
15004
+ label: indicatorTextSchema(256).optional(),
15005
+ tooltip: indicatorTextSchema(1024).optional()
15006
+ }).strict()).max(2).refine((entries) => new Set(entries.map(({ id }) => id)).size === entries.length, {
15007
+ message: "Composer indicator IDs must be unique"
15008
+ });
14988
15009
  var threadUsageSnapshotSchema = external_exports.object({
15010
+ composerIndicators: composerIndicatorsSchema.optional(),
14989
15011
  inputTokens: nonNegativeSafeIntegerSchema.optional(),
14990
15012
  cachedInputTokens: nonNegativeSafeIntegerSchema.optional(),
14991
15013
  cacheWriteInputTokens: nonNegativeSafeIntegerSchema.optional(),
@@ -15393,7 +15415,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15393
15415
  }).strict().optional(),
15394
15416
  autonomousTurns: external_exports.object({
15395
15417
  observe: external_exports.boolean()
15396
- }).strict().optional()
15418
+ }).strict().optional(),
15419
+ /** True only when `turn.steer` delivers input into the active Turn through a native primitive. */
15420
+ steer: external_exports.boolean().optional()
15397
15421
  }).strict();
15398
15422
  var harnessConfigurationStateSchema = external_exports.object({
15399
15423
  effectiveModel: harnessModelRefSchema.optional(),
@@ -15441,7 +15465,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15441
15465
  var harnessInspectParamsSchema = external_exports.object({
15442
15466
  harnessId: harnessIdSchema,
15443
15467
  cwd: nonBlankTextSchema2.max(16384).optional(),
15444
- refresh: external_exports.boolean().optional()
15468
+ refresh: external_exports.boolean().optional(),
15469
+ /** `availability` asks only whether the Harness can run; see `InspectHarnessInput.purpose`. */
15470
+ purpose: external_exports.literal("availability").optional()
15445
15471
  }).strict();
15446
15472
  var harnessWebUiOpenParamsSchema = external_exports.object({
15447
15473
  harnessId: harnessIdSchema
@@ -15524,6 +15550,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15524
15550
  seen.add(thread.threadId);
15525
15551
  }
15526
15552
  });
15553
+ var threadSteeringInspectParamsSchema = external_exports.object({
15554
+ threadId: hostThreadIdSchema,
15555
+ /** The text about to be steered; a Harness command always stops and restarts. */
15556
+ text: external_exports.string().optional()
15557
+ }).strict();
15558
+ var threadSteerDeliverySchema = external_exports.enum(["activeTurn", "newTurn"]);
15559
+ var threadSteeringInspectResultSchema = external_exports.object({
15560
+ delivery: external_exports.enum(["official", "activeTurn", "newTurn"])
15561
+ }).strict();
15527
15562
 
15528
15563
  // ../shared-contracts/dist/harness-plugins.js
15529
15564
  var HARNESS_PLUGIN_MANIFEST_MAX_BYTES = 32 * 1024;
@@ -15618,7 +15653,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15618
15653
  }).strict();
15619
15654
 
15620
15655
  // ../shared-contracts/dist/harness-installation.js
15621
- var HARNESS_INSTALLATION_METHOD = "codexhost/harness/installation";
15656
+ var HARNESS_INSTALLATION_START_METHOD = "codexhost/harness/installation/start";
15657
+ var HARNESS_INSTALLATION_STATUS_METHOD = "codexhost/harness/installation/status";
15622
15658
  var harnessInstallationParamsSchema = external_exports.object({
15623
15659
  harnessId: harnessIdSchema,
15624
15660
  action: external_exports.enum(["check", "update", "install"])
@@ -15628,6 +15664,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15628
15664
  latestVersion: external_exports.string().min(1).max(128),
15629
15665
  updateAvailable: external_exports.boolean(),
15630
15666
  canUpdate: external_exports.boolean(),
15667
+ /** Defaults to CLI; some Harnesses ship only inside a desktop application. */
15668
+ versionKind: external_exports.enum(["cli", "application"]).optional(),
15669
+ /** Official download opened by the user; does not imply an automatic installation. */
15670
+ manualUpdateUrl: external_exports.url().max(2048).refine((value) => /^https:\/\/[^/?#@]+(?:[/?#]|$)/iu.test(value), "Manual updates require a credential-free HTTPS URL").optional(),
15631
15671
  // Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
15632
15672
  message: external_exports.string().max(2048).optional(),
15633
15673
  messageCode: external_exports.string().min(1).max(128).optional(),
@@ -15635,6 +15675,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15635
15675
  notice: harnessLocalizedTextSchema.optional(),
15636
15676
  latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
15637
15677
  }).strict();
15678
+ var harnessInstallationTaskParamsSchema = external_exports.object({ taskId: external_exports.string().uuid() }).strict();
15679
+ var harnessInstallationTaskSchema = external_exports.discriminatedUnion("status", [
15680
+ external_exports.object({ taskId: external_exports.string().uuid(), status: external_exports.literal("running") }).strict(),
15681
+ external_exports.object({
15682
+ taskId: external_exports.string().uuid(),
15683
+ status: external_exports.literal("succeeded"),
15684
+ result: harnessInstallationStateSchema
15685
+ }).strict(),
15686
+ external_exports.object({
15687
+ taskId: external_exports.string().uuid(),
15688
+ status: external_exports.literal("failed"),
15689
+ error: external_exports.object({ code: external_exports.number().int(), message: external_exports.string().min(1).max(2048) }).strict()
15690
+ }).strict()
15691
+ ]);
15638
15692
 
15639
15693
  // ../shared-contracts/dist/codex-accounts.js
15640
15694
  var accountIdSchema = external_exports.string().min(1).max(256).regex(/^[A-Za-z0-9._~-]+$/u);
@@ -18298,6 +18352,8 @@ th[aria-sort] .console-usage-sort__mark {
18298
18352
  harness: "Harness",
18299
18353
  model: "Model",
18300
18354
  project: "Project",
18355
+ host: "Machine",
18356
+ localHost: "This machine",
18301
18357
  filterModel: "Filter by model",
18302
18358
  filterProject: "Filter by project",
18303
18359
  unknownModel: "Unknown model",
@@ -18481,6 +18537,8 @@ th[aria-sort] .console-usage-sort__mark {
18481
18537
  harness: "Harness",
18482
18538
  model: "\u6A21\u578B",
18483
18539
  project: "\u9879\u76EE",
18540
+ host: "\u673A\u5668",
18541
+ localHost: "\u672C\u673A",
18484
18542
  filterModel: "\u6309\u6A21\u578B\u7B5B\u9009",
18485
18543
  filterProject: "\u6309\u9879\u76EE\u7B5B\u9009",
18486
18544
  unknownModel: "\u672A\u77E5\u6A21\u578B",
@@ -19245,6 +19303,26 @@ th[aria-sort] .console-usage-sort__mark {
19245
19303
  };
19246
19304
  }
19247
19305
 
19306
+ // src/renderer-installation-client.ts
19307
+ async function runRendererInstallation(send, input) {
19308
+ const params = harnessInstallationParamsSchema.parse(input);
19309
+ const options = { priority: "background", timeoutMs: 15e3 };
19310
+ let task = harnessInstallationTaskSchema.parse(
19311
+ await send(HARNESS_INSTALLATION_START_METHOD, params, options)
19312
+ );
19313
+ const taskId = task.taskId;
19314
+ while (task.status === "running") {
19315
+ await new Promise((resolve) => globalThis.setTimeout(resolve, 500));
19316
+ task = harnessInstallationTaskSchema.parse(
19317
+ await send(HARNESS_INSTALLATION_STATUS_METHOD, { taskId }, options)
19318
+ );
19319
+ if (task.taskId !== taskId) throw new Error("Harness installation task identity changed");
19320
+ }
19321
+ if (task.status === "failed")
19322
+ throw Object.assign(new Error(task.error.message), { code: task.error.code });
19323
+ return task.result;
19324
+ }
19325
+
19248
19326
  // src/renderer-request-sender.ts
19249
19327
  var RendererMethodUnavailableError = class extends Error {
19250
19328
  constructor(method, cause) {
@@ -19393,7 +19471,15 @@ th[aria-sort] .console-usage-sort__mark {
19393
19471
  };
19394
19472
  const inspectHarness = async (input, options) => {
19395
19473
  const params = harnessInspectParamsSchema.parse(input);
19396
- const result = await manager.sendRequest(HARNESS_INSPECT_METHOD, params, options);
19474
+ let result;
19475
+ try {
19476
+ result = await manager.sendRequest(HARNESS_INSPECT_METHOD, params, options);
19477
+ } catch (error51) {
19478
+ if (!params.purpose || !isInvalidParams(error51)) throw error51;
19479
+ const full = { ...params };
19480
+ delete full.purpose;
19481
+ result = await manager.sendRequest(HARNESS_INSPECT_METHOD, full, options);
19482
+ }
19397
19483
  return harnessInspectionSchema.parse(result);
19398
19484
  };
19399
19485
  const inspectHarnessCommands = async (input) => {
@@ -19433,13 +19519,7 @@ th[aria-sort] .console-usage-sort__mark {
19433
19519
  };
19434
19520
  return Object.freeze({
19435
19521
  async installation(input) {
19436
- return harnessInstallationStateSchema.parse(
19437
- await manager.sendRequest(
19438
- HARNESS_INSTALLATION_METHOD,
19439
- harnessInstallationParamsSchema.parse(input),
19440
- { priority: "interactive" }
19441
- )
19442
- );
19522
+ return runRendererInstallation(manager.sendRequest, input);
19443
19523
  },
19444
19524
  async getHarnessDisplaySettings() {
19445
19525
  return harnessDisplaySettingsSchema.parse(
@@ -19655,6 +19735,9 @@ th[aria-sort] .console-usage-sort__mark {
19655
19735
  }
19656
19736
  });
19657
19737
  }
19738
+ function isInvalidParams(error51) {
19739
+ return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === -32602;
19740
+ }
19658
19741
 
19659
19742
  // src/settings/accounts.css
19660
19743
  var accounts_default = `.settings-harness-account__logo {
@@ -20830,10 +20913,17 @@ th[aria-sort] .console-usage-sort__mark {
20830
20913
  connectionInstallRunning: "Installing on the selected Host. You can leave this page; login or setup may still be required afterward.",
20831
20914
  harnessVersion: harnessVersionEnglish,
20832
20915
  harnessVersionTitle: "Harness CLI version",
20916
+ harnessVersionApplicationTitle: "Application version",
20833
20917
  harnessVersionCurrent: "Current version",
20834
20918
  harnessVersionLatest: "Latest version",
20835
20919
  harnessVersionChecking: "Checking versions\u2026",
20920
+ harnessVersionAvailable: "Update available",
20836
20921
  harnessVersionUpdate: "Update",
20922
+ harnessVersionDownloadUpdate: "Download update",
20923
+ harnessUpdateAll: "Update all",
20924
+ harnessUpdateAllProgress: "Updating",
20925
+ harnessUpdateAllDescription: "Update all eligible Harnesses on the selected Host.",
20926
+ harnessUpdateAllResult: "Updated {succeeded}; failed {failed}.",
20837
20927
  harnessVersionUpdating: "Updating\u2026",
20838
20928
  harnessVersionUpToDate: "Up to date",
20839
20929
  harnessVersionUpdated: "Update verified. New sessions will use the new version.",
@@ -21103,10 +21193,17 @@ th[aria-sort] .console-usage-sort__mark {
21103
21193
  connectionInstallRunning: "\u6B63\u5728\u6240\u9009 Host \u4E0A\u5B89\u88C5\uFF0C\u79BB\u5F00\u9875\u9762\u4E0D\u4F1A\u4E2D\u65AD\u3002\u5B89\u88C5\u540E\u53EF\u80FD\u4ECD\u9700\u767B\u5F55\u6216\u914D\u7F6E\u3002",
21104
21194
  harnessVersion: harnessVersionChinese,
21105
21195
  harnessVersionTitle: "Harness CLI \u7248\u672C",
21196
+ harnessVersionApplicationTitle: "\u5E94\u7528\u7248\u672C",
21106
21197
  harnessVersionCurrent: "\u5F53\u524D\u7248\u672C",
21107
21198
  harnessVersionLatest: "\u6700\u65B0\u7248\u672C",
21108
21199
  harnessVersionChecking: "\u6B63\u5728\u68C0\u67E5\u7248\u672C\u2026",
21200
+ harnessVersionAvailable: "\u6709\u66F4\u65B0",
21109
21201
  harnessVersionUpdate: "\u66F4\u65B0",
21202
+ harnessVersionDownloadUpdate: "\u4E0B\u8F7D\u66F4\u65B0",
21203
+ harnessUpdateAll: "\u5168\u90E8\u66F4\u65B0",
21204
+ harnessUpdateAllProgress: "\u66F4\u65B0\u4E2D",
21205
+ harnessUpdateAllDescription: "\u66F4\u65B0\u5F53\u524D Host \u4E0A\u652F\u6301\u81EA\u52A8\u66F4\u65B0\u4E14\u6709\u65B0\u7248\u672C\u7684 Harness\u3002",
21206
+ harnessUpdateAllResult: "\u5DF2\u66F4\u65B0 {succeeded} \u9879\uFF0C{failed} \u9879\u5931\u8D25\u3002",
21110
21207
  harnessVersionUpdating: "\u6B63\u5728\u66F4\u65B0\u2026",
21111
21208
  harnessVersionUpToDate: "\u5DF2\u662F\u6700\u65B0",
21112
21209
  harnessVersionUpdated: "\u5DF2\u786E\u8BA4\u66F4\u65B0\u6210\u529F\uFF0C\u65B0\u4F1A\u8BDD\u5C06\u4F7F\u7528\u65B0\u7248\u672C\u3002",
@@ -21225,6 +21322,34 @@ th[aria-sort] .console-usage-sort__mark {
21225
21322
  return names.size === 1 ? names.values().next().value ?? model2 : model2;
21226
21323
  }
21227
21324
 
21325
+ // src/console/usage/usage-hosts.ts
21326
+ var LOCAL_USAGE_HOST_ID = "local";
21327
+ function usageHostOptions(hosts, localLabel, selected) {
21328
+ const options = [{ key: LOCAL_USAGE_HOST_ID, label: localLabel }];
21329
+ const seen = /* @__PURE__ */ new Set([LOCAL_USAGE_HOST_ID]);
21330
+ const add = (hostId2, label) => {
21331
+ if (hostId2.length === 0 || seen.has(hostId2)) return;
21332
+ seen.add(hostId2);
21333
+ options.push({ key: hostId2, label: label !== void 0 && label.length > 0 ? label : hostId2 });
21334
+ };
21335
+ for (const host of hosts ?? []) add(host.hostId, host.label);
21336
+ if (!seen.has(selected)) add(selected, void 0);
21337
+ return options;
21338
+ }
21339
+ function createLatestKeyGuard() {
21340
+ let generation = 0;
21341
+ let key;
21342
+ return {
21343
+ begin(next) {
21344
+ generation += 1;
21345
+ key = next;
21346
+ const mine = generation;
21347
+ const selected = next;
21348
+ return () => generation === mine && Object.is(key, selected);
21349
+ }
21350
+ };
21351
+ }
21352
+
21228
21353
  // src/renderer-usage-control.ts
21229
21354
  var ENGLISH_USAGE_MESSAGES = Object.freeze({
21230
21355
  usage: "Usage",
@@ -22583,6 +22708,7 @@ th[aria-sort] .console-usage-sort__mark {
22583
22708
  const range = text("range");
22584
22709
  const measure = text("measure");
22585
22710
  const granularity = text("granularity");
22711
+ const hostId2 = text("hostId");
22586
22712
  const harness2 = text("harness");
22587
22713
  const model2 = text("model");
22588
22714
  const project2 = text("project");
@@ -22591,6 +22717,7 @@ th[aria-sort] .console-usage-sort__mark {
22591
22717
  ...range && USAGE_STATISTICS_RANGES.includes(range) ? { range } : {},
22592
22718
  ...measure && MEASURES.includes(measure) ? { measure } : {},
22593
22719
  ...granularity === "day" || granularity === "week" || granularity === "month" ? { granularity } : {},
22720
+ ...hostId2 !== void 0 && hostId2.length > 0 ? { hostId: hostId2 } : {},
22594
22721
  ...harness2 !== void 0 ? { harness: harness2 } : {},
22595
22722
  ...model2 !== void 0 ? { model: model2 } : {},
22596
22723
  ...project2 !== void 0 ? { project: project2 } : {},
@@ -22629,7 +22756,7 @@ th[aria-sort] .console-usage-sort__mark {
22629
22756
  day.setDate(day.getDate() - (day.getDay() + 6) % 7);
22630
22757
  return isoDate(day);
22631
22758
  }
22632
- function createUsageStatisticsPage(consoleMessages2, request, pageLocale) {
22759
+ function createUsageStatisticsPage(consoleMessages2, request, pageLocale, usageHosts) {
22633
22760
  const messages = consoleMessages2.usageStatistics;
22634
22761
  return Object.freeze({
22635
22762
  id: "usage-statistics",
@@ -22638,10 +22765,12 @@ th[aria-sort] .console-usage-sort__mark {
22638
22765
  mount(context) {
22639
22766
  const document2 = context.content.ownerDocument;
22640
22767
  const locale = pageLocale ?? (document2.documentElement.lang || "en");
22768
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
22641
22769
  const count3 = (value) => count2(value, locale);
22642
22770
  const tokenCount2 = (totals2, value) => tokenCount(totals2, value, locale);
22643
22771
  const saved = readView();
22644
22772
  const view = {
22773
+ hostId: saved.hostId ?? LOCAL_USAGE_HOST_ID,
22645
22774
  range: saved.range ?? "30d",
22646
22775
  measure: saved.measure ?? "cost",
22647
22776
  granularity: saved.granularity ?? null,
@@ -22672,7 +22801,7 @@ th[aria-sort] .console-usage-sort__mark {
22672
22801
  let projectLabel = /* @__PURE__ */ new Map();
22673
22802
  const projectName = (key) => key === UNKNOWN ? messages.unknownProject : projectLabel.get(key) ?? baseName(key);
22674
22803
  const measureLabel = (measure) => measure === "cost" ? messages.cost : messages.tokens;
22675
- const dateFormat = (options) => new Intl.DateTimeFormat(locale, options);
22804
+ const dateFormat = (options) => new Intl.DateTimeFormat(locale, { ...options, timeZone });
22676
22805
  const shortDate = dateFormat({ month: "short", day: "numeric" });
22677
22806
  const longDate = dateFormat({
22678
22807
  year: "numeric",
@@ -22691,10 +22820,51 @@ th[aria-sort] .console-usage-sort__mark {
22691
22820
  const prices = createModelPricesDialog(
22692
22821
  document2,
22693
22822
  consoleMessages2,
22694
- request,
22823
+ (method, params2) => request(method, params2, view.hostId),
22695
22824
  context.signal,
22696
22825
  load
22697
22826
  );
22827
+ let offeredHosts = usageHosts ? [] : void 0;
22828
+ const hostCombo = new ComboBox(document2, {
22829
+ label: messages.host,
22830
+ searchLabel: messages.search,
22831
+ emptyLabel: messages.noMatches,
22832
+ signal: context.signal,
22833
+ searchable: false,
22834
+ display: (option) => `${messages.host} \xB7 ${option.label}`,
22835
+ onChange: (key) => {
22836
+ if (key === view.hostId) return;
22837
+ view.hostId = key;
22838
+ view.harness = "";
22839
+ view.model = "";
22840
+ view.project = "";
22841
+ date5 = null;
22842
+ unpricedOnly = false;
22843
+ result = null;
22844
+ error51 = null;
22845
+ loadedAt = 0;
22846
+ names.clear();
22847
+ save();
22848
+ hostOptions();
22849
+ render();
22850
+ void refreshHarnessNames();
22851
+ load();
22852
+ }
22853
+ });
22854
+ const hostOptions = () => {
22855
+ const options = usageHostOptions(offeredHosts, messages.localHost, view.hostId);
22856
+ hostCombo.element.hidden = options.length < 2;
22857
+ hostCombo.update(options, view.hostId === LOCAL_USAGE_HOST_ID ? "" : view.hostId);
22858
+ };
22859
+ const offerHosts = () => {
22860
+ if (!usageHosts) return;
22861
+ void usageHosts().then((hosts) => {
22862
+ if (context.signal.aborted) return;
22863
+ offeredHosts = hosts;
22864
+ hostOptions();
22865
+ }).catch(() => void 0);
22866
+ };
22867
+ hostOptions();
22698
22868
  const updated = h(document2, "span", { className: "console-muted console-usage-updated" });
22699
22869
  const refresh = h(
22700
22870
  document2,
@@ -22707,7 +22877,10 @@ th[aria-sort] .console-usage-sort__mark {
22707
22877
  },
22708
22878
  createRendererSettingsIcon("refresh", 16)
22709
22879
  );
22710
- refresh.addEventListener("click", () => load());
22880
+ refresh.addEventListener("click", () => {
22881
+ offerHosts();
22882
+ load();
22883
+ });
22711
22884
  const auto = new ComboBox(document2, {
22712
22885
  label: messages.autoRefresh,
22713
22886
  searchLabel: messages.search,
@@ -22746,6 +22919,7 @@ th[aria-sort] .console-usage-sort__mark {
22746
22919
  document2,
22747
22920
  "div",
22748
22921
  { className: "console-usage-toolbar" },
22922
+ hostCombo.element,
22749
22923
  updated,
22750
22924
  refresh,
22751
22925
  auto.element,
@@ -23384,7 +23558,6 @@ ${detail}` : ""}`
23384
23558
  }
23385
23559
  function hourlyPanel(data) {
23386
23560
  const singleDay = data.filters.date !== null || data.range === "today";
23387
- const zone = Intl.DateTimeFormat().resolvedOptions().timeZone;
23388
23561
  return panel(
23389
23562
  singleDay ? messages.hourlyDay : messages.hourly,
23390
23563
  hourlyChart(document2, {
@@ -23399,7 +23572,7 @@ ${detail}` : ""}`
23399
23572
  weekStartsOnMonday: !locale.startsWith("en"),
23400
23573
  labels: { cost: messages.cost, tokens: messages.tokens }
23401
23574
  }),
23402
- h(document2, "span", { className: "console-muted console-usage-zone" }, zone)
23575
+ h(document2, "span", { className: "console-muted console-usage-zone" }, timeZone)
23403
23576
  );
23404
23577
  }
23405
23578
  function sessionsPanel(title, rows, tableKey) {
@@ -23546,6 +23719,7 @@ ${detail}` : ""}`
23546
23719
  const project2 = filterValue(view.project);
23547
23720
  return {
23548
23721
  range: view.range,
23722
+ timeZone,
23549
23723
  ...view.harness ? { harness: view.harness } : {},
23550
23724
  ...model2 !== void 0 ? { model: model2 } : {},
23551
23725
  ...project2 !== void 0 ? { project: project2 } : {},
@@ -23558,10 +23732,26 @@ ${detail}` : ""}`
23558
23732
  if (result && !result.reading.complete) poll = window.setTimeout(load, POLL_MS);
23559
23733
  else if (view.autoRefreshMs > 0) poll = window.setTimeout(load, view.autoRefreshMs);
23560
23734
  }
23735
+ const harnessNamesRead = createLatestKeyGuard();
23736
+ async function refreshHarnessNames() {
23737
+ const hostId2 = view.hostId;
23738
+ const isCurrent = harnessNamesRead.begin(hostId2);
23739
+ names.clear();
23740
+ try {
23741
+ const value = await request(HARNESS_PLUGIN_LIST_METHOD2, {}, hostId2);
23742
+ if (!isCurrent()) return;
23743
+ for (const plugin of harnessPluginListResultSchema.parse(value).plugins) {
23744
+ names.set(plugin.id, plugin.name);
23745
+ }
23746
+ } catch {
23747
+ if (!isCurrent()) return;
23748
+ }
23749
+ if (!context.signal.aborted) render();
23750
+ }
23561
23751
  function load() {
23562
23752
  window.clearTimeout(poll);
23563
23753
  const requested = params();
23564
- void context.runLatest(() => request(USAGE_STATISTICS_METHOD, requested), {
23754
+ void context.runLatest(() => request(USAGE_STATISTICS_METHOD, requested, view.hostId), {
23565
23755
  success(value) {
23566
23756
  const parsed = usageStatisticsResultSchema.safeParse(value);
23567
23757
  if (parsed.success) {
@@ -23586,12 +23776,8 @@ ${detail}` : ""}`
23586
23776
  }
23587
23777
  context.content.replaceChildren(header, prices.element, filters, notices, body);
23588
23778
  render();
23589
- void request(HARNESS_PLUGIN_LIST_METHOD2, {}).then((value) => {
23590
- for (const plugin of harnessPluginListResultSchema.parse(value).plugins) {
23591
- names.set(plugin.id, plugin.name);
23592
- }
23593
- if (!context.signal.aborted) render();
23594
- }).catch(() => void 0);
23779
+ offerHosts();
23780
+ void refreshHarnessNames();
23595
23781
  load();
23596
23782
  return () => {
23597
23783
  window.clearTimeout(poll);
@@ -25068,7 +25254,7 @@ ${detail}` : ""}`
25068
25254
  }
25069
25255
 
25070
25256
  // src/settings/harness-version-panel.ts
25071
- function createHarnessVersionPanel(document2, messages, signal, agent, client) {
25257
+ function createHarnessVersionPanel(document2, messages, signal, agent, client, onChange = () => void 0) {
25072
25258
  const panel = document2.createElement("section");
25073
25259
  panel.className = "settings-harness-version";
25074
25260
  panel.dataset.harnessVersion = agent;
@@ -25094,37 +25280,67 @@ ${detail}` : ""}`
25094
25280
  panel.append(heading, versions, status, actions, note);
25095
25281
  let state;
25096
25282
  let busy = false;
25283
+ let updating = false;
25097
25284
  let unsupported = false;
25285
+ let updatePromise = null;
25098
25286
  const render = () => {
25287
+ heading.textContent = state?.versionKind === "application" ? messages.harnessVersionApplicationTitle : messages.harnessVersionTitle;
25099
25288
  current.textContent = `${messages.harnessVersionCurrent}: ${state?.currentVersion ?? "\u2014"}`;
25100
25289
  latest.textContent = `${messages.harnessVersionLatest}: ${harnessVersionLabel(state, messages.harnessVersion)}`;
25101
25290
  update.disabled = busy || signal.aborted || !state?.canUpdate || !state.updateAvailable;
25291
+ const manualUrl = !state?.canUpdate && state?.updateAvailable ? state.manualUpdateUrl : void 0;
25292
+ actions.replaceChildren(update);
25293
+ update.hidden = !busy && !signal.aborted && Boolean(manualUrl);
25294
+ if (update.hidden && manualUrl) {
25295
+ const download2 = document2.createElement("a");
25296
+ download2.className = "settings-command-button settings-command-button--secondary";
25297
+ download2.dataset.harnessVersionAction = "download-update";
25298
+ download2.textContent = messages.harnessVersionDownloadUpdate;
25299
+ download2.href = manualUrl;
25300
+ download2.target = "_blank";
25301
+ download2.rel = "noopener noreferrer";
25302
+ actions.append(download2);
25303
+ }
25102
25304
  update.textContent = state?.canUpdate && state.latestVersion !== "Unknown" && !state.updateAvailable ? messages.harnessVersionUpToDate : messages.harnessVersionUpdate;
25103
25305
  const detail = harnessVersionNote(state, messages.harnessVersion);
25104
- note.textContent = detail ? `${detail} ${messages.harnessVersionNote}` : messages.harnessVersionNote;
25306
+ note.textContent = detail ? !state?.canUpdate ? detail : `${detail} ${messages.harnessVersionNote}` : messages.harnessVersionNote;
25105
25307
  };
25106
25308
  const run = async (action) => {
25107
- if (busy || unsupported || signal.aborted) return;
25108
- if (action === "update" && (!state?.canUpdate || !state.updateAvailable)) return;
25309
+ if (busy || unsupported || signal.aborted) return false;
25310
+ if (action === "update" && (!state?.canUpdate || !state.updateAvailable)) return false;
25109
25311
  busy = true;
25312
+ updating = action === "update";
25313
+ onChange();
25110
25314
  status.textContent = action === "check" ? messages.harnessVersionChecking : messages.harnessVersionUpdating;
25111
25315
  render();
25112
25316
  try {
25113
25317
  const result = await client.run(action);
25114
- if (signal.aborted) return;
25318
+ if (signal.aborted) return false;
25115
25319
  state = result;
25116
25320
  status.textContent = !result.canUpdate ? messages.harnessVersionManual : action === "update" ? result.updateAvailable ? messages.harnessVersionFailed : messages.harnessVersionUpdated : "";
25321
+ return result.canUpdate && !result.updateAvailable;
25117
25322
  } catch (error51) {
25118
- if (signal.aborted) return;
25323
+ if (signal.aborted) return false;
25119
25324
  unsupported = typeof error51 === "object" && error51 !== null && "code" in error51 && (error51.code === -32601 || error51.code === -32078);
25120
25325
  status.textContent = unsupported ? messages.harnessVersionUnsupported : messages.harnessVersionFailed;
25121
25326
  if (state) state = { ...state, canUpdate: false };
25327
+ return false;
25122
25328
  } finally {
25123
25329
  busy = false;
25124
- if (!signal.aborted) render();
25330
+ updating = false;
25331
+ if (!signal.aborted) {
25332
+ render();
25333
+ onChange();
25334
+ }
25125
25335
  }
25126
25336
  };
25127
- update.addEventListener("click", () => void run("update"));
25337
+ const updateVersion = () => {
25338
+ updatePromise ??= run("update").finally(() => {
25339
+ updatePromise = null;
25340
+ });
25341
+ return updatePromise;
25342
+ };
25343
+ update.addEventListener("click", () => void updateVersion());
25128
25344
  const owner = document2.defaultView;
25129
25345
  let checkFrame = null;
25130
25346
  let checkTimer = null;
@@ -25151,7 +25367,95 @@ ${detail}` : ""}`
25151
25367
  } else {
25152
25368
  void run("check");
25153
25369
  }
25154
- return panel;
25370
+ return {
25371
+ element: panel,
25372
+ get state() {
25373
+ return state;
25374
+ },
25375
+ get updating() {
25376
+ return updating;
25377
+ },
25378
+ update: updateVersion
25379
+ };
25380
+ }
25381
+
25382
+ // src/settings/connection-versions.ts
25383
+ function createConnectionVersions(document2, messages, signal, diagnostics, onChange) {
25384
+ const panels = /* @__PURE__ */ new Map();
25385
+ const installation = diagnostics?.installation?.bind(diagnostics);
25386
+ return {
25387
+ get(hostId2, agent) {
25388
+ if (!installation || signal.aborted) return void 0;
25389
+ const key = JSON.stringify([hostId2, agent]);
25390
+ let panel = panels.get(key);
25391
+ if (!panel) {
25392
+ panel = createHarnessVersionPanel(
25393
+ document2,
25394
+ messages,
25395
+ signal,
25396
+ agent,
25397
+ {
25398
+ run: (action) => installation(hostId2, agent, action)
25399
+ },
25400
+ onChange
25401
+ );
25402
+ panels.set(key, panel);
25403
+ }
25404
+ return panel;
25405
+ }
25406
+ };
25407
+ }
25408
+
25409
+ // src/settings/connection-updates.ts
25410
+ function createConnectionUpdates(document2, messages, signal, onChange) {
25411
+ const batches = /* @__PURE__ */ new Map();
25412
+ const eligible = (panels) => panels.filter((panel) => panel.state?.updateAvailable && panel.state.canUpdate);
25413
+ const start = async (hostId2, panels) => {
25414
+ if (signal.aborted || batches.get(hostId2)?.running) return;
25415
+ const targets = eligible(panels);
25416
+ if (!targets.length) return;
25417
+ const batch = { running: true, total: targets.length, succeeded: 0, failed: 0 };
25418
+ batches.set(hostId2, batch);
25419
+ onChange();
25420
+ await Promise.all(
25421
+ targets.map(async (panel) => {
25422
+ try {
25423
+ if (await panel.update()) batch.succeeded++;
25424
+ else batch.failed++;
25425
+ } catch {
25426
+ batch.failed++;
25427
+ }
25428
+ if (!signal.aborted) onChange();
25429
+ })
25430
+ );
25431
+ batch.running = false;
25432
+ if (!signal.aborted) onChange();
25433
+ };
25434
+ return {
25435
+ createControls(hostId2, panels) {
25436
+ const batch = batches.get(hostId2);
25437
+ const count3 = eligible(panels).length;
25438
+ const button2 = document2.createElement("button");
25439
+ button2.type = "button";
25440
+ button2.className = "settings-command-button settings-command-button--secondary settings-connection-update-all";
25441
+ button2.dataset.connectionAction = "update-all";
25442
+ button2.disabled = signal.aborted || Boolean(batch?.running) || !count3;
25443
+ button2.title = messages.harnessUpdateAllDescription;
25444
+ const label = batch?.running ? `${messages.harnessUpdateAllProgress} ${batch.succeeded + batch.failed}/${batch.total}` : count3 ? `${messages.harnessUpdateAll} (${count3})` : messages.harnessUpdateAll;
25445
+ button2.append(createRendererSettingsIcon("download", 15), label);
25446
+ button2.addEventListener("click", () => {
25447
+ if (!button2.disabled) void start(hostId2, panels);
25448
+ });
25449
+ const result = document2.createElement("p");
25450
+ result.className = "settings-connection-update-result";
25451
+ result.setAttribute("role", "status");
25452
+ result.hidden = !batch || batch.running;
25453
+ if (batch && !batch.running) {
25454
+ result.textContent = messages.harnessUpdateAllResult.replace("{succeeded}", String(batch.succeeded)).replace("{failed}", String(batch.failed));
25455
+ }
25456
+ return { button: button2, result };
25457
+ }
25458
+ };
25155
25459
  }
25156
25460
 
25157
25461
  // src/settings/connections-page.ts
@@ -25319,6 +25623,7 @@ ${error51.stderrTail}`] : []
25319
25623
  status.dataset.connectionTone = connectionStatusTone(item.availability, item.error !== null);
25320
25624
  status.setAttribute("role", "cell");
25321
25625
  status.textContent = item.error?.code === "authenticationRequired" ? messages.connectionLoginRequired : item.error?.code === "configurationRequired" ? messages.connectionConfigurationRequired : connectionStatusLabel(item.availability, messages, item.error !== null);
25626
+ const version2 = item.version;
25322
25627
  const action = document2.createElement("div");
25323
25628
  action.className = "settings-connection-row__action";
25324
25629
  action.setAttribute("role", "cell");
@@ -25348,6 +25653,31 @@ ${error51.stderrTail}`] : []
25348
25653
  });
25349
25654
  action.append(viewError);
25350
25655
  }
25656
+ if (version2?.state?.updateAvailable && !version2.updating) {
25657
+ const available = document2.createElement("span");
25658
+ available.className = "settings-connection-version-available";
25659
+ available.textContent = messages.harnessVersionAvailable;
25660
+ available.title = `${messages.harnessVersionCurrent}: ${version2.state.currentVersion ?? "\u2014"}
25661
+ ${messages.harnessVersionLatest}: ${harnessVersionLabel(version2.state, messages.harnessVersion)}`;
25662
+ action.append(available);
25663
+ }
25664
+ if (version2?.state?.updateAvailable && version2.state.canUpdate) {
25665
+ const update = document2.createElement("button");
25666
+ update.type = "button";
25667
+ update.className = "settings-connection-install-link";
25668
+ update.dataset.connectionAction = "update";
25669
+ update.disabled = version2.updating;
25670
+ update.title = messages.harnessVersionUpdate;
25671
+ update.setAttribute("aria-label", `${messages.harnessVersionUpdate}: ${item.name}`);
25672
+ update.append(createRendererSettingsIcon("download", 17));
25673
+ update.addEventListener("click", (event) => {
25674
+ event.stopPropagation();
25675
+ if (update.disabled) return;
25676
+ void version2.update();
25677
+ select();
25678
+ });
25679
+ action.append(update);
25680
+ }
25351
25681
  if (group) {
25352
25682
  const toggle = document2.createElement("button");
25353
25683
  toggle.type = "button";
@@ -25636,8 +25966,6 @@ ${error51.stderrTail}`] : []
25636
25966
  let selectedHostId = null;
25637
25967
  let selectedItemKey = null;
25638
25968
  let launchControls = null;
25639
- const versionPanels = /* @__PURE__ */ new Map();
25640
- const updatingVersions = /* @__PURE__ */ new Set();
25641
25969
  const hostNames = /* @__PURE__ */ new Map();
25642
25970
  let latestSnapshot = null;
25643
25971
  let disposeHostScroller = () => void 0;
@@ -25666,7 +25994,15 @@ ${error51.stderrTail}`] : []
25666
25994
  renderFrame = null;
25667
25995
  };
25668
25996
  const diagnostics = getDiagnostics();
25997
+ const versions = createConnectionVersions(
25998
+ document2,
25999
+ messages,
26000
+ context.signal,
26001
+ diagnostics,
26002
+ scheduleRender
26003
+ );
25669
26004
  const installs = diagnostics ? harnessInstallStore(diagnostics) : null;
26005
+ const updates = createConnectionUpdates(document2, messages, context.signal, scheduleRender);
25670
26006
  const runRefresh = () => {
25671
26007
  if (pending || !diagnostics) return;
25672
26008
  pending = true;
@@ -25802,10 +26138,13 @@ ${error51.stderrTail}`] : []
25802
26138
  const agent = item.agentSnapshot?.agent;
25803
26139
  if (!agent) return item;
25804
26140
  const state = installs?.get(selectedHost.hostId, agent);
26141
+ const availability = state?.status ?? item.availability;
26142
+ const version2 = item.agentSnapshot?.availability !== "notInstalled" && availability !== "installing" && availability !== "checking" ? versions.get(selectedHost.hostId, agent) : void 0;
25805
26143
  return {
25806
26144
  ...item,
25807
26145
  ...state ? { availability: state.status } : {},
25808
- ...updatingVersions.has(JSON.stringify([selectedHost.hostId, agent])) ? { availability: "updating" } : {},
26146
+ ...version2 ? { version: version2 } : {},
26147
+ ...version2?.updating ? { availability: "updating" } : {},
25809
26148
  ...state?.error ? { installError: state.error } : {},
25810
26149
  ...diagnostics?.installation && harnessHasInstallCommands(item.agentSnapshot?.plugin) ? {
25811
26150
  install: () => {
@@ -25842,30 +26181,7 @@ ${error51.stderrTail}`] : []
25842
26181
  runRefresh
25843
26182
  );
25844
26183
  launchControls = { hostId: selectedHost.hostId, itemKey: item.key, element };
25845
- const agent = item.agentSnapshot?.agent;
25846
- const installation = diagnostics?.installation?.bind(diagnostics);
25847
- if (agent && item.agentSnapshot?.availability !== "notInstalled" && item.availability !== "installing" && item.availability !== "checking" && installation) {
25848
- const key = JSON.stringify([selectedHost.hostId, agent]);
25849
- let panel = versionPanels.get(key);
25850
- if (!panel) {
25851
- const hostId2 = selectedHost.hostId;
25852
- panel = createHarnessVersionPanel(document2, messages, context.signal, agent, {
25853
- async run(action) {
25854
- if (action !== "update") return installation(hostId2, agent, action);
25855
- updatingVersions.add(key);
25856
- if (diagnostics) render(diagnostics.snapshot());
25857
- try {
25858
- return await installation(hostId2, agent, action);
25859
- } finally {
25860
- updatingVersions.delete(key);
25861
- if (!context.signal.aborted && diagnostics) render(diagnostics.snapshot());
25862
- }
25863
- }
25864
- });
25865
- versionPanels.set(key, panel);
25866
- }
25867
- inspector.append(panel);
25868
- }
26184
+ if (item.version) inspector.append(item.version.element);
25869
26185
  };
25870
26186
  const pinnedItem = items.find((item) => item.key === "renderer-adapter");
25871
26187
  if (pinnedItem) {
@@ -26021,7 +26337,14 @@ ${error51.stderrTail}`] : []
26021
26337
  }
26022
26338
  const selectedItem = items.find((item) => item.key === selectedItemKey) ?? items[0];
26023
26339
  if (selectedItem) selectItem(selectedItem);
26024
- list.append(hostStrip, tableHeader, rows);
26340
+ const updateControls = updates.createControls(
26341
+ selectedHost.hostId,
26342
+ items.flatMap((item) => item.version ? [item.version] : [])
26343
+ );
26344
+ const hostHeader = document2.createElement("div");
26345
+ hostHeader.className = "settings-connection-host-header";
26346
+ hostHeader.append(hostStrip, updateControls.button);
26347
+ list.append(hostHeader, updateControls.result, tableHeader, rows);
26025
26348
  layout.append(list, inspector);
26026
26349
  content.replaceChildren(layout);
26027
26350
  disposeHostScroller = configureHostScroller(
@@ -29147,7 +29470,7 @@ ${error51.stderrTail}`] : []
29147
29470
  }
29148
29471
  });
29149
29472
  }
29150
- function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getAccountClient = () => null, getSessionImportClient = () => null, openImportedThread = () => Promise.reject(new Error("Imported Thread navigation is unavailable")), getLoadedSessionsClient = () => null, getRemoteConnections = () => null, requestUsageStatistics = () => Promise.reject(new Error("Local Host connection is unavailable"))) {
29473
+ function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getAccountClient = () => null, getSessionImportClient = () => null, openImportedThread = () => Promise.reject(new Error("Imported Thread navigation is unavailable")), getLoadedSessionsClient = () => null, getRemoteConnections = () => null, requestUsageStatistics = () => Promise.reject(new Error("Local Host connection is unavailable")), usageStatisticsHosts) {
29151
29474
  return Object.freeze([
29152
29475
  createConnectionsSettingsPage(messages, getDiagnostics, void 0, getRemoteConnections),
29153
29476
  createRemoteConnectionsPage(messages, getRemoteConnections),
@@ -29161,7 +29484,8 @@ ${error51.stderrTail}`] : []
29161
29484
  createUsageStatisticsPage(
29162
29485
  consoleMessages(messages.locale),
29163
29486
  requestUsageStatistics,
29164
- messages.locale
29487
+ messages.locale,
29488
+ usageStatisticsHosts
29165
29489
  ),
29166
29490
  createAppearanceSettingsPage(messages, getLoadedSessionsClient),
29167
29491
  updatesPage(messages, getUpdateClient),
@@ -29938,6 +30262,20 @@ ${error51.stderrTail}`] : []
29938
30262
  gap: 18px;
29939
30263
  }
29940
30264
 
30265
+ .settings-connections-content {
30266
+ container: settings-connections / inline-size;
30267
+ }
30268
+
30269
+ @container settings-connections (max-width: 780px) {
30270
+ .settings-connections-layout {
30271
+ grid-template-columns: minmax(0, 1fr);
30272
+ }
30273
+
30274
+ .settings-connection-inspector {
30275
+ position: static;
30276
+ }
30277
+ }
30278
+
29941
30279
  .settings-connection-list,
29942
30280
  .settings-connection-inspector {
29943
30281
  overflow: hidden;
@@ -29946,14 +30284,36 @@ ${error51.stderrTail}`] : []
29946
30284
  border-radius: 10px;
29947
30285
  }
29948
30286
 
30287
+ .settings-connection-host-header {
30288
+ display: flex;
30289
+ align-items: center;
30290
+ min-width: 0;
30291
+ border-bottom: 1px solid var(--settings-divider);
30292
+ }
30293
+
30294
+ .settings-connection-update-all {
30295
+ flex: none;
30296
+ margin-right: 10px;
30297
+ white-space: nowrap;
30298
+ }
30299
+
30300
+ .settings-connection-update-result {
30301
+ margin: 0;
30302
+ padding: 7px 10px;
30303
+ color: var(--settings-muted);
30304
+ font-size: 11px;
30305
+ line-height: 18px;
30306
+ border-bottom: 1px solid var(--settings-divider);
30307
+ }
30308
+
29949
30309
  .settings-connection-host-strip {
29950
30310
  display: grid;
30311
+ flex: 1;
29951
30312
  grid-template-columns: 30px minmax(0, 1fr) 30px;
29952
30313
  align-items: center;
29953
30314
  min-width: 0;
29954
30315
  gap: 5px;
29955
30316
  padding: 9px 10px;
29956
- border-bottom: 1px solid var(--settings-divider);
29957
30317
  }
29958
30318
 
29959
30319
  .settings-connection-host-scroll {
@@ -30050,7 +30410,7 @@ ${error51.stderrTail}`] : []
30050
30410
  .settings-connection-table-header,
30051
30411
  .settings-connection-row {
30052
30412
  display: grid;
30053
- grid-template-columns: minmax(160px, 1fr) minmax(92px, auto) 108px;
30413
+ grid-template-columns: minmax(160px, 1fr) minmax(92px, auto) minmax(108px, max-content);
30054
30414
  align-items: center;
30055
30415
  min-width: 0;
30056
30416
  gap: 10px;
@@ -30143,6 +30503,14 @@ ${error51.stderrTail}`] : []
30143
30503
  line-height: 18px;
30144
30504
  }
30145
30505
 
30506
+ .settings-connection-version-available {
30507
+ flex: none;
30508
+ color: var(--settings-muted);
30509
+ font-size: 10px;
30510
+ line-height: 16px;
30511
+ white-space: nowrap;
30512
+ }
30513
+
30146
30514
  .settings-connection-row__status::before {
30147
30515
  width: 6px;
30148
30516
  height: 6px;
@@ -30179,6 +30547,7 @@ ${error51.stderrTail}`] : []
30179
30547
  justify-content: flex-end;
30180
30548
  min-width: 0;
30181
30549
  gap: 4px;
30550
+ white-space: nowrap;
30182
30551
  }
30183
30552
 
30184
30553
  .settings-connection-row__handle {