@codexhost/cli-win32-arm64 0.3.4 → 0.4.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.
- package/README.md +1 -1
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +4 -35
- package/app/host-runtime.mjs +7516 -3308
- package/app/renderer-extension.js +1496 -700
- package/bin/codexhost.exe +0 -0
- package/libexec/codexhost-shim.exe +0 -0
- package/libexec/codexhost-updater.exe +0 -0
- package/package.json +1 -1
|
@@ -15014,7 +15014,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15014
15014
|
productUsage: external_exports.array(accountCreditsProductUsageSchema).min(1).optional()
|
|
15015
15015
|
}).strict();
|
|
15016
15016
|
var threadUsageInspectionParamsSchema = external_exports.object({
|
|
15017
|
-
threadId: hostThreadIdSchema
|
|
15017
|
+
threadId: hostThreadIdSchema,
|
|
15018
|
+
refresh: external_exports.literal("exact").optional()
|
|
15018
15019
|
}).strict();
|
|
15019
15020
|
var threadUsageInspectionSchema = external_exports.object({
|
|
15020
15021
|
threadId: hostThreadIdSchema,
|
|
@@ -16558,6 +16559,86 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16558
16559
|
["path", { d: "M12 16h.01" }]
|
|
16559
16560
|
];
|
|
16560
16561
|
|
|
16562
|
+
// src/renderer-harness-localization.ts
|
|
16563
|
+
var ENGLISH_HARNESS_MESSAGES = Object.freeze({
|
|
16564
|
+
commands: "Commands",
|
|
16565
|
+
harnessCommands: "Harness commands",
|
|
16566
|
+
textArgument: "Text",
|
|
16567
|
+
permissionMode: "Permission mode",
|
|
16568
|
+
permissions: "Permissions",
|
|
16569
|
+
loadingPermissions: "Loading permissions...",
|
|
16570
|
+
selecting: "Selecting...",
|
|
16571
|
+
permissionsUnavailable: "Permissions unavailable"
|
|
16572
|
+
});
|
|
16573
|
+
var CHINESE_HARNESS_MESSAGES = Object.freeze({
|
|
16574
|
+
commands: "\u547D\u4EE4",
|
|
16575
|
+
harnessCommands: "Harness \u547D\u4EE4",
|
|
16576
|
+
textArgument: "\u6587\u672C",
|
|
16577
|
+
permissionMode: "\u6743\u9650\u6A21\u5F0F",
|
|
16578
|
+
permissions: "\u6743\u9650",
|
|
16579
|
+
loadingPermissions: "\u6B63\u5728\u52A0\u8F7D\u6743\u9650...",
|
|
16580
|
+
selecting: "\u6B63\u5728\u9009\u62E9...",
|
|
16581
|
+
permissionsUnavailable: "\u6743\u9650\u4E0D\u53EF\u7528"
|
|
16582
|
+
});
|
|
16583
|
+
var CHINESE_PERMISSION_MODE_LABELS = /* @__PURE__ */ new Map([
|
|
16584
|
+
["Always ask", "\u59CB\u7EC8\u8BE2\u95EE"],
|
|
16585
|
+
["Write", "\u5199\u5165"],
|
|
16586
|
+
["Full access", "\u5B8C\u5168\u8BBF\u95EE"],
|
|
16587
|
+
["Plan mode", "\u89C4\u5212\u6A21\u5F0F"],
|
|
16588
|
+
["Default", "\u9ED8\u8BA4"],
|
|
16589
|
+
["Accept edits", "\u63A5\u53D7\u7F16\u8F91"],
|
|
16590
|
+
["Auto mode", "\u81EA\u52A8\u6A21\u5F0F"],
|
|
16591
|
+
["Bypass permissions", "\u7ED5\u8FC7\u6743\u9650"],
|
|
16592
|
+
["Ask", "\u8BE2\u95EE"],
|
|
16593
|
+
["Auto", "\u81EA\u52A8"],
|
|
16594
|
+
["Always approve", "\u59CB\u7EC8\u6279\u51C6"]
|
|
16595
|
+
]);
|
|
16596
|
+
var CHINESE_PERMISSION_MODE_DESCRIPTIONS = /* @__PURE__ */ new Map([
|
|
16597
|
+
[
|
|
16598
|
+
"Automatically allow reads and ask before write or execution actions.",
|
|
16599
|
+
"\u81EA\u52A8\u5141\u8BB8\u8BFB\u53D6\uFF1B\u5199\u5165\u6216\u6267\u884C\u64CD\u4F5C\u524D\u8BE2\u95EE\u3002"
|
|
16600
|
+
],
|
|
16601
|
+
[
|
|
16602
|
+
"Automatically allow reads and writes; ask before execution actions.",
|
|
16603
|
+
"\u81EA\u52A8\u5141\u8BB8\u8BFB\u53D6\u548C\u5199\u5165\uFF1B\u6267\u884C\u64CD\u4F5C\u524D\u8BE2\u95EE\u3002"
|
|
16604
|
+
],
|
|
16605
|
+
["Run all tool actions without approval prompts.", "\u65E0\u9700\u6279\u51C6\u63D0\u793A\u5373\u53EF\u8FD0\u884C\u6240\u6709\u5DE5\u5177\u64CD\u4F5C\u3002"],
|
|
16606
|
+
["Analyze and plan without executing tools.", "\u4EC5\u5206\u6790\u548C\u89C4\u5212\uFF0C\u4E0D\u6267\u884C\u5DE5\u5177\u3002"],
|
|
16607
|
+
["Ask before edits and other protected actions.", "\u7F16\u8F91\u548C\u5176\u4ED6\u53D7\u4FDD\u62A4\u64CD\u4F5C\u524D\u8BE2\u95EE\u3002"],
|
|
16608
|
+
["Allow file edits and ask for other protected actions.", "\u5141\u8BB8\u6587\u4EF6\u7F16\u8F91\uFF1B\u5176\u4ED6\u53D7\u4FDD\u62A4\u64CD\u4F5C\u524D\u8BE2\u95EE\u3002"],
|
|
16609
|
+
["Let Claude classify permission requests.", "\u7531 Claude \u5224\u65AD\u6743\u9650\u8BF7\u6C42\u3002"],
|
|
16610
|
+
["Skip Claude Code permission checks.", "\u8DF3\u8FC7 Claude Code \u6743\u9650\u68C0\u67E5\u3002"],
|
|
16611
|
+
[
|
|
16612
|
+
"Use Grok Build's default interactive approval policy.",
|
|
16613
|
+
"\u4F7F\u7528 Grok Build \u7684\u9ED8\u8BA4\u4EA4\u4E92\u5F0F\u6279\u51C6\u7B56\u7565\u3002"
|
|
16614
|
+
],
|
|
16615
|
+
["Ask before protected tool actions.", "\u6267\u884C\u53D7\u4FDD\u62A4\u7684\u5DE5\u5177\u64CD\u4F5C\u524D\u8BE2\u95EE\u3002"],
|
|
16616
|
+
[
|
|
16617
|
+
"Let Grok Build decide which tool actions may run automatically.",
|
|
16618
|
+
"\u7531 Grok Build \u51B3\u5B9A\u54EA\u4E9B\u5DE5\u5177\u64CD\u4F5C\u53EF\u81EA\u52A8\u8FD0\u884C\u3002"
|
|
16619
|
+
],
|
|
16620
|
+
["Approve all tool actions without prompting.", "\u65E0\u9700\u63D0\u793A\u5373\u53EF\u6279\u51C6\u6240\u6709\u5DE5\u5177\u64CD\u4F5C\u3002"]
|
|
16621
|
+
]);
|
|
16622
|
+
function rendererHarnessMessages(locale) {
|
|
16623
|
+
return locale === "zh-CN" ? CHINESE_HARNESS_MESSAGES : ENGLISH_HARNESS_MESSAGES;
|
|
16624
|
+
}
|
|
16625
|
+
function rendererHarnessCommandPresentation(command, locale) {
|
|
16626
|
+
if (locale === "zh-CN" && command.invocation === "/compact") {
|
|
16627
|
+
return { label: "\u538B\u7F29\u4E0A\u4E0B\u6587", description: "\u538B\u7F29\u5F53\u524D\u5BF9\u8BDD\u4E0A\u4E0B\u6587" };
|
|
16628
|
+
}
|
|
16629
|
+
return {
|
|
16630
|
+
label: command.label,
|
|
16631
|
+
description: command.description ?? command.label
|
|
16632
|
+
};
|
|
16633
|
+
}
|
|
16634
|
+
function rendererPermissionModePresentation(mode, locale) {
|
|
16635
|
+
if (locale !== "zh-CN") return { label: mode.label, description: mode.description };
|
|
16636
|
+
return {
|
|
16637
|
+
label: CHINESE_PERMISSION_MODE_LABELS.get(mode.label) ?? mode.label,
|
|
16638
|
+
description: mode.description === void 0 ? void 0 : CHINESE_PERMISSION_MODE_DESCRIPTIONS.get(mode.description) ?? mode.description
|
|
16639
|
+
};
|
|
16640
|
+
}
|
|
16641
|
+
|
|
16561
16642
|
// src/renderer-permission-mode-picker.ts
|
|
16562
16643
|
var MENU_CLASSES2 = "fixed z-50 overflow-hidden rounded-lg bg-token-dropdown-background/95 text-token-foreground shadow-lg ring-[0.5px] ring-token-border backdrop-blur-xl";
|
|
16563
16644
|
var OPTION_CLASSES2 = "flex w-full cursor-interaction items-start gap-2 rounded-md px-2 py-2 text-left text-sm text-token-foreground outline-none enabled:hover:bg-token-list-hover-background enabled:active:bg-token-foreground/15 disabled:cursor-not-allowed disabled:opacity-40";
|
|
@@ -16584,13 +16665,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16584
16665
|
if (view.status === "unsupported") return true;
|
|
16585
16666
|
return (view.status === "ready" || view.status === "error") && selectedMode(view) !== void 0;
|
|
16586
16667
|
}
|
|
16587
|
-
function rendererPermissionModeLabel(view) {
|
|
16668
|
+
function rendererPermissionModeLabel(view, locale = "en") {
|
|
16588
16669
|
const selected = selectedMode(view);
|
|
16589
|
-
if (selected) return selected.label;
|
|
16590
|
-
|
|
16591
|
-
if (view.status === "
|
|
16592
|
-
if (view.status === "
|
|
16593
|
-
|
|
16670
|
+
if (selected) return rendererPermissionModePresentation(selected, locale).label;
|
|
16671
|
+
const messages = rendererHarnessMessages(locale);
|
|
16672
|
+
if (view.status === "loading") return messages.loadingPermissions;
|
|
16673
|
+
if (view.status === "selecting") return messages.selecting;
|
|
16674
|
+
if (view.status === "error") return messages.permissionsUnavailable;
|
|
16675
|
+
return messages.permissions;
|
|
16594
16676
|
}
|
|
16595
16677
|
function positionMenu(control) {
|
|
16596
16678
|
const rect = control.trigger.getBoundingClientRect();
|
|
@@ -16605,7 +16687,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16605
16687
|
control.trigger.style.maxWidth = "min(220px, 34vw)";
|
|
16606
16688
|
control.trigger.style.letterSpacing = "0";
|
|
16607
16689
|
}
|
|
16608
|
-
function mountRendererPermissionModePicker(composerId, onSelect) {
|
|
16690
|
+
function mountRendererPermissionModePicker(composerId, onSelect, locale = "en") {
|
|
16609
16691
|
ensureRendererTriggerChipStyle(document);
|
|
16610
16692
|
const root = document.createElement("div");
|
|
16611
16693
|
root.setAttribute("data-codexhost-permission-mode-control", composerId);
|
|
@@ -16637,7 +16719,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16637
16719
|
const menu = document.createElement("div");
|
|
16638
16720
|
menu.id = `${composerId}-permission-mode-menu`;
|
|
16639
16721
|
menu.setAttribute("role", "menu");
|
|
16640
|
-
menu.setAttribute("aria-label",
|
|
16722
|
+
menu.setAttribute("aria-label", rendererHarnessMessages(locale).permissionMode);
|
|
16641
16723
|
menu.setAttribute("popover", "auto");
|
|
16642
16724
|
menu.hidden = typeof menu.showPopover !== "function";
|
|
16643
16725
|
menu.className = MENU_CLASSES2;
|
|
@@ -16727,6 +16809,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16727
16809
|
label,
|
|
16728
16810
|
menu,
|
|
16729
16811
|
options,
|
|
16812
|
+
locale,
|
|
16730
16813
|
close,
|
|
16731
16814
|
dispose() {
|
|
16732
16815
|
close();
|
|
@@ -16743,10 +16826,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16743
16826
|
syncRendererPermissionModeTriggerClass(control);
|
|
16744
16827
|
return control;
|
|
16745
16828
|
}
|
|
16746
|
-
function rebuildOptions2(control, catalog) {
|
|
16829
|
+
function rebuildOptions2(control, catalog, locale) {
|
|
16747
16830
|
control.options.clear();
|
|
16748
16831
|
control.menu.replaceChildren();
|
|
16749
16832
|
for (const mode of catalog.modes) {
|
|
16833
|
+
const presentation = rendererPermissionModePresentation(mode, locale);
|
|
16750
16834
|
const button = document.createElement("button");
|
|
16751
16835
|
button.type = "button";
|
|
16752
16836
|
button.dataset.permissionModeId = mode.id;
|
|
@@ -16760,13 +16844,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16760
16844
|
const copy = document.createElement("span");
|
|
16761
16845
|
copy.className = "min-w-0 flex-1";
|
|
16762
16846
|
const title = document.createElement("span");
|
|
16763
|
-
title.textContent =
|
|
16847
|
+
title.textContent = presentation.label;
|
|
16764
16848
|
title.className = "block font-medium";
|
|
16765
16849
|
title.style.letterSpacing = "0";
|
|
16766
16850
|
copy.append(title);
|
|
16767
|
-
if (
|
|
16851
|
+
if (presentation.description) {
|
|
16768
16852
|
const description = document.createElement("span");
|
|
16769
|
-
description.textContent =
|
|
16853
|
+
description.textContent = presentation.description;
|
|
16770
16854
|
description.className = "mt-0.5 block text-xs text-token-text-tertiary";
|
|
16771
16855
|
description.style.lineHeight = "16px";
|
|
16772
16856
|
description.style.letterSpacing = "0";
|
|
@@ -16781,7 +16865,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16781
16865
|
control.menu.append(button);
|
|
16782
16866
|
}
|
|
16783
16867
|
}
|
|
16784
|
-
function renderRendererPermissionModePicker(control, view, visible) {
|
|
16868
|
+
function renderRendererPermissionModePicker(control, view, visible, locale = control.locale) {
|
|
16869
|
+
control.locale = locale;
|
|
16870
|
+
const messages = rendererHarnessMessages(locale);
|
|
16871
|
+
control.menu.setAttribute("aria-label", messages.permissionMode);
|
|
16785
16872
|
control.root.style.display = visible ? "inline-flex" : "none";
|
|
16786
16873
|
control.root.style.alignItems = "center";
|
|
16787
16874
|
control.root.style.alignSelf = "center";
|
|
@@ -16792,15 +16879,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16792
16879
|
control.close();
|
|
16793
16880
|
return;
|
|
16794
16881
|
}
|
|
16795
|
-
const signature = JSON.stringify(view.catalog)
|
|
16882
|
+
const signature = `${locale}:${JSON.stringify(view.catalog)}`;
|
|
16796
16883
|
if (view.catalog && control.root.dataset.catalogSignature !== signature) {
|
|
16797
|
-
rebuildOptions2(control, view.catalog);
|
|
16884
|
+
rebuildOptions2(control, view.catalog, locale);
|
|
16798
16885
|
control.root.dataset.catalogSignature = signature;
|
|
16799
16886
|
}
|
|
16800
|
-
const label = rendererPermissionModeLabel(view);
|
|
16887
|
+
const label = rendererPermissionModeLabel(view, locale);
|
|
16801
16888
|
if (control.label.textContent !== label) control.label.textContent = label;
|
|
16802
16889
|
control.trigger.title = view.error ? `${label}: ${view.error}` : label;
|
|
16803
|
-
control.trigger.setAttribute("aria-label",
|
|
16890
|
+
control.trigger.setAttribute("aria-label", `${messages.permissionMode}: ${label}`);
|
|
16804
16891
|
control.trigger.disabled = view.status === "loading" || view.status === "selecting" || view.catalog === void 0;
|
|
16805
16892
|
control.trigger.setAttribute("aria-busy", String(view.status === "selecting"));
|
|
16806
16893
|
if (control.trigger.disabled) control.close();
|
|
@@ -16813,6 +16900,51 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16813
16900
|
}
|
|
16814
16901
|
|
|
16815
16902
|
// src/renderer-usage-control.ts
|
|
16903
|
+
var ENGLISH_USAGE_MESSAGES = Object.freeze({
|
|
16904
|
+
usage: "Usage",
|
|
16905
|
+
context: "Context",
|
|
16906
|
+
latestCacheHit: "Latest cache hit",
|
|
16907
|
+
outputSpeed: "Output speed",
|
|
16908
|
+
cacheRead: "Cache read",
|
|
16909
|
+
cacheWrite: "Cache write",
|
|
16910
|
+
reasoning: "Reasoning",
|
|
16911
|
+
totalTokens: "Total tokens",
|
|
16912
|
+
inputOutput: "Input / output",
|
|
16913
|
+
fiveHourLimit: "5-hour limit",
|
|
16914
|
+
sevenDayLimit: "7-day limit",
|
|
16915
|
+
sessionCostEstimate: "Session cost estimate",
|
|
16916
|
+
threadUsage: "Thread Usage",
|
|
16917
|
+
threadUsageDetails: "Thread Usage details",
|
|
16918
|
+
contextSummary: "context",
|
|
16919
|
+
tokensSummary: "tokens",
|
|
16920
|
+
tokensPerSecond: "tok/s",
|
|
16921
|
+
fiveHourSummary: "5h",
|
|
16922
|
+
sevenDaySummary: "7d"
|
|
16923
|
+
});
|
|
16924
|
+
var CHINESE_USAGE_MESSAGES = Object.freeze({
|
|
16925
|
+
usage: "\u7528\u91CF",
|
|
16926
|
+
context: "\u4E0A\u4E0B\u6587",
|
|
16927
|
+
latestCacheHit: "\u6700\u8FD1\u7F13\u5B58\u547D\u4E2D\u7387",
|
|
16928
|
+
outputSpeed: "\u8F93\u51FA\u901F\u5EA6",
|
|
16929
|
+
cacheRead: "\u7F13\u5B58\u8BFB\u53D6",
|
|
16930
|
+
cacheWrite: "\u7F13\u5B58\u5199\u5165",
|
|
16931
|
+
reasoning: "\u63A8\u7406",
|
|
16932
|
+
totalTokens: "Token \u603B\u6570",
|
|
16933
|
+
inputOutput: "\u8F93\u5165 / \u8F93\u51FA",
|
|
16934
|
+
fiveHourLimit: "5 \u5C0F\u65F6\u9650\u989D",
|
|
16935
|
+
sevenDayLimit: "7 \u5929\u9650\u989D",
|
|
16936
|
+
sessionCostEstimate: "\u4F1A\u8BDD\u8D39\u7528\u4F30\u7B97",
|
|
16937
|
+
threadUsage: "\u5BF9\u8BDD\u7528\u91CF",
|
|
16938
|
+
threadUsageDetails: "\u5BF9\u8BDD\u7528\u91CF\u8BE6\u60C5",
|
|
16939
|
+
contextSummary: "\u4E0A\u4E0B\u6587",
|
|
16940
|
+
tokensSummary: "Token",
|
|
16941
|
+
tokensPerSecond: "Token/\u79D2",
|
|
16942
|
+
fiveHourSummary: "5 \u5C0F\u65F6",
|
|
16943
|
+
sevenDaySummary: "7 \u5929"
|
|
16944
|
+
});
|
|
16945
|
+
function rendererUsageMessages(locale) {
|
|
16946
|
+
return locale === "zh-CN" ? CHINESE_USAGE_MESSAGES : ENGLISH_USAGE_MESSAGES;
|
|
16947
|
+
}
|
|
16816
16948
|
function decimal(value, fractionDigits) {
|
|
16817
16949
|
return value.toFixed(fractionDigits).replace(/\.?0+$/u, "");
|
|
16818
16950
|
}
|
|
@@ -16822,14 +16954,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16822
16954
|
function formatRendererCost(value) {
|
|
16823
16955
|
return `$${value.toFixed(3)}`;
|
|
16824
16956
|
}
|
|
16825
|
-
function formatRendererTokenRate(value) {
|
|
16826
|
-
return `${decimal(value, 1)}
|
|
16957
|
+
function formatRendererTokenRate(value, locale = "en") {
|
|
16958
|
+
return `${decimal(value, 1)} ${rendererUsageMessages(locale).tokensPerSecond}`;
|
|
16827
16959
|
}
|
|
16828
16960
|
function formatRendererTokenCount(value) {
|
|
16829
16961
|
const sign = value < 0 ? "-" : "";
|
|
16830
16962
|
const absolute = Math.abs(value);
|
|
16831
16963
|
if (absolute < 1e3) return `${sign}${Math.round(absolute)}`;
|
|
16832
|
-
return `${sign}${decimal(absolute / 1e3, 1)}k`;
|
|
16964
|
+
if (absolute < 1e6) return `${sign}${decimal(absolute / 1e3, 1)}k`;
|
|
16965
|
+
if (absolute < 1e9) return `${sign}${decimal(absolute / 1e6, 1)}M`;
|
|
16966
|
+
return `${sign}${decimal(absolute / 1e9, 1)}B`;
|
|
16833
16967
|
}
|
|
16834
16968
|
function formatRendererCreditsPercent(value) {
|
|
16835
16969
|
return `${decimal(value, 1)}%`;
|
|
@@ -16871,20 +17005,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16871
17005
|
svg.append(track, fill);
|
|
16872
17006
|
return svg;
|
|
16873
17007
|
}
|
|
16874
|
-
function formatRendererPlanReset(unixSeconds) {
|
|
17008
|
+
function formatRendererPlanReset(unixSeconds, locale) {
|
|
16875
17009
|
const date5 = new Date(unixSeconds * 1e3);
|
|
16876
17010
|
if (Number.isNaN(date5.getTime())) return "";
|
|
16877
|
-
return date5.toLocaleString(void 0, {
|
|
17011
|
+
return date5.toLocaleString(locale === "zh-CN" ? "zh-CN" : void 0, {
|
|
16878
17012
|
month: "long",
|
|
16879
17013
|
day: "numeric",
|
|
16880
17014
|
hour: "numeric",
|
|
16881
17015
|
minute: "2-digit"
|
|
16882
17016
|
});
|
|
16883
17017
|
}
|
|
16884
|
-
function formatRendererPlanWindow(usedPercent, resetsAtUnix) {
|
|
17018
|
+
function formatRendererPlanWindow(usedPercent, resetsAtUnix, locale) {
|
|
16885
17019
|
const percent = formatRendererCreditsPercent(usedPercent);
|
|
16886
17020
|
if (resetsAtUnix === void 0) return percent;
|
|
16887
|
-
const reset = formatRendererPlanReset(resetsAtUnix);
|
|
17021
|
+
const reset = formatRendererPlanReset(resetsAtUnix, locale);
|
|
16888
17022
|
return reset.length > 0 ? `${percent} \xB7 ${reset}` : percent;
|
|
16889
17023
|
}
|
|
16890
17024
|
function rendererUsageTriggerMaxWidth() {
|
|
@@ -16916,10 +17050,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16916
17050
|
row.append(labelElement, valueElement);
|
|
16917
17051
|
parent.append(row);
|
|
16918
17052
|
}
|
|
16919
|
-
function renderDetails(popover, usage) {
|
|
17053
|
+
function renderDetails(popover, usage, messages, locale) {
|
|
16920
17054
|
popover.replaceChildren();
|
|
16921
17055
|
const heading = document.createElement("div");
|
|
16922
|
-
heading.textContent =
|
|
17056
|
+
heading.textContent = messages.usage;
|
|
16923
17057
|
heading.style.fontWeight = "600";
|
|
16924
17058
|
heading.style.marginBottom = "6px";
|
|
16925
17059
|
popover.append(heading);
|
|
@@ -16927,55 +17061,75 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16927
17061
|
const contextPercent = usage.contextWindowTokens > 0 ? usage.contextUsedTokens / usage.contextWindowTokens * 100 : null;
|
|
16928
17062
|
addDetailRow(
|
|
16929
17063
|
popover,
|
|
16930
|
-
|
|
17064
|
+
messages.context,
|
|
16931
17065
|
contextPercent === null ? `/${formatRendererTokenCount(usage.contextWindowTokens)}` : `${decimal(contextPercent, 1)}% / ${formatRendererTokenCount(usage.contextWindowTokens)}`
|
|
16932
17066
|
);
|
|
16933
17067
|
}
|
|
16934
17068
|
if (usage?.cacheHitRatePercent !== void 0) {
|
|
16935
17069
|
addDetailRow(
|
|
16936
17070
|
popover,
|
|
16937
|
-
|
|
17071
|
+
messages.latestCacheHit,
|
|
16938
17072
|
formatRendererCacheHitRate(usage.cacheHitRatePercent)
|
|
16939
17073
|
);
|
|
16940
17074
|
}
|
|
16941
17075
|
if (usage?.outputTokensPerSecond !== void 0) {
|
|
16942
|
-
addDetailRow(
|
|
17076
|
+
addDetailRow(
|
|
17077
|
+
popover,
|
|
17078
|
+
messages.outputSpeed,
|
|
17079
|
+
formatRendererTokenRate(usage.outputTokensPerSecond, locale)
|
|
17080
|
+
);
|
|
16943
17081
|
}
|
|
16944
17082
|
if (usage?.cachedInputTokens !== void 0) {
|
|
16945
|
-
addDetailRow(popover,
|
|
17083
|
+
addDetailRow(popover, messages.cacheRead, formatRendererTokenCount(usage.cachedInputTokens));
|
|
16946
17084
|
}
|
|
16947
17085
|
if (usage?.cacheWriteInputTokens !== void 0) {
|
|
16948
|
-
addDetailRow(
|
|
17086
|
+
addDetailRow(
|
|
17087
|
+
popover,
|
|
17088
|
+
messages.cacheWrite,
|
|
17089
|
+
formatRendererTokenCount(usage.cacheWriteInputTokens)
|
|
17090
|
+
);
|
|
16949
17091
|
}
|
|
16950
17092
|
if (usage?.reasoningOutputTokens !== void 0) {
|
|
16951
|
-
addDetailRow(
|
|
17093
|
+
addDetailRow(
|
|
17094
|
+
popover,
|
|
17095
|
+
messages.reasoning,
|
|
17096
|
+
formatRendererTokenCount(usage.reasoningOutputTokens)
|
|
17097
|
+
);
|
|
16952
17098
|
}
|
|
16953
17099
|
if (usage?.totalTokens !== void 0) {
|
|
16954
|
-
addDetailRow(popover,
|
|
17100
|
+
addDetailRow(popover, messages.totalTokens, formatRendererTokenCount(usage.totalTokens));
|
|
16955
17101
|
}
|
|
16956
17102
|
if (usage?.inputTokens !== void 0 || usage?.outputTokens !== void 0) {
|
|
16957
17103
|
addDetailRow(
|
|
16958
17104
|
popover,
|
|
16959
|
-
|
|
17105
|
+
messages.inputOutput,
|
|
16960
17106
|
`${formatRendererTokenCount(usage.inputTokens ?? 0)} / ${formatRendererTokenCount(usage.outputTokens ?? 0)}`
|
|
16961
17107
|
);
|
|
16962
17108
|
}
|
|
16963
17109
|
if (usage?.planFiveHourUsedPercent !== void 0) {
|
|
16964
17110
|
addDetailRow(
|
|
16965
17111
|
popover,
|
|
16966
|
-
|
|
16967
|
-
formatRendererPlanWindow(
|
|
17112
|
+
messages.fiveHourLimit,
|
|
17113
|
+
formatRendererPlanWindow(
|
|
17114
|
+
usage.planFiveHourUsedPercent,
|
|
17115
|
+
usage.planFiveHourResetsAtUnix,
|
|
17116
|
+
locale
|
|
17117
|
+
)
|
|
16968
17118
|
);
|
|
16969
17119
|
}
|
|
16970
17120
|
if (usage?.planSevenDayUsedPercent !== void 0) {
|
|
16971
17121
|
addDetailRow(
|
|
16972
17122
|
popover,
|
|
16973
|
-
|
|
16974
|
-
formatRendererPlanWindow(
|
|
17123
|
+
messages.sevenDayLimit,
|
|
17124
|
+
formatRendererPlanWindow(
|
|
17125
|
+
usage.planSevenDayUsedPercent,
|
|
17126
|
+
usage.planSevenDayResetsAtUnix,
|
|
17127
|
+
locale
|
|
17128
|
+
)
|
|
16975
17129
|
);
|
|
16976
17130
|
}
|
|
16977
17131
|
if (usage?.totalCostUsd !== void 0) {
|
|
16978
|
-
addDetailRow(popover,
|
|
17132
|
+
addDetailRow(popover, messages.sessionCostEstimate, formatRendererCost(usage.totalCostUsd));
|
|
16979
17133
|
}
|
|
16980
17134
|
}
|
|
16981
17135
|
function popoverIsOpen(popover) {
|
|
@@ -17003,19 +17157,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17003
17157
|
control.trigger.setAttribute("aria-expanded", "false");
|
|
17004
17158
|
}
|
|
17005
17159
|
function openPopover(control) {
|
|
17160
|
+
const wasOpen = control.trigger.getAttribute("aria-expanded") === "true";
|
|
17006
17161
|
positionPopover(control);
|
|
17007
17162
|
control.popover.hidden = false;
|
|
17008
17163
|
if (typeof control.popover.showPopover === "function" && !popoverIsOpen(control.popover)) {
|
|
17009
17164
|
control.popover.showPopover();
|
|
17010
17165
|
}
|
|
17011
17166
|
control.trigger.setAttribute("aria-expanded", "true");
|
|
17167
|
+
if (!wasOpen) control.onOpen?.();
|
|
17012
17168
|
}
|
|
17013
17169
|
function togglePopover(control) {
|
|
17014
17170
|
if (control.trigger.getAttribute("aria-expanded") === "true") closePopover(control);
|
|
17015
17171
|
else openPopover(control);
|
|
17016
17172
|
}
|
|
17017
|
-
function mountRendererUsageControl(composerId) {
|
|
17173
|
+
function mountRendererUsageControl(composerId, locale = "en") {
|
|
17018
17174
|
ensureRendererTriggerChipStyle(document);
|
|
17175
|
+
const messages = rendererUsageMessages(locale);
|
|
17019
17176
|
const root = document.createElement("div");
|
|
17020
17177
|
root.dataset.codexhostUsageControl = composerId;
|
|
17021
17178
|
root.className = "relative min-w-0";
|
|
@@ -17030,8 +17187,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17030
17187
|
trigger.type = "button";
|
|
17031
17188
|
trigger.setAttribute("aria-haspopup", "dialog");
|
|
17032
17189
|
trigger.setAttribute("aria-expanded", "false");
|
|
17033
|
-
trigger.setAttribute("aria-label",
|
|
17034
|
-
trigger.title =
|
|
17190
|
+
trigger.setAttribute("aria-label", messages.threadUsage);
|
|
17191
|
+
trigger.title = messages.threadUsage;
|
|
17035
17192
|
trigger.style.color = "var(--color-text-tertiary, #8f8f8f)";
|
|
17036
17193
|
trigger.style.gap = "4px";
|
|
17037
17194
|
trigger.style.width = "fit-content";
|
|
@@ -17053,7 +17210,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17053
17210
|
const popover = document.createElement("div");
|
|
17054
17211
|
popover.id = `${composerId}-usage-popover`;
|
|
17055
17212
|
popover.setAttribute("role", "dialog");
|
|
17056
|
-
popover.setAttribute("aria-label",
|
|
17213
|
+
popover.setAttribute("aria-label", messages.threadUsageDetails);
|
|
17057
17214
|
popover.setAttribute("popover", "auto");
|
|
17058
17215
|
popover.hidden = typeof popover.showPopover !== "function";
|
|
17059
17216
|
popover.style.position = "fixed";
|
|
@@ -17073,6 +17230,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17073
17230
|
popover,
|
|
17074
17231
|
anchor: null,
|
|
17075
17232
|
label,
|
|
17233
|
+
locale,
|
|
17234
|
+
onOpen: null,
|
|
17076
17235
|
dispose() {
|
|
17077
17236
|
closePopover(control);
|
|
17078
17237
|
if (closeTimer !== null) window.clearTimeout(closeTimer);
|
|
@@ -17126,7 +17285,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17126
17285
|
document.body.append(popover);
|
|
17127
17286
|
return control;
|
|
17128
17287
|
}
|
|
17129
|
-
function renderRendererUsageControl(control, usage) {
|
|
17288
|
+
function renderRendererUsageControl(control, usage, locale = control.locale) {
|
|
17289
|
+
control.locale = locale;
|
|
17290
|
+
const messages = rendererUsageMessages(locale);
|
|
17291
|
+
control.popover.setAttribute("aria-label", messages.threadUsageDetails);
|
|
17130
17292
|
const cacheHitRatePercent = usage?.cacheHitRatePercent;
|
|
17131
17293
|
const outputTokensPerSecond = usage?.outputTokensPerSecond;
|
|
17132
17294
|
const totalCostUsd = usage?.totalCostUsd;
|
|
@@ -17141,34 +17303,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17141
17303
|
}
|
|
17142
17304
|
const summary = [
|
|
17143
17305
|
cacheHitRatePercent !== void 0 ? formatRendererCacheHitRate(cacheHitRatePercent) : null,
|
|
17144
|
-
outputTokensPerSecond !== void 0 ? formatRendererTokenRate(outputTokensPerSecond) : null,
|
|
17306
|
+
outputTokensPerSecond !== void 0 ? formatRendererTokenRate(outputTokensPerSecond, locale) : null,
|
|
17145
17307
|
totalCostUsd !== void 0 ? formatRendererCost(totalCostUsd) : null
|
|
17146
17308
|
].filter((value) => value !== null);
|
|
17147
17309
|
if (summary.length === 0 && hasContext && usage?.contextWindowTokens !== void 0 && usage.contextWindowTokens > 0) {
|
|
17148
17310
|
summary.push(
|
|
17149
|
-
`${decimal((usage.contextUsedTokens ?? 0) / usage.contextWindowTokens * 100, 1)}%
|
|
17311
|
+
`${decimal((usage.contextUsedTokens ?? 0) / usage.contextWindowTokens * 100, 1)}% ${messages.contextSummary}`
|
|
17150
17312
|
);
|
|
17151
17313
|
}
|
|
17152
17314
|
if (summary.length === 0 && usage?.totalTokens !== void 0) {
|
|
17153
|
-
summary.push(`${formatRendererTokenCount(usage.totalTokens)}
|
|
17315
|
+
summary.push(`${formatRendererTokenCount(usage.totalTokens)} ${messages.tokensSummary}`);
|
|
17154
17316
|
}
|
|
17155
17317
|
if (summary.length === 0 && hasTokenUsage) {
|
|
17156
17318
|
summary.push(
|
|
17157
|
-
`${formatRendererTokenCount((usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0))}
|
|
17319
|
+
`${formatRendererTokenCount((usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0))} ${messages.tokensSummary}`
|
|
17158
17320
|
);
|
|
17159
17321
|
}
|
|
17160
17322
|
if (summary.length === 0 && hasPlanLimit) {
|
|
17161
17323
|
summary.push(
|
|
17162
|
-
usage?.planFiveHourUsedPercent !== void 0 ?
|
|
17324
|
+
usage?.planFiveHourUsedPercent !== void 0 ? `${messages.fiveHourSummary} ${formatRendererCreditsPercent(usage.planFiveHourUsedPercent)}` : `${messages.sevenDaySummary} ${formatRendererCreditsPercent(usage?.planSevenDayUsedPercent ?? 0)}`
|
|
17163
17325
|
);
|
|
17164
17326
|
}
|
|
17165
17327
|
const compactSummary = summary.join(" \xB7 ");
|
|
17166
|
-
const accessibleSummary =
|
|
17328
|
+
const accessibleSummary = `${messages.threadUsage}: ${compactSummary}`;
|
|
17167
17329
|
control.trigger.style.maxWidth = rendererUsageTriggerMaxWidth();
|
|
17168
17330
|
control.trigger.setAttribute("aria-label", accessibleSummary);
|
|
17169
17331
|
control.trigger.title = accessibleSummary;
|
|
17170
17332
|
control.label.textContent = compactSummary;
|
|
17171
|
-
renderDetails(control.popover, usage);
|
|
17333
|
+
renderDetails(control.popover, usage, messages, locale);
|
|
17172
17334
|
return true;
|
|
17173
17335
|
}
|
|
17174
17336
|
|
|
@@ -17507,12 +17669,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17507
17669
|
}
|
|
17508
17670
|
return svg;
|
|
17509
17671
|
}
|
|
17510
|
-
function menuItem(ownerDocument, command, onSelect) {
|
|
17672
|
+
function menuItem(ownerDocument, command, locale, messages, onSelect) {
|
|
17673
|
+
const presentation = rendererHarnessCommandPresentation(command, locale);
|
|
17511
17674
|
const item = ownerDocument.createElement("button");
|
|
17512
17675
|
item.type = "button";
|
|
17513
17676
|
item.setAttribute("role", "menuitem");
|
|
17514
17677
|
item.setAttribute("data-command-id", command.id);
|
|
17515
|
-
item.setAttribute("aria-label", `${command.invocation} ${
|
|
17678
|
+
item.setAttribute("aria-label", `${command.invocation} ${presentation.label}`);
|
|
17516
17679
|
item.style.display = "flex";
|
|
17517
17680
|
item.style.alignItems = "center";
|
|
17518
17681
|
item.style.width = "100%";
|
|
@@ -17543,14 +17706,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17543
17706
|
title.style.font = "600 13px/18px system-ui, sans-serif";
|
|
17544
17707
|
title.style.whiteSpace = "nowrap";
|
|
17545
17708
|
const description = ownerDocument.createElement("span");
|
|
17546
|
-
description.textContent =
|
|
17709
|
+
description.textContent = presentation.description;
|
|
17547
17710
|
description.style.overflow = "hidden";
|
|
17548
17711
|
description.style.color = "rgba(127, 127, 127, 0.9)";
|
|
17549
17712
|
description.style.font = "400 11px/16px system-ui, sans-serif";
|
|
17550
17713
|
description.style.textOverflow = "ellipsis";
|
|
17551
17714
|
description.style.whiteSpace = "nowrap";
|
|
17552
17715
|
const hint = ownerDocument.createElement("span");
|
|
17553
|
-
hint.textContent = command.argumentMode === "text" ?
|
|
17716
|
+
hint.textContent = command.argumentMode === "text" ? messages.textArgument : "\u21B5";
|
|
17554
17717
|
hint.style.flex = "0 0 auto";
|
|
17555
17718
|
hint.style.color = "rgba(127, 127, 127, 0.75)";
|
|
17556
17719
|
hint.style.font = "400 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace";
|
|
@@ -17576,8 +17739,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17576
17739
|
button.style.cursor = "pointer";
|
|
17577
17740
|
button.style.whiteSpace = "nowrap";
|
|
17578
17741
|
}
|
|
17579
|
-
function mountRendererHarnessCommandControl(parent, insertBefore, onCommandSelected) {
|
|
17742
|
+
function mountRendererHarnessCommandControl(parent, insertBefore, onCommandSelected, initialLocale = "en") {
|
|
17580
17743
|
const ownerDocument = parent.ownerDocument;
|
|
17744
|
+
let locale = initialLocale;
|
|
17745
|
+
let messages = rendererHarnessMessages(locale);
|
|
17581
17746
|
const root = ownerDocument.createElement("div");
|
|
17582
17747
|
root.setAttribute(CONTROL_ATTRIBUTE2, "true");
|
|
17583
17748
|
root.style.display = "inline-flex";
|
|
@@ -17587,15 +17752,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17587
17752
|
trigger.type = "button";
|
|
17588
17753
|
trigger.setAttribute("aria-haspopup", "menu");
|
|
17589
17754
|
trigger.setAttribute("aria-expanded", "false");
|
|
17590
|
-
trigger.setAttribute("aria-label",
|
|
17591
|
-
trigger.title =
|
|
17755
|
+
trigger.setAttribute("aria-label", messages.harnessCommands);
|
|
17756
|
+
trigger.title = messages.harnessCommands;
|
|
17592
17757
|
setButtonClass(trigger);
|
|
17593
17758
|
trigger.append(commandIcon(ownerDocument));
|
|
17594
17759
|
root.append(trigger);
|
|
17595
17760
|
const menu = ownerDocument.createElement("div");
|
|
17596
17761
|
menu.setAttribute(MENU_ATTRIBUTE, "true");
|
|
17597
17762
|
menu.setAttribute("role", "menu");
|
|
17598
|
-
menu.setAttribute("aria-label",
|
|
17763
|
+
menu.setAttribute("aria-label", messages.harnessCommands);
|
|
17599
17764
|
menu.hidden = true;
|
|
17600
17765
|
menu.style.position = "fixed";
|
|
17601
17766
|
menu.style.inset = "auto";
|
|
@@ -17673,12 +17838,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17673
17838
|
const renderItems = () => {
|
|
17674
17839
|
menu.replaceChildren();
|
|
17675
17840
|
const header = ownerDocument.createElement("div");
|
|
17676
|
-
header.textContent =
|
|
17841
|
+
header.textContent = messages.commands;
|
|
17677
17842
|
header.style.padding = "5px 8px 4px";
|
|
17678
17843
|
header.style.color = "rgba(127, 127, 127, 0.75)";
|
|
17679
17844
|
header.style.font = "600 11px/16px system-ui, sans-serif";
|
|
17680
17845
|
menu.append(header);
|
|
17681
|
-
items = commands.map(
|
|
17846
|
+
items = commands.map(
|
|
17847
|
+
(command) => menuItem(ownerDocument, command, locale, messages, () => select(command))
|
|
17848
|
+
);
|
|
17682
17849
|
menu.append(...items);
|
|
17683
17850
|
activeIndex = Math.min(activeIndex, Math.max(0, items.length - 1));
|
|
17684
17851
|
if (executingCommandId !== null) {
|
|
@@ -17776,6 +17943,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17776
17943
|
trigger.style.opacity = commandId !== null ? "0.65" : "1";
|
|
17777
17944
|
syncTriggerBackground();
|
|
17778
17945
|
},
|
|
17946
|
+
setLocale(nextLocale) {
|
|
17947
|
+
if (locale === nextLocale) return;
|
|
17948
|
+
locale = nextLocale;
|
|
17949
|
+
messages = rendererHarnessMessages(locale);
|
|
17950
|
+
trigger.setAttribute("aria-label", messages.harnessCommands);
|
|
17951
|
+
trigger.title = messages.harnessCommands;
|
|
17952
|
+
menu.setAttribute("aria-label", messages.harnessCommands);
|
|
17953
|
+
renderItems();
|
|
17954
|
+
},
|
|
17779
17955
|
close,
|
|
17780
17956
|
dispose() {
|
|
17781
17957
|
if (disposed) return;
|
|
@@ -18134,9 +18310,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18134
18310
|
refreshCreditsPlacement(control);
|
|
18135
18311
|
return control;
|
|
18136
18312
|
}
|
|
18137
|
-
function renderComposerAgentControl(control, state, adapterState, switching, availability = {}, modelView = { status: "idle" }, permissionModeView = { status: "idle" }, usage = null, accountCredits = null) {
|
|
18313
|
+
function renderComposerAgentControl(control, state, adapterState, switching, availability = {}, modelView = { status: "idle" }, permissionModeView = { status: "idle" }, usage = null, accountCredits = null, locale = "en") {
|
|
18138
18314
|
if (control.usage === null) {
|
|
18139
|
-
control.usage = mountRendererUsageControl(control.composerId);
|
|
18315
|
+
control.usage = mountRendererUsageControl(control.composerId, locale);
|
|
18140
18316
|
}
|
|
18141
18317
|
const selectedModel = modelView.selected;
|
|
18142
18318
|
const selectedCatalogModel = modelView.catalog?.models.find(
|
|
@@ -18172,9 +18348,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18172
18348
|
renderRendererPermissionModePicker(
|
|
18173
18349
|
control.permissionModePicker,
|
|
18174
18350
|
permissionModeView,
|
|
18175
|
-
permissionModeVisible
|
|
18351
|
+
permissionModeVisible,
|
|
18352
|
+
locale
|
|
18176
18353
|
);
|
|
18177
|
-
if (control.usage) renderRendererUsageControl(control.usage, usage);
|
|
18354
|
+
if (control.usage) renderRendererUsageControl(control.usage, usage, locale);
|
|
18355
|
+
control.harnessCommands.setLocale(locale);
|
|
18178
18356
|
renderRendererCreditsControl(control.credits, accountCredits);
|
|
18179
18357
|
}
|
|
18180
18358
|
function disposeComposerAgentControl(control) {
|
|
@@ -18675,7 +18853,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18675
18853
|
const parsed = hostThreadIdSchema.safeParse(params.threadId);
|
|
18676
18854
|
return parsed.success ? parsed.data : null;
|
|
18677
18855
|
}
|
|
18678
|
-
function
|
|
18856
|
+
function notificationTarget(manager) {
|
|
18679
18857
|
if (typeof manager.addNotificationCallback === "function") return manager;
|
|
18680
18858
|
const nested = manager.requestClient;
|
|
18681
18859
|
return nested && typeof nested.addNotificationCallback === "function" ? nested : null;
|
|
@@ -18776,7 +18954,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18776
18954
|
},
|
|
18777
18955
|
inspectThreadUsage,
|
|
18778
18956
|
subscribeThreadUsage(listener) {
|
|
18779
|
-
const notifications =
|
|
18957
|
+
const notifications = notificationTarget(manager);
|
|
18780
18958
|
if (!notifications?.addNotificationCallback) {
|
|
18781
18959
|
throw new Error("Renderer Usage notification callback is unavailable");
|
|
18782
18960
|
}
|
|
@@ -18952,19 +19130,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18952
19130
|
...thinking?.success ? { thinkingOptionId: thinking.data } : {}
|
|
18953
19131
|
};
|
|
18954
19132
|
}
|
|
18955
|
-
function deepSeekHarnessTransportModelId(model) {
|
|
18956
|
-
if (!model)
|
|
18957
|
-
|
|
19133
|
+
function deepSeekHarnessTransportModelId(model, permissionModeId) {
|
|
19134
|
+
if (!model) {
|
|
19135
|
+
if (permissionModeId) {
|
|
19136
|
+
throw new Error("DeepSeek Harness transport Permission Mode requires a Model Ref");
|
|
19137
|
+
}
|
|
19138
|
+
return DEEPSEEK_HARNESS_TRANSPORT_MODEL_ID;
|
|
19139
|
+
}
|
|
19140
|
+
const parsedPermissionModeId = permissionModeId ? harnessPermissionModeIdSchema.parse(permissionModeId) : void 0;
|
|
19141
|
+
return `${DEEPSEEK_HARNESS_TRANSPORT_MODEL_PREFIX}${harnessModelRefSchema.parse(model).id}${parsedPermissionModeId ? `@${parsedPermissionModeId}` : ""}`;
|
|
18958
19142
|
}
|
|
18959
19143
|
function decodeDeepSeekHarnessTransportModelId(value) {
|
|
18960
19144
|
if (value === DEEPSEEK_HARNESS_TRANSPORT_MODEL_ID) return {};
|
|
18961
19145
|
if (typeof value !== "string" || !value.startsWith(DEEPSEEK_HARNESS_TRANSPORT_MODEL_PREFIX)) {
|
|
18962
19146
|
return null;
|
|
18963
19147
|
}
|
|
18964
|
-
const
|
|
18965
|
-
|
|
18966
|
-
|
|
18967
|
-
|
|
19148
|
+
const components = value.slice(DEEPSEEK_HARNESS_TRANSPORT_MODEL_PREFIX.length).split("@");
|
|
19149
|
+
if (components.length < 1 || components.length > 2) return null;
|
|
19150
|
+
const [modelId, permissionModeId] = components;
|
|
19151
|
+
if (components.length === 2 && !permissionModeId) return null;
|
|
19152
|
+
const model = harnessModelRefSchema.safeParse({ id: modelId });
|
|
19153
|
+
if (!model.success) return null;
|
|
19154
|
+
const permissionMode = permissionModeId ? harnessPermissionModeIdSchema.safeParse(permissionModeId) : null;
|
|
19155
|
+
if (permissionMode && !permissionMode.success) return null;
|
|
19156
|
+
return {
|
|
19157
|
+
model: model.data,
|
|
19158
|
+
...permissionMode?.success ? { permissionModeId: permissionMode.data } : {}
|
|
19159
|
+
};
|
|
18968
19160
|
}
|
|
18969
19161
|
function decodePiTransportModelId(value) {
|
|
18970
19162
|
if (value === PI_TRANSPORT_MODEL_ID) return {};
|
|
@@ -19141,12 +19333,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19141
19333
|
const hostId = target.getHostId?.() ?? bridge.hostId;
|
|
19142
19334
|
return typeof hostId === "string" && hostId.length > 0 ? hostId : null;
|
|
19143
19335
|
}
|
|
19336
|
+
function isRendererRequestTarget(value) {
|
|
19337
|
+
if (!isRecord5(value) || typeof value.sendRequest !== "function") return false;
|
|
19338
|
+
return isCurrentRequestBridge(value.requestClient ?? value);
|
|
19339
|
+
}
|
|
19340
|
+
function hasPolicyRequestTarget(policy) {
|
|
19341
|
+
return "requestTarget" in policy;
|
|
19342
|
+
}
|
|
19343
|
+
function exactRendererRequestTarget(policy) {
|
|
19344
|
+
if (typeof policy.requestTarget !== "function") return null;
|
|
19345
|
+
try {
|
|
19346
|
+
const target = policy.requestTarget();
|
|
19347
|
+
if (!isRendererRequestTarget(target) || prewarmTargetHostId(target) !== policy.hostId) {
|
|
19348
|
+
return null;
|
|
19349
|
+
}
|
|
19350
|
+
return [target];
|
|
19351
|
+
} catch {
|
|
19352
|
+
return null;
|
|
19353
|
+
}
|
|
19354
|
+
}
|
|
19144
19355
|
function rendererRequestTargetsForHost(targets, hostId) {
|
|
19145
19356
|
const matching = targets.filter((target) => prewarmTargetHostId(target) === hostId);
|
|
19146
19357
|
return matching.length === 1 ? matching : null;
|
|
19147
19358
|
}
|
|
19148
19359
|
function activeRendererDraftPrewarmTargets(policy, targets) {
|
|
19149
19360
|
if (!isDraftPrewarmPolicyReady(policy)) return null;
|
|
19361
|
+
if (hasPolicyRequestTarget(policy)) return exactRendererRequestTarget(policy);
|
|
19150
19362
|
return rendererRequestTargetsForHost(targets, policy.hostId);
|
|
19151
19363
|
}
|
|
19152
19364
|
function resolveRendererRequestRoute(policy, discoveredTargets, previous) {
|
|
@@ -19154,13 +19366,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19154
19366
|
if (isDraftPrewarmPolicyReady(policy) && activeTargets) {
|
|
19155
19367
|
return { policy, targets: activeTargets };
|
|
19156
19368
|
}
|
|
19369
|
+
if (isDraftPrewarmPolicyReady(policy) && hasPolicyRequestTarget(policy)) return null;
|
|
19157
19370
|
return discoveredTargets.length === 0 && isDraftPrewarmPolicyReady(policy) && previous?.policy === policy ? previous : null;
|
|
19158
19371
|
}
|
|
19159
19372
|
function createRendererRequestRouteResolver(readPolicy, discoverTargets) {
|
|
19160
19373
|
let route = null;
|
|
19161
19374
|
return {
|
|
19162
19375
|
resolve() {
|
|
19163
|
-
|
|
19376
|
+
const policy = readPolicy();
|
|
19377
|
+
const discoveredTargets = isDraftPrewarmPolicyReady(policy) && hasPolicyRequestTarget(policy) ? [] : discoverTargets();
|
|
19378
|
+
route = resolveRendererRequestRoute(policy, discoveredTargets, route);
|
|
19164
19379
|
return route;
|
|
19165
19380
|
},
|
|
19166
19381
|
clear() {
|
|
@@ -19181,7 +19396,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19181
19396
|
}
|
|
19182
19397
|
}
|
|
19183
19398
|
function modelSelectionForAgent(officialSelection, reasoningEffort, agent, model, thinkingOptionId, permissionModeId) {
|
|
19184
|
-
const transportModelId = agent === "pi" ? piTransportModelId(model, thinkingOptionId) : agent === "claude-code" ? claudeTransportModelId(model, permissionModeId, thinkingOptionId) : agent === "deepseek-harness" ? deepSeekHarnessTransportModelId(model) : agent === "grok" ? grokTransportModelId(model, permissionModeId, thinkingOptionId) : agent === "omp" ? ompTransportModelId(model, thinkingOptionId) : transportModelIdForAgent(agent);
|
|
19399
|
+
const transportModelId = agent === "pi" ? piTransportModelId(model, thinkingOptionId) : agent === "claude-code" ? claudeTransportModelId(model, permissionModeId, thinkingOptionId) : agent === "deepseek-harness" ? deepSeekHarnessTransportModelId(model, permissionModeId) : agent === "grok" ? grokTransportModelId(model, permissionModeId, thinkingOptionId) : agent === "omp" ? ompTransportModelId(model, thinkingOptionId) : transportModelIdForAgent(agent);
|
|
19185
19400
|
return transportModelId ? { model: transportModelId, reasoningEffort } : officialSelection;
|
|
19186
19401
|
}
|
|
19187
19402
|
function installCurrentRendererAdapter() {
|
|
@@ -19211,7 +19426,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19211
19426
|
() => window.__codexhostDraftPrewarmPolicyV1,
|
|
19212
19427
|
() => findActivePrewarmTargets(document)
|
|
19213
19428
|
);
|
|
19214
|
-
const currentRequestRoute = () => requestRouteResolver.resolve();
|
|
19215
19429
|
const clientsByTarget = /* @__PURE__ */ new WeakMap();
|
|
19216
19430
|
const modelClientForTargets = (targets) => {
|
|
19217
19431
|
const target = targets[0];
|
|
@@ -19222,8 +19436,23 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19222
19436
|
if (client) clientsByTarget.set(target, client);
|
|
19223
19437
|
return client;
|
|
19224
19438
|
};
|
|
19439
|
+
let activeRoutePolicy = null;
|
|
19440
|
+
let activeRouteClient = null;
|
|
19441
|
+
const syncActiveRoute = (route) => {
|
|
19442
|
+
const policy = route?.policy ?? null;
|
|
19443
|
+
const client = route ? modelClientForTargets(route.targets) : null;
|
|
19444
|
+
if (activeRoutePolicy === policy && activeRouteClient === client) return client;
|
|
19445
|
+
activeRoutePolicy = policy;
|
|
19446
|
+
activeRouteClient = client;
|
|
19447
|
+
return client;
|
|
19448
|
+
};
|
|
19449
|
+
const currentRequestRoute = () => {
|
|
19450
|
+
const route = requestRouteResolver.resolve();
|
|
19451
|
+
syncActiveRoute(route);
|
|
19452
|
+
return route;
|
|
19453
|
+
};
|
|
19225
19454
|
const currentModelClient = () => {
|
|
19226
|
-
const client =
|
|
19455
|
+
const client = currentRequestRoute() ? activeRouteClient : null;
|
|
19227
19456
|
if (!client) throw new Error("Renderer Model request manager is unavailable");
|
|
19228
19457
|
usageSubscription.connect(client);
|
|
19229
19458
|
return client;
|
|
@@ -19231,6 +19460,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19231
19460
|
const modelControl = Object.freeze({
|
|
19232
19461
|
currentHostId: () => currentRequestRoute()?.policy.hostId ?? null,
|
|
19233
19462
|
clientForHost(hostId) {
|
|
19463
|
+
const route = currentRequestRoute();
|
|
19464
|
+
if (route?.policy.hostId === hostId) return modelClientForTargets(route.targets);
|
|
19465
|
+
const policy = window.__codexhostDraftPrewarmPolicyV1;
|
|
19466
|
+
if (isDraftPrewarmPolicyReady(policy) && hasPolicyRequestTarget(policy)) return null;
|
|
19234
19467
|
const targets = rendererRequestTargetsForHost(findActivePrewarmTargets(document), hostId);
|
|
19235
19468
|
return modelClientForTargets(targets ?? []);
|
|
19236
19469
|
},
|
|
@@ -19264,25 +19497,76 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19264
19497
|
});
|
|
19265
19498
|
let routingPolicy = null;
|
|
19266
19499
|
let policyTimer = null;
|
|
19500
|
+
let policyRecaptureObserver = null;
|
|
19501
|
+
let hasCapturedRoutingPolicy = false;
|
|
19502
|
+
let selectedRoutingPolicy = null;
|
|
19503
|
+
let selectedCarrier = null;
|
|
19267
19504
|
let desiredCarrier = null;
|
|
19505
|
+
const stopPolicyCapture = () => {
|
|
19506
|
+
if (policyTimer === null) return;
|
|
19507
|
+
window.clearInterval(policyTimer);
|
|
19508
|
+
policyTimer = null;
|
|
19509
|
+
};
|
|
19510
|
+
const stopPolicyRecapture = () => {
|
|
19511
|
+
policyRecaptureObserver?.disconnect();
|
|
19512
|
+
policyRecaptureObserver = null;
|
|
19513
|
+
};
|
|
19268
19514
|
const captureRoutingPolicy = () => {
|
|
19269
19515
|
const route = currentRequestRoute();
|
|
19270
19516
|
if (!route) return false;
|
|
19271
19517
|
routingPolicy = route.policy;
|
|
19272
|
-
|
|
19273
|
-
if (
|
|
19274
|
-
|
|
19275
|
-
|
|
19518
|
+
stopPolicyRecapture();
|
|
19519
|
+
if (selectedRoutingPolicy !== routingPolicy || selectedCarrier !== desiredCarrier) {
|
|
19520
|
+
try {
|
|
19521
|
+
routingPolicy.select(desiredCarrier);
|
|
19522
|
+
} catch {
|
|
19523
|
+
updateStatus("installing", "draft-routing-policy-unavailable", null);
|
|
19524
|
+
return false;
|
|
19525
|
+
}
|
|
19526
|
+
selectedRoutingPolicy = routingPolicy;
|
|
19527
|
+
selectedCarrier = desiredCarrier;
|
|
19276
19528
|
}
|
|
19529
|
+
hasCapturedRoutingPolicy = true;
|
|
19530
|
+
stopPolicyCapture();
|
|
19277
19531
|
updateStatus("ready", "ready", "request-bridge");
|
|
19278
19532
|
return true;
|
|
19279
19533
|
};
|
|
19534
|
+
const startPolicyCapture = () => {
|
|
19535
|
+
stopPolicyCapture();
|
|
19536
|
+
policyTimer = window.setInterval(captureRoutingPolicy, DRAFT_PREWARM_POLICY_POLL_INTERVAL_MS);
|
|
19537
|
+
};
|
|
19538
|
+
const startPolicyRecapture = () => {
|
|
19539
|
+
stopPolicyRecapture();
|
|
19540
|
+
policyRecaptureObserver = new MutationObserver(() => {
|
|
19541
|
+
captureRoutingPolicy();
|
|
19542
|
+
});
|
|
19543
|
+
policyRecaptureObserver.observe(document.documentElement, {
|
|
19544
|
+
attributes: true,
|
|
19545
|
+
attributeFilter: ["hidden", "aria-hidden", "data-codex-composer-root"],
|
|
19546
|
+
characterData: true,
|
|
19547
|
+
childList: true,
|
|
19548
|
+
subtree: true
|
|
19549
|
+
});
|
|
19550
|
+
};
|
|
19280
19551
|
if (!captureRoutingPolicy()) {
|
|
19281
19552
|
updateStatus("installing", "draft-routing-policy-unavailable", null);
|
|
19282
|
-
|
|
19553
|
+
const policy = window.__codexhostDraftPrewarmPolicyV1;
|
|
19554
|
+
if (!isDraftPrewarmPolicyReady(policy) || !hasPolicyRequestTarget(policy)) {
|
|
19555
|
+
startPolicyCapture();
|
|
19556
|
+
}
|
|
19283
19557
|
}
|
|
19284
19558
|
const handleRoutingPolicyChange = () => {
|
|
19285
|
-
|
|
19559
|
+
stopPolicyRecapture();
|
|
19560
|
+
if (captureRoutingPolicy()) return;
|
|
19561
|
+
const policy = window.__codexhostDraftPrewarmPolicyV1;
|
|
19562
|
+
if (isDraftPrewarmPolicyReady(policy) && hasPolicyRequestTarget(policy)) {
|
|
19563
|
+
stopPolicyCapture();
|
|
19564
|
+
}
|
|
19565
|
+
if (!hasCapturedRoutingPolicy) return;
|
|
19566
|
+
updateStatus("installing", "draft-routing-policy-unavailable", null);
|
|
19567
|
+
if (isDraftPrewarmPolicyReady(policy) && !hasPolicyRequestTarget(policy)) {
|
|
19568
|
+
startPolicyRecapture();
|
|
19569
|
+
}
|
|
19286
19570
|
};
|
|
19287
19571
|
window.addEventListener("codexhost:draft-prewarm-policy-changed", handleRoutingPolicyChange);
|
|
19288
19572
|
const applyAgent = (agent, model, thinkingOptionId, permissionModeId) => {
|
|
@@ -19301,9 +19585,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19301
19585
|
const route = currentRequestRoute();
|
|
19302
19586
|
if (!route) return false;
|
|
19303
19587
|
routingPolicy = route.policy;
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
19588
|
+
try {
|
|
19589
|
+
if (route.policy.select(desiredCarrier)) {
|
|
19590
|
+
modelUpdates += 1;
|
|
19591
|
+
liveStatus.modelUpdates = modelUpdates;
|
|
19592
|
+
}
|
|
19593
|
+
selectedRoutingPolicy = route.policy;
|
|
19594
|
+
selectedCarrier = desiredCarrier;
|
|
19595
|
+
} catch {
|
|
19596
|
+
updateStatus("installing", "draft-routing-policy-unavailable", null);
|
|
19597
|
+
return false;
|
|
19307
19598
|
}
|
|
19308
19599
|
return true;
|
|
19309
19600
|
};
|
|
@@ -19314,16 +19605,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19314
19605
|
dispose() {
|
|
19315
19606
|
if (disposed) return;
|
|
19316
19607
|
disposed = true;
|
|
19317
|
-
|
|
19608
|
+
stopPolicyCapture();
|
|
19609
|
+
stopPolicyRecapture();
|
|
19318
19610
|
window.removeEventListener(
|
|
19319
19611
|
"codexhost:draft-prewarm-policy-changed",
|
|
19320
19612
|
handleRoutingPolicyChange
|
|
19321
19613
|
);
|
|
19322
|
-
routingPolicy
|
|
19614
|
+
const activeRoutingPolicy = routingPolicy;
|
|
19323
19615
|
routingPolicy = null;
|
|
19324
19616
|
requestRouteResolver.clear();
|
|
19325
|
-
|
|
19326
|
-
|
|
19617
|
+
const cleanups = [
|
|
19618
|
+
() => activeRoutingPolicy?.select(null),
|
|
19619
|
+
() => syncActiveRoute(null),
|
|
19620
|
+
() => forkControl.dispose(),
|
|
19621
|
+
() => usageSubscription.dispose()
|
|
19622
|
+
];
|
|
19623
|
+
for (const cleanup of cleanups) {
|
|
19624
|
+
try {
|
|
19625
|
+
cleanup();
|
|
19626
|
+
} catch {
|
|
19627
|
+
}
|
|
19628
|
+
}
|
|
19327
19629
|
}
|
|
19328
19630
|
};
|
|
19329
19631
|
}
|
|
@@ -19646,11 +19948,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19646
19948
|
close: "Close settings",
|
|
19647
19949
|
starOnGitHub: "Give us a Star~",
|
|
19648
19950
|
sectionsLabel: "Settings sections",
|
|
19951
|
+
generalSection: "General",
|
|
19952
|
+
otherSection: "Other",
|
|
19649
19953
|
pageUnavailable: "Page unavailable",
|
|
19650
19954
|
inDevelopment: "In development",
|
|
19651
19955
|
notAvailable: "Not available",
|
|
19652
19956
|
runtimeCapabilityNotInstalled: "This runtime capability is not installed yet.",
|
|
19653
|
-
connectionsDescription: "
|
|
19957
|
+
connectionsDescription: "View runtime status by Host. Select an item to inspect details or complete its setup.",
|
|
19654
19958
|
connectionAdapter: "Renderer adapter",
|
|
19655
19959
|
connectionHosts: "Hosts",
|
|
19656
19960
|
connectionLocalHost: "Local",
|
|
@@ -19659,9 +19963,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19659
19963
|
connectionReason: "Reason",
|
|
19660
19964
|
connectionRefresh: "Run connection diagnostics",
|
|
19661
19965
|
connectionRefreshing: "Running diagnostics...",
|
|
19662
|
-
|
|
19966
|
+
connectionViewError: "View error",
|
|
19663
19967
|
connectionCopyDetails: "Copy diagnostics",
|
|
19664
|
-
connectionCopyAll: "Copy all diagnostics",
|
|
19665
19968
|
connectionCopied: "Copied",
|
|
19666
19969
|
connectionCopyFailed: "Copy failed",
|
|
19667
19970
|
connectionErrorCode: "Error code",
|
|
@@ -19678,6 +19981,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19678
19981
|
connectionStatusError: "Error",
|
|
19679
19982
|
connectionStatusInstalling: "Installing",
|
|
19680
19983
|
connectionStatusUnsupported: "Unsupported",
|
|
19984
|
+
connectionComponent: "Component",
|
|
19985
|
+
connectionStatus: "Status",
|
|
19986
|
+
connectionHostsScrollLeft: "Show previous Hosts",
|
|
19987
|
+
connectionHostsScrollRight: "Show more Hosts",
|
|
19988
|
+
connectionOpenInstallation: "Open official installation page",
|
|
19989
|
+
connectionInstall: "Install",
|
|
19990
|
+
connectionInstallDescription: "This Harness was not detected. Follow its official installation guide, then return here and run the check again.",
|
|
19991
|
+
connectionErrorTitle: "Connection check failed",
|
|
19992
|
+
connectionErrorLog: "Error log",
|
|
19993
|
+
connectionOpenIssue: "Open GitHub Issue",
|
|
19994
|
+
connectionIssueDescription: "Copy the error log and include the Host and reproduction steps when reporting the issue.",
|
|
19995
|
+
connectionReadyDescription: "This component is available on the selected Host.",
|
|
19996
|
+
connectionUnavailableDescription: "This component is not currently available on the selected Host.",
|
|
19997
|
+
enabled: "Enabled",
|
|
19998
|
+
disabled: "Disabled",
|
|
19681
19999
|
openSettings: "Open codexhost settings",
|
|
19682
20000
|
settingsButtonTitle: "codexhost settings",
|
|
19683
20001
|
settingsUnavailableTitle: "codexhost settings unavailable",
|
|
@@ -19690,7 +20008,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19690
20008
|
updateLatestVersion: "Latest version",
|
|
19691
20009
|
updateUpToDate: "You are up to date.",
|
|
19692
20010
|
updateAvailable: "A new version is available.",
|
|
19693
|
-
|
|
20011
|
+
updateWindowsManualRequired: "Automatic updates are unavailable on Windows. Update manually below.",
|
|
20012
|
+
updateAndRestart: "Update",
|
|
19694
20013
|
updateChecking: "Checking for updates...",
|
|
19695
20014
|
updateDownloading: "Downloading update...",
|
|
19696
20015
|
updatePreparing: "Preparing update...",
|
|
@@ -19703,13 +20022,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19703
20022
|
updateFailed: "Update failed.",
|
|
19704
20023
|
updateRetry: "Retry",
|
|
19705
20024
|
updateManualNpmDescription: "To update manually, quit codexhost and run this command:",
|
|
20025
|
+
updateWindowsNpmDescription: "Automatic updates are unavailable on Windows. Quit codexhost and run this command in a terminal:",
|
|
20026
|
+
updateWindowsInstallerDescription: "Automatic updates are unavailable on Windows. Download and run the installer for this system.",
|
|
20027
|
+
updateManualTitle: "Manual update",
|
|
20028
|
+
updateManualFallbackDescription: "The automatic update did not complete. Run this command in a terminal instead, then quit Codex and relaunch it with codexhost.",
|
|
20029
|
+
updateCopyCommand: "Copy",
|
|
20030
|
+
updateCommandCopied: "Copied",
|
|
20031
|
+
updateCopyFailed: "Copy failed",
|
|
19706
20032
|
updateDownloadFromReleases: "Download from GitHub Releases",
|
|
20033
|
+
updateDownloadWindowsInstaller: "Download Windows installer",
|
|
20034
|
+
aboutTagline: "Run Pi and other Harnesses in Codex Desktop",
|
|
20035
|
+
aboutParagraphs: Object.freeze([
|
|
20036
|
+
"We believe Codex Desktop offers the best desktop development experience available today.",
|
|
20037
|
+
"But Codex is not the only excellent Agent Harness. Some developers prefer Claude Code or Pi Agent.",
|
|
20038
|
+
"codexhost lets you choose the Agent that actually executes tasks inside Codex Desktop, while preserving the native Codex experience and enabling them to collaborate."
|
|
20039
|
+
]),
|
|
20040
|
+
aboutOpenSource: "codexhost is an open-source project. The source code is available at:",
|
|
20041
|
+
aboutStarCallout: "\u2B50 If this project helps you, please give us a Star! \u2B50",
|
|
20042
|
+
aboutRepository: "Open-source repository",
|
|
19707
20043
|
pageLabels: Object.freeze({
|
|
19708
20044
|
connections: "Connections",
|
|
19709
|
-
|
|
19710
|
-
|
|
19711
|
-
gateway: "Gateway",
|
|
19712
|
-
updates: "Updates"
|
|
20045
|
+
updates: "Updates",
|
|
20046
|
+
about: "About"
|
|
19713
20047
|
})
|
|
19714
20048
|
});
|
|
19715
20049
|
var CHINESE_MESSAGES = Object.freeze({
|
|
@@ -19718,11 +20052,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19718
20052
|
close: "\u5173\u95ED\u8BBE\u7F6E",
|
|
19719
20053
|
starOnGitHub: "\u70B9\u4E2A Star~",
|
|
19720
20054
|
sectionsLabel: "\u8BBE\u7F6E\u5206\u7C7B",
|
|
20055
|
+
generalSection: "\u901A\u7528",
|
|
20056
|
+
otherSection: "\u5176\u4ED6",
|
|
19721
20057
|
pageUnavailable: "\u9875\u9762\u4E0D\u53EF\u7528",
|
|
19722
20058
|
inDevelopment: "\u5F00\u53D1\u4E2D",
|
|
19723
20059
|
notAvailable: "\u6682\u4E0D\u53EF\u7528",
|
|
19724
20060
|
runtimeCapabilityNotInstalled: "\u8FD0\u884C\u65F6\u5C1A\u672A\u5B89\u88C5\u8BE5\u9879\u80FD\u529B\uFF0C\u56E0\u6B64\u6682\u4E0D\u53EF\u7528\u3002",
|
|
19725
|
-
connectionsDescription: "\u67E5\u770B\
|
|
20061
|
+
connectionsDescription: "\u6309 Host \u67E5\u770B\u8FD0\u884C\u65F6\u72B6\u6001\u3002\u9009\u62E9\u4E00\u9879\uFF0C\u5728\u53F3\u4FA7\u68C0\u67E5\u8BE6\u60C5\u6216\u5B8C\u6210\u914D\u7F6E\u3002",
|
|
19726
20062
|
connectionAdapter: "Renderer \u9002\u914D\u5668",
|
|
19727
20063
|
connectionHosts: "Host \u5217\u8868",
|
|
19728
20064
|
connectionLocalHost: "\u672C\u5730",
|
|
@@ -19731,9 +20067,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19731
20067
|
connectionReason: "\u539F\u56E0",
|
|
19732
20068
|
connectionRefresh: "\u91CD\u65B0\u8BCA\u65AD\u8FDE\u63A5",
|
|
19733
20069
|
connectionRefreshing: "\u6B63\u5728\u8BCA\u65AD...",
|
|
19734
|
-
|
|
20070
|
+
connectionViewError: "\u67E5\u770B\u9519\u8BEF",
|
|
19735
20071
|
connectionCopyDetails: "\u590D\u5236\u8BCA\u65AD\u4FE1\u606F",
|
|
19736
|
-
connectionCopyAll: "\u590D\u5236\u5168\u90E8\u8BCA\u65AD\u4FE1\u606F",
|
|
19737
20072
|
connectionCopied: "\u5DF2\u590D\u5236",
|
|
19738
20073
|
connectionCopyFailed: "\u590D\u5236\u5931\u8D25",
|
|
19739
20074
|
connectionErrorCode: "\u9519\u8BEF\u7801",
|
|
@@ -19750,6 +20085,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19750
20085
|
connectionStatusError: "\u9519\u8BEF",
|
|
19751
20086
|
connectionStatusInstalling: "\u5B89\u88C5\u4E2D",
|
|
19752
20087
|
connectionStatusUnsupported: "\u4E0D\u652F\u6301",
|
|
20088
|
+
connectionComponent: "\u7EC4\u4EF6",
|
|
20089
|
+
connectionStatus: "\u72B6\u6001",
|
|
20090
|
+
connectionHostsScrollLeft: "\u67E5\u770B\u524D\u9762\u7684 Host",
|
|
20091
|
+
connectionHostsScrollRight: "\u67E5\u770B\u66F4\u591A Host",
|
|
20092
|
+
connectionOpenInstallation: "\u524D\u5F80\u5B98\u65B9\u5B89\u88C5\u9875\u9762",
|
|
20093
|
+
connectionInstall: "\u5B89\u88C5",
|
|
20094
|
+
connectionInstallDescription: "\u5C1A\u672A\u68C0\u6D4B\u5230\u8BE5 Harness\u3002\u8BF7\u6309\u7167\u5B98\u65B9\u5B89\u88C5\u6307\u5357\u5B8C\u6210\u5B89\u88C5\uFF0C\u7136\u540E\u8FD4\u56DE\u6B64\u9875\u9762\u91CD\u65B0\u68C0\u67E5\u3002",
|
|
20095
|
+
connectionErrorTitle: "\u8FDE\u63A5\u68C0\u67E5\u5931\u8D25",
|
|
20096
|
+
connectionErrorLog: "\u9519\u8BEF\u65E5\u5FD7",
|
|
20097
|
+
connectionOpenIssue: "\u63D0\u4EA4 GitHub Issue",
|
|
20098
|
+
connectionIssueDescription: "\u63D0\u4EA4\u524D\u8BF7\u590D\u5236\u9519\u8BEF\u65E5\u5FD7\uFF0C\u5E76\u5728 Issue \u4E2D\u8BF4\u660E\u5F53\u524D Host \u4E0E\u590D\u73B0\u6B65\u9AA4\u3002",
|
|
20099
|
+
connectionReadyDescription: "\u8BE5\u7EC4\u4EF6\u5728\u5F53\u524D Host \u4E0A\u53EF\u7528\u3002",
|
|
20100
|
+
connectionUnavailableDescription: "\u8BE5\u7EC4\u4EF6\u5F53\u524D\u65E0\u6CD5\u5728\u6240\u9009 Host \u4E0A\u4F7F\u7528\u3002",
|
|
20101
|
+
enabled: "\u5DF2\u5F00\u542F",
|
|
20102
|
+
disabled: "\u5DF2\u5173\u95ED",
|
|
19753
20103
|
openSettings: "\u6253\u5F00 codexhost \u8BBE\u7F6E",
|
|
19754
20104
|
settingsButtonTitle: "codexhost \u8BBE\u7F6E",
|
|
19755
20105
|
settingsUnavailableTitle: "codexhost \u8BBE\u7F6E\u4E0D\u53EF\u7528",
|
|
@@ -19762,7 +20112,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19762
20112
|
updateLatestVersion: "\u6700\u65B0\u7248\u672C",
|
|
19763
20113
|
updateUpToDate: "\u5F53\u524D\u5DF2\u662F\u6700\u65B0\u7248\u672C\u3002",
|
|
19764
20114
|
updateAvailable: "\u6709\u65B0\u7248\u672C\u53EF\u7528\u3002",
|
|
19765
|
-
|
|
20115
|
+
updateWindowsManualRequired: "Windows \u6682\u4E0D\u652F\u6301\u81EA\u52A8\u66F4\u65B0\uFF0C\u8BF7\u5728\u4E0B\u65B9\u624B\u52A8\u66F4\u65B0\u3002",
|
|
20116
|
+
updateAndRestart: "\u66F4\u65B0",
|
|
19766
20117
|
updateChecking: "\u6B63\u5728\u68C0\u67E5\u66F4\u65B0...",
|
|
19767
20118
|
updateDownloading: "\u6B63\u5728\u4E0B\u8F7D\u66F4\u65B0...",
|
|
19768
20119
|
updatePreparing: "\u6B63\u5728\u51C6\u5907\u66F4\u65B0...",
|
|
@@ -19775,13 +20126,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19775
20126
|
updateFailed: "\u66F4\u65B0\u5931\u8D25\u3002",
|
|
19776
20127
|
updateRetry: "\u91CD\u8BD5",
|
|
19777
20128
|
updateManualNpmDescription: "\u5982\u9700\u624B\u52A8\u66F4\u65B0\uFF0C\u8BF7\u5728\u7EC8\u7AEF\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u3002\u66F4\u65B0\u5B8C\u6210\u540E\uFF0C\u8BF7\u9000\u51FA Codex \u5E76\u901A\u8FC7 codexhost \u91CD\u65B0\u542F\u52A8\u3002",
|
|
20129
|
+
updateWindowsNpmDescription: "Windows \u6682\u4E0D\u652F\u6301\u81EA\u52A8\u66F4\u65B0\u3002\u8BF7\u9000\u51FA codexhost\uFF0C\u5728\u7EC8\u7AEF\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u5B8C\u6210\u66F4\u65B0\u3002",
|
|
20130
|
+
updateWindowsInstallerDescription: "Windows \u6682\u4E0D\u652F\u6301\u81EA\u52A8\u66F4\u65B0\u3002\u8BF7\u4E0B\u8F7D\u5E76\u8FD0\u884C\u9002\u7528\u4E8E\u5F53\u524D\u7CFB\u7EDF\u7684\u5B89\u88C5\u5305\u3002",
|
|
20131
|
+
updateManualTitle: "\u624B\u52A8\u66F4\u65B0",
|
|
20132
|
+
updateManualFallbackDescription: "\u81EA\u52A8\u66F4\u65B0\u672A\u80FD\u5B8C\u6210\uFF0C\u8BF7\u6539\u7528\u4E0B\u5217\u547D\u4EE4\u5728\u7EC8\u7AEF\u624B\u52A8\u66F4\u65B0\u3002\u5B8C\u6210\u540E\u8BF7\u9000\u51FA Codex \u5E76\u901A\u8FC7 codexhost \u91CD\u65B0\u542F\u52A8\u3002",
|
|
20133
|
+
updateCopyCommand: "\u590D\u5236",
|
|
20134
|
+
updateCommandCopied: "\u5DF2\u590D\u5236",
|
|
20135
|
+
updateCopyFailed: "\u590D\u5236\u5931\u8D25",
|
|
19778
20136
|
updateDownloadFromReleases: "\u524D\u5F80 GitHub Releases \u4E0B\u8F7D",
|
|
20137
|
+
updateDownloadWindowsInstaller: "\u4E0B\u8F7D Windows \u5B89\u88C5\u5305",
|
|
20138
|
+
aboutTagline: "\u5728 Codex Desktop \u4E2D\u8FD0\u884C Pi \u548C\u5176\u4ED6 Harness",
|
|
20139
|
+
aboutParagraphs: Object.freeze([
|
|
20140
|
+
"\u6211\u4EEC\u8BA4\u4E3A Codex Desktop \u63D0\u4F9B\u4E86\u76EE\u524D\u6700\u597D\u7684\u684C\u9762\u5F00\u53D1\u4EA4\u4E92\u4F53\u9A8C\u3002",
|
|
20141
|
+
"\u4F46 Codex \u5E76\u4E0D\u662F\u552F\u4E00\u4F18\u79C0\u7684 Agent Harness\uFF0C\u4E5F\u6709\u4EBA\u504F\u597D Claude Code \u548C Pi Agent\u3002",
|
|
20142
|
+
"codexhost \u8BA9\u4F60\u5728 Codex Desktop \u4E2D\u9009\u62E9\u771F\u6B63\u6267\u884C\u4EFB\u52A1\u7684 Agent\uFF0C\u540C\u65F6\u4FDD\u7559 Codex \u7684\u539F\u751F\u4F53\u9A8C\uFF0C\u5E76\u8BA9\u5B83\u4EEC\u534F\u4F5C\u5B8C\u6210\u4EFB\u52A1\u3002"
|
|
20143
|
+
]),
|
|
20144
|
+
aboutOpenSource: "codexhost \u662F\u4E00\u4E2A\u5F00\u6E90\u9879\u76EE\uFF0C\u5F00\u6E90\u5730\u5740\uFF1A",
|
|
20145
|
+
aboutStarCallout: "\u2B50 \u5982\u679C\u8FD9\u4E2A\u9879\u76EE\u5BF9\u4F60\u6709\u5E2E\u52A9\uFF0C\u8BF7\u7ED9\u6211\u4EEC\u4E00\u4E2A Star\uFF01\u2B50",
|
|
20146
|
+
aboutRepository: "\u5F00\u6E90\u4ED3\u5E93",
|
|
19779
20147
|
pageLabels: Object.freeze({
|
|
19780
20148
|
connections: "\u8FDE\u63A5",
|
|
19781
|
-
|
|
19782
|
-
|
|
19783
|
-
gateway: "\u7F51\u5173",
|
|
19784
|
-
updates: "\u66F4\u65B0"
|
|
20149
|
+
updates: "\u66F4\u65B0",
|
|
20150
|
+
about: "\u5173\u4E8E"
|
|
19785
20151
|
})
|
|
19786
20152
|
});
|
|
19787
20153
|
var DEFAULT_RENDERER_SETTINGS_MESSAGES = ENGLISH_MESSAGES;
|
|
@@ -19835,6 +20201,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19835
20201
|
["path", { d: "M12 13.5V8" }]
|
|
19836
20202
|
];
|
|
19837
20203
|
|
|
20204
|
+
// ../../node_modules/lucide/dist/esm/icons/circle-check.mjs
|
|
20205
|
+
var CircleCheck = [
|
|
20206
|
+
["circle", { cx: "12", cy: "12", r: "10" }],
|
|
20207
|
+
["path", { d: "m9 12 2 2 4-4" }]
|
|
20208
|
+
];
|
|
20209
|
+
|
|
20210
|
+
// ../../node_modules/lucide/dist/esm/icons/chevron-left.mjs
|
|
20211
|
+
var ChevronLeft = [["path", { d: "m15 18-6-6 6-6" }]];
|
|
20212
|
+
|
|
20213
|
+
// ../../node_modules/lucide/dist/esm/icons/chevron-right.mjs
|
|
20214
|
+
var ChevronRight = [["path", { d: "m9 18 6-6-6-6" }]];
|
|
20215
|
+
|
|
19838
20216
|
// ../../node_modules/lucide/dist/esm/icons/circle-off.mjs
|
|
19839
20217
|
var CircleOff = [
|
|
19840
20218
|
["path", { d: "m2 2 20 20" }],
|
|
@@ -19862,6 +20240,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19862
20240
|
["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }]
|
|
19863
20241
|
];
|
|
19864
20242
|
|
|
20243
|
+
// ../../node_modules/lucide/dist/esm/icons/info.mjs
|
|
20244
|
+
var Info = [
|
|
20245
|
+
["circle", { cx: "12", cy: "12", r: "10" }],
|
|
20246
|
+
["path", { d: "M12 16v-4" }],
|
|
20247
|
+
["path", { d: "M12 8h.01" }]
|
|
20248
|
+
];
|
|
20249
|
+
|
|
19865
20250
|
// ../../node_modules/lucide/dist/esm/icons/languages.mjs
|
|
19866
20251
|
var Languages = [
|
|
19867
20252
|
["path", { d: "m5 8 6 6" }],
|
|
@@ -19935,6 +20320,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19935
20320
|
]
|
|
19936
20321
|
];
|
|
19937
20322
|
|
|
20323
|
+
// ../../node_modules/lucide/dist/esm/icons/triangle-alert.mjs
|
|
20324
|
+
var TriangleAlert = [
|
|
20325
|
+
["path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" }],
|
|
20326
|
+
["path", { d: "M12 9v4" }],
|
|
20327
|
+
["path", { d: "M12 17h.01" }]
|
|
20328
|
+
];
|
|
20329
|
+
|
|
19938
20330
|
// ../../node_modules/lucide/dist/esm/icons/x.mjs
|
|
19939
20331
|
var X = [
|
|
19940
20332
|
["path", { d: "M18 6 6 18" }],
|
|
@@ -19955,11 +20347,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19955
20347
|
"routes",
|
|
19956
20348
|
"gateway",
|
|
19957
20349
|
"updates",
|
|
20350
|
+
"about",
|
|
19958
20351
|
"external-link",
|
|
19959
20352
|
"refresh",
|
|
19960
20353
|
"unavailable",
|
|
20354
|
+
"alert",
|
|
20355
|
+
"check",
|
|
19961
20356
|
"diagnose",
|
|
19962
|
-
"copy"
|
|
20357
|
+
"copy",
|
|
20358
|
+
"download",
|
|
20359
|
+
"chevron-left",
|
|
20360
|
+
"chevron-right"
|
|
19963
20361
|
];
|
|
19964
20362
|
var iconNodes = {
|
|
19965
20363
|
settings: Settings,
|
|
@@ -19971,11 +20369,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19971
20369
|
routes: Route,
|
|
19972
20370
|
gateway: Network,
|
|
19973
20371
|
updates: Download,
|
|
20372
|
+
about: Info,
|
|
19974
20373
|
"external-link": ExternalLink,
|
|
19975
20374
|
refresh: RefreshCw,
|
|
19976
20375
|
unavailable: CircleOff,
|
|
20376
|
+
alert: TriangleAlert,
|
|
20377
|
+
check: CircleCheck,
|
|
19977
20378
|
diagnose: Stethoscope,
|
|
19978
|
-
copy: Copy
|
|
20379
|
+
copy: Copy,
|
|
20380
|
+
download: Download,
|
|
20381
|
+
"chevron-left": ChevronLeft,
|
|
20382
|
+
"chevron-right": ChevronRight
|
|
19979
20383
|
};
|
|
19980
20384
|
function isRendererSettingsIconName(value) {
|
|
19981
20385
|
return RENDERER_SETTINGS_ICON_NAMES.includes(value);
|
|
@@ -20108,101 +20512,650 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20108
20512
|
}
|
|
20109
20513
|
};
|
|
20110
20514
|
|
|
20111
|
-
// src/settings/
|
|
20112
|
-
var
|
|
20113
|
-
var
|
|
20114
|
-
|
|
20115
|
-
|
|
20116
|
-
|
|
20117
|
-
|
|
20118
|
-
|
|
20119
|
-
|
|
20120
|
-
function
|
|
20121
|
-
|
|
20122
|
-
|
|
20123
|
-
|
|
20124
|
-
return
|
|
20515
|
+
// src/settings/connections-page.ts
|
|
20516
|
+
var CODEXHOST_GITHUB_ISSUES_NEW_URL = "https://github.com/BytePioneer-AI/codex-host/issues/new";
|
|
20517
|
+
var HARNESS_INSTALL_URLS = Object.freeze({
|
|
20518
|
+
pi: "https://pi.dev/",
|
|
20519
|
+
"claude-code": "https://code.claude.com/docs/en/quickstart",
|
|
20520
|
+
"deepseek-harness": "https://deepseek-harness.github.io/deepseek-harness/",
|
|
20521
|
+
grok: "https://grok.com/",
|
|
20522
|
+
omp: "https://github.com/can1357/oh-my-pi"
|
|
20523
|
+
});
|
|
20524
|
+
function connectionStatusLabel(availability, messages, hasError = false) {
|
|
20525
|
+
if (hasError && availability !== "notInstalled") return messages.connectionStatusError;
|
|
20526
|
+
if (availability === "ready") return messages.connectionStatusReady;
|
|
20527
|
+
if (availability === "checking") return messages.connectionStatusChecking;
|
|
20528
|
+
if (availability === "notInstalled") return messages.connectionStatusNotInstalled;
|
|
20529
|
+
if (availability === "unavailable" || availability === "error") {
|
|
20530
|
+
return availability === "error" ? messages.connectionStatusError : messages.connectionStatusUnavailable;
|
|
20531
|
+
}
|
|
20532
|
+
return availability === "installing" ? messages.connectionStatusInstalling : messages.connectionStatusUnsupported;
|
|
20125
20533
|
}
|
|
20126
|
-
function
|
|
20127
|
-
|
|
20128
|
-
|
|
20129
|
-
|
|
20130
|
-
|
|
20131
|
-
|
|
20132
|
-
|
|
20133
|
-
|
|
20134
|
-
|
|
20135
|
-
|
|
20136
|
-
|
|
20137
|
-
|
|
20138
|
-
|
|
20139
|
-
}
|
|
20140
|
-
|
|
20141
|
-
|
|
20142
|
-
|
|
20143
|
-
|
|
20144
|
-
|
|
20145
|
-
|
|
20146
|
-
|
|
20147
|
-
|
|
20148
|
-
|
|
20149
|
-
|
|
20150
|
-
|
|
20151
|
-
|
|
20152
|
-
|
|
20153
|
-
|
|
20154
|
-
|
|
20155
|
-
|
|
20156
|
-
|
|
20157
|
-
|
|
20158
|
-
|
|
20159
|
-
|
|
20160
|
-
|
|
20161
|
-
|
|
20162
|
-
|
|
20163
|
-
|
|
20164
|
-
|
|
20165
|
-
|
|
20166
|
-
|
|
20534
|
+
function connectionStatusTone(availability, hasError = false) {
|
|
20535
|
+
if (hasError && availability !== "notInstalled") return "failed";
|
|
20536
|
+
if (availability === "ready") return "ready";
|
|
20537
|
+
if (availability === "checking" || availability === "installing") return "checking";
|
|
20538
|
+
if (availability === "notInstalled") return "setup";
|
|
20539
|
+
return "failed";
|
|
20540
|
+
}
|
|
20541
|
+
function diagnosticText(hostId, item) {
|
|
20542
|
+
const error51 = item.error;
|
|
20543
|
+
return [
|
|
20544
|
+
"codexhost connection diagnostics",
|
|
20545
|
+
`host: ${hostId}`,
|
|
20546
|
+
`agent: ${item.name}`,
|
|
20547
|
+
`status: ${item.availability}`,
|
|
20548
|
+
...error51 ? [
|
|
20549
|
+
`error.code: ${error51.code}`,
|
|
20550
|
+
`error.message: ${error51.message}`,
|
|
20551
|
+
`retryable: ${error51.retryable}`,
|
|
20552
|
+
...error51.stage ? [`stage: ${error51.stage}`] : [],
|
|
20553
|
+
...error51.durationMs !== void 0 ? [`durationMs: ${error51.durationMs}`] : [],
|
|
20554
|
+
...error51.diagnostic ? [`diagnostic: ${error51.diagnostic}`] : [],
|
|
20555
|
+
...error51.stderrTail ? [`stderr:
|
|
20556
|
+
${error51.stderrTail}`] : []
|
|
20557
|
+
] : []
|
|
20558
|
+
].join("\n");
|
|
20559
|
+
}
|
|
20560
|
+
function detailLine(document2, label, value) {
|
|
20561
|
+
const line = document2.createElement("div");
|
|
20562
|
+
line.className = "settings-connection-detail-line";
|
|
20563
|
+
const name = document2.createElement("span");
|
|
20564
|
+
name.textContent = label;
|
|
20565
|
+
const content = document2.createElement("code");
|
|
20566
|
+
content.textContent = value;
|
|
20567
|
+
line.append(name, content);
|
|
20568
|
+
return line;
|
|
20569
|
+
}
|
|
20570
|
+
function setCopyButtonLabel(button, label) {
|
|
20571
|
+
button.replaceChildren(createRendererSettingsIcon("copy", 16), label);
|
|
20572
|
+
}
|
|
20573
|
+
function showCopyButtonFeedback(button, label, restoreLabel) {
|
|
20574
|
+
setCopyButtonLabel(button, label);
|
|
20575
|
+
button.ownerDocument.defaultView?.setTimeout(() => {
|
|
20576
|
+
setCopyButtonLabel(button, restoreLabel);
|
|
20577
|
+
}, 2e3);
|
|
20578
|
+
}
|
|
20579
|
+
function copyDiagnosticsToClipboard(document2, button, report, messages, restoreLabel) {
|
|
20580
|
+
const clipboard = document2.defaultView?.navigator.clipboard;
|
|
20581
|
+
if (!clipboard) {
|
|
20582
|
+
showCopyButtonFeedback(button, messages.connectionCopyFailed, restoreLabel);
|
|
20583
|
+
return;
|
|
20167
20584
|
}
|
|
20585
|
+
void clipboard.writeText(report).then(
|
|
20586
|
+
() => showCopyButtonFeedback(button, messages.connectionCopied, restoreLabel),
|
|
20587
|
+
() => showCopyButtonFeedback(button, messages.connectionCopyFailed, restoreLabel)
|
|
20588
|
+
);
|
|
20168
20589
|
}
|
|
20169
|
-
function
|
|
20170
|
-
|
|
20171
|
-
|
|
20172
|
-
|
|
20173
|
-
|
|
20174
|
-
|
|
20590
|
+
function connectionHostName(hostId, messages) {
|
|
20591
|
+
if (hostId === "local") return messages.connectionLocalHost;
|
|
20592
|
+
const separator = hostId.lastIndexOf(":");
|
|
20593
|
+
const encodedName = separator >= 0 ? hostId.slice(separator + 1) : hostId;
|
|
20594
|
+
try {
|
|
20595
|
+
return decodeURIComponent(encodedName);
|
|
20596
|
+
} catch {
|
|
20597
|
+
return encodedName;
|
|
20175
20598
|
}
|
|
20176
|
-
if (index < lines.length) index += 1;
|
|
20177
|
-
const pre = document2.createElement("pre");
|
|
20178
|
-
const code = document2.createElement("code");
|
|
20179
|
-
if (language.length > 0) code.className = `language-${language}`;
|
|
20180
|
-
code.textContent = body.join("\n");
|
|
20181
|
-
pre.append(code);
|
|
20182
|
-
root.append(pre);
|
|
20183
|
-
return index;
|
|
20184
20599
|
}
|
|
20185
|
-
function
|
|
20186
|
-
const
|
|
20187
|
-
|
|
20188
|
-
|
|
20189
|
-
|
|
20190
|
-
|
|
20191
|
-
|
|
20192
|
-
|
|
20193
|
-
|
|
20600
|
+
function createHostScrollButton(document2, direction, messages) {
|
|
20601
|
+
const button = document2.createElement("button");
|
|
20602
|
+
button.type = "button";
|
|
20603
|
+
button.className = "settings-connection-host-scroll";
|
|
20604
|
+
button.dataset.connectionHostScroll = direction;
|
|
20605
|
+
const label = direction === "left" ? messages.connectionHostsScrollLeft : messages.connectionHostsScrollRight;
|
|
20606
|
+
button.setAttribute("aria-label", label);
|
|
20607
|
+
button.title = label;
|
|
20608
|
+
button.append(
|
|
20609
|
+
createRendererSettingsIcon(direction === "left" ? "chevron-left" : "chevron-right", 16)
|
|
20610
|
+
);
|
|
20611
|
+
return button;
|
|
20612
|
+
}
|
|
20613
|
+
function configureHostScroller(document2, strip, tabs, left, right) {
|
|
20614
|
+
const maxScrollLeft = () => Math.max(0, (tabs.scrollWidth || 0) - (tabs.clientWidth || 0));
|
|
20615
|
+
const updateButtons = () => {
|
|
20616
|
+
const maximum = maxScrollLeft();
|
|
20617
|
+
strip.dataset.connectionHostOverflow = String(maximum > 1);
|
|
20618
|
+
left.disabled = tabs.scrollLeft <= 1;
|
|
20619
|
+
right.disabled = maximum <= 1 || tabs.scrollLeft >= maximum - 1;
|
|
20620
|
+
};
|
|
20621
|
+
const scroll = (direction) => {
|
|
20622
|
+
const distance = Math.max(180, Math.round((tabs.clientWidth || 250) * 0.72));
|
|
20623
|
+
if (typeof tabs.scrollBy === "function") {
|
|
20624
|
+
tabs.scrollBy({ left: direction * distance, behavior: "smooth" });
|
|
20625
|
+
} else {
|
|
20626
|
+
tabs.scrollLeft += direction * distance;
|
|
20627
|
+
updateButtons();
|
|
20628
|
+
}
|
|
20629
|
+
};
|
|
20630
|
+
const onLeft = () => scroll(-1);
|
|
20631
|
+
const onRight = () => scroll(1);
|
|
20632
|
+
const onWheel = (event) => {
|
|
20633
|
+
const delta = Math.abs(event.deltaX) > Math.abs(event.deltaY) ? event.deltaX : event.deltaY;
|
|
20634
|
+
const maximum = maxScrollLeft();
|
|
20635
|
+
const canScroll = delta < 0 ? tabs.scrollLeft > 1 : tabs.scrollLeft < maximum - 1;
|
|
20636
|
+
if (!delta || maximum <= 1 || !canScroll) return;
|
|
20637
|
+
event.preventDefault();
|
|
20638
|
+
tabs.scrollLeft += delta;
|
|
20639
|
+
};
|
|
20640
|
+
left.addEventListener("click", onLeft);
|
|
20641
|
+
right.addEventListener("click", onRight);
|
|
20642
|
+
tabs.addEventListener("scroll", updateButtons, { passive: true });
|
|
20643
|
+
tabs.addEventListener("wheel", onWheel, { passive: false });
|
|
20644
|
+
const ownerWindow = document2.defaultView;
|
|
20645
|
+
ownerWindow?.addEventListener("resize", updateButtons);
|
|
20646
|
+
ownerWindow?.setTimeout(updateButtons, 0);
|
|
20647
|
+
updateButtons();
|
|
20648
|
+
return () => {
|
|
20649
|
+
left.removeEventListener("click", onLeft);
|
|
20650
|
+
right.removeEventListener("click", onRight);
|
|
20651
|
+
tabs.removeEventListener("scroll", updateButtons);
|
|
20652
|
+
tabs.removeEventListener("wheel", onWheel);
|
|
20653
|
+
ownerWindow?.removeEventListener("resize", updateButtons);
|
|
20654
|
+
};
|
|
20655
|
+
}
|
|
20656
|
+
function createConnectionIdentityIcon(document2, item, size) {
|
|
20657
|
+
const container = document2.createElement("span");
|
|
20658
|
+
container.className = item.agentSnapshot ? "settings-connection-row__mark settings-connection-row__mark--logo" : "settings-connection-row__mark";
|
|
20659
|
+
container.setAttribute("aria-hidden", "true");
|
|
20660
|
+
if (item.agentSnapshot) {
|
|
20661
|
+
container.append(createRendererAgentIcon(item.agentSnapshot.agent, size, document2));
|
|
20662
|
+
} else {
|
|
20663
|
+
container.textContent = "CH";
|
|
20194
20664
|
}
|
|
20195
|
-
|
|
20196
|
-
appendInline(document2, paragraph, content.join(" ").trim());
|
|
20197
|
-
blockquote.append(paragraph);
|
|
20198
|
-
root.append(blockquote);
|
|
20199
|
-
return index;
|
|
20665
|
+
return container;
|
|
20200
20666
|
}
|
|
20201
|
-
function
|
|
20202
|
-
const
|
|
20203
|
-
|
|
20204
|
-
|
|
20205
|
-
|
|
20667
|
+
function createConnectionRow(document2, item, messages, selected, select) {
|
|
20668
|
+
const row = document2.createElement("div");
|
|
20669
|
+
row.className = "settings-connection-row";
|
|
20670
|
+
row.dataset.connectionItem = item.key;
|
|
20671
|
+
row.dataset.connectionSelected = String(selected);
|
|
20672
|
+
row.tabIndex = selected ? 0 : -1;
|
|
20673
|
+
row.setAttribute("role", "row");
|
|
20674
|
+
const identity = document2.createElement("div");
|
|
20675
|
+
identity.className = "settings-connection-row__identity";
|
|
20676
|
+
identity.setAttribute("role", "cell");
|
|
20677
|
+
const label = document2.createElement("strong");
|
|
20678
|
+
label.textContent = item.name;
|
|
20679
|
+
identity.append(createConnectionIdentityIcon(document2, item, 19), label);
|
|
20680
|
+
const status = document2.createElement("span");
|
|
20681
|
+
status.className = "settings-connection-row__status";
|
|
20682
|
+
status.dataset.connectionTone = connectionStatusTone(item.availability, item.error !== null);
|
|
20683
|
+
status.setAttribute("role", "cell");
|
|
20684
|
+
status.textContent = connectionStatusLabel(item.availability, messages, item.error !== null);
|
|
20685
|
+
const action = document2.createElement("div");
|
|
20686
|
+
action.className = "settings-connection-row__action";
|
|
20687
|
+
action.setAttribute("role", "cell");
|
|
20688
|
+
if (item.agentSnapshot?.availability === "notInstalled") {
|
|
20689
|
+
const install = document2.createElement("a");
|
|
20690
|
+
install.className = "settings-connection-install-link";
|
|
20691
|
+
install.href = HARNESS_INSTALL_URLS[item.agentSnapshot.agent];
|
|
20692
|
+
install.target = "_blank";
|
|
20693
|
+
install.rel = "noopener noreferrer";
|
|
20694
|
+
install.setAttribute("aria-label", `${messages.connectionOpenInstallation}: ${item.name}`);
|
|
20695
|
+
install.title = messages.connectionOpenInstallation;
|
|
20696
|
+
install.append(createRendererSettingsIcon("download", 17));
|
|
20697
|
+
action.append(install);
|
|
20698
|
+
} else if (item.error) {
|
|
20699
|
+
const viewError = document2.createElement("button");
|
|
20700
|
+
viewError.type = "button";
|
|
20701
|
+
viewError.className = "settings-connection-view-error";
|
|
20702
|
+
viewError.textContent = messages.connectionViewError;
|
|
20703
|
+
viewError.addEventListener("click", (event) => {
|
|
20704
|
+
event.stopPropagation();
|
|
20705
|
+
select();
|
|
20706
|
+
});
|
|
20707
|
+
action.append(viewError);
|
|
20708
|
+
}
|
|
20709
|
+
row.addEventListener("click", (event) => {
|
|
20710
|
+
const target = event.target;
|
|
20711
|
+
if (target?.closest?.("a")) return;
|
|
20712
|
+
select();
|
|
20713
|
+
});
|
|
20714
|
+
row.addEventListener("keydown", (event) => {
|
|
20715
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
20716
|
+
event.preventDefault();
|
|
20717
|
+
select();
|
|
20718
|
+
});
|
|
20719
|
+
row.append(identity, status, action);
|
|
20720
|
+
return row;
|
|
20721
|
+
}
|
|
20722
|
+
function createInspectorHeader(document2, item, messages) {
|
|
20723
|
+
const header = document2.createElement("header");
|
|
20724
|
+
header.className = "settings-connection-inspector__header";
|
|
20725
|
+
const identity = document2.createElement("div");
|
|
20726
|
+
identity.className = "settings-connection-inspector__identity";
|
|
20727
|
+
const title = document2.createElement("strong");
|
|
20728
|
+
title.textContent = item.name;
|
|
20729
|
+
identity.append(createConnectionIdentityIcon(document2, item, 20), title);
|
|
20730
|
+
const status = document2.createElement("span");
|
|
20731
|
+
status.className = "settings-connection-row__status";
|
|
20732
|
+
status.dataset.connectionTone = connectionStatusTone(item.availability, item.error !== null);
|
|
20733
|
+
status.textContent = connectionStatusLabel(item.availability, messages, item.error !== null);
|
|
20734
|
+
header.append(identity, status);
|
|
20735
|
+
return header;
|
|
20736
|
+
}
|
|
20737
|
+
function renderConnectionInspector(document2, inspector, item, hostId, messages) {
|
|
20738
|
+
inspector.replaceChildren(createInspectorHeader(document2, item, messages));
|
|
20739
|
+
const body = document2.createElement("div");
|
|
20740
|
+
body.className = "settings-connection-inspector__body";
|
|
20741
|
+
if (item.agentSnapshot?.availability === "notInstalled") {
|
|
20742
|
+
const callout = document2.createElement("div");
|
|
20743
|
+
callout.className = "settings-connection-install-callout";
|
|
20744
|
+
const icon2 = document2.createElement("span");
|
|
20745
|
+
icon2.className = "settings-connection-install-callout__icon";
|
|
20746
|
+
icon2.append(createRendererSettingsIcon("download", 18));
|
|
20747
|
+
const copy = document2.createElement("div");
|
|
20748
|
+
const title = document2.createElement("strong");
|
|
20749
|
+
title.textContent = `${messages.connectionInstall} ${item.name}`;
|
|
20750
|
+
const description = document2.createElement("p");
|
|
20751
|
+
description.textContent = messages.connectionInstallDescription;
|
|
20752
|
+
copy.append(title, description);
|
|
20753
|
+
callout.append(icon2, copy);
|
|
20754
|
+
const install = document2.createElement("a");
|
|
20755
|
+
install.className = "settings-command-button settings-connection-install-button";
|
|
20756
|
+
install.href = HARNESS_INSTALL_URLS[item.agentSnapshot.agent];
|
|
20757
|
+
install.target = "_blank";
|
|
20758
|
+
install.rel = "noopener noreferrer";
|
|
20759
|
+
install.append(
|
|
20760
|
+
messages.connectionOpenInstallation,
|
|
20761
|
+
createRendererSettingsIcon("external-link", 14)
|
|
20762
|
+
);
|
|
20763
|
+
body.append(callout, install);
|
|
20764
|
+
} else if (item.error) {
|
|
20765
|
+
const summary = document2.createElement("div");
|
|
20766
|
+
summary.className = "settings-connection-error-summary";
|
|
20767
|
+
const title = document2.createElement("strong");
|
|
20768
|
+
title.textContent = messages.connectionErrorTitle;
|
|
20769
|
+
const description = document2.createElement("p");
|
|
20770
|
+
description.textContent = item.error.message;
|
|
20771
|
+
summary.append(title, description);
|
|
20772
|
+
const metadata = document2.createElement("div");
|
|
20773
|
+
metadata.className = "settings-connection-error-metadata";
|
|
20774
|
+
metadata.append(
|
|
20775
|
+
detailLine(document2, messages.connectionErrorCode, item.error.code),
|
|
20776
|
+
detailLine(document2, messages.connectionRetryable, String(item.error.retryable))
|
|
20777
|
+
);
|
|
20778
|
+
if (item.error.stage) {
|
|
20779
|
+
metadata.append(detailLine(document2, messages.connectionFailureStage, item.error.stage));
|
|
20780
|
+
}
|
|
20781
|
+
if (item.error.durationMs !== void 0) {
|
|
20782
|
+
metadata.append(
|
|
20783
|
+
detailLine(document2, messages.connectionDuration, `${item.error.durationMs} ms`)
|
|
20784
|
+
);
|
|
20785
|
+
}
|
|
20786
|
+
if (item.error.diagnostic) {
|
|
20787
|
+
metadata.append(detailLine(document2, messages.connectionDiagnostic, item.error.diagnostic));
|
|
20788
|
+
}
|
|
20789
|
+
const logHeader = document2.createElement("div");
|
|
20790
|
+
logHeader.className = "settings-connection-error-log-header";
|
|
20791
|
+
const logTitle = document2.createElement("strong");
|
|
20792
|
+
logTitle.textContent = messages.connectionErrorLog;
|
|
20793
|
+
const copy = document2.createElement("button");
|
|
20794
|
+
copy.type = "button";
|
|
20795
|
+
copy.className = "settings-command-button settings-command-button--secondary";
|
|
20796
|
+
setCopyButtonLabel(copy, messages.connectionCopyDetails);
|
|
20797
|
+
const report = diagnosticText(hostId, item);
|
|
20798
|
+
copy.addEventListener("click", () => {
|
|
20799
|
+
copyDiagnosticsToClipboard(document2, copy, report, messages, messages.connectionCopyDetails);
|
|
20800
|
+
});
|
|
20801
|
+
logHeader.append(logTitle, copy);
|
|
20802
|
+
const log = document2.createElement("pre");
|
|
20803
|
+
log.className = "settings-connection-stderr";
|
|
20804
|
+
log.textContent = item.error.stderrTail ?? item.error.diagnostic ?? report;
|
|
20805
|
+
const actions = document2.createElement("div");
|
|
20806
|
+
actions.className = "settings-connection-error-actions";
|
|
20807
|
+
const issue2 = document2.createElement("a");
|
|
20808
|
+
issue2.className = "settings-command-button settings-command-button--secondary";
|
|
20809
|
+
issue2.href = CODEXHOST_GITHUB_ISSUES_NEW_URL;
|
|
20810
|
+
issue2.target = "_blank";
|
|
20811
|
+
issue2.rel = "noopener noreferrer";
|
|
20812
|
+
issue2.append(messages.connectionOpenIssue, createRendererSettingsIcon("external-link", 14));
|
|
20813
|
+
actions.append(issue2);
|
|
20814
|
+
const issueNote = document2.createElement("p");
|
|
20815
|
+
issueNote.className = "settings-connection-issue-note";
|
|
20816
|
+
issueNote.textContent = messages.connectionIssueDescription;
|
|
20817
|
+
body.append(summary, metadata, logHeader, log, actions, issueNote);
|
|
20818
|
+
} else {
|
|
20819
|
+
const status = document2.createElement("div");
|
|
20820
|
+
status.className = "settings-connection-state-summary";
|
|
20821
|
+
const title = document2.createElement("strong");
|
|
20822
|
+
title.textContent = connectionStatusLabel(item.availability, messages);
|
|
20823
|
+
const description = document2.createElement("p");
|
|
20824
|
+
description.textContent = item.availability === "ready" ? messages.connectionReadyDescription : messages.connectionUnavailableDescription;
|
|
20825
|
+
status.append(title, description);
|
|
20826
|
+
body.append(status);
|
|
20827
|
+
}
|
|
20828
|
+
inspector.append(body);
|
|
20829
|
+
}
|
|
20830
|
+
function connectionItems(snapshot, host, messages) {
|
|
20831
|
+
return [
|
|
20832
|
+
{
|
|
20833
|
+
key: "renderer-adapter",
|
|
20834
|
+
name: messages.connectionAdapter,
|
|
20835
|
+
availability: snapshot.adapter.state,
|
|
20836
|
+
error: null
|
|
20837
|
+
},
|
|
20838
|
+
...host.agents.map((agent) => ({
|
|
20839
|
+
key: agent.agent,
|
|
20840
|
+
name: RENDERER_AGENT_LABELS[agent.agent],
|
|
20841
|
+
availability: agent.availability,
|
|
20842
|
+
error: agent.availability === "notInstalled" ? null : agent.error,
|
|
20843
|
+
agentSnapshot: agent
|
|
20844
|
+
}))
|
|
20845
|
+
];
|
|
20846
|
+
}
|
|
20847
|
+
function createConnectionsSettingsPage(messages, getDiagnostics) {
|
|
20848
|
+
return Object.freeze({
|
|
20849
|
+
id: "connections",
|
|
20850
|
+
label: messages.pageLabels.connections,
|
|
20851
|
+
icon: "connections",
|
|
20852
|
+
mount(context) {
|
|
20853
|
+
const document2 = context.content.ownerDocument;
|
|
20854
|
+
const header = document2.createElement("div");
|
|
20855
|
+
header.className = "settings-connection-page-header";
|
|
20856
|
+
const headingCopy = document2.createElement("div");
|
|
20857
|
+
const heading = document2.createElement("div");
|
|
20858
|
+
heading.className = "settings-section-label";
|
|
20859
|
+
heading.textContent = messages.pageLabels.connections;
|
|
20860
|
+
const description = document2.createElement("p");
|
|
20861
|
+
description.className = "settings-page-description";
|
|
20862
|
+
description.textContent = messages.connectionsDescription;
|
|
20863
|
+
headingCopy.append(heading, description);
|
|
20864
|
+
const refresh = document2.createElement("button");
|
|
20865
|
+
refresh.type = "button";
|
|
20866
|
+
refresh.className = "settings-command-button settings-command-button--secondary";
|
|
20867
|
+
refresh.dataset.connectionAction = "refresh";
|
|
20868
|
+
refresh.append(createRendererSettingsIcon("diagnose", 16), messages.connectionRefresh);
|
|
20869
|
+
header.append(headingCopy, refresh);
|
|
20870
|
+
const content = document2.createElement("div");
|
|
20871
|
+
content.className = "settings-connections-content";
|
|
20872
|
+
context.content.append(header, content);
|
|
20873
|
+
let pending = false;
|
|
20874
|
+
let selectedHostId = null;
|
|
20875
|
+
let selectedItemKey = null;
|
|
20876
|
+
let latestSnapshot = null;
|
|
20877
|
+
let disposeHostScroller = () => void 0;
|
|
20878
|
+
const diagnostics = getDiagnostics();
|
|
20879
|
+
const runRefresh = () => {
|
|
20880
|
+
if (pending || !diagnostics) return;
|
|
20881
|
+
pending = true;
|
|
20882
|
+
refresh.disabled = true;
|
|
20883
|
+
refresh.replaceChildren(
|
|
20884
|
+
createRendererSettingsIcon("diagnose", 16),
|
|
20885
|
+
messages.connectionRefreshing
|
|
20886
|
+
);
|
|
20887
|
+
void context.runLatest(() => diagnostics.refresh(), {
|
|
20888
|
+
success() {
|
|
20889
|
+
pending = false;
|
|
20890
|
+
refresh.disabled = false;
|
|
20891
|
+
refresh.replaceChildren(
|
|
20892
|
+
createRendererSettingsIcon("diagnose", 16),
|
|
20893
|
+
messages.connectionRefresh
|
|
20894
|
+
);
|
|
20895
|
+
render(diagnostics.snapshot());
|
|
20896
|
+
},
|
|
20897
|
+
failure(error51) {
|
|
20898
|
+
pending = false;
|
|
20899
|
+
refresh.disabled = false;
|
|
20900
|
+
refresh.replaceChildren(
|
|
20901
|
+
createRendererSettingsIcon("diagnose", 16),
|
|
20902
|
+
messages.connectionRefresh
|
|
20903
|
+
);
|
|
20904
|
+
const snapshot = diagnostics.snapshot();
|
|
20905
|
+
render({
|
|
20906
|
+
...snapshot,
|
|
20907
|
+
hosts: snapshot.hosts.map((host) => ({
|
|
20908
|
+
...host,
|
|
20909
|
+
agents: host.agents.map((agent) => ({
|
|
20910
|
+
...agent,
|
|
20911
|
+
availability: "error",
|
|
20912
|
+
error: {
|
|
20913
|
+
code: "internalError",
|
|
20914
|
+
message: error51 instanceof Error ? error51.message : String(error51),
|
|
20915
|
+
retryable: true,
|
|
20916
|
+
stage: "request"
|
|
20917
|
+
}
|
|
20918
|
+
}))
|
|
20919
|
+
}))
|
|
20920
|
+
});
|
|
20921
|
+
}
|
|
20922
|
+
});
|
|
20923
|
+
};
|
|
20924
|
+
const render = (snapshot) => {
|
|
20925
|
+
latestSnapshot = snapshot;
|
|
20926
|
+
disposeHostScroller();
|
|
20927
|
+
disposeHostScroller = () => void 0;
|
|
20928
|
+
content.replaceChildren();
|
|
20929
|
+
if (!snapshot) {
|
|
20930
|
+
const empty = document2.createElement("div");
|
|
20931
|
+
empty.className = "settings-empty";
|
|
20932
|
+
empty.textContent = messages.connectionNoRuntime;
|
|
20933
|
+
content.append(empty);
|
|
20934
|
+
return;
|
|
20935
|
+
}
|
|
20936
|
+
const selectedHost = (selectedHostId ? snapshot.hosts.find((host) => host.hostId === selectedHostId) : void 0) ?? snapshot.hosts.find((host) => host.active) ?? snapshot.hosts.find((host) => host.hostId === "local") ?? snapshot.hosts[0];
|
|
20937
|
+
if (!selectedHost) return;
|
|
20938
|
+
selectedHostId = selectedHost.hostId;
|
|
20939
|
+
const layout = document2.createElement("div");
|
|
20940
|
+
layout.className = "settings-connections-layout";
|
|
20941
|
+
const list = document2.createElement("section");
|
|
20942
|
+
list.className = "settings-connection-list";
|
|
20943
|
+
const hostStrip = document2.createElement("div");
|
|
20944
|
+
hostStrip.className = "settings-connection-host-strip";
|
|
20945
|
+
const scrollLeft = createHostScrollButton(document2, "left", messages);
|
|
20946
|
+
const tabs = document2.createElement("div");
|
|
20947
|
+
tabs.className = "settings-connection-host-tabs";
|
|
20948
|
+
tabs.setAttribute("role", "tablist");
|
|
20949
|
+
tabs.setAttribute("aria-label", messages.connectionHosts);
|
|
20950
|
+
const scrollRight = createHostScrollButton(document2, "right", messages);
|
|
20951
|
+
const panelId = "codexhost-settings-connection-host-panel";
|
|
20952
|
+
snapshot.hosts.forEach((host, index) => {
|
|
20953
|
+
const tab = document2.createElement("button");
|
|
20954
|
+
tab.type = "button";
|
|
20955
|
+
tab.className = "settings-connection-host-tab";
|
|
20956
|
+
tab.dataset.connectionHostTab = host.hostId;
|
|
20957
|
+
tab.dataset.connectionHostActive = String(host.active);
|
|
20958
|
+
tab.setAttribute("role", "tab");
|
|
20959
|
+
tab.setAttribute("aria-controls", panelId);
|
|
20960
|
+
tab.setAttribute("aria-selected", String(host.hostId === selectedHost.hostId));
|
|
20961
|
+
tab.tabIndex = host.hostId === selectedHost.hostId ? 0 : -1;
|
|
20962
|
+
const hostName = connectionHostName(host.hostId, messages);
|
|
20963
|
+
tab.textContent = hostName;
|
|
20964
|
+
tab.title = host.active ? `${hostName} \xB7 ${messages.connectionActiveHost}` : hostName;
|
|
20965
|
+
tab.addEventListener("click", () => {
|
|
20966
|
+
selectedHostId = host.hostId;
|
|
20967
|
+
render(latestSnapshot);
|
|
20968
|
+
});
|
|
20969
|
+
tab.addEventListener("keydown", (event) => {
|
|
20970
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
20971
|
+
event.preventDefault();
|
|
20972
|
+
const direction = event.key === "ArrowRight" ? 1 : -1;
|
|
20973
|
+
const next = snapshot.hosts[(index + direction + snapshot.hosts.length) % snapshot.hosts.length];
|
|
20974
|
+
if (!next) return;
|
|
20975
|
+
selectedHostId = next.hostId;
|
|
20976
|
+
render(latestSnapshot);
|
|
20977
|
+
const nextTab = [
|
|
20978
|
+
...content.querySelectorAll("[data-connection-host-tab]")
|
|
20979
|
+
].find((candidate) => candidate.dataset.connectionHostTab === next.hostId);
|
|
20980
|
+
nextTab?.focus();
|
|
20981
|
+
});
|
|
20982
|
+
tabs.append(tab);
|
|
20983
|
+
});
|
|
20984
|
+
hostStrip.append(scrollLeft, tabs, scrollRight);
|
|
20985
|
+
const tableHeader = document2.createElement("div");
|
|
20986
|
+
tableHeader.className = "settings-connection-table-header";
|
|
20987
|
+
tableHeader.setAttribute("role", "row");
|
|
20988
|
+
const componentHeading = document2.createElement("span");
|
|
20989
|
+
componentHeading.textContent = messages.connectionComponent;
|
|
20990
|
+
componentHeading.setAttribute("role", "columnheader");
|
|
20991
|
+
const statusHeading = document2.createElement("span");
|
|
20992
|
+
statusHeading.textContent = messages.connectionStatus;
|
|
20993
|
+
statusHeading.setAttribute("role", "columnheader");
|
|
20994
|
+
const actionHeading = document2.createElement("span");
|
|
20995
|
+
actionHeading.setAttribute("aria-hidden", "true");
|
|
20996
|
+
tableHeader.append(componentHeading, statusHeading, actionHeading);
|
|
20997
|
+
const rows = document2.createElement("div");
|
|
20998
|
+
rows.className = "settings-connection-rows";
|
|
20999
|
+
rows.id = panelId;
|
|
21000
|
+
rows.dataset.connectionHost = selectedHost.hostId;
|
|
21001
|
+
rows.setAttribute("role", "rowgroup");
|
|
21002
|
+
const inspector = document2.createElement("aside");
|
|
21003
|
+
inspector.className = "settings-connection-inspector";
|
|
21004
|
+
inspector.setAttribute("aria-live", "polite");
|
|
21005
|
+
const items = connectionItems(snapshot, selectedHost, messages);
|
|
21006
|
+
if (!items.some((item) => item.key === selectedItemKey)) {
|
|
21007
|
+
selectedItemKey = items.find(
|
|
21008
|
+
(item) => item.agentSnapshot?.availability === "notInstalled" || item.error !== null
|
|
21009
|
+
)?.key ?? items[0]?.key ?? null;
|
|
21010
|
+
}
|
|
21011
|
+
const rowElements = /* @__PURE__ */ new Map();
|
|
21012
|
+
const selectItem = (item) => {
|
|
21013
|
+
selectedItemKey = item.key;
|
|
21014
|
+
for (const [key, row] of rowElements) {
|
|
21015
|
+
const selected = key === item.key;
|
|
21016
|
+
row.dataset.connectionSelected = String(selected);
|
|
21017
|
+
row.tabIndex = selected ? 0 : -1;
|
|
21018
|
+
}
|
|
21019
|
+
renderConnectionInspector(document2, inspector, item, selectedHost.hostId, messages);
|
|
21020
|
+
};
|
|
21021
|
+
for (const item of items) {
|
|
21022
|
+
const row = createConnectionRow(
|
|
21023
|
+
document2,
|
|
21024
|
+
item,
|
|
21025
|
+
messages,
|
|
21026
|
+
item.key === selectedItemKey,
|
|
21027
|
+
() => selectItem(item)
|
|
21028
|
+
);
|
|
21029
|
+
rowElements.set(item.key, row);
|
|
21030
|
+
rows.append(row);
|
|
21031
|
+
}
|
|
21032
|
+
const selectedItem = items.find((item) => item.key === selectedItemKey) ?? items[0];
|
|
21033
|
+
if (selectedItem) selectItem(selectedItem);
|
|
21034
|
+
list.append(hostStrip, tableHeader, rows);
|
|
21035
|
+
layout.append(list, inspector);
|
|
21036
|
+
content.append(layout);
|
|
21037
|
+
disposeHostScroller = configureHostScroller(
|
|
21038
|
+
document2,
|
|
21039
|
+
hostStrip,
|
|
21040
|
+
tabs,
|
|
21041
|
+
scrollLeft,
|
|
21042
|
+
scrollRight
|
|
21043
|
+
);
|
|
21044
|
+
const selectedTab = [...tabs.children].find(
|
|
21045
|
+
(child) => child.getAttribute("aria-selected") === "true"
|
|
21046
|
+
);
|
|
21047
|
+
selectedTab?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
21048
|
+
};
|
|
21049
|
+
render(diagnostics?.snapshot() ?? null);
|
|
21050
|
+
if (!diagnostics) {
|
|
21051
|
+
refresh.disabled = true;
|
|
21052
|
+
return void 0;
|
|
21053
|
+
}
|
|
21054
|
+
refresh.addEventListener("click", runRefresh);
|
|
21055
|
+
const unsubscribe = diagnostics.subscribe(() => render(diagnostics.snapshot()));
|
|
21056
|
+
return () => {
|
|
21057
|
+
disposeHostScroller();
|
|
21058
|
+
unsubscribe();
|
|
21059
|
+
};
|
|
21060
|
+
}
|
|
21061
|
+
});
|
|
21062
|
+
}
|
|
21063
|
+
|
|
21064
|
+
// src/settings/release-notes.ts
|
|
21065
|
+
var HEADING_PATTERN = /^(#{1,6})[ \t]+(.+?)\s*$/u;
|
|
21066
|
+
var BLOCKQUOTE_PATTERN = /^>[ \t]?(.*?)\s*$/u;
|
|
21067
|
+
var UNORDERED_ITEM_PATTERN = /^[-*][ \t]+(.+?)\s*$/u;
|
|
21068
|
+
var CONTINUATION_PATTERN = /^[ \t]+(.+?)\s*$/u;
|
|
21069
|
+
var ORDERED_ITEM_PATTERN = /^\d+[.)][ \t]+(.+?)\s*$/u;
|
|
21070
|
+
var FENCE_PATTERN = /^```([\w+-]*)\s*$/u;
|
|
21071
|
+
var THEMATIC_BREAK_PATTERN = /^(?:---|___|\*\*\*)[ \t]*$/u;
|
|
21072
|
+
var INLINE_PATTERN = /(`+)((?:(?!\1).)+)\1|\*\*(.+?)\*\*|\[([^\]]+)\]\(([^)\s]+)\)/gu;
|
|
21073
|
+
function createReleaseNotesElement(document2, markdown) {
|
|
21074
|
+
const root = document2.createElement("div");
|
|
21075
|
+
root.className = "settings-update-notes";
|
|
21076
|
+
appendReleaseNotesBlocks(document2, root, markdown);
|
|
21077
|
+
return root;
|
|
21078
|
+
}
|
|
21079
|
+
function appendReleaseNotesBlocks(document2, root, markdown) {
|
|
21080
|
+
const lines = markdown.replaceAll("\r\n", "\n").split("\n");
|
|
21081
|
+
let index = 0;
|
|
21082
|
+
while (index < lines.length) {
|
|
21083
|
+
const line = lines[index] ?? "";
|
|
21084
|
+
if (line.trim().length === 0) {
|
|
21085
|
+
index += 1;
|
|
21086
|
+
continue;
|
|
21087
|
+
}
|
|
21088
|
+
const fence = FENCE_PATTERN.exec(line);
|
|
21089
|
+
if (fence) {
|
|
21090
|
+
index = appendFencedCode(document2, root, lines, index, fence[1] ?? "");
|
|
21091
|
+
continue;
|
|
21092
|
+
}
|
|
21093
|
+
const heading = HEADING_PATTERN.exec(line);
|
|
21094
|
+
if (heading?.[1] && heading[2]) {
|
|
21095
|
+
const tag = `h${heading[1].length}`;
|
|
21096
|
+
const element = document2.createElement(tag);
|
|
21097
|
+
appendInline(document2, element, heading[2]);
|
|
21098
|
+
root.append(element);
|
|
21099
|
+
index += 1;
|
|
21100
|
+
continue;
|
|
21101
|
+
}
|
|
21102
|
+
if (BLOCKQUOTE_PATTERN.test(line)) {
|
|
21103
|
+
index = appendBlockquote(document2, root, lines, index);
|
|
21104
|
+
continue;
|
|
21105
|
+
}
|
|
21106
|
+
if (THEMATIC_BREAK_PATTERN.test(line)) {
|
|
21107
|
+
root.append(document2.createElement("hr"));
|
|
21108
|
+
index += 1;
|
|
21109
|
+
continue;
|
|
21110
|
+
}
|
|
21111
|
+
if (UNORDERED_ITEM_PATTERN.test(line)) {
|
|
21112
|
+
index = appendList(document2, root, lines, index, "ul", UNORDERED_ITEM_PATTERN);
|
|
21113
|
+
continue;
|
|
21114
|
+
}
|
|
21115
|
+
if (ORDERED_ITEM_PATTERN.test(line)) {
|
|
21116
|
+
index = appendList(document2, root, lines, index, "ol", ORDERED_ITEM_PATTERN);
|
|
21117
|
+
continue;
|
|
21118
|
+
}
|
|
21119
|
+
index = appendParagraph(document2, root, lines, index);
|
|
21120
|
+
}
|
|
21121
|
+
}
|
|
21122
|
+
function appendFencedCode(document2, root, lines, start, language) {
|
|
21123
|
+
const body = [];
|
|
21124
|
+
let index = start + 1;
|
|
21125
|
+
while (index < lines.length && !FENCE_PATTERN.test(lines[index] ?? "")) {
|
|
21126
|
+
body.push(lines[index] ?? "");
|
|
21127
|
+
index += 1;
|
|
21128
|
+
}
|
|
21129
|
+
if (index < lines.length) index += 1;
|
|
21130
|
+
const pre = document2.createElement("pre");
|
|
21131
|
+
const code = document2.createElement("code");
|
|
21132
|
+
if (language.length > 0) code.className = `language-${language}`;
|
|
21133
|
+
code.textContent = body.join("\n");
|
|
21134
|
+
pre.append(code);
|
|
21135
|
+
root.append(pre);
|
|
21136
|
+
return index;
|
|
21137
|
+
}
|
|
21138
|
+
function appendBlockquote(document2, root, lines, start) {
|
|
21139
|
+
const blockquote = document2.createElement("blockquote");
|
|
21140
|
+
const content = [];
|
|
21141
|
+
let index = start;
|
|
21142
|
+
while (index < lines.length) {
|
|
21143
|
+
const match = BLOCKQUOTE_PATTERN.exec(lines[index] ?? "");
|
|
21144
|
+
if (!match) break;
|
|
21145
|
+
content.push(match[1] ?? "");
|
|
21146
|
+
index += 1;
|
|
21147
|
+
}
|
|
21148
|
+
const paragraph = document2.createElement("p");
|
|
21149
|
+
appendInline(document2, paragraph, content.join(" ").trim());
|
|
21150
|
+
blockquote.append(paragraph);
|
|
21151
|
+
root.append(blockquote);
|
|
21152
|
+
return index;
|
|
21153
|
+
}
|
|
21154
|
+
function appendList(document2, root, lines, start, tag, pattern) {
|
|
21155
|
+
const list = document2.createElement(tag);
|
|
21156
|
+
let index = start;
|
|
21157
|
+
while (index < lines.length) {
|
|
21158
|
+
const item = pattern.exec(lines[index] ?? "");
|
|
20206
21159
|
if (!item?.[1]) break;
|
|
20207
21160
|
const entry = document2.createElement("li");
|
|
20208
21161
|
appendInline(document2, entry, item[1]);
|
|
@@ -20265,424 +21218,107 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20265
21218
|
const link = document2.createElement("a");
|
|
20266
21219
|
link.textContent = match[4] ?? "";
|
|
20267
21220
|
link.setAttribute("href", href);
|
|
20268
|
-
link.setAttribute("target", "_blank");
|
|
20269
|
-
link.setAttribute("rel", "noopener noreferrer");
|
|
20270
|
-
parent.append(link);
|
|
20271
|
-
}
|
|
20272
|
-
}
|
|
20273
|
-
lastIndex = index + match[0].length;
|
|
20274
|
-
}
|
|
20275
|
-
if (lastIndex < text.length) parent.append(text.slice(lastIndex));
|
|
20276
|
-
}
|
|
20277
|
-
function isSafeLink(href) {
|
|
20278
|
-
try {
|
|
20279
|
-
const url2 = new URL(href, "https://codexhost.invalid");
|
|
20280
|
-
return url2.protocol === "http:" || url2.protocol === "https:";
|
|
20281
|
-
} catch {
|
|
20282
|
-
return false;
|
|
20283
|
-
}
|
|
20284
|
-
}
|
|
20285
|
-
|
|
20286
|
-
// src/settings/update-request.ts
|
|
20287
|
-
var RENDERER_UPDATE_REQUEST_TIMEOUT_MS = 15e3;
|
|
20288
|
-
var RendererUpdateRequestTimeoutError = class extends Error {
|
|
20289
|
-
constructor() {
|
|
20290
|
-
super("Update request timed out");
|
|
20291
|
-
this.name = "RendererUpdateRequestTimeoutError";
|
|
20292
|
-
}
|
|
20293
|
-
};
|
|
20294
|
-
function runBoundedRendererUpdateRequest(operation, signal, timeoutMs = RENDERER_UPDATE_REQUEST_TIMEOUT_MS) {
|
|
20295
|
-
return new Promise((resolve, reject) => {
|
|
20296
|
-
let settled = false;
|
|
20297
|
-
const settle = (handler) => {
|
|
20298
|
-
if (settled) return;
|
|
20299
|
-
settled = true;
|
|
20300
|
-
clearTimeout(timeout);
|
|
20301
|
-
signal.removeEventListener("abort", abort);
|
|
20302
|
-
handler();
|
|
20303
|
-
};
|
|
20304
|
-
const timeout = setTimeout(() => {
|
|
20305
|
-
settle(() => reject(new RendererUpdateRequestTimeoutError()));
|
|
20306
|
-
}, timeoutMs);
|
|
20307
|
-
const abort = () => {
|
|
20308
|
-
settle(() => reject(new Error("Update request was aborted")));
|
|
20309
|
-
};
|
|
20310
|
-
const rejectRequest = (error51) => {
|
|
20311
|
-
settle(() => reject(error51));
|
|
20312
|
-
};
|
|
20313
|
-
if (signal.aborted) {
|
|
20314
|
-
abort();
|
|
20315
|
-
return;
|
|
20316
|
-
}
|
|
20317
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
20318
|
-
try {
|
|
20319
|
-
void operation().then(
|
|
20320
|
-
(value) => settle(() => resolve(value)),
|
|
20321
|
-
(error51) => rejectRequest(error51)
|
|
20322
|
-
);
|
|
20323
|
-
} catch (error51) {
|
|
20324
|
-
rejectRequest(error51);
|
|
20325
|
-
}
|
|
20326
|
-
});
|
|
20327
|
-
}
|
|
20328
|
-
|
|
20329
|
-
// src/settings/pages.ts
|
|
20330
|
-
var CODEXHOST_RELEASES_LATEST_URL = "https://github.com/BytePioneer-AI/codex-host/releases/latest";
|
|
20331
|
-
var CODEXHOST_NPM_MANUAL_UPDATE_COMMAND = "npm install -g @codexhost/cli@latest";
|
|
20332
|
-
var DEFAULT_RENDERER_SETTINGS_PAGE_IDS = [
|
|
20333
|
-
"connections",
|
|
20334
|
-
"model-pool",
|
|
20335
|
-
"routes",
|
|
20336
|
-
"gateway",
|
|
20337
|
-
"updates"
|
|
20338
|
-
];
|
|
20339
|
-
function appendUnavailableStatus(content, messages) {
|
|
20340
|
-
const status = content.ownerDocument.createElement("div");
|
|
20341
|
-
status.className = "settings-empty";
|
|
20342
|
-
const copy = content.ownerDocument.createElement("div");
|
|
20343
|
-
const title = content.ownerDocument.createElement("strong");
|
|
20344
|
-
title.textContent = messages.inDevelopment;
|
|
20345
|
-
copy.append(title);
|
|
20346
|
-
status.append(copy);
|
|
20347
|
-
content.append(status);
|
|
20348
|
-
}
|
|
20349
|
-
function unavailablePage(id, messages) {
|
|
20350
|
-
return Object.freeze({
|
|
20351
|
-
id,
|
|
20352
|
-
label: messages.pageLabels[id],
|
|
20353
|
-
icon: id,
|
|
20354
|
-
mount(context) {
|
|
20355
|
-
appendUnavailableStatus(context.content, messages);
|
|
20356
|
-
return void 0;
|
|
20357
|
-
}
|
|
20358
|
-
});
|
|
20359
|
-
}
|
|
20360
|
-
function connectionStatusLabel(availability, messages) {
|
|
20361
|
-
if (availability === "ready") return messages.connectionStatusReady;
|
|
20362
|
-
if (availability === "checking") return messages.connectionStatusChecking;
|
|
20363
|
-
if (availability === "notInstalled") return messages.connectionStatusNotInstalled;
|
|
20364
|
-
if (availability === "unavailable" || availability === "error") {
|
|
20365
|
-
return availability === "error" ? messages.connectionStatusError : messages.connectionStatusUnavailable;
|
|
20366
|
-
}
|
|
20367
|
-
return availability === "installing" ? messages.connectionStatusInstalling : messages.connectionStatusUnsupported;
|
|
20368
|
-
}
|
|
20369
|
-
function connectionStatusTone(availability) {
|
|
20370
|
-
if (availability === "ready") return "ready";
|
|
20371
|
-
if (availability === "checking" || availability === "installing") return "checking";
|
|
20372
|
-
return "failed";
|
|
20373
|
-
}
|
|
20374
|
-
function diagnosticText(hostId, name, snapshot) {
|
|
20375
|
-
const error51 = snapshot.error;
|
|
20376
|
-
const lines = [
|
|
20377
|
-
"codexhost connection diagnostics",
|
|
20378
|
-
`host: ${hostId}`,
|
|
20379
|
-
`agent: ${name}`,
|
|
20380
|
-
`status: ${snapshot.availability}`,
|
|
20381
|
-
...error51 ? [
|
|
20382
|
-
`error.code: ${error51.code}`,
|
|
20383
|
-
`error.message: ${error51.message}`,
|
|
20384
|
-
`retryable: ${error51.retryable}`,
|
|
20385
|
-
...error51.stage ? [`stage: ${error51.stage}`] : [],
|
|
20386
|
-
...error51.durationMs !== void 0 ? [`durationMs: ${error51.durationMs}`] : [],
|
|
20387
|
-
...error51.diagnostic ? [`diagnostic: ${error51.diagnostic}`] : [],
|
|
20388
|
-
...error51.stderrTail ? [`stderr:
|
|
20389
|
-
${error51.stderrTail}`] : []
|
|
20390
|
-
] : []
|
|
20391
|
-
];
|
|
20392
|
-
return lines.join("\n");
|
|
20393
|
-
}
|
|
20394
|
-
function detailLine(document2, label, value) {
|
|
20395
|
-
const line = document2.createElement("div");
|
|
20396
|
-
line.className = "settings-connection-detail-line";
|
|
20397
|
-
const name = document2.createElement("span");
|
|
20398
|
-
name.textContent = label;
|
|
20399
|
-
const content = document2.createElement("code");
|
|
20400
|
-
content.textContent = value;
|
|
20401
|
-
line.append(name, content);
|
|
20402
|
-
return line;
|
|
20403
|
-
}
|
|
20404
|
-
function setCopyButtonLabel(button, label) {
|
|
20405
|
-
button.replaceChildren(createRendererSettingsIcon("copy", 16), label);
|
|
20406
|
-
}
|
|
20407
|
-
function showCopyButtonFeedback(button, label, restoreLabel) {
|
|
20408
|
-
setCopyButtonLabel(button, label);
|
|
20409
|
-
button.ownerDocument.defaultView?.setTimeout(() => {
|
|
20410
|
-
setCopyButtonLabel(button, restoreLabel);
|
|
20411
|
-
}, 2e3);
|
|
20412
|
-
}
|
|
20413
|
-
function copyDiagnosticsToClipboard(document2, button, report, messages, restoreLabel) {
|
|
20414
|
-
const clipboard = document2.defaultView?.navigator.clipboard;
|
|
20415
|
-
if (!clipboard) {
|
|
20416
|
-
showCopyButtonFeedback(button, messages.connectionCopyFailed, restoreLabel);
|
|
20417
|
-
return;
|
|
20418
|
-
}
|
|
20419
|
-
void clipboard.writeText(report).then(
|
|
20420
|
-
() => showCopyButtonFeedback(button, messages.connectionCopied, restoreLabel),
|
|
20421
|
-
() => showCopyButtonFeedback(button, messages.connectionCopyFailed, restoreLabel)
|
|
20422
|
-
);
|
|
20423
|
-
}
|
|
20424
|
-
function appendConnectionRow(document2, parent, name, availability, detail, error51, messages, rowAttribute, diagnosticSnapshot, diagnosticHostId) {
|
|
20425
|
-
const row = document2.createElement("div");
|
|
20426
|
-
row.className = "settings-connection-row";
|
|
20427
|
-
if (rowAttribute) row.dataset.connectionAgent = rowAttribute;
|
|
20428
|
-
const identity = document2.createElement("div");
|
|
20429
|
-
identity.className = "settings-connection-row__identity";
|
|
20430
|
-
const dot = document2.createElement("span");
|
|
20431
|
-
dot.className = "settings-connection-row__dot";
|
|
20432
|
-
dot.dataset.connectionTone = connectionStatusTone(availability);
|
|
20433
|
-
dot.setAttribute("aria-hidden", "true");
|
|
20434
|
-
const label = document2.createElement("strong");
|
|
20435
|
-
label.textContent = name;
|
|
20436
|
-
identity.append(dot, label);
|
|
20437
|
-
const status = document2.createElement("span");
|
|
20438
|
-
status.className = "settings-status-badge";
|
|
20439
|
-
status.dataset.connectionTone = connectionStatusTone(availability);
|
|
20440
|
-
status.textContent = connectionStatusLabel(availability, messages);
|
|
20441
|
-
const detailElement = document2.createElement("div");
|
|
20442
|
-
detailElement.className = "settings-connection-row__detail";
|
|
20443
|
-
const summary = document2.createElement("span");
|
|
20444
|
-
summary.className = "settings-connection-row__reason";
|
|
20445
|
-
summary.textContent = error51 ? `${messages.connectionReason}: ${error51.code}: ${error51.message}` : detail ? `${messages.connectionReason}: ${detail}` : "";
|
|
20446
|
-
detailElement.append(summary);
|
|
20447
|
-
let toggle = null;
|
|
20448
|
-
if (error51) {
|
|
20449
|
-
toggle = document2.createElement("button");
|
|
20450
|
-
toggle.type = "button";
|
|
20451
|
-
toggle.className = "settings-connection-details-toggle";
|
|
20452
|
-
toggle.textContent = messages.connectionViewDetails;
|
|
20453
|
-
toggle.setAttribute("aria-expanded", "true");
|
|
20454
|
-
detailElement.append(toggle);
|
|
20455
|
-
}
|
|
20456
|
-
const details = document2.createElement("div");
|
|
20457
|
-
details.className = "settings-connection-details";
|
|
20458
|
-
details.hidden = !error51;
|
|
20459
|
-
if (error51) {
|
|
20460
|
-
details.append(
|
|
20461
|
-
detailLine(document2, messages.connectionErrorCode, error51.code),
|
|
20462
|
-
detailLine(document2, messages.connectionErrorMessage, error51.message),
|
|
20463
|
-
detailLine(document2, messages.connectionRetryable, String(error51.retryable))
|
|
20464
|
-
);
|
|
20465
|
-
if (error51.stage)
|
|
20466
|
-
details.append(detailLine(document2, messages.connectionFailureStage, error51.stage));
|
|
20467
|
-
if (error51.durationMs !== void 0) {
|
|
20468
|
-
details.append(detailLine(document2, messages.connectionDuration, `${error51.durationMs} ms`));
|
|
20469
|
-
}
|
|
20470
|
-
if (error51.diagnostic)
|
|
20471
|
-
details.append(detailLine(document2, messages.connectionDiagnostic, error51.diagnostic));
|
|
20472
|
-
if (error51.stderrTail) {
|
|
20473
|
-
const stderr = document2.createElement("pre");
|
|
20474
|
-
stderr.className = "settings-connection-stderr";
|
|
20475
|
-
stderr.textContent = error51.stderrTail;
|
|
20476
|
-
details.append(stderr);
|
|
20477
|
-
}
|
|
20478
|
-
const copy = document2.createElement("button");
|
|
20479
|
-
copy.type = "button";
|
|
20480
|
-
copy.className = "settings-command-button settings-command-button--secondary";
|
|
20481
|
-
setCopyButtonLabel(copy, messages.connectionCopyDetails);
|
|
20482
|
-
copy.addEventListener("click", () => {
|
|
20483
|
-
if (!diagnosticSnapshot) return;
|
|
20484
|
-
copyDiagnosticsToClipboard(
|
|
20485
|
-
document2,
|
|
20486
|
-
copy,
|
|
20487
|
-
diagnosticText(diagnosticHostId ?? "unknown", name, diagnosticSnapshot),
|
|
20488
|
-
messages,
|
|
20489
|
-
messages.connectionCopyDetails
|
|
20490
|
-
);
|
|
20491
|
-
});
|
|
20492
|
-
details.append(copy);
|
|
20493
|
-
}
|
|
20494
|
-
if (toggle) {
|
|
20495
|
-
toggle.addEventListener("click", () => {
|
|
20496
|
-
details.hidden = !details.hidden;
|
|
20497
|
-
toggle?.setAttribute("aria-expanded", String(!details.hidden));
|
|
20498
|
-
});
|
|
21221
|
+
link.setAttribute("target", "_blank");
|
|
21222
|
+
link.setAttribute("rel", "noopener noreferrer");
|
|
21223
|
+
parent.append(link);
|
|
21224
|
+
}
|
|
21225
|
+
}
|
|
21226
|
+
lastIndex = index + match[0].length;
|
|
20499
21227
|
}
|
|
20500
|
-
|
|
20501
|
-
parent.append(row);
|
|
21228
|
+
if (lastIndex < text.length) parent.append(text.slice(lastIndex));
|
|
20502
21229
|
}
|
|
20503
|
-
function
|
|
20504
|
-
const activeLabel = active ? ` \xB7 ${messages.connectionActiveHost}` : "";
|
|
20505
|
-
if (hostId === "local") return `${messages.connectionLocalHost}${activeLabel}`;
|
|
20506
|
-
const separator = hostId.lastIndexOf(":");
|
|
20507
|
-
const encodedName = separator >= 0 ? hostId.slice(separator + 1) : hostId;
|
|
20508
|
-
let name = encodedName;
|
|
21230
|
+
function isSafeLink(href) {
|
|
20509
21231
|
try {
|
|
20510
|
-
|
|
21232
|
+
const url2 = new URL(href, "https://codexhost.invalid");
|
|
21233
|
+
return url2.protocol === "http:" || url2.protocol === "https:";
|
|
20511
21234
|
} catch {
|
|
21235
|
+
return false;
|
|
20512
21236
|
}
|
|
20513
|
-
return `${messages.connectionRemoteHost}: ${name}${activeLabel}`;
|
|
20514
21237
|
}
|
|
20515
|
-
|
|
20516
|
-
|
|
20517
|
-
|
|
20518
|
-
|
|
20519
|
-
|
|
20520
|
-
|
|
20521
|
-
|
|
20522
|
-
|
|
20523
|
-
|
|
20524
|
-
|
|
20525
|
-
|
|
20526
|
-
|
|
20527
|
-
|
|
20528
|
-
|
|
20529
|
-
|
|
20530
|
-
|
|
20531
|
-
|
|
20532
|
-
|
|
20533
|
-
|
|
20534
|
-
|
|
20535
|
-
|
|
20536
|
-
|
|
20537
|
-
|
|
20538
|
-
|
|
20539
|
-
|
|
20540
|
-
|
|
20541
|
-
|
|
20542
|
-
|
|
20543
|
-
|
|
20544
|
-
|
|
20545
|
-
|
|
20546
|
-
|
|
20547
|
-
|
|
20548
|
-
|
|
20549
|
-
|
|
20550
|
-
|
|
20551
|
-
|
|
20552
|
-
|
|
20553
|
-
|
|
20554
|
-
|
|
20555
|
-
return;
|
|
20556
|
-
}
|
|
20557
|
-
appendConnectionRow(
|
|
20558
|
-
document2,
|
|
20559
|
-
content,
|
|
20560
|
-
messages.connectionAdapter,
|
|
20561
|
-
snapshot.adapter.state,
|
|
20562
|
-
`reason=${snapshot.adapter.reason}, hook=${snapshot.adapter.hook ?? "none"}`,
|
|
20563
|
-
null,
|
|
20564
|
-
messages,
|
|
20565
|
-
"renderer-adapter"
|
|
20566
|
-
);
|
|
20567
|
-
const selectedHost = snapshot.hosts.find((host) => host.hostId === selectedHostId) ?? snapshot.hosts.find((host) => host.hostId === "local") ?? snapshot.hosts[0];
|
|
20568
|
-
if (!selectedHost) return;
|
|
20569
|
-
selectedHostId = selectedHost.hostId;
|
|
20570
|
-
const tabs = document2.createElement("div");
|
|
20571
|
-
tabs.className = "settings-connection-host-tabs";
|
|
20572
|
-
tabs.setAttribute("role", "tablist");
|
|
20573
|
-
tabs.setAttribute("aria-label", messages.connectionHosts);
|
|
20574
|
-
const hostSection = document2.createElement("section");
|
|
20575
|
-
hostSection.className = "settings-connection-host";
|
|
20576
|
-
hostSection.dataset.connectionHost = selectedHost.hostId;
|
|
20577
|
-
hostSection.setAttribute("role", "tabpanel");
|
|
20578
|
-
const panelId = "codexhost-settings-connection-host-panel";
|
|
20579
|
-
hostSection.id = panelId;
|
|
20580
|
-
for (const host of snapshot.hosts) {
|
|
20581
|
-
const tab = document2.createElement("button");
|
|
20582
|
-
tab.type = "button";
|
|
20583
|
-
tab.className = "settings-connection-host-tab";
|
|
20584
|
-
tab.dataset.connectionHostTab = host.hostId;
|
|
20585
|
-
tab.setAttribute("role", "tab");
|
|
20586
|
-
tab.setAttribute("aria-controls", panelId);
|
|
20587
|
-
tab.setAttribute("aria-selected", String(host.hostId === selectedHost.hostId));
|
|
20588
|
-
tab.tabIndex = host.hostId === selectedHost.hostId ? 0 : -1;
|
|
20589
|
-
tab.textContent = connectionHostLabel(host.hostId, host.active, messages);
|
|
20590
|
-
tab.addEventListener("click", () => {
|
|
20591
|
-
selectedHostId = host.hostId;
|
|
20592
|
-
render(latestSnapshot);
|
|
20593
|
-
});
|
|
20594
|
-
tabs.append(tab);
|
|
20595
|
-
}
|
|
20596
|
-
for (const agent of selectedHost.agents) {
|
|
20597
|
-
appendConnectionRow(
|
|
20598
|
-
document2,
|
|
20599
|
-
hostSection,
|
|
20600
|
-
RENDERER_AGENT_LABELS[agent.agent],
|
|
20601
|
-
agent.availability,
|
|
20602
|
-
null,
|
|
20603
|
-
agent.error,
|
|
20604
|
-
messages,
|
|
20605
|
-
agent.agent,
|
|
20606
|
-
agent,
|
|
20607
|
-
selectedHost.hostId
|
|
20608
|
-
);
|
|
20609
|
-
}
|
|
20610
|
-
content.append(tabs, hostSection);
|
|
20611
|
-
};
|
|
20612
|
-
const diagnostics = getDiagnostics();
|
|
20613
|
-
render(diagnostics?.snapshot() ?? null);
|
|
20614
|
-
if (!diagnostics) {
|
|
20615
|
-
copyAll.disabled = true;
|
|
20616
|
-
return void 0;
|
|
20617
|
-
}
|
|
20618
|
-
copyAll.addEventListener("click", () => {
|
|
20619
|
-
const snapshot = diagnostics.snapshot();
|
|
20620
|
-
const report = snapshot.hosts.flatMap(
|
|
20621
|
-
(host) => host.agents.map(
|
|
20622
|
-
(agent) => diagnosticText(host.hostId, RENDERER_AGENT_LABELS[agent.agent], agent)
|
|
20623
|
-
)
|
|
20624
|
-
).join("\n\n");
|
|
20625
|
-
copyDiagnosticsToClipboard(document2, copyAll, report, messages, messages.connectionCopyAll);
|
|
20626
|
-
});
|
|
20627
|
-
const unsubscribe = diagnostics.subscribe(() => render(diagnostics.snapshot()));
|
|
20628
|
-
refresh.addEventListener("click", () => {
|
|
20629
|
-
if (pending) return;
|
|
20630
|
-
pending = true;
|
|
20631
|
-
refresh.disabled = true;
|
|
20632
|
-
refresh.replaceChildren(
|
|
20633
|
-
createRendererSettingsIcon("diagnose", 16),
|
|
20634
|
-
messages.connectionRefreshing
|
|
20635
|
-
);
|
|
20636
|
-
void context.runLatest(() => diagnostics.refresh(), {
|
|
20637
|
-
success() {
|
|
20638
|
-
pending = false;
|
|
20639
|
-
refresh.disabled = false;
|
|
20640
|
-
refresh.replaceChildren(
|
|
20641
|
-
createRendererSettingsIcon("diagnose", 16),
|
|
20642
|
-
messages.connectionRefresh
|
|
20643
|
-
);
|
|
20644
|
-
render(diagnostics.snapshot());
|
|
20645
|
-
},
|
|
20646
|
-
failure(error51) {
|
|
20647
|
-
pending = false;
|
|
20648
|
-
refresh.disabled = false;
|
|
20649
|
-
refresh.replaceChildren(
|
|
20650
|
-
createRendererSettingsIcon("diagnose", 16),
|
|
20651
|
-
messages.connectionRefresh
|
|
20652
|
-
);
|
|
20653
|
-
const snapshot = diagnostics.snapshot();
|
|
20654
|
-
render({
|
|
20655
|
-
...snapshot,
|
|
20656
|
-
hosts: snapshot.hosts.map((host) => ({
|
|
20657
|
-
...host,
|
|
20658
|
-
agents: host.agents.map((agent) => ({
|
|
20659
|
-
...agent,
|
|
20660
|
-
availability: "error",
|
|
20661
|
-
error: {
|
|
20662
|
-
code: "internalError",
|
|
20663
|
-
message: error51 instanceof Error ? error51.message : String(error51),
|
|
20664
|
-
retryable: true,
|
|
20665
|
-
stage: "request"
|
|
20666
|
-
}
|
|
20667
|
-
}))
|
|
20668
|
-
}))
|
|
20669
|
-
});
|
|
20670
|
-
}
|
|
20671
|
-
});
|
|
20672
|
-
});
|
|
20673
|
-
return unsubscribe;
|
|
21238
|
+
|
|
21239
|
+
// src/settings/update-request.ts
|
|
21240
|
+
var RENDERER_UPDATE_REQUEST_TIMEOUT_MS = 15e3;
|
|
21241
|
+
var RendererUpdateRequestTimeoutError = class extends Error {
|
|
21242
|
+
constructor() {
|
|
21243
|
+
super("Update request timed out");
|
|
21244
|
+
this.name = "RendererUpdateRequestTimeoutError";
|
|
21245
|
+
}
|
|
21246
|
+
};
|
|
21247
|
+
function runBoundedRendererUpdateRequest(operation, signal, timeoutMs = RENDERER_UPDATE_REQUEST_TIMEOUT_MS) {
|
|
21248
|
+
return new Promise((resolve, reject) => {
|
|
21249
|
+
let settled = false;
|
|
21250
|
+
const settle = (handler) => {
|
|
21251
|
+
if (settled) return;
|
|
21252
|
+
settled = true;
|
|
21253
|
+
clearTimeout(timeout);
|
|
21254
|
+
signal.removeEventListener("abort", abort);
|
|
21255
|
+
handler();
|
|
21256
|
+
};
|
|
21257
|
+
const timeout = setTimeout(() => {
|
|
21258
|
+
settle(() => reject(new RendererUpdateRequestTimeoutError()));
|
|
21259
|
+
}, timeoutMs);
|
|
21260
|
+
const abort = () => {
|
|
21261
|
+
settle(() => reject(new Error("Update request was aborted")));
|
|
21262
|
+
};
|
|
21263
|
+
const rejectRequest = (error51) => {
|
|
21264
|
+
settle(() => reject(error51));
|
|
21265
|
+
};
|
|
21266
|
+
if (signal.aborted) {
|
|
21267
|
+
abort();
|
|
21268
|
+
return;
|
|
21269
|
+
}
|
|
21270
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
21271
|
+
try {
|
|
21272
|
+
void operation().then(
|
|
21273
|
+
(value) => settle(() => resolve(value)),
|
|
21274
|
+
(error51) => rejectRequest(error51)
|
|
21275
|
+
);
|
|
21276
|
+
} catch (error51) {
|
|
21277
|
+
rejectRequest(error51);
|
|
20674
21278
|
}
|
|
20675
21279
|
});
|
|
20676
21280
|
}
|
|
20677
|
-
|
|
20678
|
-
|
|
20679
|
-
|
|
20680
|
-
|
|
20681
|
-
|
|
20682
|
-
|
|
20683
|
-
|
|
20684
|
-
|
|
20685
|
-
|
|
21281
|
+
|
|
21282
|
+
// src/settings/pages.ts
|
|
21283
|
+
var CODEXHOST_GITHUB_REPOSITORY_URL = "https://github.com/BytePioneer-AI/codex-host";
|
|
21284
|
+
var CODEXHOST_RELEASES_LATEST_URL = `${CODEXHOST_GITHUB_REPOSITORY_URL}/releases/latest`;
|
|
21285
|
+
var CODEXHOST_NPM_MANUAL_UPDATE_COMMAND = "npm install -g @codexhost/cli@latest";
|
|
21286
|
+
function rendererUserAgentData(navigator2) {
|
|
21287
|
+
return navigator2.userAgentData;
|
|
21288
|
+
}
|
|
21289
|
+
function isWindowsRenderer(window2) {
|
|
21290
|
+
const navigator2 = window2?.navigator;
|
|
21291
|
+
if (!navigator2) return false;
|
|
21292
|
+
const identity = `${rendererUserAgentData(navigator2)?.platform ?? ""} ${navigator2.platform ?? ""} ${navigator2.userAgent}`;
|
|
21293
|
+
return /windows|win32|win64/iu.test(identity);
|
|
21294
|
+
}
|
|
21295
|
+
function windowsInstallerDownloadUrl(window2, version2) {
|
|
21296
|
+
const navigator2 = window2?.navigator;
|
|
21297
|
+
const hints = navigator2 ? rendererUserAgentData(navigator2) : void 0;
|
|
21298
|
+
const identity = `${hints?.architecture ?? ""} ${hints?.platform ?? ""} ${navigator2?.platform ?? ""} ${navigator2?.userAgent ?? ""}`;
|
|
21299
|
+
const architecture = /arm64|aarch64|\barm\b/iu.test(identity) ? "arm64" : "x64";
|
|
21300
|
+
return `https://github.com/BytePioneer-AI/codex-host/releases/download/v${version2}/codexhost-${version2}-windows-${architecture}.exe`;
|
|
21301
|
+
}
|
|
21302
|
+
function panelIconName(view) {
|
|
21303
|
+
if (view === "failed" || view === "error") return "alert";
|
|
21304
|
+
if (view === "unavailable") return "unavailable";
|
|
21305
|
+
if (view === "current") return "check";
|
|
21306
|
+
return "updates";
|
|
21307
|
+
}
|
|
21308
|
+
function createPanelHead(document2, view, title) {
|
|
21309
|
+
const head = document2.createElement("div");
|
|
21310
|
+
head.className = "settings-update-panel__head";
|
|
21311
|
+
const label = document2.createElement("strong");
|
|
21312
|
+
label.className = "settings-update-panel__title";
|
|
21313
|
+
label.textContent = title;
|
|
21314
|
+
head.append(createRendererSettingsIcon(panelIconName(view), 16), label);
|
|
21315
|
+
return head;
|
|
21316
|
+
}
|
|
21317
|
+
function createPanelActions(document2, ...buttons) {
|
|
21318
|
+
const actions = document2.createElement("div");
|
|
21319
|
+
actions.className = "settings-update-actions";
|
|
21320
|
+
actions.append(...buttons);
|
|
21321
|
+
return actions;
|
|
20686
21322
|
}
|
|
20687
21323
|
function installationLabel(installation, messages) {
|
|
20688
21324
|
if (installation === "npm") return messages.updateInstallationNpm;
|
|
@@ -20719,6 +21355,57 @@ ${error51.stderrTail}`] : []
|
|
|
20719
21355
|
}
|
|
20720
21356
|
return `${scaled.toFixed(scaled >= 10 ? 0 : 1)} ${unit}`;
|
|
20721
21357
|
}
|
|
21358
|
+
function aboutPage(messages) {
|
|
21359
|
+
return Object.freeze({
|
|
21360
|
+
id: "about",
|
|
21361
|
+
label: messages.pageLabels.about,
|
|
21362
|
+
icon: "about",
|
|
21363
|
+
mount(context) {
|
|
21364
|
+
const document2 = context.content.ownerDocument;
|
|
21365
|
+
const heading = document2.createElement("div");
|
|
21366
|
+
heading.className = "settings-section-label";
|
|
21367
|
+
heading.textContent = messages.pageLabels.about;
|
|
21368
|
+
const panel = document2.createElement("section");
|
|
21369
|
+
panel.className = "settings-about-panel";
|
|
21370
|
+
const product = document2.createElement("strong");
|
|
21371
|
+
product.className = "settings-about-product";
|
|
21372
|
+
product.textContent = "CodexHost";
|
|
21373
|
+
const tagline = document2.createElement("strong");
|
|
21374
|
+
tagline.className = "settings-about-tagline";
|
|
21375
|
+
tagline.textContent = messages.aboutTagline;
|
|
21376
|
+
const introduction = document2.createElement("div");
|
|
21377
|
+
introduction.className = "settings-about-copy";
|
|
21378
|
+
for (const paragraphText of messages.aboutParagraphs) {
|
|
21379
|
+
const paragraph = document2.createElement("p");
|
|
21380
|
+
paragraph.textContent = paragraphText;
|
|
21381
|
+
introduction.append(paragraph);
|
|
21382
|
+
}
|
|
21383
|
+
const starCallout = document2.createElement("p");
|
|
21384
|
+
starCallout.className = "settings-about-star-callout";
|
|
21385
|
+
starCallout.textContent = messages.aboutStarCallout;
|
|
21386
|
+
const repositorySection = document2.createElement("div");
|
|
21387
|
+
repositorySection.className = "settings-about-repository";
|
|
21388
|
+
const openSource = document2.createElement("p");
|
|
21389
|
+
openSource.textContent = messages.aboutOpenSource;
|
|
21390
|
+
const repository = document2.createElement("a");
|
|
21391
|
+
repository.className = "settings-about-repository-link";
|
|
21392
|
+
repository.href = CODEXHOST_GITHUB_REPOSITORY_URL;
|
|
21393
|
+
repository.target = "_blank";
|
|
21394
|
+
repository.rel = "noopener noreferrer";
|
|
21395
|
+
const repositoryUrl = document2.createElement("code");
|
|
21396
|
+
repositoryUrl.textContent = CODEXHOST_GITHUB_REPOSITORY_URL;
|
|
21397
|
+
repository.append(
|
|
21398
|
+
createRendererSettingsIcon("external-link", 14),
|
|
21399
|
+
messages.aboutRepository,
|
|
21400
|
+
repositoryUrl
|
|
21401
|
+
);
|
|
21402
|
+
repositorySection.append(openSource, repository);
|
|
21403
|
+
panel.append(product, tagline, introduction, starCallout, repositorySection);
|
|
21404
|
+
context.content.append(heading, panel);
|
|
21405
|
+
return void 0;
|
|
21406
|
+
}
|
|
21407
|
+
});
|
|
21408
|
+
}
|
|
20722
21409
|
function updatesPage(messages, getClient) {
|
|
20723
21410
|
return Object.freeze({
|
|
20724
21411
|
id: "updates",
|
|
@@ -20726,37 +21413,90 @@ ${error51.stderrTail}`] : []
|
|
|
20726
21413
|
icon: "updates",
|
|
20727
21414
|
mount(context) {
|
|
20728
21415
|
const document2 = context.content.ownerDocument;
|
|
21416
|
+
const windows = isWindowsRenderer(document2.defaultView);
|
|
20729
21417
|
const heading = document2.createElement("div");
|
|
20730
21418
|
heading.className = "settings-section-label";
|
|
20731
21419
|
heading.textContent = messages.pageLabels.updates;
|
|
20732
21420
|
const metadata = document2.createElement("div");
|
|
20733
21421
|
metadata.className = "settings-update-metadata";
|
|
20734
|
-
const
|
|
20735
|
-
|
|
20736
|
-
|
|
20737
|
-
|
|
20738
|
-
|
|
20739
|
-
|
|
20740
|
-
|
|
20741
|
-
|
|
20742
|
-
|
|
20743
|
-
|
|
20744
|
-
|
|
20745
|
-
const
|
|
20746
|
-
|
|
20747
|
-
|
|
20748
|
-
metadata.append(currentVersion, installation);
|
|
21422
|
+
const createMetadataItem = (label) => {
|
|
21423
|
+
const item = document2.createElement("div");
|
|
21424
|
+
item.className = "settings-update-metadata__item";
|
|
21425
|
+
const name = document2.createElement("span");
|
|
21426
|
+
name.textContent = label;
|
|
21427
|
+
const value = document2.createElement("strong");
|
|
21428
|
+
value.textContent = "-";
|
|
21429
|
+
item.append(name, value);
|
|
21430
|
+
metadata.append(item);
|
|
21431
|
+
return value;
|
|
21432
|
+
};
|
|
21433
|
+
const currentVersionValue = createMetadataItem(messages.updateCurrentVersion);
|
|
21434
|
+
const latestVersionValue = createMetadataItem(messages.updateLatestVersion);
|
|
21435
|
+
const installationValue = createMetadataItem(messages.updateInstallation);
|
|
20749
21436
|
const panel = document2.createElement("section");
|
|
20750
21437
|
panel.className = "settings-update-panel";
|
|
20751
21438
|
panel.setAttribute("aria-live", "polite");
|
|
21439
|
+
const controls = document2.createElement("div");
|
|
21440
|
+
controls.className = "settings-update-controls";
|
|
21441
|
+
const manualTitle = document2.createElement("div");
|
|
21442
|
+
manualTitle.className = "settings-update-manual-title";
|
|
21443
|
+
manualTitle.textContent = messages.updateManualTitle;
|
|
20752
21444
|
const manualNpm = document2.createElement("div");
|
|
20753
21445
|
manualNpm.className = "settings-update-manual";
|
|
20754
21446
|
manualNpm.hidden = true;
|
|
20755
|
-
const manualNpmDescription = document2.createElement("
|
|
21447
|
+
const manualNpmDescription = document2.createElement("p");
|
|
21448
|
+
manualNpmDescription.className = "settings-update-manual-description";
|
|
20756
21449
|
manualNpmDescription.textContent = messages.updateManualNpmDescription;
|
|
21450
|
+
const manualNpmCommandRow = document2.createElement("div");
|
|
21451
|
+
manualNpmCommandRow.className = "settings-update-command";
|
|
20757
21452
|
const manualNpmCommand = document2.createElement("code");
|
|
20758
21453
|
manualNpmCommand.textContent = CODEXHOST_NPM_MANUAL_UPDATE_COMMAND;
|
|
20759
|
-
|
|
21454
|
+
const copyCommand = document2.createElement("button");
|
|
21455
|
+
copyCommand.type = "button";
|
|
21456
|
+
copyCommand.className = "settings-update-command__copy";
|
|
21457
|
+
const setCopyLabel = (label) => {
|
|
21458
|
+
copyCommand.replaceChildren(createRendererSettingsIcon("copy", 14), label);
|
|
21459
|
+
};
|
|
21460
|
+
setCopyLabel(messages.updateCopyCommand);
|
|
21461
|
+
copyCommand.addEventListener("click", () => {
|
|
21462
|
+
const clipboard = document2.defaultView?.navigator.clipboard;
|
|
21463
|
+
const restore = (label) => {
|
|
21464
|
+
setCopyLabel(label);
|
|
21465
|
+
document2.defaultView?.setTimeout(() => setCopyLabel(messages.updateCopyCommand), 2e3);
|
|
21466
|
+
};
|
|
21467
|
+
if (!clipboard) {
|
|
21468
|
+
restore(messages.updateCopyFailed);
|
|
21469
|
+
return;
|
|
21470
|
+
}
|
|
21471
|
+
void clipboard.writeText(CODEXHOST_NPM_MANUAL_UPDATE_COMMAND).then(
|
|
21472
|
+
() => restore(messages.updateCommandCopied),
|
|
21473
|
+
() => restore(messages.updateCopyFailed)
|
|
21474
|
+
);
|
|
21475
|
+
});
|
|
21476
|
+
manualNpmCommandRow.append(manualNpmCommand, copyCommand);
|
|
21477
|
+
manualNpm.append(manualNpmDescription, manualNpmCommandRow);
|
|
21478
|
+
const manualWindowsInstaller = document2.createElement("div");
|
|
21479
|
+
manualWindowsInstaller.className = "settings-update-manual";
|
|
21480
|
+
manualWindowsInstaller.hidden = true;
|
|
21481
|
+
const manualWindowsInstallerDescription = document2.createElement("p");
|
|
21482
|
+
manualWindowsInstallerDescription.className = "settings-update-manual-description";
|
|
21483
|
+
manualWindowsInstallerDescription.textContent = messages.updateWindowsInstallerDescription;
|
|
21484
|
+
const manualWindowsInstallerActions = document2.createElement("div");
|
|
21485
|
+
manualWindowsInstallerActions.className = "settings-update-actions";
|
|
21486
|
+
const manualWindowsInstallerLink = document2.createElement("a");
|
|
21487
|
+
manualWindowsInstallerLink.className = "settings-update-link";
|
|
21488
|
+
manualWindowsInstallerLink.href = CODEXHOST_RELEASES_LATEST_URL;
|
|
21489
|
+
manualWindowsInstallerLink.target = "_blank";
|
|
21490
|
+
manualWindowsInstallerLink.rel = "noopener noreferrer";
|
|
21491
|
+
manualWindowsInstallerLink.append(
|
|
21492
|
+
messages.updateDownloadWindowsInstaller,
|
|
21493
|
+
createRendererSettingsIcon("external-link", 14)
|
|
21494
|
+
);
|
|
21495
|
+
manualWindowsInstallerActions.append(manualWindowsInstallerLink);
|
|
21496
|
+
manualWindowsInstaller.append(
|
|
21497
|
+
manualWindowsInstallerDescription,
|
|
21498
|
+
manualWindowsInstallerActions
|
|
21499
|
+
);
|
|
20760
21500
|
const actions = document2.createElement("div");
|
|
20761
21501
|
actions.className = "settings-update-actions";
|
|
20762
21502
|
const releaseLink = document2.createElement("a");
|
|
@@ -20769,7 +21509,14 @@ ${error51.stderrTail}`] : []
|
|
|
20769
21509
|
createRendererSettingsIcon("external-link", 14)
|
|
20770
21510
|
);
|
|
20771
21511
|
actions.append(releaseLink);
|
|
20772
|
-
|
|
21512
|
+
controls.append(manualTitle, manualNpm, manualWindowsInstaller, actions);
|
|
21513
|
+
const notes = document2.createElement("div");
|
|
21514
|
+
notes.className = "settings-update-notes-section";
|
|
21515
|
+
context.content.append(heading, metadata, panel, controls, notes);
|
|
21516
|
+
const setManualFallback = (fallback) => {
|
|
21517
|
+
manualNpmDescription.textContent = windows ? messages.updateWindowsNpmDescription : fallback ? messages.updateManualFallbackDescription : messages.updateManualNpmDescription;
|
|
21518
|
+
manualNpmDescription.className = fallback ? "settings-update-manual-description is-fallback" : "settings-update-manual-description";
|
|
21519
|
+
};
|
|
20773
21520
|
let pollTimer;
|
|
20774
21521
|
let pollAttempts = 0;
|
|
20775
21522
|
let pending = false;
|
|
@@ -20782,11 +21529,11 @@ ${error51.stderrTail}`] : []
|
|
|
20782
21529
|
const renderUnavailable = (detail) => {
|
|
20783
21530
|
panel.dataset.updateState = "unavailable";
|
|
20784
21531
|
panel.replaceChildren();
|
|
20785
|
-
const
|
|
20786
|
-
|
|
20787
|
-
const copy = document2.createElement("span");
|
|
21532
|
+
const copy = document2.createElement("p");
|
|
21533
|
+
copy.className = "settings-update-summary";
|
|
20788
21534
|
copy.textContent = detail;
|
|
20789
|
-
panel.append(
|
|
21535
|
+
panel.append(createPanelHead(document2, "unavailable", messages.notAvailable), copy);
|
|
21536
|
+
notes.replaceChildren();
|
|
20790
21537
|
};
|
|
20791
21538
|
const renderRequestFailure = (error51) => {
|
|
20792
21539
|
renderPendingStatus(
|
|
@@ -20822,9 +21569,8 @@ ${error51.stderrTail}`] : []
|
|
|
20822
21569
|
const renderPendingStatus = (status, message, viewPhase = status?.phase ?? "pending") => {
|
|
20823
21570
|
panel.dataset.updateState = viewPhase;
|
|
20824
21571
|
panel.replaceChildren();
|
|
20825
|
-
|
|
20826
|
-
|
|
20827
|
-
panel.append(state);
|
|
21572
|
+
panel.append(createPanelHead(document2, viewPhase, message));
|
|
21573
|
+
setManualFallback(viewPhase === "failed");
|
|
20828
21574
|
if (status?.phase === "downloading" && status.totalBytes !== void 0 && status.downloadedBytes !== void 0) {
|
|
20829
21575
|
const progress = document2.createElement("progress");
|
|
20830
21576
|
progress.className = "settings-update-progress";
|
|
@@ -20846,7 +21592,7 @@ ${error51.stderrTail}`] : []
|
|
|
20846
21592
|
retry.className = "settings-command-button";
|
|
20847
21593
|
retry.append(createRendererSettingsIcon("refresh", 16), messages.updateRetry);
|
|
20848
21594
|
retry.addEventListener("click", () => void load());
|
|
20849
|
-
panel.append(retry);
|
|
21595
|
+
panel.append(createPanelActions(document2, retry));
|
|
20850
21596
|
}
|
|
20851
21597
|
};
|
|
20852
21598
|
const start = (client) => {
|
|
@@ -20873,8 +21619,19 @@ ${error51.stderrTail}`] : []
|
|
|
20873
21619
|
};
|
|
20874
21620
|
const renderCheck = (result, client) => {
|
|
20875
21621
|
currentVersionValue.textContent = `v${result.currentVersion}`;
|
|
21622
|
+
latestVersionValue.textContent = result.latestVersion ? `v${result.latestVersion}` : "-";
|
|
21623
|
+
latestVersionValue.className = result.updateAvailable ? "settings-update-metadata__value--newer" : "";
|
|
20876
21624
|
installationValue.textContent = installationLabel(result.installation, messages);
|
|
20877
21625
|
manualNpm.hidden = result.installation !== "npm";
|
|
21626
|
+
manualWindowsInstaller.hidden = !windows || result.installation !== "windows-installer";
|
|
21627
|
+
releaseLink.hidden = windows;
|
|
21628
|
+
manualTitle.hidden = windows && !["npm", "windows-installer"].includes(result.installation ?? "");
|
|
21629
|
+
if (windows && result.installation === "windows-installer" && result.latestVersion) {
|
|
21630
|
+
manualWindowsInstallerLink.href = windowsInstallerDownloadUrl(
|
|
21631
|
+
document2.defaultView,
|
|
21632
|
+
result.latestVersion
|
|
21633
|
+
);
|
|
21634
|
+
}
|
|
20878
21635
|
if (result.releaseNotesUrl) releaseLink.href = result.releaseNotesUrl;
|
|
20879
21636
|
const operationMessage = statusMessage(result.status, messages);
|
|
20880
21637
|
if (isPendingStatus(result.status)) {
|
|
@@ -20882,42 +21639,53 @@ ${error51.stderrTail}`] : []
|
|
|
20882
21639
|
scheduleStatusPoll(client, true);
|
|
20883
21640
|
return;
|
|
20884
21641
|
}
|
|
20885
|
-
|
|
21642
|
+
const actionableStatus = result.status?.phase === "failed" && result.status.version === result.latestVersion ? result.status : null;
|
|
21643
|
+
const view = result.error ? "error" : result.updateAvailable ? "available" : "current";
|
|
21644
|
+
panel.dataset.updateState = view;
|
|
20886
21645
|
panel.replaceChildren();
|
|
20887
|
-
|
|
20888
|
-
|
|
21646
|
+
setManualFallback(Boolean(result.error) || actionableStatus !== null);
|
|
21647
|
+
if (result.error || !result.updateAvailable || windows || actionableStatus) {
|
|
21648
|
+
panel.append(
|
|
21649
|
+
createPanelHead(
|
|
21650
|
+
document2,
|
|
21651
|
+
view,
|
|
21652
|
+
actionableStatus ? statusMessage(actionableStatus, messages) ?? messages.updateFailed : result.error ? messages.updateFailed : result.updateAvailable ? messages.updateWindowsManualRequired : messages.updateUpToDate
|
|
21653
|
+
)
|
|
21654
|
+
);
|
|
20889
21655
|
}
|
|
20890
|
-
|
|
20891
|
-
|
|
20892
|
-
|
|
20893
|
-
|
|
20894
|
-
|
|
20895
|
-
panel.append(createReleaseNotesElement(document2, result.releaseNotes));
|
|
21656
|
+
if (actionableStatus?.error) {
|
|
21657
|
+
const error51 = document2.createElement("p");
|
|
21658
|
+
error51.className = "settings-update-error";
|
|
21659
|
+
error51.textContent = actionableStatus.error;
|
|
21660
|
+
panel.append(error51);
|
|
20896
21661
|
}
|
|
20897
|
-
if (result.
|
|
21662
|
+
if (result.error) {
|
|
20898
21663
|
const error51 = document2.createElement("p");
|
|
20899
21664
|
error51.className = "settings-update-error";
|
|
20900
|
-
error51.textContent = result.
|
|
21665
|
+
error51.textContent = result.error;
|
|
20901
21666
|
panel.append(error51);
|
|
20902
21667
|
}
|
|
20903
|
-
|
|
21668
|
+
const buttons = [];
|
|
21669
|
+
if (!windows && result.updateAvailable && result.installationAvailable) {
|
|
20904
21670
|
const update = document2.createElement("button");
|
|
20905
21671
|
update.type = "button";
|
|
20906
21672
|
update.className = "settings-command-button";
|
|
20907
21673
|
update.append(createRendererSettingsIcon("updates", 16), messages.updateAndRestart);
|
|
20908
21674
|
update.addEventListener("click", () => start(client));
|
|
20909
|
-
|
|
21675
|
+
buttons.push(update);
|
|
20910
21676
|
}
|
|
20911
21677
|
if (result.error) {
|
|
20912
|
-
const error51 = document2.createElement("p");
|
|
20913
|
-
error51.className = "settings-update-error";
|
|
20914
|
-
error51.textContent = result.error;
|
|
20915
21678
|
const retry = document2.createElement("button");
|
|
20916
21679
|
retry.type = "button";
|
|
20917
21680
|
retry.className = "settings-command-button settings-command-button--secondary";
|
|
20918
21681
|
retry.append(createRendererSettingsIcon("refresh", 16), messages.updateRetry);
|
|
20919
21682
|
retry.addEventListener("click", () => void load());
|
|
20920
|
-
|
|
21683
|
+
buttons.push(retry);
|
|
21684
|
+
}
|
|
21685
|
+
if (buttons.length > 0) panel.append(createPanelActions(document2, ...buttons));
|
|
21686
|
+
notes.replaceChildren();
|
|
21687
|
+
if (result.releaseNotes) {
|
|
21688
|
+
notes.append(createReleaseNotesElement(document2, result.releaseNotes));
|
|
20921
21689
|
}
|
|
20922
21690
|
};
|
|
20923
21691
|
const load = () => {
|
|
@@ -20948,13 +21716,10 @@ ${error51.stderrTail}`] : []
|
|
|
20948
21716
|
});
|
|
20949
21717
|
}
|
|
20950
21718
|
function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null) {
|
|
20951
|
-
const unavailableIds = DEFAULT_RENDERER_SETTINGS_PAGE_IDS.filter(
|
|
20952
|
-
(id) => id !== "updates" && id !== "connections"
|
|
20953
|
-
);
|
|
20954
21719
|
return Object.freeze([
|
|
20955
|
-
|
|
20956
|
-
|
|
20957
|
-
|
|
21720
|
+
createConnectionsSettingsPage(messages, getDiagnostics),
|
|
21721
|
+
updatesPage(messages, getUpdateClient),
|
|
21722
|
+
aboutPage(messages)
|
|
20958
21723
|
]);
|
|
20959
21724
|
}
|
|
20960
21725
|
function createDefaultRendererSettingsRegistry(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null) {
|
|
@@ -20964,11 +21729,10 @@ ${error51.stderrTail}`] : []
|
|
|
20964
21729
|
}
|
|
20965
21730
|
|
|
20966
21731
|
// src/settings/shell.css
|
|
20967
|
-
var shell_default = ':host {\n --settings-bg: #181818;\n --settings-sidebar: #1c1c1c;\n --settings-panel: transparent;\n --settings-text: #f5f5f5;\n --settings-muted: #a1a1a1;\n --settings-border: rgb(255 255 255 / 10%);\n --settings-divider: rgb(255 255 255 / 10%);\n --settings-hover: rgb(255 255 255 / 6%);\n --settings-active: rgb(51 156 255 / 12%);\n --settings-focus: #339cff;\n color: var(--settings-text);\n color-scheme: dark;\n font:\n 14px/1.5 system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n letter-spacing: 0;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n letter-spacing: 0;\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\nbutton {\n color: inherit;\n}\n\n[hidden] {\n display: none !important;\n}\n\n.codexhost-settings-dialog {\n width: min(1120px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 32px));\n max-width: none;\n max-height: none;\n margin: auto;\n padding: 0;\n overflow: hidden;\n color: var(--settings-text);\n background: var(--settings-bg);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n box-shadow: 0 24px 64px rgb(0 0 0 / 38%);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: rgb(0 0 0 / 52%);\n}\n\n.settings-frame,\n.settings-layout {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n}\n\n.settings-frame {\n display: flex;\n flex-direction: column;\n}\n\n.settings-layout {\n flex: 1;\n display: grid;\n grid-template-columns: 240px minmax(0, 1fr);\n background: var(--settings-bg);\n}\n\n.settings-sidebar {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n background: var(--settings-sidebar);\n border-right: 1px solid var(--settings-border);\n padding-top: 28px;\n}\n\n.settings-header {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 64px;\n flex: none;\n padding: 0 16px;\n border-bottom: 1px solid var(--settings-border);\n}\n\n.settings-header-actions {\n display: flex;\n align-items: center;\n flex: none;\n gap: 12px;\n margin-left: auto;\n}\n\n.settings-icon-button.settings-star-link {\n width: auto;\n gap: 6px;\n padding-inline: 8px;\n font-size: 12px;\n line-height: 18px;\n text-decoration: none;\n border: 2px dashed #f5c542;\n white-space: nowrap;\n}\n\n.settings-star-link .codexhost-settings-icon {\n color: #f5c542;\n fill: currentColor;\n stroke: currentColor;\n}\n\n.settings-brand {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-brand__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n flex: none;\n color: var(--settings-text);\n}\n\n.settings-brand__mark .codexhost-settings-icon {\n width: 32px;\n height: 32px;\n object-fit: contain;\n}\n\n.settings-brand__copy {\n display: flex;\n min-width: 0;\n align-items: baseline;\n gap: 0;\n line-height: 20px;\n}\n\n.settings-brand__name {\n overflow: hidden;\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-brand__title {\n margin-left: 14px;\n padding-left: 14px;\n color: var(--settings-muted);\n font-size: 14px;\n font-weight: 400;\n border-left: 1px solid var(--settings-border);\n}\n\n.settings-nav {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 4px;\n padding: 0 12px 16px;\n overflow-y: auto;\n}\n\n.settings-nav-button {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n width: 100%;\n position: relative;\n min-height: 40px;\n flex: none;\n gap: 12px;\n padding: 8px 12px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 21px;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: 10px;\n cursor: pointer;\n}\n\n.settings-nav-button .codexhost-settings-icon {\n width: 18px;\n height: 18px;\n opacity: 0.9;\n}\n\n.settings-nav-button:hover {\n background: var(--settings-hover);\n}\n\n.settings-nav-button[aria-current="page"] {\n background: var(--settings-active);\n color: var(--settings-focus);\n}\n\n.settings-nav-button[aria-current="page"]::before {\n position: absolute;\n left: 0;\n width: 3px;\n height: 22px;\n content: "";\n background: var(--settings-focus);\n border-radius: 0 3px 3px 0;\n}\n\n.settings-nav-button span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex: none;\n padding: 0;\n color: var(--settings-muted);\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n}\n\n.settings-icon-button:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-icon-button:focus-visible,\n.settings-nav-button:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 1px;\n}\n\n.settings-page {\n display: block;\n position: relative;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n background: var(--settings-bg);\n scrollbar-gutter: stable;\n}\n\n.settings-page__content {\n width: min(930px, calc(100% - 80px));\n margin-inline: auto;\n}\n\n.settings-page__content {\n min-width: 0;\n padding: 44px 0 56px;\n}\n\n.settings-section-label {\n min-height: auto;\n padding: 0 0 28px;\n color: var(--settings-text);\n font-size: 24px;\n font-weight: 600;\n line-height: 30px;\n}\n\n.settings-status-list,\n.settings-empty {\n overflow: hidden;\n background: var(--settings-panel);\n}\n\n.settings-status-row {\n display: grid;\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\n position: relative;\n align-items: center;\n min-height: 88px;\n gap: 28px;\n padding: 16px 0;\n}\n\n.settings-status-row:not(:last-child)::after {\n content: "";\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 1px;\n background: var(--settings-divider);\n}\n\n.settings-status-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n color: var(--settings-text);\n gap: 14px;\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-status-row__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n flex: none;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 7%);\n border-radius: 50%;\n}\n\n.settings-status-badge {\n flex: none;\n padding: 5px 12px;\n color: var(--settings-muted);\n font-size: 13px;\n font-weight: 500;\n line-height: 18px;\n background: rgb(255 255 255 / 9%);\n border: 1px solid rgb(255 255 255 / 6%);\n border-radius: 6px;\n}\n\n.settings-status-row__detail {\n min-width: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-page-description {\n max-width: 760px;\n margin: -12px 0 24px;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-connection-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.settings-connection-list {\n min-width: 0;\n border-top: 1px solid var(--settings-divider);\n}\n\n.settings-connection-host-tabs {\n display: flex;\n gap: 6px;\n padding: 20px 0 8px;\n overflow-x: auto;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-host-tab {\n flex: none;\n padding: 7px 12px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: var(--settings-muted);\n font: inherit;\n font-size: 13px;\n line-height: 18px;\n cursor: pointer;\n}\n\n.settings-connection-host-tab:hover {\n background: var(--settings-hover);\n color: var(--settings-text);\n}\n\n.settings-connection-host-tab[aria-selected="true"] {\n background: var(--settings-active);\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-connection-host-tab:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: -2px;\n}\n\n.settings-connection-row {\n display: grid;\n grid-template-columns: minmax(180px, 1fr) auto minmax(260px, 1.5fr);\n align-items: center;\n min-width: 0;\n min-height: 76px;\n gap: 24px;\n padding: 14px 0;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n gap: 10px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 20px;\n}\n\n.settings-connection-row__identity strong {\n min-width: 0;\n overflow-wrap: anywhere;\n font-weight: 500;\n}\n\n.settings-connection-row__dot {\n width: 9px;\n height: 9px;\n flex: none;\n border-radius: 50%;\n background: var(--settings-muted);\n}\n\n.settings-connection-row__dot[data-connection-tone="ready"] {\n background: #22c55e;\n}\n\n.settings-connection-row__dot[data-connection-tone="checking"] {\n background: #f5c542;\n}\n\n.settings-connection-row__dot[data-connection-tone="failed"] {\n background: #ef4444;\n}\n\n.settings-status-badge[data-connection-tone="ready"] {\n color: #4ade80;\n}\n\n.settings-status-badge[data-connection-tone="checking"] {\n color: #f5c542;\n}\n\n.settings-status-badge[data-connection-tone="failed"] {\n color: #f87171;\n}\n\n.settings-connection-row__detail {\n display: grid;\n min-width: 0;\n align-items: center;\n gap: 2px 12px;\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-connection-row__reason {\n min-width: 0;\n overflow-wrap: anywhere;\n white-space: pre-wrap;\n}\n\n.settings-connection-details-toggle {\n width: fit-content;\n padding: 0;\n color: var(--settings-focus);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n background: transparent;\n border: 0;\n cursor: pointer;\n}\n\n.settings-connection-details-toggle:hover {\n text-decoration: underline;\n}\n\n.settings-connection-details {\n display: grid;\n grid-column: 1 / -1;\n gap: 6px;\n min-width: 0;\n margin: 4px 0 2px 32px;\n padding: 12px;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 4%);\n border-left: 2px solid #ef4444;\n border-radius: 4px;\n}\n\n.settings-connection-detail-line {\n display: grid;\n grid-template-columns: 112px minmax(0, 1fr);\n gap: 12px;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-connection-detail-line span {\n color: var(--settings-muted);\n}\n\n.settings-connection-detail-line code {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n white-space: pre-wrap;\n}\n\n.settings-connection-stderr {\n max-height: 220px;\n min-width: 0;\n margin: 4px 0 0;\n padding: 10px;\n overflow: auto;\n color: #fca5a5;\n font:\n 12px/18px ui-monospace,\n "SFMono-Regular",\n Consolas,\n "Liberation Mono",\n monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n background: rgb(0 0 0 / 28%);\n border-radius: 4px;\n}\n\n.settings-connection-details .settings-command-button {\n justify-self: start;\n min-height: 30px;\n font-size: 12px;\n}\n\n.settings-connection-row__detail time {\n color: var(--settings-muted);\n opacity: 0.8;\n}\n\n.settings-empty {\n display: flex;\n align-items: center;\n min-height: 72px;\n padding: 12px 16px;\n}\n\n.settings-empty > div {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n\n.settings-empty strong {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 500;\n line-height: 19px;\n}\n\n.settings-empty span {\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 19px;\n}\n\n.settings-page-error {\n padding: 16px;\n color: var(--settings-text);\n font-size: 13px;\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 20px;\n}\n\n.settings-update-metadata {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 24px;\n margin-bottom: 24px;\n padding: 0 4px 20px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-update-metadata__item {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n\n.settings-update-metadata__item span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-metadata__item strong {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-update-panel {\n display: grid;\n gap: 16px;\n min-height: 128px;\n padding: 20px;\n color: var(--settings-text);\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n}\n\n.settings-update-panel > strong,\n.settings-update-panel > span,\n.settings-update-summary,\n.settings-update-error {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-panel > span,\n.settings-update-summary {\n color: var(--settings-muted);\n}\n\n.settings-update-error {\n color: #ef4444;\n}\n\n.settings-update-progress {\n width: 100%;\n height: 8px;\n accent-color: #238be8;\n}\n\n.settings-update-progress-detail {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-notes {\n display: grid;\n min-width: 0;\n gap: 12px;\n color: var(--settings-muted);\n font-size: 14px;\n line-height: 22px;\n overflow-wrap: anywhere;\n}\n\n.settings-update-notes > :first-child {\n margin-top: 0;\n}\n\n.settings-update-notes > :last-child {\n margin-bottom: 0;\n}\n\n.settings-update-notes h1,\n.settings-update-notes h2,\n.settings-update-notes h3,\n.settings-update-notes h4,\n.settings-update-notes h5,\n.settings-update-notes h6 {\n margin: 6px 0 0;\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-update-notes h1 {\n font-size: 18px;\n line-height: 26px;\n}\n\n.settings-update-notes h2 {\n font-size: 17px;\n line-height: 24px;\n}\n\n.settings-update-notes h3,\n.settings-update-notes h4,\n.settings-update-notes h5,\n.settings-update-notes h6 {\n font-size: 14px;\n line-height: 22px;\n}\n\n.settings-update-notes p,\n.settings-update-notes ul,\n.settings-update-notes ol,\n.settings-update-notes pre,\n.settings-update-notes blockquote {\n margin: 0;\n}\n\n.settings-update-notes ul,\n.settings-update-notes ol {\n padding-left: 24px;\n}\n\n.settings-update-notes li {\n padding-left: 4px;\n}\n\n.settings-update-notes li::marker {\n color: var(--settings-muted);\n font-size: 0.85em;\n}\n\n.settings-update-notes li + li {\n margin-top: 14px;\n}\n\n.settings-update-notes .release-note-translation {\n display: block;\n margin-top: 3px;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-notes blockquote {\n padding: 8px 12px;\n color: var(--settings-muted);\n border-left: 3px solid var(--settings-focus);\n background: rgb(255 255 255 / 4%);\n}\n\n.settings-update-notes hr {\n width: 100%;\n margin: 2px 0;\n border: 0;\n border-top: 1px solid var(--settings-divider);\n}\n\n.settings-update-notes strong {\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-update-notes a {\n color: #7cb8ff;\n text-decoration: none;\n}\n\n.settings-update-notes a:hover {\n text-decoration: underline;\n}\n\n.settings-update-notes code {\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 12px;\n}\n\n.settings-update-notes :not(pre) > code {\n padding: 1px 5px;\n background: rgb(255 255 255 / 8%);\n border-radius: 4px;\n}\n\n.settings-update-notes pre {\n min-width: 0;\n max-width: 100%;\n padding: 10px 12px;\n overflow-x: auto;\n overflow-y: hidden;\n background: rgb(0 0 0 / 28%);\n border-radius: 6px;\n}\n\n.settings-update-notes pre code {\n line-height: 18px;\n white-space: pre-wrap;\n}\n\n.settings-update-version-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: 20px;\n min-height: 32px;\n color: var(--settings-muted);\n font-size: 13px;\n}\n\n.settings-update-version-row strong {\n color: var(--settings-text);\n font-size: 15px;\n}\n\n.settings-update-manual {\n display: grid;\n min-width: 0;\n gap: 6px;\n margin-top: 14px;\n padding-inline: 4px;\n}\n\n.settings-update-manual[hidden] {\n display: none;\n}\n\n.settings-update-manual span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-manual code {\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-actions {\n display: flex;\n min-width: 0;\n margin-top: 16px;\n}\n\n.settings-command-button,\n.settings-update-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: fit-content;\n min-height: 36px;\n gap: 8px;\n padding: 8px 12px;\n color: white;\n font: inherit;\n font-size: 13px;\n text-decoration: none;\n background: #1677d2;\n border: 1px solid #238be8;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.settings-command-button--secondary,\n.settings-update-link {\n color: var(--settings-text);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button:hover,\n.settings-update-link:hover {\n filter: brightness(1.08);\n}\n\n.settings-command-button:focus-visible,\n.settings-update-link:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 2px;\n}\n\n.codexhost-settings-icon {\n display: block;\n flex: none;\n stroke: currentColor;\n}\n\n@media (max-width: 720px) {\n .codexhost-settings-dialog {\n width: calc(100vw - 16px);\n height: calc(100vh - 16px);\n border-radius: 10px;\n }\n\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .settings-sidebar {\n border-right: 0;\n border-bottom: 1px solid var(--settings-border);\n }\n\n .settings-header {\n height: 56px;\n padding-inline: 14px;\n }\n\n .settings-icon-button.settings-star-link {\n width: 28px;\n padding: 0;\n }\n\n .settings-star-link span {\n display: none;\n }\n\n .settings-sidebar {\n padding-top: 20px;\n }\n\n .settings-nav {\n flex: none;\n flex-direction: row;\n gap: 4px;\n padding: 7px 8px 8px;\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n .settings-nav-button {\n width: auto;\n min-width: max-content;\n min-height: 34px;\n grid-template-columns: 16px auto;\n border-radius: 10px;\n }\n\n .settings-page__content {\n width: calc(100% - 40px);\n }\n\n .settings-page__content {\n padding-top: 32px;\n padding-bottom: 32px;\n }\n\n .settings-section-label {\n padding-bottom: 20px;\n font-size: 20px;\n line-height: 26px;\n }\n\n .settings-status-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 16px;\n }\n\n .settings-connection-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 10px 16px;\n }\n\n .settings-connection-row__detail {\n grid-column: 1 / -1;\n }\n\n .settings-status-row__detail {\n grid-column: 1 / -1;\n margin: -8px 0 0 58px;\n }\n}\n\n@media (forced-colors: active) {\n :host,\n :host([data-theme="dark"]) {\n --settings-bg: Canvas;\n --settings-sidebar: Canvas;\n --settings-panel: Canvas;\n --settings-text: CanvasText;\n --settings-muted: GrayText;\n --settings-border: ButtonBorder;\n --settings-divider: ButtonBorder;\n --settings-hover: Highlight;\n --settings-active: Highlight;\n --settings-focus: Highlight;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
|
|
21732
|
+
var shell_default = ':host {\n --settings-bg: #181818;\n --settings-sidebar: #1c1c1c;\n --settings-panel: transparent;\n --settings-text: #f5f5f5;\n --settings-muted: #a1a1a1;\n --settings-border: rgb(255 255 255 / 10%);\n --settings-divider: rgb(255 255 255 / 10%);\n --settings-hover: rgb(255 255 255 / 6%);\n --settings-active: rgb(51 156 255 / 12%);\n --settings-focus: #339cff;\n color: var(--settings-text);\n color-scheme: dark;\n font:\n 14px/1.5 system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n letter-spacing: 0;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n letter-spacing: 0;\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\nbutton {\n color: inherit;\n}\n\n[hidden] {\n display: none !important;\n}\n\n.codexhost-settings-dialog {\n width: min(1120px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 32px));\n max-width: none;\n max-height: none;\n margin: auto;\n padding: 0;\n overflow: hidden;\n color: var(--settings-text);\n background: var(--settings-bg);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n box-shadow: 0 24px 64px rgb(0 0 0 / 38%);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: rgb(0 0 0 / 52%);\n}\n\n.settings-frame,\n.settings-layout {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n}\n\n.settings-frame {\n display: flex;\n flex-direction: column;\n}\n\n.settings-layout {\n flex: 1;\n display: grid;\n grid-template-columns: 240px minmax(0, 1fr);\n background: var(--settings-bg);\n}\n\n.settings-sidebar {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n background: var(--settings-sidebar);\n border-right: 1px solid var(--settings-border);\n padding-top: 28px;\n}\n\n.settings-header {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 64px;\n flex: none;\n padding: 0 16px;\n border-bottom: 1px solid var(--settings-border);\n}\n\n.settings-header-actions {\n display: flex;\n align-items: center;\n flex: none;\n gap: 12px;\n margin-left: auto;\n}\n\n.settings-brand {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-brand__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n flex: none;\n color: var(--settings-text);\n}\n\n.settings-brand__mark .codexhost-settings-icon {\n width: 32px;\n height: 32px;\n object-fit: contain;\n}\n\n.settings-brand__copy {\n display: flex;\n min-width: 0;\n align-items: baseline;\n gap: 0;\n line-height: 20px;\n}\n\n.settings-brand__name {\n overflow: hidden;\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-brand__title {\n margin-left: 14px;\n padding-left: 14px;\n color: var(--settings-muted);\n font-size: 14px;\n font-weight: 400;\n border-left: 1px solid var(--settings-border);\n}\n\n.settings-nav {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 4px;\n padding: 0 12px 16px;\n overflow-y: auto;\n}\n\n.settings-nav-section-label {\n min-height: 28px;\n padding: 7px 12px 3px;\n color: #777;\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n}\n\n.settings-nav-section-label:not(:first-child) {\n margin-top: 14px;\n}\n\n.settings-nav-button {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n width: 100%;\n position: relative;\n min-height: 48px;\n flex: none;\n gap: 14px;\n padding: 10px 14px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 21px;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: 12px;\n cursor: pointer;\n}\n\n.settings-nav-button .codexhost-settings-icon {\n width: 18px;\n height: 18px;\n opacity: 0.9;\n}\n\n.settings-nav-button:hover {\n background: var(--settings-hover);\n}\n\n.settings-nav-button[aria-current="page"] {\n background: var(--settings-active);\n color: var(--settings-focus);\n}\n\n.settings-nav-button[aria-current="page"]::before {\n position: absolute;\n left: 0;\n width: 3px;\n height: 22px;\n content: "";\n background: var(--settings-focus);\n border-radius: 0 3px 3px 0;\n}\n\n.settings-nav-button span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-nav-star-link {\n margin-top: 0;\n color: var(--settings-text);\n text-decoration: none;\n}\n\n.settings-nav-star-link .codexhost-settings-icon {\n color: #f5c542;\n}\n\n.settings-nav-star-link:hover {\n color: #fff4bd;\n background: rgb(245 197 66 / 8%);\n}\n\n.settings-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex: none;\n padding: 0;\n color: var(--settings-muted);\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n}\n\n.settings-icon-button:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-icon-button:focus-visible,\n.settings-nav-button:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 1px;\n}\n\n.settings-page {\n display: block;\n position: relative;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n background: var(--settings-bg);\n scrollbar-gutter: stable;\n}\n\n.settings-page__content {\n width: min(930px, calc(100% - 80px));\n margin-inline: auto;\n}\n\n.settings-page__content {\n min-width: 0;\n padding: 44px 0 56px;\n}\n\n.settings-section-label {\n min-height: auto;\n padding: 0 0 28px;\n color: var(--settings-text);\n font-size: 24px;\n font-weight: 600;\n line-height: 30px;\n}\n\n.settings-status-list,\n.settings-empty {\n overflow: hidden;\n background: var(--settings-panel);\n}\n\n.settings-status-row {\n display: grid;\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\n position: relative;\n align-items: center;\n min-height: 88px;\n gap: 28px;\n padding: 16px 0;\n}\n\n.settings-status-row:not(:last-child)::after {\n content: "";\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 1px;\n background: var(--settings-divider);\n}\n\n.settings-status-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n color: var(--settings-text);\n gap: 14px;\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-status-row__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n flex: none;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 7%);\n border-radius: 50%;\n}\n\n.settings-status-badge {\n flex: none;\n padding: 5px 12px;\n color: var(--settings-muted);\n font-size: 13px;\n font-weight: 500;\n line-height: 18px;\n background: rgb(255 255 255 / 9%);\n border: 1px solid rgb(255 255 255 / 6%);\n border-radius: 6px;\n}\n\n.settings-status-row__detail {\n min-width: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-page-description {\n max-width: 760px;\n margin: -12px 0 24px;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-preference-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 32px;\n min-height: 88px;\n padding: 18px 0;\n border-top: 1px solid var(--settings-divider);\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-preference-row__copy {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n min-width: 0;\n gap: 5px;\n}\n\n.settings-preference-row__copy strong {\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 600;\n line-height: 22px;\n}\n\n.settings-preference-row__copy span {\n max-width: 680px;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-preference-switch {\n display: inline-flex;\n align-items: center;\n width: 42px;\n height: 24px;\n flex: none;\n padding: 2px;\n border: 0;\n border-radius: 999px;\n background: rgb(255 255 255 / 16%);\n cursor: pointer;\n transition: background 120ms ease;\n}\n\n.settings-preference-switch[aria-checked="true"] {\n justify-content: flex-end;\n background: var(--settings-focus);\n}\n\n.settings-preference-switch:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 2px;\n}\n\n.settings-preference-switch__thumb {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: white;\n box-shadow: 0 1px 3px rgb(0 0 0 / 35%);\n}\n\n.settings-connection-page-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 24px;\n margin-bottom: 24px;\n}\n\n.settings-connection-page-header .settings-section-label {\n padding-bottom: 0;\n}\n\n.settings-connection-page-header .settings-page-description {\n margin: 8px 0 0;\n}\n\n.settings-connections-content,\n.settings-connections-layout,\n.settings-connection-list,\n.settings-connection-rows {\n min-width: 0;\n}\n\n.settings-connections-layout {\n display: grid;\n grid-template-columns: minmax(0, 1.55fr) minmax(280px, 0.85fr);\n align-items: start;\n gap: 18px;\n}\n\n.settings-connection-list,\n.settings-connection-inspector {\n overflow: hidden;\n background: rgb(255 255 255 / 2%);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n}\n\n.settings-connection-host-strip {\n display: grid;\n grid-template-columns: 30px minmax(0, 1fr) 30px;\n align-items: center;\n min-width: 0;\n gap: 6px;\n padding: 12px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-host-scroll {\n display: none;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 34px;\n padding: 0;\n color: var(--settings-muted);\n background: rgb(0 0 0 / 18%);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n cursor: pointer;\n}\n\n.settings-connection-host-strip[data-connection-host-overflow="true"]\n .settings-connection-host-scroll {\n display: inline-flex;\n}\n\n.settings-connection-host-strip:not([data-connection-host-overflow="true"]) {\n grid-template-columns: minmax(0, 1fr);\n}\n\n.settings-connection-host-scroll:hover:not(:disabled) {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-connection-host-scroll:disabled {\n cursor: default;\n opacity: 0.35;\n}\n\n.settings-connection-host-scroll:focus-visible,\n.settings-connection-host-tab:focus-visible,\n.settings-connection-row:focus-visible,\n.settings-connection-install-link:focus-visible,\n.settings-connection-view-error:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 1px;\n}\n\n.settings-connection-host-tabs {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 6px;\n overflow-x: auto;\n overflow-y: hidden;\n overscroll-behavior-x: contain;\n scrollbar-width: none;\n scroll-behavior: smooth;\n scroll-snap-type: x proximity;\n touch-action: pan-x;\n}\n\n.settings-connection-host-tabs::-webkit-scrollbar {\n display: none;\n}\n\n.settings-connection-host-tab {\n display: inline-flex;\n align-items: center;\n height: 34px;\n min-width: max-content;\n flex: none;\n padding: 0 11px;\n color: var(--settings-muted);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n white-space: nowrap;\n background: rgb(0 0 0 / 18%);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n cursor: pointer;\n scroll-snap-align: start;\n}\n\n.settings-connection-host-tab:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-connection-host-tab[aria-selected="true"] {\n color: #e8f3ff;\n font-weight: 600;\n background: var(--settings-active);\n border-color: rgb(51 156 255 / 50%);\n}\n\n.settings-connection-table-header,\n.settings-connection-row {\n display: grid;\n grid-template-columns: minmax(160px, 1fr) minmax(92px, auto) 82px;\n align-items: center;\n min-width: 0;\n gap: 14px;\n}\n\n.settings-connection-table-header {\n min-height: 36px;\n padding: 0 12px;\n color: var(--settings-muted);\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n background: rgb(255 255 255 / 2%);\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-row {\n min-height: 64px;\n padding: 10px 12px;\n cursor: pointer;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-row:last-child {\n border-bottom: 0;\n}\n\n.settings-connection-row:hover {\n background: var(--settings-hover);\n}\n\n.settings-connection-row[data-connection-selected="true"] {\n background: var(--settings-active);\n}\n\n.settings-connection-row__identity,\n.settings-connection-inspector__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n gap: 9px;\n color: var(--settings-text);\n}\n\n.settings-connection-row__identity strong,\n.settings-connection-inspector__identity strong {\n min-width: 0;\n overflow-wrap: anywhere;\n font-size: 13px;\n font-weight: 600;\n line-height: 19px;\n}\n\n.settings-connection-row__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex: none;\n color: #d4d8de;\n font-size: 10px;\n font-weight: 700;\n background: rgb(255 255 255 / 6%);\n border-radius: 7px;\n}\n\n.settings-connection-row__mark--logo {\n color: var(--settings-text);\n background: transparent;\n}\n\n.settings-connection-row__mark--logo > img,\n.settings-connection-row__mark--logo > svg {\n display: block;\n max-width: 22px;\n max-height: 22px;\n}\n\n.settings-connection-row__status {\n display: inline-flex;\n align-items: center;\n width: fit-content;\n gap: 6px;\n color: var(--settings-muted);\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n}\n\n.settings-connection-row__status::before {\n width: 7px;\n height: 7px;\n flex: none;\n content: "";\n background: currentColor;\n border-radius: 50%;\n}\n\n.settings-connection-row__status[data-connection-tone="ready"] {\n color: #4ade80;\n}\n\n.settings-connection-row__status[data-connection-tone="checking"] {\n color: #f5c542;\n}\n\n.settings-connection-row__status[data-connection-tone="setup"] {\n color: var(--settings-muted);\n}\n\n.settings-connection-row__status[data-connection-tone="setup"]::before {\n background: transparent;\n border: 1.5px solid currentColor;\n}\n\n.settings-connection-row__status[data-connection-tone="failed"] {\n color: #f87171;\n}\n\n.settings-connection-row__action {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n min-width: 0;\n}\n\n.settings-connection-install-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n color: var(--settings-focus);\n text-decoration: none;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 7px;\n}\n\n.settings-connection-install-link:hover {\n color: #8cc5ff;\n background: rgb(51 156 255 / 10%);\n border-color: rgb(51 156 255 / 22%);\n}\n\n.settings-connection-view-error {\n padding: 4px 7px;\n color: #f87171;\n font: inherit;\n font-size: 11px;\n line-height: 18px;\n background: transparent;\n border: 0;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.settings-connection-view-error:hover {\n color: #fca5a5;\n background: rgb(239 68 68 / 9%);\n}\n\n.settings-connection-inspector {\n position: sticky;\n top: 24px;\n}\n\n.settings-connection-inspector__header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n min-width: 0;\n gap: 12px;\n padding: 16px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-inspector__body {\n display: grid;\n min-width: 0;\n gap: 14px;\n padding: 16px;\n}\n\n.settings-connection-install-callout {\n display: grid;\n grid-template-columns: 32px minmax(0, 1fr);\n gap: 10px;\n padding: 14px;\n background: linear-gradient(rgb(51 156 255 / 8%), rgb(51 156 255 / 4%));\n border: 1px solid rgb(51 156 255 / 20%);\n border-radius: 10px;\n}\n\n.settings-connection-install-callout__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n color: var(--settings-focus);\n background: var(--settings-active);\n border-radius: 8px;\n}\n\n.settings-connection-install-callout strong,\n.settings-connection-error-summary strong,\n.settings-connection-state-summary strong {\n display: block;\n margin: 0 0 4px;\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 600;\n line-height: 19px;\n}\n\n.settings-connection-install-callout p,\n.settings-connection-error-summary p,\n.settings-connection-state-summary p,\n.settings-connection-issue-note {\n margin: 0;\n color: var(--settings-muted);\n font-size: 11px;\n line-height: 17px;\n}\n\n.settings-connection-install-button {\n width: 100%;\n}\n\n.settings-connection-error-summary {\n padding: 13px 14px;\n color: #fecaca;\n background: rgb(239 68 68 / 7%);\n border: 1px solid rgb(239 68 68 / 20%);\n border-radius: 10px;\n}\n\n.settings-connection-error-metadata {\n display: grid;\n gap: 7px;\n padding: 12px;\n background: rgb(0 0 0 / 18%);\n border: 1px solid var(--settings-border);\n border-radius: 9px;\n}\n\n.settings-connection-detail-line {\n display: grid;\n grid-template-columns: 92px minmax(0, 1fr);\n gap: 10px;\n min-width: 0;\n color: var(--settings-muted);\n font-size: 10px;\n line-height: 16px;\n}\n\n.settings-connection-detail-line code {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n white-space: pre-wrap;\n}\n\n.settings-connection-error-log-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n}\n\n.settings-connection-error-log-header strong {\n color: var(--settings-text);\n font-size: 11px;\n font-weight: 600;\n}\n\n.settings-connection-error-log-header .settings-command-button {\n min-height: 30px;\n padding: 5px 9px;\n font-size: 11px;\n}\n\n.settings-connection-stderr {\n max-height: 220px;\n min-width: 0;\n margin: 0;\n padding: 11px;\n overflow: auto;\n color: #e3e5e8;\n font:\n 10px/16px ui-monospace,\n "SFMono-Regular",\n Consolas,\n "Liberation Mono",\n monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n background: rgb(0 0 0 / 28%);\n border: 1px solid var(--settings-border);\n border-radius: 9px;\n}\n\n.settings-connection-error-actions {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n gap: 8px;\n}\n\n.settings-connection-error-actions .settings-command-button {\n width: 100%;\n}\n\n.settings-connection-issue-note {\n margin-top: -4px;\n}\n\n.settings-connection-state-summary {\n padding: 14px;\n background: rgb(255 255 255 / 3%);\n border: 1px solid var(--settings-border);\n border-radius: 10px;\n}\n\n.settings-empty {\n display: flex;\n align-items: center;\n min-height: 72px;\n padding: 12px 16px;\n}\n\n.settings-empty > div {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n\n.settings-empty strong {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 500;\n line-height: 19px;\n}\n\n.settings-empty span {\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 19px;\n}\n\n.settings-about-panel {\n display: grid;\n max-width: 720px;\n gap: 18px;\n padding: 28px;\n background: rgb(255 255 255 / 2%);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n}\n\n.settings-about-product {\n color: var(--settings-text);\n font-size: 24px;\n font-weight: 700;\n line-height: 32px;\n}\n\n.settings-about-tagline {\n color: var(--settings-text);\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n.settings-about-copy {\n display: grid;\n max-width: 660px;\n gap: 12px;\n}\n\n.settings-about-copy p,\n.settings-about-repository p {\n margin: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 21px;\n}\n\n.settings-about-star-callout {\n margin: 2px 0;\n color: #f5c542;\n font-size: 14px;\n font-weight: 600;\n line-height: 22px;\n}\n\n.settings-about-repository {\n display: grid;\n gap: 10px;\n padding-top: 18px;\n border-top: 1px solid var(--settings-divider);\n}\n\n.settings-about-repository-link {\n display: flex;\n align-items: center;\n width: fit-content;\n min-width: 0;\n max-width: 100%;\n gap: 8px;\n color: #7cb8ff;\n font-size: 13px;\n font-weight: 600;\n text-decoration: none;\n}\n\n.settings-about-repository-link:hover {\n text-decoration: underline;\n}\n\n.settings-about-repository-link code {\n min-width: 0;\n overflow: hidden;\n color: var(--settings-muted);\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 11px;\n font-weight: 400;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-page-error {\n padding: 16px;\n color: var(--settings-text);\n font-size: 13px;\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 20px;\n}\n\n.settings-update-metadata {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 24px;\n margin-bottom: 24px;\n padding: 0 4px 20px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-update-metadata__item {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n\n.settings-update-metadata__item span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-metadata__item strong {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n/* The only emphasis on this screen: a latest version newer than the installed one. */\n.settings-update-metadata__value--newer {\n color: #4aa3f0;\n}\n\n.settings-update-panel {\n display: grid;\n gap: 12px;\n padding: 20px;\n color: var(--settings-text);\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n}\n\n.settings-update-panel__head {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-update-panel__head .codexhost-settings-icon {\n color: var(--settings-muted);\n}\n\n.settings-update-panel[data-update-state="available"] .codexhost-settings-icon,\n.settings-update-panel[data-update-state="downloading"] .codexhost-settings-icon,\n.settings-update-panel[data-update-state="installing"] .codexhost-settings-icon,\n.settings-update-panel[data-update-state="restarting"] .codexhost-settings-icon {\n color: #4aa3f0;\n}\n\n.settings-update-panel[data-update-state="current"] .codexhost-settings-icon {\n color: #4ade80;\n}\n\n.settings-update-panel[data-update-state="failed"] .codexhost-settings-icon,\n.settings-update-panel[data-update-state="error"] .codexhost-settings-icon {\n color: #ef4444;\n}\n\n.settings-update-panel__title {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 600;\n line-height: 22px;\n}\n\n.settings-update-summary,\n.settings-update-error {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-summary {\n color: var(--settings-muted);\n}\n\n.settings-update-error {\n color: #ef4444;\n}\n\n.settings-update-progress {\n width: 100%;\n height: 8px;\n accent-color: #238be8;\n}\n\n.settings-update-progress-detail {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n/* Release notes scroll with the page; a scroller inside a scroller traps the wheel. */\n.settings-update-notes-section {\n min-width: 0;\n margin-top: 24px;\n padding-top: 24px;\n border-top: 1px solid var(--settings-divider);\n}\n\n.settings-update-notes-section:empty {\n display: none;\n}\n\n.settings-update-notes {\n display: grid;\n min-width: 0;\n gap: 12px;\n color: var(--settings-muted);\n font-size: 14px;\n line-height: 22px;\n overflow-wrap: anywhere;\n}\n\n.settings-update-notes > :first-child {\n margin-top: 0;\n}\n\n.settings-update-notes > :last-child {\n margin-bottom: 0;\n}\n\n.settings-update-notes h1,\n.settings-update-notes h2,\n.settings-update-notes h3,\n.settings-update-notes h4,\n.settings-update-notes h5,\n.settings-update-notes h6 {\n margin: 6px 0 0;\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-update-notes h1 {\n font-size: 18px;\n line-height: 26px;\n}\n\n.settings-update-notes h2 {\n font-size: 17px;\n line-height: 24px;\n}\n\n.settings-update-notes h3,\n.settings-update-notes h4,\n.settings-update-notes h5,\n.settings-update-notes h6 {\n font-size: 14px;\n line-height: 22px;\n}\n\n.settings-update-notes p,\n.settings-update-notes ul,\n.settings-update-notes ol,\n.settings-update-notes pre,\n.settings-update-notes blockquote {\n margin: 0;\n}\n\n.settings-update-notes ul,\n.settings-update-notes ol {\n padding-left: 24px;\n}\n\n.settings-update-notes li {\n padding-left: 4px;\n}\n\n.settings-update-notes li::marker {\n color: var(--settings-muted);\n font-size: 0.85em;\n}\n\n.settings-update-notes li + li {\n margin-top: 14px;\n}\n\n.settings-update-notes .release-note-translation {\n display: block;\n margin-top: 3px;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-notes blockquote {\n padding: 8px 12px;\n color: var(--settings-muted);\n border-left: 3px solid var(--settings-focus);\n background: rgb(255 255 255 / 4%);\n}\n\n.settings-update-notes hr {\n width: 100%;\n margin: 2px 0;\n border: 0;\n border-top: 1px solid var(--settings-divider);\n}\n\n.settings-update-notes strong {\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-update-notes a {\n color: #7cb8ff;\n text-decoration: none;\n}\n\n.settings-update-notes a:hover {\n text-decoration: underline;\n}\n\n.settings-update-notes code {\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 12px;\n}\n\n.settings-update-notes :not(pre) > code {\n padding: 1px 5px;\n background: rgb(255 255 255 / 8%);\n border-radius: 4px;\n}\n\n.settings-update-notes pre {\n min-width: 0;\n max-width: 100%;\n padding: 10px 12px;\n overflow-x: auto;\n overflow-y: hidden;\n background: rgb(0 0 0 / 28%);\n border-radius: 6px;\n}\n\n.settings-update-notes pre code {\n line-height: 18px;\n white-space: pre-wrap;\n}\n\n/* Manual update sits directly under the status panel, not behind a disclosure:\n automatic updates can fail for machine-local reasons and this is the way out. */\n.settings-update-controls {\n display: grid;\n min-width: 0;\n gap: 10px;\n margin-top: 24px;\n}\n\n.settings-update-manual-title {\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 600;\n line-height: 22px;\n}\n\n.settings-update-manual {\n display: grid;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-update-manual[hidden] {\n display: none;\n}\n\n.settings-update-manual-description {\n margin: 0;\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-manual-description.is-fallback {\n color: #ef4444;\n}\n\n.settings-update-command {\n display: flex;\n align-items: stretch;\n min-width: 0;\n overflow: hidden;\n border: 1px solid var(--settings-border);\n border-radius: 6px;\n}\n\n.settings-update-command code {\n min-width: 0;\n flex: 1;\n padding: 9px 12px;\n overflow-x: auto;\n color: var(--settings-text);\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 12px;\n line-height: 20px;\n white-space: nowrap;\n}\n\n.settings-update-command__copy {\n display: inline-flex;\n align-items: center;\n flex: none;\n gap: 6px;\n padding: 0 12px;\n color: var(--settings-muted);\n font-size: 12px;\n background: transparent;\n border: 0;\n border-left: 1px solid var(--settings-border);\n cursor: pointer;\n}\n\n.settings-update-command__copy:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-update-command__copy:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: -2px;\n}\n\n.settings-update-actions {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.settings-command-button,\n.settings-update-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: fit-content;\n min-height: 36px;\n gap: 8px;\n padding: 8px 12px;\n color: white;\n font: inherit;\n font-size: 13px;\n text-decoration: none;\n background: #1677d2;\n border: 1px solid #238be8;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.settings-command-button--secondary,\n.settings-update-link {\n color: var(--settings-text);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button:hover,\n.settings-update-link:hover {\n filter: brightness(1.08);\n}\n\n.settings-command-button:focus-visible,\n.settings-update-link:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 2px;\n}\n\n.codexhost-settings-icon {\n display: block;\n flex: none;\n stroke: currentColor;\n}\n\n@media (max-width: 720px) {\n .codexhost-settings-dialog {\n width: calc(100vw - 16px);\n height: calc(100vh - 16px);\n border-radius: 10px;\n }\n\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .settings-sidebar {\n border-right: 0;\n border-bottom: 1px solid var(--settings-border);\n }\n\n .settings-header {\n height: 56px;\n padding-inline: 14px;\n }\n\n .settings-sidebar {\n padding-top: 20px;\n }\n\n .settings-nav {\n flex: none;\n flex-direction: row;\n gap: 4px;\n padding: 7px 8px 8px;\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n .settings-nav-section-label {\n display: none;\n }\n\n .settings-nav-button {\n width: auto;\n min-width: max-content;\n min-height: 34px;\n grid-template-columns: 16px auto;\n border-radius: 10px;\n }\n\n .settings-nav-star-link {\n margin-top: 0;\n }\n\n .settings-page__content {\n width: calc(100% - 40px);\n }\n\n .settings-page__content {\n padding-top: 32px;\n padding-bottom: 32px;\n }\n\n .settings-section-label {\n padding-bottom: 20px;\n font-size: 20px;\n line-height: 26px;\n }\n\n .settings-update-metadata {\n grid-template-columns: minmax(0, 1fr);\n gap: 16px;\n }\n\n .settings-status-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 16px;\n }\n\n .settings-connection-page-header {\n flex-direction: column;\n }\n\n .settings-connection-page-header > .settings-command-button {\n width: 100%;\n }\n\n .settings-connections-layout {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .settings-connection-inspector {\n position: static;\n }\n\n .settings-status-row__detail {\n grid-column: 1 / -1;\n margin: -8px 0 0 58px;\n }\n}\n\n@media (forced-colors: active) {\n :host,\n :host([data-theme="dark"]) {\n --settings-bg: Canvas;\n --settings-sidebar: Canvas;\n --settings-panel: Canvas;\n --settings-text: CanvasText;\n --settings-muted: GrayText;\n --settings-border: ButtonBorder;\n --settings-divider: ButtonBorder;\n --settings-hover: Highlight;\n --settings-active: Highlight;\n --settings-focus: Highlight;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
|
|
20968
21733
|
|
|
20969
21734
|
// src/settings/shell.ts
|
|
20970
21735
|
var SETTINGS_SHELL_ATTRIBUTE = "data-codexhost-settings-shell";
|
|
20971
|
-
var CODEXHOST_GITHUB_REPOSITORY_URL = "https://github.com/BytePioneer-AI/codex-host";
|
|
20972
21736
|
function isRendererSettingsDialogSupported(dialog) {
|
|
20973
21737
|
return typeof dialog.showModal === "function" && typeof dialog.close === "function";
|
|
20974
21738
|
}
|
|
@@ -21015,23 +21779,13 @@ ${error51.stderrTail}`] : []
|
|
|
21015
21779
|
brand.append(brandMark, brandCopy);
|
|
21016
21780
|
const headerActions = ownerDocument.createElement("div");
|
|
21017
21781
|
headerActions.className = "settings-header-actions";
|
|
21018
|
-
const starLink = ownerDocument.createElement("a");
|
|
21019
|
-
starLink.className = "settings-icon-button settings-star-link";
|
|
21020
|
-
starLink.href = CODEXHOST_GITHUB_REPOSITORY_URL;
|
|
21021
|
-
starLink.target = "_blank";
|
|
21022
|
-
starLink.rel = "noopener noreferrer";
|
|
21023
|
-
starLink.setAttribute("aria-label", messages.starOnGitHub);
|
|
21024
|
-
starLink.title = messages.starOnGitHub;
|
|
21025
|
-
const starLabel = ownerDocument.createElement("span");
|
|
21026
|
-
starLabel.textContent = messages.starOnGitHub;
|
|
21027
|
-
starLink.append(createRendererSettingsIcon("star", 16), starLabel);
|
|
21028
21782
|
const closeButton = ownerDocument.createElement("button");
|
|
21029
21783
|
closeButton.type = "button";
|
|
21030
21784
|
closeButton.className = "settings-icon-button";
|
|
21031
21785
|
closeButton.setAttribute("aria-label", messages.close);
|
|
21032
21786
|
closeButton.title = messages.close;
|
|
21033
21787
|
closeButton.append(createRendererSettingsIcon("close", 18));
|
|
21034
|
-
headerActions.append(
|
|
21788
|
+
headerActions.append(closeButton);
|
|
21035
21789
|
header.append(brand, headerActions);
|
|
21036
21790
|
const layout = ownerDocument.createElement("div");
|
|
21037
21791
|
layout.className = "settings-layout";
|
|
@@ -21097,7 +21851,19 @@ ${error51.stderrTail}`] : []
|
|
|
21097
21851
|
renderMountFailure();
|
|
21098
21852
|
}
|
|
21099
21853
|
};
|
|
21854
|
+
const appendNavigationSection = (label) => {
|
|
21855
|
+
const section = ownerDocument.createElement("div");
|
|
21856
|
+
section.className = "settings-nav-section-label";
|
|
21857
|
+
section.textContent = label;
|
|
21858
|
+
navigation.append(section);
|
|
21859
|
+
};
|
|
21860
|
+
let otherSectionAdded = false;
|
|
21861
|
+
appendNavigationSection(messages.generalSection);
|
|
21100
21862
|
for (const definition of resolvedRegistry.pages) {
|
|
21863
|
+
if (definition.id === "about" && !otherSectionAdded) {
|
|
21864
|
+
appendNavigationSection(messages.otherSection);
|
|
21865
|
+
otherSectionAdded = true;
|
|
21866
|
+
}
|
|
21101
21867
|
const button = ownerDocument.createElement("button");
|
|
21102
21868
|
button.type = "button";
|
|
21103
21869
|
button.className = "settings-nav-button";
|
|
@@ -21109,6 +21875,18 @@ ${error51.stderrTail}`] : []
|
|
|
21109
21875
|
navigationButtons.set(definition.id, button);
|
|
21110
21876
|
navigation.append(button);
|
|
21111
21877
|
}
|
|
21878
|
+
const starLink = ownerDocument.createElement("a");
|
|
21879
|
+
starLink.className = "settings-nav-button settings-nav-star-link";
|
|
21880
|
+
starLink.href = CODEXHOST_GITHUB_REPOSITORY_URL;
|
|
21881
|
+
starLink.target = "_blank";
|
|
21882
|
+
starLink.rel = "noopener noreferrer";
|
|
21883
|
+
starLink.setAttribute("aria-label", messages.starOnGitHub);
|
|
21884
|
+
starLink.title = messages.starOnGitHub;
|
|
21885
|
+
starLink.append(createRendererSettingsIcon("star", 17));
|
|
21886
|
+
const starLabel = ownerDocument.createElement("span");
|
|
21887
|
+
starLabel.textContent = messages.starOnGitHub;
|
|
21888
|
+
starLink.append(starLabel);
|
|
21889
|
+
navigation.append(starLink);
|
|
21112
21890
|
const supported = isRendererSettingsDialogSupported(dialog);
|
|
21113
21891
|
const focusActiveNavigation = () => {
|
|
21114
21892
|
navigationButtons.get(navigationState.activePageId)?.focus();
|
|
@@ -21450,6 +22228,7 @@ ${error51.stderrTail}`] : []
|
|
|
21450
22228
|
trigger = null;
|
|
21451
22229
|
shell = null;
|
|
21452
22230
|
const mounted = mount();
|
|
22231
|
+
options.onLocaleChange?.(locale);
|
|
21453
22232
|
if (reopen) {
|
|
21454
22233
|
const opener = mounted.trigger.root?.querySelector("button") ?? void 0;
|
|
21455
22234
|
mounted.shell.openSettings(opener, activePageId);
|
|
@@ -21562,23 +22341,6 @@ ${error51.stderrTail}`] : []
|
|
|
21562
22341
|
};
|
|
21563
22342
|
}
|
|
21564
22343
|
|
|
21565
|
-
// src/compatibility-update.ts
|
|
21566
|
-
async function startCompatibilityUpdate(client) {
|
|
21567
|
-
if (!client) return "unavailable";
|
|
21568
|
-
try {
|
|
21569
|
-
const check2 = await client.checkUpdate();
|
|
21570
|
-
if (check2.updateAvailable && check2.installationAvailable) {
|
|
21571
|
-
void client.startUpdate().catch(() => void 0);
|
|
21572
|
-
return "update-started";
|
|
21573
|
-
}
|
|
21574
|
-
if (check2.error === null && check2.latestVersion !== null && check2.currentVersion === check2.latestVersion) {
|
|
21575
|
-
return "current";
|
|
21576
|
-
}
|
|
21577
|
-
} catch {
|
|
21578
|
-
}
|
|
21579
|
-
return "unavailable";
|
|
21580
|
-
}
|
|
21581
|
-
|
|
21582
22344
|
// src/renderer-binding-probe.ts
|
|
21583
22345
|
var externalHarnessIds = {
|
|
21584
22346
|
pi: harnessIdSchema.parse("pi"),
|
|
@@ -21608,6 +22370,9 @@ ${error51.stderrTail}`] : []
|
|
|
21608
22370
|
);
|
|
21609
22371
|
}
|
|
21610
22372
|
var rendererUsageRefreshDelays = [250, 500, 1e3, 2e3, 4e3, 8e3];
|
|
22373
|
+
function refreshConnectionHosts(hostIds, refreshHost) {
|
|
22374
|
+
return Promise.all([...hostIds].map((hostId) => refreshHost(hostId))).then(() => void 0);
|
|
22375
|
+
}
|
|
21611
22376
|
function rendererUsageRefreshDelay(attempt) {
|
|
21612
22377
|
const index = Math.max(0, Math.min(Math.trunc(attempt), rendererUsageRefreshDelays.length - 1));
|
|
21613
22378
|
return rendererUsageRefreshDelays[index] ?? rendererUsageRefreshDelays[0];
|
|
@@ -21632,6 +22397,13 @@ ${error51.stderrTail}`] : []
|
|
|
21632
22397
|
function draftPermissionMode(catalog, requested) {
|
|
21633
22398
|
return catalog.modes.find(({ id }) => id === requested)?.id ?? catalog.modes.find(({ id }) => id === catalog.defaultModeId)?.id ?? catalog.defaultModeId;
|
|
21634
22399
|
}
|
|
22400
|
+
function lockedPermissionMode(catalog, effective, carrier) {
|
|
22401
|
+
const restored = effective ?? carrier;
|
|
22402
|
+
if (restored && !catalog.modes.some(({ id }) => id === restored)) {
|
|
22403
|
+
throw new Error("Existing Thread Permission Mode is absent from the current Catalog");
|
|
22404
|
+
}
|
|
22405
|
+
return restored;
|
|
22406
|
+
}
|
|
21635
22407
|
function shouldPersistNewThreadConfigurationSelection(phase) {
|
|
21636
22408
|
return phase === "draft";
|
|
21637
22409
|
}
|
|
@@ -21698,7 +22470,12 @@ ${error51.stderrTail}`] : []
|
|
|
21698
22470
|
throw new Error("DeepSeek Harness Thread reported an incompatible transport Model");
|
|
21699
22471
|
}
|
|
21700
22472
|
const model = inspection.effectiveModel ?? transportSelection.model;
|
|
21701
|
-
|
|
22473
|
+
const permissionModeId = inspection.effectivePermissionModeId ?? transportSelection.permissionModeId;
|
|
22474
|
+
return {
|
|
22475
|
+
agent: "deepseek-harness",
|
|
22476
|
+
...model ? { model } : {},
|
|
22477
|
+
...permissionModeId ? { permissionModeId } : {}
|
|
22478
|
+
};
|
|
21702
22479
|
}
|
|
21703
22480
|
throw new Error("Thread owner is not a Renderer Agent");
|
|
21704
22481
|
}
|
|
@@ -21805,7 +22582,10 @@ ${error51.stderrTail}`] : []
|
|
|
21805
22582
|
let connectionDiagnostics = null;
|
|
21806
22583
|
const settingsLifecycle = installRendererSettingsLifecycle(window, {
|
|
21807
22584
|
getUpdateClient: () => modelControl,
|
|
21808
|
-
getConnectionDiagnostics: () => connectionDiagnostics
|
|
22585
|
+
getConnectionDiagnostics: () => connectionDiagnostics,
|
|
22586
|
+
onLocaleChange() {
|
|
22587
|
+
for (const mounted of mountedByComposer.values()) renderMounted(mounted);
|
|
22588
|
+
}
|
|
21809
22589
|
});
|
|
21810
22590
|
let adapterStatus = {
|
|
21811
22591
|
state: "installing",
|
|
@@ -21884,8 +22664,15 @@ ${error51.stderrTail}`] : []
|
|
|
21884
22664
|
mounted.modelView,
|
|
21885
22665
|
mounted.permissionModeView,
|
|
21886
22666
|
mounted.usage,
|
|
21887
|
-
mounted.accountCredits
|
|
22667
|
+
mounted.accountCredits,
|
|
22668
|
+
settingsLifecycle.locale
|
|
21888
22669
|
);
|
|
22670
|
+
if (mounted.control.usage) {
|
|
22671
|
+
mounted.control.usage.onOpen = () => {
|
|
22672
|
+
if (controller.get(mounted.composer).agent === "codex") return;
|
|
22673
|
+
void refreshThreadUsage(mounted, "exact");
|
|
22674
|
+
};
|
|
22675
|
+
}
|
|
21889
22676
|
};
|
|
21890
22677
|
const refreshCommands = async (mounted) => {
|
|
21891
22678
|
const state = controller.get(mounted.composer);
|
|
@@ -21931,7 +22718,7 @@ ${error51.stderrTail}`] : []
|
|
|
21931
22718
|
renderMounted(mounted);
|
|
21932
22719
|
}
|
|
21933
22720
|
};
|
|
21934
|
-
const refreshThreadUsage = async (mounted) => {
|
|
22721
|
+
const refreshThreadUsage = async (mounted, refresh) => {
|
|
21935
22722
|
const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
|
|
21936
22723
|
if (!threadId || !modelControl) {
|
|
21937
22724
|
mounted.usage = null;
|
|
@@ -21942,7 +22729,10 @@ ${error51.stderrTail}`] : []
|
|
|
21942
22729
|
}
|
|
21943
22730
|
const generation = ++mounted.usageRequestGeneration;
|
|
21944
22731
|
try {
|
|
21945
|
-
const result = await modelControl.inspectThreadUsage({
|
|
22732
|
+
const result = await modelControl.inspectThreadUsage({
|
|
22733
|
+
threadId,
|
|
22734
|
+
...refresh ? { refresh } : {}
|
|
22735
|
+
});
|
|
21946
22736
|
if (disposed || mountedByComposer.get(mounted.composer) !== mounted || !mounted.composer.isConnected || mounted.usageRequestGeneration !== generation || threadIdFromComposerModelTarget(mounted.modelTarget) !== threadId || result.threadId !== threadId) {
|
|
21947
22737
|
return;
|
|
21948
22738
|
}
|
|
@@ -22163,11 +22953,15 @@ ${error51.stderrTail}`] : []
|
|
|
22163
22953
|
throw new Error("External Harness omitted its Permission Mode catalog");
|
|
22164
22954
|
}
|
|
22165
22955
|
mounted.permissionModeView = { status: "loading", catalog: permissionModes };
|
|
22166
|
-
const
|
|
22956
|
+
const restoredPermissionModeId = current.phase === "locked" ? lockedPermissionMode(
|
|
22957
|
+
permissionModes,
|
|
22958
|
+
mounted.threadConfiguration?.effectivePermissionModeId,
|
|
22959
|
+
previousPermissionModeId
|
|
22960
|
+
) : void 0;
|
|
22167
22961
|
const preferredPermissionModeId = preferredConfiguration?.permissionModeId ?? (agent === "claude-code" ? readClaudePermissionModePreference(permissionModes) : void 0);
|
|
22168
22962
|
selectedPermissionModeId = draftPermissionMode(
|
|
22169
22963
|
permissionModes,
|
|
22170
|
-
|
|
22964
|
+
restoredPermissionModeId ?? previousPermissionModeId ?? preferredPermissionModeId
|
|
22171
22965
|
);
|
|
22172
22966
|
mounted.permissionModeView = {
|
|
22173
22967
|
status: "loading",
|
|
@@ -22875,10 +23669,10 @@ ${error51.stderrTail}`] : []
|
|
|
22875
23669
|
};
|
|
22876
23670
|
},
|
|
22877
23671
|
refresh() {
|
|
22878
|
-
|
|
22879
|
-
|
|
22880
|
-
|
|
22881
|
-
|
|
23672
|
+
return refreshConnectionHosts(
|
|
23673
|
+
harnessAvailabilityByHost.keys(),
|
|
23674
|
+
(hostId) => refreshHarnessAvailabilityForHost(hostId, true, false, true)
|
|
23675
|
+
);
|
|
22882
23676
|
},
|
|
22883
23677
|
subscribe(listener) {
|
|
22884
23678
|
connectionListeners.add(listener);
|
|
@@ -23259,9 +24053,6 @@ ${error51.stderrTail}`] : []
|
|
|
23259
24053
|
...permissionModeId ? { permissionModeId } : {}
|
|
23260
24054
|
};
|
|
23261
24055
|
},
|
|
23262
|
-
requestCompatibilityUpdate() {
|
|
23263
|
-
return startCompatibilityUpdate(modelControl);
|
|
23264
|
-
},
|
|
23265
24056
|
setAdapter(status, dispose, applyAgent, nextModelControl) {
|
|
23266
24057
|
usageNotificationDispose?.();
|
|
23267
24058
|
usageNotificationDispose = null;
|
|
@@ -23389,10 +24180,14 @@ lucide/dist/esm/icons/chevron-down.mjs:
|
|
|
23389
24180
|
lucide/dist/esm/icons/shield.mjs:
|
|
23390
24181
|
lucide/dist/esm/icons/shield-alert.mjs:
|
|
23391
24182
|
lucide/dist/esm/icons/boxes.mjs:
|
|
24183
|
+
lucide/dist/esm/icons/circle-check.mjs:
|
|
24184
|
+
lucide/dist/esm/icons/chevron-left.mjs:
|
|
24185
|
+
lucide/dist/esm/icons/chevron-right.mjs:
|
|
23392
24186
|
lucide/dist/esm/icons/circle-off.mjs:
|
|
23393
24187
|
lucide/dist/esm/icons/copy.mjs:
|
|
23394
24188
|
lucide/dist/esm/icons/download.mjs:
|
|
23395
24189
|
lucide/dist/esm/icons/external-link.mjs:
|
|
24190
|
+
lucide/dist/esm/icons/info.mjs:
|
|
23396
24191
|
lucide/dist/esm/icons/languages.mjs:
|
|
23397
24192
|
lucide/dist/esm/icons/network.mjs:
|
|
23398
24193
|
lucide/dist/esm/icons/plug-zap.mjs:
|
|
@@ -23401,6 +24196,7 @@ lucide/dist/esm/icons/route.mjs:
|
|
|
23401
24196
|
lucide/dist/esm/icons/settings.mjs:
|
|
23402
24197
|
lucide/dist/esm/icons/stethoscope.mjs:
|
|
23403
24198
|
lucide/dist/esm/icons/star.mjs:
|
|
24199
|
+
lucide/dist/esm/icons/triangle-alert.mjs:
|
|
23404
24200
|
lucide/dist/esm/icons/x.mjs:
|
|
23405
24201
|
(**
|
|
23406
24202
|
* @license lucide v1.28.0 - ISC
|