@liberseek/boft-cli-win32-arm64 0.4.4 → 0.5.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/host-runtime.mjs +13730 -1886
- package/app/renderer-extension.js +814 -78
- package/bin/codexhost.exe +0 -0
- package/libexec/codexhost-node-repl.exe +0 -0
- package/libexec/codexhost-shim.exe +0 -0
- package/libexec/codexhost-updater.exe +0 -0
- package/package.json +1 -1
|
@@ -14916,6 +14916,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14916
14916
|
stderrTail: external_exports.string().min(1).optional()
|
|
14917
14917
|
}).superRefine(rejectExplicitUndefined(["diagnostic", "stage", "durationMs", "stderrTail"]));
|
|
14918
14918
|
|
|
14919
|
+
// ../shared-contracts/dist/harness-session-import.js
|
|
14920
|
+
var HARNESS_SESSION_IMPORT_ID_MAX_LENGTH = 1024;
|
|
14921
|
+
var HARNESS_SESSION_IMPORT_CWD_MAX_LENGTH = 16384;
|
|
14922
|
+
var HARNESS_SESSION_IMPORT_TITLE_MAX_LENGTH = 4096;
|
|
14923
|
+
var HARNESS_SESSION_IMPORT_LIST_MAX_LENGTH = 1e3;
|
|
14924
|
+
var HARNESS_SESSION_IMPORT_UPDATED_AT_MAX = 864e13;
|
|
14925
|
+
var nonBlankTextSchema = external_exports.string().refine((value) => value.trim().length > 0, "Value must not be empty or whitespace").refine((value) => !value.includes("\0"), "Value must not contain NUL");
|
|
14926
|
+
var harnessSessionImportIdSchema = nonBlankTextSchema.max(HARNESS_SESSION_IMPORT_ID_MAX_LENGTH);
|
|
14927
|
+
var harnessSessionImportCandidateSchema = external_exports.object({
|
|
14928
|
+
nativeSessionId: harnessSessionImportIdSchema,
|
|
14929
|
+
title: nonBlankTextSchema.max(HARNESS_SESSION_IMPORT_TITLE_MAX_LENGTH).nullable(),
|
|
14930
|
+
updatedAt: external_exports.number().int().nonnegative().max(HARNESS_SESSION_IMPORT_UPDATED_AT_MAX),
|
|
14931
|
+
cwd: nonBlankTextSchema.max(HARNESS_SESSION_IMPORT_CWD_MAX_LENGTH),
|
|
14932
|
+
running: external_exports.boolean()
|
|
14933
|
+
}).strict();
|
|
14934
|
+
|
|
14919
14935
|
// ../shared-contracts/dist/ids.js
|
|
14920
14936
|
var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
|
|
14921
14937
|
message: "Identifier must not be empty or whitespace"
|
|
@@ -14926,6 +14942,23 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14926
14942
|
var hostItemIdSchema = opaqueIdSchema.brand();
|
|
14927
14943
|
var hostInteractionIdSchema = opaqueIdSchema.brand();
|
|
14928
14944
|
|
|
14945
|
+
// ../shared-contracts/dist/deepseek-modern-sessions.js
|
|
14946
|
+
var DEEPSEEK_MODERN_SESSION_LIST_MAX_LENGTH = HARNESS_SESSION_IMPORT_LIST_MAX_LENGTH;
|
|
14947
|
+
var DEEPSEEK_MODERN_HOST_THREAD_ID_MAX_LENGTH = 1024;
|
|
14948
|
+
var nonBlankTextSchema2 = external_exports.string().refine((value) => value.trim().length > 0, "Value must not be empty or whitespace").refine((value) => !value.includes("\0"), "Value must not contain NUL");
|
|
14949
|
+
var deepSeekModernSessionIdSchema = harnessSessionImportIdSchema;
|
|
14950
|
+
var deepSeekModernSessionCandidateSchema = harnessSessionImportCandidateSchema;
|
|
14951
|
+
var deepSeekModernSessionListParamsSchema = external_exports.object({}).strict();
|
|
14952
|
+
var deepSeekModernSessionListResultSchema = external_exports.object({
|
|
14953
|
+
candidates: external_exports.array(deepSeekModernSessionCandidateSchema).max(DEEPSEEK_MODERN_SESSION_LIST_MAX_LENGTH)
|
|
14954
|
+
}).strict();
|
|
14955
|
+
var deepSeekModernSessionImportParamsSchema = external_exports.object({
|
|
14956
|
+
nativeSessionId: deepSeekModernSessionIdSchema
|
|
14957
|
+
}).strict();
|
|
14958
|
+
var deepSeekModernSessionImportResultSchema = external_exports.object({
|
|
14959
|
+
threadId: nonBlankTextSchema2.max(DEEPSEEK_MODERN_HOST_THREAD_ID_MAX_LENGTH).pipe(hostThreadIdSchema)
|
|
14960
|
+
}).strict();
|
|
14961
|
+
|
|
14929
14962
|
// ../shared-contracts/dist/external-thread-fork.js
|
|
14930
14963
|
var externalThreadForkParamsSchema = external_exports.object({
|
|
14931
14964
|
threadId: hostThreadIdSchema,
|
|
@@ -14940,14 +14973,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14940
14973
|
var HARNESS_PERMISSION_MODE_LABEL_MAX_LENGTH = 256;
|
|
14941
14974
|
var HARNESS_PERMISSION_MODE_DESCRIPTION_MAX_LENGTH = 1024;
|
|
14942
14975
|
var HARNESS_PERMISSION_MODE_CATALOG_MAX_LENGTH = 32;
|
|
14943
|
-
var
|
|
14976
|
+
var nonBlankTextSchema3 = external_exports.string().refine((value) => value.trim().length > 0, {
|
|
14944
14977
|
message: "Value must not be empty or whitespace"
|
|
14945
14978
|
});
|
|
14946
|
-
var harnessPermissionModeIdSchema =
|
|
14979
|
+
var harnessPermissionModeIdSchema = nonBlankTextSchema3.max(HARNESS_PERMISSION_MODE_ID_MAX_LENGTH).regex(/^[A-Za-z0-9._~-]+$/u, "Permission Mode ID must use transport-safe characters").brand();
|
|
14947
14980
|
var harnessPermissionModeSchema = external_exports.object({
|
|
14948
14981
|
id: harnessPermissionModeIdSchema,
|
|
14949
|
-
label:
|
|
14950
|
-
description:
|
|
14982
|
+
label: nonBlankTextSchema3.max(HARNESS_PERMISSION_MODE_LABEL_MAX_LENGTH),
|
|
14983
|
+
description: nonBlankTextSchema3.max(HARNESS_PERMISSION_MODE_DESCRIPTION_MAX_LENGTH).optional(),
|
|
14951
14984
|
dangerous: external_exports.boolean().optional()
|
|
14952
14985
|
}).strict();
|
|
14953
14986
|
var harnessPermissionModeCatalogSchema = external_exports.object({
|
|
@@ -15060,22 +15093,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15060
15093
|
var HARNESS_MODEL_LABEL_MAX_LENGTH = 256;
|
|
15061
15094
|
var HARNESS_THINKING_OPTION_ID_MAX_LENGTH = 128;
|
|
15062
15095
|
var THREAD_OWNERSHIP_LIST_MAX_LENGTH = 100;
|
|
15063
|
-
var
|
|
15096
|
+
var nonBlankTextSchema4 = external_exports.string().refine((value) => value.trim().length > 0, {
|
|
15064
15097
|
message: "Value must not be empty or whitespace"
|
|
15065
15098
|
});
|
|
15066
|
-
var harnessModelRefIdSchema =
|
|
15099
|
+
var harnessModelRefIdSchema = nonBlankTextSchema4.max(HARNESS_MODEL_REF_MAX_LENGTH).regex(/^[A-Za-z0-9._~-]+$/u, "Model Ref must use transport-safe opaque characters").brand();
|
|
15067
15100
|
var harnessModelRefSchema = external_exports.object({
|
|
15068
15101
|
id: harnessModelRefIdSchema
|
|
15069
15102
|
}).strict();
|
|
15070
|
-
var harnessThinkingOptionIdSchema =
|
|
15071
|
-
var harnessResolvedModelLabelSchema =
|
|
15103
|
+
var harnessThinkingOptionIdSchema = nonBlankTextSchema4.max(HARNESS_THINKING_OPTION_ID_MAX_LENGTH).regex(/^[A-Za-z0-9._~-]+$/u, "Thinking option ID must use transport-safe characters").brand();
|
|
15104
|
+
var harnessResolvedModelLabelSchema = nonBlankTextSchema4.max(HARNESS_MODEL_LABEL_MAX_LENGTH);
|
|
15072
15105
|
var harnessThinkingOptionSchema = external_exports.object({
|
|
15073
15106
|
id: harnessThinkingOptionIdSchema,
|
|
15074
|
-
label:
|
|
15107
|
+
label: nonBlankTextSchema4.max(HARNESS_MODEL_LABEL_MAX_LENGTH)
|
|
15075
15108
|
}).strict();
|
|
15076
15109
|
var harnessModelSchema = external_exports.object({
|
|
15077
15110
|
ref: harnessModelRefSchema,
|
|
15078
|
-
label:
|
|
15111
|
+
label: nonBlankTextSchema4.max(HARNESS_MODEL_LABEL_MAX_LENGTH),
|
|
15079
15112
|
resolvedModelLabel: harnessResolvedModelLabelSchema.optional(),
|
|
15080
15113
|
supportedThinkingOptionIds: external_exports.array(harnessThinkingOptionIdSchema).optional()
|
|
15081
15114
|
}).strict();
|
|
@@ -15187,11 +15220,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15187
15220
|
}
|
|
15188
15221
|
});
|
|
15189
15222
|
var harnessModelSelectionStateSchema = harnessConfigurationStateSchema;
|
|
15223
|
+
var harnessWebUiCapabilitySchema = external_exports.object({
|
|
15224
|
+
open: external_exports.literal(true)
|
|
15225
|
+
}).strict();
|
|
15190
15226
|
var readyHarnessInspectionSchema = external_exports.object({
|
|
15191
15227
|
status: external_exports.literal("ready"),
|
|
15192
15228
|
catalog: harnessModelCatalogSchema,
|
|
15193
15229
|
permissionModes: harnessPermissionModeCatalogSchema.optional(),
|
|
15194
|
-
capabilities: harnessSessionCapabilitiesSchema
|
|
15230
|
+
capabilities: harnessSessionCapabilitiesSchema,
|
|
15231
|
+
webUi: harnessWebUiCapabilitySchema.optional()
|
|
15195
15232
|
}).strict().superRefine((inspection, context) => {
|
|
15196
15233
|
const selectable = inspection.capabilities.configuration.selectPermissionMode;
|
|
15197
15234
|
if (selectable !== Boolean(inspection.permissionModes)) {
|
|
@@ -15212,9 +15249,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15212
15249
|
]);
|
|
15213
15250
|
var harnessInspectParamsSchema = external_exports.object({
|
|
15214
15251
|
harnessId: harnessIdSchema,
|
|
15215
|
-
cwd:
|
|
15252
|
+
cwd: nonBlankTextSchema4.max(16384).optional(),
|
|
15216
15253
|
refresh: external_exports.boolean().optional()
|
|
15217
15254
|
}).strict();
|
|
15255
|
+
var harnessWebUiOpenParamsSchema = external_exports.object({
|
|
15256
|
+
harnessId: harnessIdSchema
|
|
15257
|
+
}).strict();
|
|
15258
|
+
var harnessWebUiOpenResultSchema = external_exports.object({}).strict();
|
|
15218
15259
|
var threadModelSelectParamsSchema = external_exports.object({
|
|
15219
15260
|
threadId: hostThreadIdSchema,
|
|
15220
15261
|
model: harnessModelRefSchema
|
|
@@ -15232,8 +15273,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15232
15273
|
}).strict();
|
|
15233
15274
|
var externalThreadInspectionSchema = external_exports.object({
|
|
15234
15275
|
owner: external_exports.literal("external"),
|
|
15235
|
-
harnessId:
|
|
15236
|
-
transportModelId:
|
|
15276
|
+
harnessId: nonBlankTextSchema4.max(256),
|
|
15277
|
+
transportModelId: nonBlankTextSchema4.max(1024),
|
|
15237
15278
|
effectiveModel: harnessModelRefSchema.optional(),
|
|
15238
15279
|
resolvedModelLabel: harnessResolvedModelLabelSchema.optional(),
|
|
15239
15280
|
effectiveThinkingOptionId: harnessThinkingOptionIdSchema.optional(),
|
|
@@ -16255,7 +16296,34 @@ ${error51.stderrTail}`] : []
|
|
|
16255
16296
|
body.append(callout, install2);
|
|
16256
16297
|
return body;
|
|
16257
16298
|
}
|
|
16258
|
-
if (!item.error)
|
|
16299
|
+
if (!item.error) {
|
|
16300
|
+
if (item.openWebUi) {
|
|
16301
|
+
const status = document2.createElement("div");
|
|
16302
|
+
status.className = "settings-connection-state-summary";
|
|
16303
|
+
const title2 = document2.createElement("strong");
|
|
16304
|
+
title2.textContent = connectionStatusLabel(item.availability, messages);
|
|
16305
|
+
const description2 = document2.createElement("p");
|
|
16306
|
+
description2.textContent = item.availability === "ready" ? messages.connectionReadyDescription : messages.connectionUnavailableDescription;
|
|
16307
|
+
status.append(title2, description2);
|
|
16308
|
+
const open = document2.createElement("button");
|
|
16309
|
+
open.type = "button";
|
|
16310
|
+
open.className = "settings-command-button settings-command-button--secondary";
|
|
16311
|
+
open.dataset.connectionAction = "open-web-ui";
|
|
16312
|
+
open.append(
|
|
16313
|
+
messages.connectionOpenHarnessWeb,
|
|
16314
|
+
createRendererSettingsIcon("external-link", 14)
|
|
16315
|
+
);
|
|
16316
|
+
open.addEventListener("click", () => {
|
|
16317
|
+
if (open.disabled) return;
|
|
16318
|
+
open.disabled = true;
|
|
16319
|
+
void item.openWebUi?.().catch(() => void 0).finally(() => {
|
|
16320
|
+
open.disabled = false;
|
|
16321
|
+
});
|
|
16322
|
+
});
|
|
16323
|
+
body.append(status, open);
|
|
16324
|
+
}
|
|
16325
|
+
return body;
|
|
16326
|
+
}
|
|
16259
16327
|
const summary = document2.createElement("div");
|
|
16260
16328
|
summary.className = "settings-connection-error-summary";
|
|
16261
16329
|
const title = document2.createElement("strong");
|
|
@@ -16343,7 +16411,7 @@ ${error51.stderrTail}`] : []
|
|
|
16343
16411
|
const action = document2.createElement("div");
|
|
16344
16412
|
action.className = "settings-connection-row__action";
|
|
16345
16413
|
action.setAttribute("role", "cell");
|
|
16346
|
-
const canExpand = item.error !== null || item.agentSnapshot?.availability === "notInstalled";
|
|
16414
|
+
const canExpand = item.error !== null || item.agentSnapshot?.availability === "notInstalled" || item.openWebUi !== void 0;
|
|
16347
16415
|
if (item.agentSnapshot?.availability === "notInstalled") {
|
|
16348
16416
|
const install2 = document2.createElement("a");
|
|
16349
16417
|
install2.className = "settings-connection-install-link";
|
|
@@ -16366,12 +16434,6 @@ ${error51.stderrTail}`] : []
|
|
|
16366
16434
|
});
|
|
16367
16435
|
action.append(viewError);
|
|
16368
16436
|
}
|
|
16369
|
-
row.addEventListener("click", (event) => {
|
|
16370
|
-
const target = event.target;
|
|
16371
|
-
if (target?.closest?.("a")) return;
|
|
16372
|
-
if (!canExpand) return;
|
|
16373
|
-
toggleExpand();
|
|
16374
|
-
});
|
|
16375
16437
|
row.addEventListener("keydown", (event) => {
|
|
16376
16438
|
if (event.key !== "Enter" && event.key !== " ") return;
|
|
16377
16439
|
if (!canExpand) return;
|
|
@@ -16392,15 +16454,24 @@ ${error51.stderrTail}`] : []
|
|
|
16392
16454
|
if (expanded && canExpand) {
|
|
16393
16455
|
block.append(createInlineErrorDetail(document2, item, hostId, messages));
|
|
16394
16456
|
}
|
|
16457
|
+
block.addEventListener("click", (event) => {
|
|
16458
|
+
const target = event.target;
|
|
16459
|
+
if (target?.closest?.("a, button")) return;
|
|
16460
|
+
if (!canExpand) return;
|
|
16461
|
+
toggleExpand();
|
|
16462
|
+
});
|
|
16395
16463
|
return { block, row };
|
|
16396
16464
|
}
|
|
16397
|
-
function connectionItems(host) {
|
|
16465
|
+
function connectionItems(host, diagnostics) {
|
|
16398
16466
|
return host.agents.map((agent) => ({
|
|
16399
16467
|
key: agent.agent,
|
|
16400
16468
|
name: RENDERER_AGENT_LABELS[agent.agent],
|
|
16401
16469
|
availability: agent.availability,
|
|
16402
16470
|
error: agent.availability === "notInstalled" ? null : agent.error,
|
|
16403
|
-
agentSnapshot: agent
|
|
16471
|
+
agentSnapshot: agent,
|
|
16472
|
+
...host.hostId === "local" && agent.webUiAvailable && diagnostics?.openWebUi ? {
|
|
16473
|
+
openWebUi: () => diagnostics.openWebUi?.(host.hostId, agent.agent) ?? Promise.resolve()
|
|
16474
|
+
} : {}
|
|
16404
16475
|
}));
|
|
16405
16476
|
}
|
|
16406
16477
|
var pendingFocusAgent = null;
|
|
@@ -16554,7 +16625,7 @@ ${error51.stderrTail}`] : []
|
|
|
16554
16625
|
rows.id = panelId;
|
|
16555
16626
|
rows.dataset.connectionHost = selectedHost.hostId;
|
|
16556
16627
|
rows.setAttribute("role", "rowgroup");
|
|
16557
|
-
const items = connectionItems(selectedHost);
|
|
16628
|
+
const items = connectionItems(selectedHost, diagnostics);
|
|
16558
16629
|
if (expandedItemKey && !items.some((item) => item.key === expandedItemKey)) {
|
|
16559
16630
|
expandedItemKey = null;
|
|
16560
16631
|
}
|
|
@@ -16810,6 +16881,29 @@ ${error51.stderrTail}`] : []
|
|
|
16810
16881
|
inDevelopment: "In development",
|
|
16811
16882
|
notAvailable: "Not available",
|
|
16812
16883
|
runtimeCapabilityNotInstalled: "This runtime capability is not installed yet.",
|
|
16884
|
+
sessionImportHarness: "Harness",
|
|
16885
|
+
sessionImportDescription: "Sessions keep their original project path. If a folder is not in the Codex sidebar, add it as a project first. Original history remains managed by the Harness.",
|
|
16886
|
+
sessionImportAvailabilityNote: "Currently, only DeepSeek Harness Modern sessions can be imported. Support for other Harnesses is coming later.",
|
|
16887
|
+
sessionImportRefresh: "Refresh",
|
|
16888
|
+
sessionImportRefreshing: "Loading local sessions...",
|
|
16889
|
+
sessionImportUnavailable: "Session import requires a local, BOFT CLI-managed DeepSeek Harness 0.1.2-rc.1 Modern runtime.",
|
|
16890
|
+
sessionImportEmpty: "No local DeepSeek Harness sessions are available to import.",
|
|
16891
|
+
sessionImportLoadFailed: "Local sessions could not be loaded.",
|
|
16892
|
+
sessionImportFailed: "The session could not be imported.",
|
|
16893
|
+
sessionImportUntitled: "Untitled session",
|
|
16894
|
+
sessionImportUpdatedAt: "Updated",
|
|
16895
|
+
sessionImportSessionId: "Session ID",
|
|
16896
|
+
sessionImportRunning: "Running",
|
|
16897
|
+
sessionImportRunningHint: "Stop this session in DSH, then refresh.",
|
|
16898
|
+
sessionImportAction: "Import and open",
|
|
16899
|
+
sessionImportImporting: "Importing...",
|
|
16900
|
+
sessionImportImported: "Session imported",
|
|
16901
|
+
sessionImportOpenFailed: "The Codex sidebar has not shown it yet. Make sure the folder below is added as a project, then try opening it again.",
|
|
16902
|
+
sessionImportCopyProjectPath: "Copy project path",
|
|
16903
|
+
sessionImportPathCopied: "Copied",
|
|
16904
|
+
sessionImportPathCopyFailed: "Copy failed",
|
|
16905
|
+
sessionImportRetryOpen: "Try opening again",
|
|
16906
|
+
sessionImportRetrying: "Opening...",
|
|
16813
16907
|
connectionsDescription: "Add and configure Agent Harnesses supported by the system.",
|
|
16814
16908
|
pluginsDescription: "Extend and manage Codex plugins.",
|
|
16815
16909
|
pluginsRefresh: "Scan environment",
|
|
@@ -16846,6 +16940,7 @@ ${error51.stderrTail}`] : []
|
|
|
16846
16940
|
connectionHostsScrollLeft: "Show previous Hosts",
|
|
16847
16941
|
connectionHostsScrollRight: "Show more Hosts",
|
|
16848
16942
|
connectionOpenInstallation: "Open official installation page",
|
|
16943
|
+
connectionOpenHarnessWeb: "Open DeepSeek Harness Web",
|
|
16849
16944
|
connectionInstall: "Install",
|
|
16850
16945
|
connectionInstallDescription: "This Harness was not detected. Follow its official installation guide, then return here and run the check again.",
|
|
16851
16946
|
connectionErrorTitle: "Connection check failed",
|
|
@@ -16925,6 +17020,7 @@ ${error51.stderrTail}`] : []
|
|
|
16925
17020
|
pageLabels: Object.freeze({
|
|
16926
17021
|
connections: "Agents",
|
|
16927
17022
|
plugins: "Plugin",
|
|
17023
|
+
"session-import": "Session Import",
|
|
16928
17024
|
updates: "Updates",
|
|
16929
17025
|
about: "About"
|
|
16930
17026
|
})
|
|
@@ -16940,6 +17036,29 @@ ${error51.stderrTail}`] : []
|
|
|
16940
17036
|
inDevelopment: "\u5F00\u53D1\u4E2D",
|
|
16941
17037
|
notAvailable: "\u6682\u4E0D\u53EF\u7528",
|
|
16942
17038
|
runtimeCapabilityNotInstalled: "\u8FD0\u884C\u65F6\u5C1A\u672A\u5B89\u88C5\u8BE5\u9879\u80FD\u529B\uFF0C\u56E0\u6B64\u6682\u4E0D\u53EF\u7528\u3002",
|
|
17039
|
+
sessionImportHarness: "Harness",
|
|
17040
|
+
sessionImportDescription: "\u4F1A\u8BDD\u5C06\u4FDD\u7559\u539F\u59CB\u9879\u76EE\u8DEF\u5F84\uFF1B\u82E5\u8BE5\u6587\u4EF6\u5939\u5C1A\u672A\u51FA\u73B0\u5728 Codex \u4FA7\u680F\uFF0C\u8BF7\u5148\u5C06\u5176\u6DFB\u52A0\u4E3A\u9879\u76EE\u3002\u539F\u59CB\u5386\u53F2\u4ECD\u7531 Harness \u7BA1\u7406\u3002",
|
|
17041
|
+
sessionImportAvailabilityNote: "\u5F53\u524D\u4EC5\u652F\u6301\u5BFC\u5165 DeepSeek Harness Modern \u4F1A\u8BDD\uFF1B\u5176\u4ED6 Harness \u7684\u4F1A\u8BDD\u5BFC\u5165\u80FD\u529B\u656C\u8BF7\u671F\u5F85\u3002",
|
|
17042
|
+
sessionImportRefresh: "\u5237\u65B0",
|
|
17043
|
+
sessionImportRefreshing: "\u6B63\u5728\u8BFB\u53D6\u672C\u5730\u4F1A\u8BDD\u2026\u2026",
|
|
17044
|
+
sessionImportUnavailable: "\u4F1A\u8BDD\u5BFC\u5165\u4EC5\u652F\u6301\u672C\u5730\u3001\u7531 BOFT CLI \u7BA1\u7406\u7684 DeepSeek Harness 0.1.2-rc.1 Modern \u8FD0\u884C\u65F6\u3002",
|
|
17045
|
+
sessionImportEmpty: "\u6CA1\u6709\u53EF\u5BFC\u5165\u7684\u672C\u5730 DeepSeek Harness \u4F1A\u8BDD\u3002",
|
|
17046
|
+
sessionImportLoadFailed: "\u65E0\u6CD5\u8BFB\u53D6\u672C\u5730\u4F1A\u8BDD\u3002",
|
|
17047
|
+
sessionImportFailed: "\u65E0\u6CD5\u5BFC\u5165\u8BE5\u4F1A\u8BDD\u3002",
|
|
17048
|
+
sessionImportUntitled: "\u672A\u547D\u540D\u4F1A\u8BDD",
|
|
17049
|
+
sessionImportUpdatedAt: "\u66F4\u65B0\u65F6\u95F4",
|
|
17050
|
+
sessionImportSessionId: "\u4F1A\u8BDD ID",
|
|
17051
|
+
sessionImportRunning: "\u8FD0\u884C\u4E2D",
|
|
17052
|
+
sessionImportRunningHint: "\u8BF7\u5148\u5728 DSH \u4E2D\u505C\u6B62\u8BE5\u4F1A\u8BDD\uFF0C\u7136\u540E\u5237\u65B0\u3002",
|
|
17053
|
+
sessionImportAction: "\u5BFC\u5165\u5E76\u6253\u5F00",
|
|
17054
|
+
sessionImportImporting: "\u6B63\u5728\u5BFC\u5165\u2026\u2026",
|
|
17055
|
+
sessionImportImported: "\u4F1A\u8BDD\u5DF2\u5BFC\u5165",
|
|
17056
|
+
sessionImportOpenFailed: "Codex \u4FA7\u680F\u5C1A\u672A\u663E\u793A\u8BE5\u4F1A\u8BDD\u3002\u8BF7\u786E\u8BA4\u4EE5\u4E0B\u6587\u4EF6\u5939\u5DF2\u6DFB\u52A0\u4E3A\u9879\u76EE\uFF0C\u7136\u540E\u91CD\u8BD5\u6253\u5F00\u3002",
|
|
17057
|
+
sessionImportCopyProjectPath: "\u590D\u5236\u9879\u76EE\u8DEF\u5F84",
|
|
17058
|
+
sessionImportPathCopied: "\u5DF2\u590D\u5236",
|
|
17059
|
+
sessionImportPathCopyFailed: "\u590D\u5236\u5931\u8D25",
|
|
17060
|
+
sessionImportRetryOpen: "\u91CD\u8BD5\u6253\u5F00",
|
|
17061
|
+
sessionImportRetrying: "\u6B63\u5728\u6253\u5F00\u2026\u2026",
|
|
16943
17062
|
connectionsDescription: "\u6DFB\u52A0\u548C\u914D\u7F6E\u7CFB\u7EDF\u4E2D\u652F\u6301\u7684 Agent Harness\u3002",
|
|
16944
17063
|
pluginsDescription: "\u6269\u5C55\u548C\u7BA1\u7406 Codex \u7684\u63D2\u4EF6\u3002",
|
|
16945
17064
|
pluginsRefresh: "\u626B\u63CF\u73AF\u5883",
|
|
@@ -16976,6 +17095,7 @@ ${error51.stderrTail}`] : []
|
|
|
16976
17095
|
connectionHostsScrollLeft: "\u67E5\u770B\u524D\u9762\u7684 Host",
|
|
16977
17096
|
connectionHostsScrollRight: "\u67E5\u770B\u66F4\u591A Host",
|
|
16978
17097
|
connectionOpenInstallation: "\u524D\u5F80\u5B98\u65B9\u5B89\u88C5\u9875\u9762",
|
|
17098
|
+
connectionOpenHarnessWeb: "\u6253\u5F00 DeepSeek Harness Web",
|
|
16979
17099
|
connectionInstall: "\u5B89\u88C5",
|
|
16980
17100
|
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",
|
|
16981
17101
|
connectionErrorTitle: "\u8FDE\u63A5\u68C0\u67E5\u5931\u8D25",
|
|
@@ -17055,6 +17175,7 @@ ${error51.stderrTail}`] : []
|
|
|
17055
17175
|
pageLabels: Object.freeze({
|
|
17056
17176
|
connections: "Agents",
|
|
17057
17177
|
plugins: "Plugin",
|
|
17178
|
+
"session-import": "\u4F1A\u8BDD\u5BFC\u5165",
|
|
17058
17179
|
updates: "\u66F4\u65B0",
|
|
17059
17180
|
about: "\u5173\u4E8E"
|
|
17060
17181
|
})
|
|
@@ -18766,7 +18887,6 @@ ${error51.stderrTail}`] : []
|
|
|
18766
18887
|
sessionCostEstimate: "Session cost estimate",
|
|
18767
18888
|
threadUsage: "Thread Usage",
|
|
18768
18889
|
threadUsageDetails: "Thread Usage details",
|
|
18769
|
-
contextSummary: "context",
|
|
18770
18890
|
tokensSummary: "tokens",
|
|
18771
18891
|
tokensPerSecond: "tok/s",
|
|
18772
18892
|
fiveHourSummary: "5h",
|
|
@@ -18787,7 +18907,6 @@ ${error51.stderrTail}`] : []
|
|
|
18787
18907
|
sessionCostEstimate: "\u4F1A\u8BDD\u8D39\u7528\u4F30\u7B97",
|
|
18788
18908
|
threadUsage: "\u5BF9\u8BDD\u7528\u91CF",
|
|
18789
18909
|
threadUsageDetails: "\u5BF9\u8BDD\u7528\u91CF\u8BE6\u60C5",
|
|
18790
|
-
contextSummary: "\u4E0A\u4E0B\u6587",
|
|
18791
18910
|
tokensSummary: "Token",
|
|
18792
18911
|
tokensPerSecond: "Token/\u79D2",
|
|
18793
18912
|
fiveHourSummary: "5 \u5C0F\u65F6",
|
|
@@ -18816,6 +18935,9 @@ ${error51.stderrTail}`] : []
|
|
|
18816
18935
|
if (absolute < 1e9) return `${sign}${decimal(absolute / 1e6, 1)}M`;
|
|
18817
18936
|
return `${sign}${decimal(absolute / 1e9, 1)}B`;
|
|
18818
18937
|
}
|
|
18938
|
+
function formatRendererContextSummary(usedTokens, windowTokens) {
|
|
18939
|
+
return `${decimal(usedTokens / windowTokens * 100, 1)}% / ${formatRendererTokenCount(windowTokens)}`;
|
|
18940
|
+
}
|
|
18819
18941
|
function formatRendererCreditsPercent(value) {
|
|
18820
18942
|
return `${decimal(value, 1)}%`;
|
|
18821
18943
|
}
|
|
@@ -19155,7 +19277,7 @@ ${error51.stderrTail}`] : []
|
|
|
19155
19277
|
].filter((value) => value !== null);
|
|
19156
19278
|
if (summary.length === 0 && hasContext && usage?.contextWindowTokens !== void 0 && usage.contextWindowTokens > 0) {
|
|
19157
19279
|
summary.push(
|
|
19158
|
-
|
|
19280
|
+
formatRendererContextSummary(usage.contextUsedTokens ?? 0, usage.contextWindowTokens)
|
|
19159
19281
|
);
|
|
19160
19282
|
}
|
|
19161
19283
|
if (summary.length === 0 && usage?.totalTokens !== void 0) {
|
|
@@ -19617,11 +19739,7 @@ ${error51.stderrTail}`] : []
|
|
|
19617
19739
|
menu.style.maxHeight = "min(360px, calc(100vh - 16px))";
|
|
19618
19740
|
menu.style.overflowY = "auto";
|
|
19619
19741
|
menu.style.padding = "4px";
|
|
19620
|
-
menu
|
|
19621
|
-
menu.style.borderRadius = "10px";
|
|
19622
|
-
menu.style.background = "Canvas";
|
|
19623
|
-
menu.style.color = "CanvasText";
|
|
19624
|
-
menu.style.boxShadow = "0 12px 32px rgba(0, 0, 0, 0.22)";
|
|
19742
|
+
applyRendererPopoverChrome(menu);
|
|
19625
19743
|
ownerDocument.body.append(menu);
|
|
19626
19744
|
if (insertBefore?.parentElement === parent) parent.insertBefore(root, insertBefore);
|
|
19627
19745
|
else parent.append(root);
|
|
@@ -20059,11 +20177,8 @@ ${error51.stderrTail}`] : []
|
|
|
20059
20177
|
if (control.usage) control.usage.anchor = null;
|
|
20060
20178
|
return;
|
|
20061
20179
|
}
|
|
20062
|
-
const previousUsageParent = control.usage.root.parentElement;
|
|
20063
|
-
const previousUsageNextSibling = control.usage.root.nextElementSibling;
|
|
20064
20180
|
control.usage.place(anchor);
|
|
20065
|
-
|
|
20066
|
-
if (usagePositionChanged) control.harnessCommands?.placeBefore(control.usage.root);
|
|
20181
|
+
control.harnessCommands?.placeBefore(control.usage.root);
|
|
20067
20182
|
}
|
|
20068
20183
|
function refreshCreditsPlacement(control) {
|
|
20069
20184
|
const anchor = creditsPlacementAnchor(control);
|
|
@@ -20232,7 +20347,9 @@ ${error51.stderrTail}`] : []
|
|
|
20232
20347
|
var SIDEBAR_THREAD_ID_ATTRIBUTE = "data-app-action-sidebar-thread-id";
|
|
20233
20348
|
var SIDEBAR_THREAD_HOST_ID_ATTRIBUTE = "data-app-action-sidebar-thread-host-id";
|
|
20234
20349
|
var SIDEBAR_AGENT_ICON_ATTRIBUTE = "data-codexhost-sidebar-agent-icon";
|
|
20350
|
+
var SIDEBAR_EXTERNAL_THREAD_ATTRIBUTE = "data-codexhost-sidebar-external-thread";
|
|
20235
20351
|
var OWNERSHIP_RETRY_DELAYS_MS = [100, 300, 800, 1500, 3e3];
|
|
20352
|
+
var PIN_REPLAY_RETRY_DELAYS_MS = [50, 150, 300];
|
|
20236
20353
|
function isRecord2(value) {
|
|
20237
20354
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20238
20355
|
}
|
|
@@ -20315,9 +20432,11 @@ ${error51.stderrTail}`] : []
|
|
|
20315
20432
|
...this.element.querySelectorAll(`[${SIDEBAR_AGENT_ICON_ATTRIBUTE}]`)
|
|
20316
20433
|
];
|
|
20317
20434
|
if (icons.length === 1 && icons[0]?.parentElement === titleTrigger && icons[0].getAttribute(SIDEBAR_AGENT_ICON_ATTRIBUTE) === agent) {
|
|
20435
|
+
this.element.setAttribute(SIDEBAR_EXTERNAL_THREAD_ATTRIBUTE, "true");
|
|
20318
20436
|
return;
|
|
20319
20437
|
}
|
|
20320
20438
|
this.clear();
|
|
20439
|
+
this.element.setAttribute(SIDEBAR_EXTERNAL_THREAD_ATTRIBUTE, "true");
|
|
20321
20440
|
const label = `${RENDERER_AGENT_LABELS[agent]} Agent`;
|
|
20322
20441
|
const marker = this.element.ownerDocument.createElement("span");
|
|
20323
20442
|
marker.setAttribute(SIDEBAR_AGENT_ICON_ATTRIBUTE, agent);
|
|
@@ -20335,11 +20454,84 @@ ${error51.stderrTail}`] : []
|
|
|
20335
20454
|
titleTrigger.insertBefore(marker, title);
|
|
20336
20455
|
}
|
|
20337
20456
|
clear() {
|
|
20457
|
+
this.element.removeAttribute(SIDEBAR_EXTERNAL_THREAD_ATTRIBUTE);
|
|
20338
20458
|
for (const icon2 of this.element.querySelectorAll(`[${SIDEBAR_AGENT_ICON_ATTRIBUTE}]`)) {
|
|
20339
20459
|
icon2.remove();
|
|
20340
20460
|
}
|
|
20341
20461
|
}
|
|
20342
20462
|
};
|
|
20463
|
+
function sidebarExternalPinActionFromTarget(target) {
|
|
20464
|
+
if (!(target instanceof Element)) return null;
|
|
20465
|
+
const button = target.closest("button");
|
|
20466
|
+
const row = target.closest(SIDEBAR_THREAD_ROW_SELECTOR);
|
|
20467
|
+
if (!button || !row || row.getAttribute(SIDEBAR_EXTERNAL_THREAD_ATTRIBUTE) !== "true") {
|
|
20468
|
+
return null;
|
|
20469
|
+
}
|
|
20470
|
+
if (row.querySelector("button") !== button) return null;
|
|
20471
|
+
const attributes = sidebarThreadAttributes(row);
|
|
20472
|
+
const threadId = hostThreadIdSchema.safeParse(threadIdFromSidebarRowElement(row));
|
|
20473
|
+
if (!attributes || !threadId.success) return null;
|
|
20474
|
+
return {
|
|
20475
|
+
hostId: attributes.hostId,
|
|
20476
|
+
threadId: threadId.data,
|
|
20477
|
+
isPinned: row.getAttribute("data-app-action-sidebar-thread-pinned") !== "true"
|
|
20478
|
+
};
|
|
20479
|
+
}
|
|
20480
|
+
function installRendererSidebarExternalPinning(options) {
|
|
20481
|
+
const root = options.root ?? document;
|
|
20482
|
+
const replayingButtons = /* @__PURE__ */ new WeakSet();
|
|
20483
|
+
const replayTimers = /* @__PURE__ */ new Set();
|
|
20484
|
+
const currentPinRow = (action) => {
|
|
20485
|
+
for (const row of root.querySelectorAll(SIDEBAR_THREAD_ROW_SELECTOR)) {
|
|
20486
|
+
const attributes = sidebarThreadAttributes(row);
|
|
20487
|
+
if (attributes?.hostId === action.hostId && row.getAttribute(SIDEBAR_EXTERNAL_THREAD_ATTRIBUTE) === "true" && threadIdFromSidebarRowElement(row) === action.threadId) {
|
|
20488
|
+
return row;
|
|
20489
|
+
}
|
|
20490
|
+
}
|
|
20491
|
+
return null;
|
|
20492
|
+
};
|
|
20493
|
+
const replayNativePinAction = (action, originalButton, retryIndex = 0) => {
|
|
20494
|
+
const row = currentPinRow(action);
|
|
20495
|
+
if (row?.getAttribute("data-app-action-sidebar-thread-pinned") === String(action.isPinned)) {
|
|
20496
|
+
return;
|
|
20497
|
+
}
|
|
20498
|
+
const currentButton = row?.querySelector("button") ?? (originalButton.isConnected === false ? null : originalButton);
|
|
20499
|
+
if (currentButton) {
|
|
20500
|
+
replayingButtons.add(currentButton);
|
|
20501
|
+
currentButton.click();
|
|
20502
|
+
return;
|
|
20503
|
+
}
|
|
20504
|
+
const delay = PIN_REPLAY_RETRY_DELAYS_MS[retryIndex];
|
|
20505
|
+
if (delay === void 0) return;
|
|
20506
|
+
const timer = setTimeout(() => {
|
|
20507
|
+
replayTimers.delete(timer);
|
|
20508
|
+
replayNativePinAction(action, originalButton, retryIndex + 1);
|
|
20509
|
+
}, delay);
|
|
20510
|
+
replayTimers.add(timer);
|
|
20511
|
+
};
|
|
20512
|
+
const onClick = (event) => {
|
|
20513
|
+
const action = sidebarExternalPinActionFromTarget(event.target);
|
|
20514
|
+
if (!action) return;
|
|
20515
|
+
const button = event.target instanceof Element ? event.target.closest("button") : null;
|
|
20516
|
+
if (!button) return;
|
|
20517
|
+
if (replayingButtons.delete(button)) return;
|
|
20518
|
+
const update = options.getClient(action.hostId)?.updateThreadPinned;
|
|
20519
|
+
if (!update) return;
|
|
20520
|
+
event.preventDefault();
|
|
20521
|
+
event.stopImmediatePropagation();
|
|
20522
|
+
void update({ threadId: action.threadId, isPinned: action.isPinned }).then(() => {
|
|
20523
|
+
replayNativePinAction(action, button);
|
|
20524
|
+
}).catch((error51) => {
|
|
20525
|
+
options.reportError?.(error51);
|
|
20526
|
+
});
|
|
20527
|
+
};
|
|
20528
|
+
root.addEventListener("click", onClick, true);
|
|
20529
|
+
return () => {
|
|
20530
|
+
root.removeEventListener("click", onClick, true);
|
|
20531
|
+
for (const timer of replayTimers) clearTimeout(timer);
|
|
20532
|
+
replayTimers.clear();
|
|
20533
|
+
};
|
|
20534
|
+
}
|
|
20343
20535
|
var BrowserSidebarAgentIconDom = class {
|
|
20344
20536
|
constructor(root) {
|
|
20345
20537
|
this.root = root;
|
|
@@ -20549,6 +20741,64 @@ ${error51.stderrTail}`] : []
|
|
|
20549
20741
|
var RESPONSE_CONVERSATION_ATTRIBUTE = "data-response-annotation-conversation";
|
|
20550
20742
|
var TURN_KEY_ATTRIBUTE = "data-content-search-turn-key";
|
|
20551
20743
|
var OPEN_THREAD_TIMEOUT_MS = 5e3;
|
|
20744
|
+
function abortError() {
|
|
20745
|
+
return Object.assign(new Error("Thread opening was aborted"), { name: "AbortError" });
|
|
20746
|
+
}
|
|
20747
|
+
function openRendererThread(threadId, options = {}) {
|
|
20748
|
+
const find = () => {
|
|
20749
|
+
for (const row of document.querySelectorAll(SIDEBAR_THREAD_ROW_SELECTOR)) {
|
|
20750
|
+
if ((options.hostId === void 0 || row.getAttribute(SIDEBAR_THREAD_HOST_ID_ATTRIBUTE) === options.hostId) && threadIdFromSidebarRowElement(row) === threadId) {
|
|
20751
|
+
return row;
|
|
20752
|
+
}
|
|
20753
|
+
}
|
|
20754
|
+
return null;
|
|
20755
|
+
};
|
|
20756
|
+
if (options.signal?.aborted) return Promise.reject(abortError());
|
|
20757
|
+
const current = find();
|
|
20758
|
+
if (current) {
|
|
20759
|
+
current.click();
|
|
20760
|
+
return Promise.resolve();
|
|
20761
|
+
}
|
|
20762
|
+
return new Promise((resolve, reject) => {
|
|
20763
|
+
let settled = false;
|
|
20764
|
+
const cleanup = () => {
|
|
20765
|
+
window.clearTimeout(timeout);
|
|
20766
|
+
observer.disconnect();
|
|
20767
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
20768
|
+
};
|
|
20769
|
+
const finish = (row2) => {
|
|
20770
|
+
if (settled) return;
|
|
20771
|
+
settled = true;
|
|
20772
|
+
cleanup();
|
|
20773
|
+
row2.click();
|
|
20774
|
+
resolve();
|
|
20775
|
+
};
|
|
20776
|
+
const observer = new MutationObserver(() => {
|
|
20777
|
+
const row2 = find();
|
|
20778
|
+
if (row2) finish(row2);
|
|
20779
|
+
});
|
|
20780
|
+
const timeout = window.setTimeout(() => {
|
|
20781
|
+
if (settled) return;
|
|
20782
|
+
settled = true;
|
|
20783
|
+
cleanup();
|
|
20784
|
+
reject(new Error("Thread did not appear in the sidebar"));
|
|
20785
|
+
}, options.timeoutMs ?? OPEN_THREAD_TIMEOUT_MS);
|
|
20786
|
+
const onAbort = () => {
|
|
20787
|
+
if (settled) return;
|
|
20788
|
+
settled = true;
|
|
20789
|
+
cleanup();
|
|
20790
|
+
reject(abortError());
|
|
20791
|
+
};
|
|
20792
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
20793
|
+
observer.observe(document.documentElement, { childList: true, subtree: true });
|
|
20794
|
+
if (options.signal?.aborted) {
|
|
20795
|
+
onAbort();
|
|
20796
|
+
return;
|
|
20797
|
+
}
|
|
20798
|
+
const row = find();
|
|
20799
|
+
if (row) finish(row);
|
|
20800
|
+
});
|
|
20801
|
+
}
|
|
20552
20802
|
function isRecord3(value) {
|
|
20553
20803
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20554
20804
|
}
|
|
@@ -20622,35 +20872,7 @@ ${error51.stderrTail}`] : []
|
|
|
20622
20872
|
target.control.click();
|
|
20623
20873
|
}
|
|
20624
20874
|
openThread(threadId) {
|
|
20625
|
-
|
|
20626
|
-
for (const row of document.querySelectorAll(SIDEBAR_THREAD_ROW_SELECTOR)) {
|
|
20627
|
-
if (threadIdFromSidebarRowElement(row) === threadId) return row;
|
|
20628
|
-
}
|
|
20629
|
-
return null;
|
|
20630
|
-
};
|
|
20631
|
-
const current = find();
|
|
20632
|
-
if (current) {
|
|
20633
|
-
current.click();
|
|
20634
|
-
return Promise.resolve();
|
|
20635
|
-
}
|
|
20636
|
-
return new Promise((resolve, reject) => {
|
|
20637
|
-
const observer = new MutationObserver(() => {
|
|
20638
|
-
const row = find();
|
|
20639
|
-
if (!row) return;
|
|
20640
|
-
cleanup();
|
|
20641
|
-
row.click();
|
|
20642
|
-
resolve();
|
|
20643
|
-
});
|
|
20644
|
-
const timeout = window.setTimeout(() => {
|
|
20645
|
-
cleanup();
|
|
20646
|
-
reject(new Error("Forked Thread did not appear in the sidebar"));
|
|
20647
|
-
}, OPEN_THREAD_TIMEOUT_MS);
|
|
20648
|
-
const cleanup = () => {
|
|
20649
|
-
window.clearTimeout(timeout);
|
|
20650
|
-
observer.disconnect();
|
|
20651
|
-
};
|
|
20652
|
-
observer.observe(document.documentElement, { childList: true, subtree: true });
|
|
20653
|
-
});
|
|
20875
|
+
return openRendererThread(threadId);
|
|
20654
20876
|
}
|
|
20655
20877
|
};
|
|
20656
20878
|
function installRendererForkControl(options) {
|
|
@@ -20690,6 +20912,9 @@ ${error51.stderrTail}`] : []
|
|
|
20690
20912
|
|
|
20691
20913
|
// src/renderer-model-client.ts
|
|
20692
20914
|
var HARNESS_INSPECT_METHOD = "codexhost/harness/inspect";
|
|
20915
|
+
var DEEPSEEK_MODERN_SESSION_LIST_METHOD = "codexhost/deepseek/modern-session/list";
|
|
20916
|
+
var DEEPSEEK_MODERN_SESSION_IMPORT_METHOD = "codexhost/deepseek/modern-session/import";
|
|
20917
|
+
var HARNESS_WEB_UI_OPEN_METHOD = "codexhost/harness/web-ui/open";
|
|
20693
20918
|
var THREAD_FORK_METHOD = "codexhost/thread/fork";
|
|
20694
20919
|
var THREAD_INSPECT_METHOD = "codexhost/thread/inspect";
|
|
20695
20920
|
var THREAD_COMMANDS_INSPECT_METHOD = "codexhost/thread/commands/inspect";
|
|
@@ -20698,15 +20923,26 @@ ${error51.stderrTail}`] : []
|
|
|
20698
20923
|
var THREAD_THINKING_SELECT_METHOD = "codexhost/thread/thinking/select";
|
|
20699
20924
|
var THREAD_PERMISSION_MODE_SELECT_METHOD = "codexhost/thread/permission-mode/select";
|
|
20700
20925
|
var THREAD_OWNERSHIP_LIST_METHOD = "codexhost/thread/ownership/list";
|
|
20926
|
+
var THREAD_METADATA_UPDATE_METHOD = "thread/metadata/update";
|
|
20701
20927
|
var THREAD_USAGE_INSPECT_METHOD = "codexhost/thread/usage/inspect";
|
|
20702
20928
|
var THREAD_USAGE_UPDATED_METHOD = "codexhost/thread/usage/updated";
|
|
20703
20929
|
var THREAD_TOKEN_USAGE_UPDATED_METHOD = "thread/tokenUsage/updated";
|
|
20704
20930
|
var UPDATE_CHECK_METHOD = "codexhost/update/check";
|
|
20705
20931
|
var UPDATE_START_METHOD = "codexhost/update/start";
|
|
20706
20932
|
var UPDATE_STATUS_METHOD = "codexhost/update/status";
|
|
20933
|
+
var RendererDeepSeekSessionUnavailableError = class extends Error {
|
|
20934
|
+
constructor() {
|
|
20935
|
+
super("DeepSeek Modern Session import is unavailable");
|
|
20936
|
+
this.name = "RendererDeepSeekSessionUnavailableError";
|
|
20937
|
+
}
|
|
20938
|
+
};
|
|
20707
20939
|
function isRecord4(value) {
|
|
20708
20940
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20709
20941
|
}
|
|
20942
|
+
function normalizeDeepSeekSessionError(error51) {
|
|
20943
|
+
const code = isRecord4(error51) ? error51.code : void 0;
|
|
20944
|
+
return code === -32076 || code === -32077 ? new RendererDeepSeekSessionUnavailableError() : error51;
|
|
20945
|
+
}
|
|
20710
20946
|
function notifiedThreadId(notification) {
|
|
20711
20947
|
if (!isRecord4(notification) || notification.method !== THREAD_TOKEN_USAGE_UPDATED_METHOD && notification.method !== THREAD_USAGE_UPDATED_METHOD) {
|
|
20712
20948
|
return null;
|
|
@@ -20757,6 +20993,7 @@ ${error51.stderrTail}`] : []
|
|
|
20757
20993
|
);
|
|
20758
20994
|
const manager = managers[0];
|
|
20759
20995
|
if (managers.length !== 1 || !manager) return null;
|
|
20996
|
+
const pendingDeepSeekImports = /* @__PURE__ */ new Map();
|
|
20760
20997
|
const inspectHarness = async (input) => {
|
|
20761
20998
|
const params = harnessInspectParamsSchema.parse(input);
|
|
20762
20999
|
const result = await manager.sendRequest(HARNESS_INSPECT_METHOD, params);
|
|
@@ -20792,13 +21029,47 @@ ${error51.stderrTail}`] : []
|
|
|
20792
21029
|
const result = await manager.sendRequest(THREAD_PERMISSION_MODE_SELECT_METHOD, params);
|
|
20793
21030
|
return harnessConfigurationStateSchema.parse(result);
|
|
20794
21031
|
};
|
|
21032
|
+
const importDeepSeekModernSession = async (input) => {
|
|
21033
|
+
const params = deepSeekModernSessionImportParamsSchema.parse(input);
|
|
21034
|
+
const pending = pendingDeepSeekImports.get(params.nativeSessionId);
|
|
21035
|
+
if (pending) return pending;
|
|
21036
|
+
const request = (async () => {
|
|
21037
|
+
try {
|
|
21038
|
+
const result = await manager.sendRequest(DEEPSEEK_MODERN_SESSION_IMPORT_METHOD, params);
|
|
21039
|
+
return deepSeekModernSessionImportResultSchema.parse(result);
|
|
21040
|
+
} catch (error51) {
|
|
21041
|
+
throw normalizeDeepSeekSessionError(error51);
|
|
21042
|
+
}
|
|
21043
|
+
})().finally(() => {
|
|
21044
|
+
if (pendingDeepSeekImports.get(params.nativeSessionId) === request) {
|
|
21045
|
+
pendingDeepSeekImports.delete(params.nativeSessionId);
|
|
21046
|
+
}
|
|
21047
|
+
});
|
|
21048
|
+
pendingDeepSeekImports.set(params.nativeSessionId, request);
|
|
21049
|
+
return request;
|
|
21050
|
+
};
|
|
20795
21051
|
return Object.freeze({
|
|
21052
|
+
async listDeepSeekModernSessions(input) {
|
|
21053
|
+
const params = deepSeekModernSessionListParamsSchema.parse(input);
|
|
21054
|
+
try {
|
|
21055
|
+
const result = await manager.sendRequest(DEEPSEEK_MODERN_SESSION_LIST_METHOD, params);
|
|
21056
|
+
return deepSeekModernSessionListResultSchema.parse(result);
|
|
21057
|
+
} catch (error51) {
|
|
21058
|
+
throw normalizeDeepSeekSessionError(error51);
|
|
21059
|
+
}
|
|
21060
|
+
},
|
|
21061
|
+
importDeepSeekModernSession,
|
|
20796
21062
|
async forkThread(input) {
|
|
20797
21063
|
const params = externalThreadForkParamsSchema.parse(input);
|
|
20798
21064
|
const result = await manager.sendRequest(THREAD_FORK_METHOD, params);
|
|
20799
21065
|
return externalThreadForkResultSchema.parse(result);
|
|
20800
21066
|
},
|
|
20801
21067
|
inspectHarness,
|
|
21068
|
+
async openHarnessWebUi(input) {
|
|
21069
|
+
const params = harnessWebUiOpenParamsSchema.parse(input);
|
|
21070
|
+
const result = await manager.sendRequest(HARNESS_WEB_UI_OPEN_METHOD, params);
|
|
21071
|
+
harnessWebUiOpenResultSchema.parse(result);
|
|
21072
|
+
},
|
|
20802
21073
|
async inspectThread(input) {
|
|
20803
21074
|
const params = threadInspectionParamsSchema.parse(input);
|
|
20804
21075
|
const result = await manager.sendRequest(THREAD_INSPECT_METHOD, params);
|
|
@@ -20815,6 +21086,13 @@ ${error51.stderrTail}`] : []
|
|
|
20815
21086
|
}
|
|
20816
21087
|
return result;
|
|
20817
21088
|
},
|
|
21089
|
+
async updateThreadPinned(input) {
|
|
21090
|
+
const threadId = hostThreadIdSchema.parse(input.threadId);
|
|
21091
|
+
await manager.sendRequest(THREAD_METADATA_UPDATE_METHOD, {
|
|
21092
|
+
threadId,
|
|
21093
|
+
isPinned: input.isPinned
|
|
21094
|
+
});
|
|
21095
|
+
},
|
|
20818
21096
|
inspectThreadUsage,
|
|
20819
21097
|
subscribeThreadUsage(listener) {
|
|
20820
21098
|
const notifications = notificationTarget(manager);
|
|
@@ -21701,6 +21979,55 @@ ${error51.stderrTail}`] : []
|
|
|
21701
21979
|
);
|
|
21702
21980
|
}
|
|
21703
21981
|
|
|
21982
|
+
// src/renderer-harness-command-claim.ts
|
|
21983
|
+
function inputEvent(editor, text) {
|
|
21984
|
+
const view = editor.ownerDocument.defaultView;
|
|
21985
|
+
return view?.InputEvent ? new view.InputEvent("input", {
|
|
21986
|
+
bubbles: true,
|
|
21987
|
+
composed: true,
|
|
21988
|
+
data: text,
|
|
21989
|
+
inputType: "insertText"
|
|
21990
|
+
}) : new (view?.Event ?? Event)("input", { bubbles: true, composed: true });
|
|
21991
|
+
}
|
|
21992
|
+
function prependTextarea(editor, prefix) {
|
|
21993
|
+
const view = editor.ownerDocument.defaultView;
|
|
21994
|
+
if (!view || !(editor instanceof view.HTMLTextAreaElement)) return false;
|
|
21995
|
+
const setter = Object.getOwnPropertyDescriptor(view.HTMLTextAreaElement.prototype, "value")?.set;
|
|
21996
|
+
if (!setter) return false;
|
|
21997
|
+
const start = editor.selectionStart;
|
|
21998
|
+
const end = editor.selectionEnd;
|
|
21999
|
+
setter.call(editor, prefix + editor.value);
|
|
22000
|
+
editor.dispatchEvent(inputEvent(editor, prefix));
|
|
22001
|
+
editor.focus({ preventScroll: true });
|
|
22002
|
+
if (start !== null && end !== null) {
|
|
22003
|
+
editor.setSelectionRange(start + prefix.length, end + prefix.length);
|
|
22004
|
+
}
|
|
22005
|
+
return true;
|
|
22006
|
+
}
|
|
22007
|
+
function prependContentEditable(editor, prefix) {
|
|
22008
|
+
if (editor.getAttribute("contenteditable") !== "true") return false;
|
|
22009
|
+
const document2 = editor.ownerDocument;
|
|
22010
|
+
const selection = document2.getSelection();
|
|
22011
|
+
if (!selection || typeof document2.execCommand !== "function") return false;
|
|
22012
|
+
const range = document2.createRange();
|
|
22013
|
+
range.selectNodeContents(editor);
|
|
22014
|
+
range.collapse(true);
|
|
22015
|
+
editor.focus({ preventScroll: true });
|
|
22016
|
+
selection.removeAllRanges();
|
|
22017
|
+
selection.addRange(range);
|
|
22018
|
+
return document2.execCommand("insertText", false, prefix);
|
|
22019
|
+
}
|
|
22020
|
+
function prependEditor(editor, prefix) {
|
|
22021
|
+
return prependTextarea(editor, prefix) || prependContentEditable(editor, prefix);
|
|
22022
|
+
}
|
|
22023
|
+
function routeRendererHarnessCommandSelection(editor, command, execute) {
|
|
22024
|
+
if (command.argumentMode === "none") {
|
|
22025
|
+
execute();
|
|
22026
|
+
return true;
|
|
22027
|
+
}
|
|
22028
|
+
return editor !== null && prependEditor(editor, `${command.invocation} `);
|
|
22029
|
+
}
|
|
22030
|
+
|
|
21704
22031
|
// src/codex-locale-adapter.ts
|
|
21705
22032
|
var GET_LOCALE_OVERRIDE_URL = "vscode://codex/get-setting";
|
|
21706
22033
|
var GET_LOCALE_INFO_URL = "vscode://codex/locale-info";
|
|
@@ -21723,7 +22050,7 @@ ${error51.stderrTail}`] : []
|
|
|
21723
22050
|
}
|
|
21724
22051
|
return canonicalLocale(ownerWindow.navigator.language);
|
|
21725
22052
|
}
|
|
21726
|
-
function
|
|
22053
|
+
function abortError2() {
|
|
21727
22054
|
return new DOMException("The operation was aborted", "AbortError");
|
|
21728
22055
|
}
|
|
21729
22056
|
function parseLocaleOverride(value) {
|
|
@@ -21753,7 +22080,7 @@ ${error51.stderrTail}`] : []
|
|
|
21753
22080
|
if (typeof bridge?.sendMessageFromView !== "function") {
|
|
21754
22081
|
return Promise.reject(new Error("Codex locale bridge is unavailable"));
|
|
21755
22082
|
}
|
|
21756
|
-
if (signal?.aborted) return Promise.reject(
|
|
22083
|
+
if (signal?.aborted) return Promise.reject(abortError2());
|
|
21757
22084
|
const requestId = ownerWindow.crypto.randomUUID();
|
|
21758
22085
|
return new Promise((resolve, reject) => {
|
|
21759
22086
|
let settled = false;
|
|
@@ -21768,7 +22095,7 @@ ${error51.stderrTail}`] : []
|
|
|
21768
22095
|
cleanup();
|
|
21769
22096
|
operation();
|
|
21770
22097
|
};
|
|
21771
|
-
const onAbort = () => settle(() => reject(
|
|
22098
|
+
const onAbort = () => settle(() => reject(abortError2()));
|
|
21772
22099
|
const onMessage = (event) => {
|
|
21773
22100
|
const message2 = event.data;
|
|
21774
22101
|
if (!isRecord7(message2) || message2.type !== "fetch-response") return;
|
|
@@ -21835,12 +22162,12 @@ ${error51.stderrTail}`] : []
|
|
|
21835
22162
|
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
21836
22163
|
throw new Error("Codex locale request timeout must be positive");
|
|
21837
22164
|
}
|
|
21838
|
-
if (options.signal?.aborted) throw
|
|
22165
|
+
if (options.signal?.aborted) throw abortError2();
|
|
21839
22166
|
const [overrideResult, localeInfoResult] = await Promise.allSettled([
|
|
21840
22167
|
readLocaleOverride(ownerWindow, options.signal, timeoutMs),
|
|
21841
22168
|
readLocaleInfo(ownerWindow, options.signal, timeoutMs)
|
|
21842
22169
|
]);
|
|
21843
|
-
if (options.signal?.aborted) throw
|
|
22170
|
+
if (options.signal?.aborted) throw abortError2();
|
|
21844
22171
|
const navigatorLocale = firstNavigatorLocale(ownerWindow);
|
|
21845
22172
|
const overrideKnown = overrideResult.status === "fulfilled";
|
|
21846
22173
|
const localeOverride = overrideKnown ? overrideResult.value.value : void 0;
|
|
@@ -21983,6 +22310,346 @@ ${error51.stderrTail}`] : []
|
|
|
21983
22310
|
}
|
|
21984
22311
|
};
|
|
21985
22312
|
|
|
22313
|
+
// src/settings/deepseek-session-import-page.ts
|
|
22314
|
+
var SESSION_IMPORT_HARNESSES = KNOWN_RENDERER_AGENTS.filter(
|
|
22315
|
+
(agent) => agent !== "codex"
|
|
22316
|
+
);
|
|
22317
|
+
function shortSessionId(value) {
|
|
22318
|
+
return value.length <= 18 ? value : `${value.slice(0, 10)}\u2026${value.slice(-6)}`;
|
|
22319
|
+
}
|
|
22320
|
+
function createStatus(document2, message, error51 = false) {
|
|
22321
|
+
const status = document2.createElement("div");
|
|
22322
|
+
status.className = error51 ? "settings-session-import-status is-error" : "settings-session-import-status";
|
|
22323
|
+
status.setAttribute("role", error51 ? "alert" : "status");
|
|
22324
|
+
status.append(createRendererSettingsIcon(error51 ? "alert" : "download", 18));
|
|
22325
|
+
const copy = document2.createElement("span");
|
|
22326
|
+
copy.textContent = message;
|
|
22327
|
+
status.append(copy);
|
|
22328
|
+
return status;
|
|
22329
|
+
}
|
|
22330
|
+
function createAccessibleText(document2, message) {
|
|
22331
|
+
const text = document2.createElement("span");
|
|
22332
|
+
text.className = "settings-visually-hidden";
|
|
22333
|
+
text.textContent = message;
|
|
22334
|
+
return text;
|
|
22335
|
+
}
|
|
22336
|
+
function createDeepSeekSessionImportSettingsPage(messages, getClient, openImportedThread) {
|
|
22337
|
+
return Object.freeze({
|
|
22338
|
+
id: "session-import",
|
|
22339
|
+
label: messages.pageLabels["session-import"],
|
|
22340
|
+
icon: "download",
|
|
22341
|
+
mount(context) {
|
|
22342
|
+
const document2 = context.content.ownerDocument;
|
|
22343
|
+
const header = document2.createElement("div");
|
|
22344
|
+
header.className = "settings-connection-page-header";
|
|
22345
|
+
const headingCopy = document2.createElement("div");
|
|
22346
|
+
const heading = document2.createElement("h2");
|
|
22347
|
+
heading.className = "settings-section-label";
|
|
22348
|
+
heading.textContent = messages.pageLabels["session-import"];
|
|
22349
|
+
const description = document2.createElement("p");
|
|
22350
|
+
description.className = "settings-page-description";
|
|
22351
|
+
description.textContent = messages.sessionImportDescription;
|
|
22352
|
+
headingCopy.append(heading, description);
|
|
22353
|
+
const refresh = document2.createElement("button");
|
|
22354
|
+
refresh.type = "button";
|
|
22355
|
+
refresh.className = "settings-command-button settings-command-button--secondary";
|
|
22356
|
+
refresh.dataset.sessionImportAction = "refresh";
|
|
22357
|
+
const setRefreshLabel = (loading) => {
|
|
22358
|
+
refresh.replaceChildren(
|
|
22359
|
+
createRendererSettingsIcon("refresh", 15),
|
|
22360
|
+
loading ? messages.sessionImportRefreshing : messages.sessionImportRefresh
|
|
22361
|
+
);
|
|
22362
|
+
};
|
|
22363
|
+
setRefreshLabel(false);
|
|
22364
|
+
header.append(headingCopy, refresh);
|
|
22365
|
+
const harness = document2.createElement("div");
|
|
22366
|
+
harness.className = "settings-session-import-harness";
|
|
22367
|
+
const harnessLabel = document2.createElement("span");
|
|
22368
|
+
harnessLabel.textContent = messages.sessionImportHarness;
|
|
22369
|
+
const harnessOptions = document2.createElement("div");
|
|
22370
|
+
harnessOptions.className = "settings-segmented settings-session-import-harness__options";
|
|
22371
|
+
harnessOptions.dataset.sessionImportHarness = "selector";
|
|
22372
|
+
harnessOptions.setAttribute("role", "group");
|
|
22373
|
+
harnessOptions.setAttribute("aria-label", messages.sessionImportHarness);
|
|
22374
|
+
for (const agent of SESSION_IMPORT_HARNESSES) {
|
|
22375
|
+
const selected = agent === "deepseek-harness";
|
|
22376
|
+
const option = document2.createElement("button");
|
|
22377
|
+
option.type = "button";
|
|
22378
|
+
option.className = selected ? "settings-segmented__item settings-segmented__item--selected settings-session-import-harness__option" : "settings-segmented__item settings-session-import-harness__option";
|
|
22379
|
+
option.dataset.sessionImportHarnessOption = agent;
|
|
22380
|
+
option.textContent = RENDERER_AGENT_LABELS[agent];
|
|
22381
|
+
option.disabled = !selected;
|
|
22382
|
+
option.setAttribute("aria-pressed", selected ? "true" : "false");
|
|
22383
|
+
harnessOptions.append(option);
|
|
22384
|
+
}
|
|
22385
|
+
harness.append(harnessLabel, harnessOptions);
|
|
22386
|
+
const availabilityNote = document2.createElement("p");
|
|
22387
|
+
availabilityNote.className = "settings-page-description settings-session-import-availability-note";
|
|
22388
|
+
availabilityNote.textContent = messages.sessionImportAvailabilityNote;
|
|
22389
|
+
const content = document2.createElement("section");
|
|
22390
|
+
content.className = "settings-session-import-content";
|
|
22391
|
+
context.content.append(header, harness, availabilityNote, content);
|
|
22392
|
+
let candidates = [];
|
|
22393
|
+
let importingId = null;
|
|
22394
|
+
let actions = [];
|
|
22395
|
+
const updateImportActions = () => {
|
|
22396
|
+
for (const { button, candidate } of actions) {
|
|
22397
|
+
const importing = importingId === candidate.nativeSessionId;
|
|
22398
|
+
button.disabled = candidate.running;
|
|
22399
|
+
button.setAttribute(
|
|
22400
|
+
"aria-disabled",
|
|
22401
|
+
candidate.running || importingId !== null ? "true" : "false"
|
|
22402
|
+
);
|
|
22403
|
+
button.setAttribute("aria-busy", importing ? "true" : "false");
|
|
22404
|
+
button.replaceChildren(
|
|
22405
|
+
createRendererSettingsIcon("download", 15),
|
|
22406
|
+
importing ? messages.sessionImportImporting : messages.sessionImportAction
|
|
22407
|
+
);
|
|
22408
|
+
}
|
|
22409
|
+
};
|
|
22410
|
+
const renderUnavailable = (focus = false) => {
|
|
22411
|
+
candidates = [];
|
|
22412
|
+
actions = [];
|
|
22413
|
+
const status = createStatus(document2, messages.sessionImportUnavailable);
|
|
22414
|
+
content.replaceChildren(status);
|
|
22415
|
+
if (focus) {
|
|
22416
|
+
status.tabIndex = -1;
|
|
22417
|
+
status.focus();
|
|
22418
|
+
}
|
|
22419
|
+
};
|
|
22420
|
+
const renderFailure = (error51, operation = "list") => {
|
|
22421
|
+
if (error51 instanceof RendererDeepSeekSessionUnavailableError) {
|
|
22422
|
+
renderUnavailable(operation === "import");
|
|
22423
|
+
return;
|
|
22424
|
+
}
|
|
22425
|
+
actions = [];
|
|
22426
|
+
const status = createStatus(
|
|
22427
|
+
document2,
|
|
22428
|
+
operation === "import" ? messages.sessionImportFailed : messages.sessionImportLoadFailed,
|
|
22429
|
+
true
|
|
22430
|
+
);
|
|
22431
|
+
content.replaceChildren(status);
|
|
22432
|
+
if (operation === "import") {
|
|
22433
|
+
status.tabIndex = -1;
|
|
22434
|
+
status.focus();
|
|
22435
|
+
}
|
|
22436
|
+
};
|
|
22437
|
+
const renderOpenRecovery = (candidate, threadId) => {
|
|
22438
|
+
actions = [];
|
|
22439
|
+
refresh.disabled = false;
|
|
22440
|
+
const recovery = document2.createElement("section");
|
|
22441
|
+
recovery.className = "settings-session-import-recovery";
|
|
22442
|
+
recovery.setAttribute("role", "region");
|
|
22443
|
+
recovery.setAttribute("aria-label", messages.sessionImportImported);
|
|
22444
|
+
recovery.tabIndex = -1;
|
|
22445
|
+
const recoveryCopy = document2.createElement("div");
|
|
22446
|
+
recoveryCopy.className = "settings-session-import-recovery__copy";
|
|
22447
|
+
const title = document2.createElement("strong");
|
|
22448
|
+
title.textContent = messages.sessionImportImported;
|
|
22449
|
+
const explanation = document2.createElement("p");
|
|
22450
|
+
explanation.textContent = messages.sessionImportOpenFailed;
|
|
22451
|
+
recoveryCopy.append(title, explanation);
|
|
22452
|
+
const path = document2.createElement("div");
|
|
22453
|
+
path.className = "settings-session-import-recovery__path";
|
|
22454
|
+
const cwd = document2.createElement("code");
|
|
22455
|
+
cwd.textContent = candidate.cwd;
|
|
22456
|
+
cwd.title = candidate.cwd;
|
|
22457
|
+
const copyPath = document2.createElement("button");
|
|
22458
|
+
copyPath.type = "button";
|
|
22459
|
+
copyPath.className = "settings-command-button settings-command-button--secondary";
|
|
22460
|
+
copyPath.dataset.sessionImportAction = "copy-project-path";
|
|
22461
|
+
const setCopyLabel = (label) => {
|
|
22462
|
+
copyPath.replaceChildren(createRendererSettingsIcon("copy", 15), label);
|
|
22463
|
+
};
|
|
22464
|
+
const showCopyFeedback = (label) => {
|
|
22465
|
+
setCopyLabel(label);
|
|
22466
|
+
document2.defaultView?.setTimeout(
|
|
22467
|
+
() => setCopyLabel(messages.sessionImportCopyProjectPath),
|
|
22468
|
+
2e3
|
|
22469
|
+
);
|
|
22470
|
+
};
|
|
22471
|
+
setCopyLabel(messages.sessionImportCopyProjectPath);
|
|
22472
|
+
copyPath.addEventListener("click", () => {
|
|
22473
|
+
const clipboard = document2.defaultView?.navigator.clipboard;
|
|
22474
|
+
if (!clipboard) {
|
|
22475
|
+
showCopyFeedback(messages.sessionImportPathCopyFailed);
|
|
22476
|
+
return;
|
|
22477
|
+
}
|
|
22478
|
+
void clipboard.writeText(candidate.cwd).then(
|
|
22479
|
+
() => showCopyFeedback(messages.sessionImportPathCopied),
|
|
22480
|
+
() => showCopyFeedback(messages.sessionImportPathCopyFailed)
|
|
22481
|
+
);
|
|
22482
|
+
});
|
|
22483
|
+
path.append(cwd, copyPath);
|
|
22484
|
+
const retry = document2.createElement("button");
|
|
22485
|
+
retry.type = "button";
|
|
22486
|
+
retry.className = "settings-command-button";
|
|
22487
|
+
retry.dataset.sessionImportAction = "retry-open";
|
|
22488
|
+
const setRetrying = (pending) => {
|
|
22489
|
+
retry.disabled = pending;
|
|
22490
|
+
refresh.disabled = pending;
|
|
22491
|
+
retry.setAttribute("aria-busy", pending ? "true" : "false");
|
|
22492
|
+
retry.replaceChildren(
|
|
22493
|
+
createRendererSettingsIcon("refresh", 15),
|
|
22494
|
+
pending ? messages.sessionImportRetrying : messages.sessionImportRetryOpen
|
|
22495
|
+
);
|
|
22496
|
+
};
|
|
22497
|
+
setRetrying(false);
|
|
22498
|
+
retry.addEventListener("click", () => {
|
|
22499
|
+
if (retry.disabled) return;
|
|
22500
|
+
setRetrying(true);
|
|
22501
|
+
void context.runLatest((signal) => openImportedThread(threadId, signal), {
|
|
22502
|
+
success() {
|
|
22503
|
+
setRetrying(false);
|
|
22504
|
+
},
|
|
22505
|
+
failure() {
|
|
22506
|
+
renderOpenRecovery(candidate, threadId);
|
|
22507
|
+
}
|
|
22508
|
+
});
|
|
22509
|
+
});
|
|
22510
|
+
recovery.append(recoveryCopy, path, retry);
|
|
22511
|
+
content.replaceChildren(recovery);
|
|
22512
|
+
recovery.focus();
|
|
22513
|
+
};
|
|
22514
|
+
const renderCandidates = () => {
|
|
22515
|
+
actions = [];
|
|
22516
|
+
content.replaceChildren();
|
|
22517
|
+
if (candidates.length === 0) {
|
|
22518
|
+
content.append(createStatus(document2, messages.sessionImportEmpty));
|
|
22519
|
+
return;
|
|
22520
|
+
}
|
|
22521
|
+
const list = document2.createElement("div");
|
|
22522
|
+
list.className = "settings-session-import-list";
|
|
22523
|
+
for (const candidate of candidates) {
|
|
22524
|
+
const row = document2.createElement("article");
|
|
22525
|
+
row.className = "settings-session-import-row";
|
|
22526
|
+
row.dataset.sessionImportId = candidate.nativeSessionId;
|
|
22527
|
+
const copy = document2.createElement("div");
|
|
22528
|
+
copy.className = "settings-session-import-row__copy";
|
|
22529
|
+
const title = document2.createElement("strong");
|
|
22530
|
+
title.textContent = candidate.title ?? messages.sessionImportUntitled;
|
|
22531
|
+
const metadata = document2.createElement("span");
|
|
22532
|
+
metadata.textContent = `${messages.sessionImportUpdatedAt}: ${new Intl.DateTimeFormat(
|
|
22533
|
+
messages.locale === "zh-CN" ? "zh-CN" : "en",
|
|
22534
|
+
{ dateStyle: "medium", timeStyle: "short" }
|
|
22535
|
+
).format(new Date(candidate.updatedAt))}`;
|
|
22536
|
+
const cwd = document2.createElement("code");
|
|
22537
|
+
cwd.className = "settings-session-import-row__cwd";
|
|
22538
|
+
cwd.textContent = candidate.cwd;
|
|
22539
|
+
cwd.title = candidate.cwd;
|
|
22540
|
+
const identity = document2.createElement("span");
|
|
22541
|
+
identity.textContent = `${messages.sessionImportSessionId}: ${shortSessionId(candidate.nativeSessionId)}`;
|
|
22542
|
+
identity.title = candidate.nativeSessionId;
|
|
22543
|
+
identity.setAttribute("aria-hidden", "true");
|
|
22544
|
+
copy.append(
|
|
22545
|
+
title,
|
|
22546
|
+
metadata,
|
|
22547
|
+
cwd,
|
|
22548
|
+
identity,
|
|
22549
|
+
createAccessibleText(
|
|
22550
|
+
document2,
|
|
22551
|
+
`${messages.sessionImportSessionId}: ${candidate.nativeSessionId}`
|
|
22552
|
+
)
|
|
22553
|
+
);
|
|
22554
|
+
const actionArea = document2.createElement("div");
|
|
22555
|
+
actionArea.className = "settings-session-import-row__action";
|
|
22556
|
+
if (candidate.running) {
|
|
22557
|
+
const running = document2.createElement("span");
|
|
22558
|
+
running.className = "settings-session-import-running";
|
|
22559
|
+
running.textContent = messages.sessionImportRunning;
|
|
22560
|
+
running.title = messages.sessionImportRunningHint;
|
|
22561
|
+
running.setAttribute("aria-hidden", "true");
|
|
22562
|
+
actionArea.append(
|
|
22563
|
+
running,
|
|
22564
|
+
createAccessibleText(
|
|
22565
|
+
document2,
|
|
22566
|
+
`${messages.sessionImportRunning}: ${messages.sessionImportRunningHint}`
|
|
22567
|
+
)
|
|
22568
|
+
);
|
|
22569
|
+
}
|
|
22570
|
+
const action = document2.createElement("button");
|
|
22571
|
+
action.type = "button";
|
|
22572
|
+
action.className = "settings-command-button";
|
|
22573
|
+
action.dataset.sessionImportAction = "import";
|
|
22574
|
+
action.addEventListener("click", () => {
|
|
22575
|
+
if (candidate.running || importingId !== null) return;
|
|
22576
|
+
const client = getClient();
|
|
22577
|
+
if (!client) {
|
|
22578
|
+
renderUnavailable(true);
|
|
22579
|
+
return;
|
|
22580
|
+
}
|
|
22581
|
+
importingId = candidate.nativeSessionId;
|
|
22582
|
+
refresh.disabled = true;
|
|
22583
|
+
updateImportActions();
|
|
22584
|
+
let committedThreadId = null;
|
|
22585
|
+
void context.runLatest(
|
|
22586
|
+
async (signal) => {
|
|
22587
|
+
const result = await client.importDeepSeekModernSession({
|
|
22588
|
+
nativeSessionId: candidate.nativeSessionId
|
|
22589
|
+
});
|
|
22590
|
+
committedThreadId = result.threadId;
|
|
22591
|
+
await openImportedThread(result.threadId, signal);
|
|
22592
|
+
},
|
|
22593
|
+
{
|
|
22594
|
+
success() {
|
|
22595
|
+
importingId = null;
|
|
22596
|
+
refresh.disabled = false;
|
|
22597
|
+
updateImportActions();
|
|
22598
|
+
},
|
|
22599
|
+
failure(error51) {
|
|
22600
|
+
importingId = null;
|
|
22601
|
+
refresh.disabled = false;
|
|
22602
|
+
if (committedThreadId) {
|
|
22603
|
+
renderOpenRecovery(candidate, committedThreadId);
|
|
22604
|
+
} else {
|
|
22605
|
+
renderFailure(error51, "import");
|
|
22606
|
+
}
|
|
22607
|
+
}
|
|
22608
|
+
}
|
|
22609
|
+
);
|
|
22610
|
+
});
|
|
22611
|
+
actions.push({ button: action, candidate });
|
|
22612
|
+
actionArea.append(action);
|
|
22613
|
+
row.append(copy, actionArea);
|
|
22614
|
+
list.append(row);
|
|
22615
|
+
}
|
|
22616
|
+
content.append(list);
|
|
22617
|
+
updateImportActions();
|
|
22618
|
+
};
|
|
22619
|
+
const load = () => {
|
|
22620
|
+
if (importingId !== null) return;
|
|
22621
|
+
const client = getClient();
|
|
22622
|
+
if (!client) {
|
|
22623
|
+
refresh.disabled = false;
|
|
22624
|
+
setRefreshLabel(false);
|
|
22625
|
+
renderUnavailable();
|
|
22626
|
+
return;
|
|
22627
|
+
}
|
|
22628
|
+
refresh.disabled = true;
|
|
22629
|
+
setRefreshLabel(true);
|
|
22630
|
+
content.replaceChildren(createStatus(document2, messages.sessionImportRefreshing));
|
|
22631
|
+
void context.runLatest(() => client.listDeepSeekModernSessions({}), {
|
|
22632
|
+
success(result) {
|
|
22633
|
+
candidates = result.candidates;
|
|
22634
|
+
refresh.disabled = false;
|
|
22635
|
+
setRefreshLabel(false);
|
|
22636
|
+
renderCandidates();
|
|
22637
|
+
},
|
|
22638
|
+
failure(error51) {
|
|
22639
|
+
candidates = [];
|
|
22640
|
+
refresh.disabled = false;
|
|
22641
|
+
setRefreshLabel(false);
|
|
22642
|
+
renderFailure(error51);
|
|
22643
|
+
}
|
|
22644
|
+
});
|
|
22645
|
+
};
|
|
22646
|
+
refresh.addEventListener("click", load);
|
|
22647
|
+
load();
|
|
22648
|
+
return void 0;
|
|
22649
|
+
}
|
|
22650
|
+
});
|
|
22651
|
+
}
|
|
22652
|
+
|
|
21986
22653
|
// src/settings/plugins-page.ts
|
|
21987
22654
|
function adapterStatusLabel(availability, messages) {
|
|
21988
22655
|
if (availability === "ready") return messages.connectionStatusReady;
|
|
@@ -22844,22 +23511,29 @@ ${error51.stderrTail}`] : []
|
|
|
22844
23511
|
}
|
|
22845
23512
|
});
|
|
22846
23513
|
}
|
|
22847
|
-
function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null) {
|
|
23514
|
+
function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getSessionImportClient = () => null, openImportedThread = () => Promise.reject(new Error("Imported Thread navigation is unavailable"))) {
|
|
22848
23515
|
return Object.freeze([
|
|
22849
23516
|
createConnectionsSettingsPage(messages, getDiagnostics),
|
|
22850
23517
|
createPluginsSettingsPage(messages, getDiagnostics),
|
|
23518
|
+
createDeepSeekSessionImportSettingsPage(messages, getSessionImportClient, openImportedThread),
|
|
22851
23519
|
updatesPage(messages, getUpdateClient),
|
|
22852
23520
|
aboutPage(messages)
|
|
22853
23521
|
]);
|
|
22854
23522
|
}
|
|
22855
|
-
function createDefaultRendererSettingsRegistry(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null) {
|
|
23523
|
+
function createDefaultRendererSettingsRegistry(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getSessionImportClient = () => null, openImportedThread) {
|
|
22856
23524
|
return createRendererSettingsPageRegistry(
|
|
22857
|
-
createDefaultRendererSettingsPages(
|
|
23525
|
+
createDefaultRendererSettingsPages(
|
|
23526
|
+
messages,
|
|
23527
|
+
getUpdateClient,
|
|
23528
|
+
getDiagnostics,
|
|
23529
|
+
getSessionImportClient,
|
|
23530
|
+
openImportedThread
|
|
23531
|
+
)
|
|
22858
23532
|
);
|
|
22859
23533
|
}
|
|
22860
23534
|
|
|
22861
23535
|
// src/settings/shell.css
|
|
22862
|
-
var shell_default = ':host {\n /* Inherit Codex Desktop color-scheme; light-dark() tracks the host page. */\n --settings-bg: light-dark(#ffffff, #181818);\n --settings-sidebar: light-dark(#f4f4f5, #1c1c1c);\n --settings-panel: transparent;\n --settings-text: light-dark(#171717, #f5f5f5);\n --settings-muted: light-dark(#737373, #a1a1a1);\n --settings-border: light-dark(rgb(15 23 42 / 10%), rgb(255 255 255 / 10%));\n --settings-divider: light-dark(rgb(15 23 42 / 10%), rgb(255 255 255 / 10%));\n --settings-hover: light-dark(rgb(15 23 42 / 5%), rgb(255 255 255 / 6%));\n --settings-active: light-dark(rgb(51 156 255 / 14%), rgb(51 156 255 / 12%));\n --settings-focus: #339cff;\n --settings-elevated: light-dark(#ffffff, #2c2c2e);\n --settings-inset: light-dark(rgb(15 23 42 / 4%), rgb(0 0 0 / 18%));\n --settings-surface: light-dark(rgb(15 23 42 / 3%), rgb(255 255 255 / 2%));\n --settings-surface-strong: light-dark(rgb(15 23 42 / 6%), rgb(255 255 255 / 6%));\n --settings-mark: light-dark(#52525b, #d4d8de);\n --settings-dialog-shadow: light-dark(\n 0 24px 64px rgb(15 23 42 / 16%),\n 0 24px 64px rgb(0 0 0 / 38%)\n );\n --settings-backdrop: light-dark(rgb(15 23 42 / 28%), rgb(0 0 0 / 52%));\n --settings-segmented-shadow:\n 0 0 0 0.5px light-dark(rgb(15 23 42 / 6%), rgb(0 0 0 / 4%)),\n 0 3px 1px 0 light-dark(rgb(15 23 42 / 4%), rgb(0 0 0 / 4%)),\n 0 3px 8px 0 light-dark(rgb(15 23 42 / 10%), rgb(0 0 0 / 12%));\n color: var(--settings-text);\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: var(--settings-dialog-shadow);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: var(--settings-backdrop);\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: var(--settings-muted);\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 font-weight: 600;\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-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: var(--settings-surface-strong);\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: var(--settings-surface-strong);\n border: 1px solid var(--settings-border);\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: var(--settings-surface-strong);\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-plugins-content,\n.settings-connection-list,\n.settings-connection-rows {\n min-width: 0;\n}\n\n.settings-connections-content,\n.settings-plugins-content {\n display: grid;\n gap: 12px;\n}\n\n.settings-connection-list {\n overflow: hidden;\n background: var(--settings-surface);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n}\n\n.settings-segmented {\n display: inline-flex;\n flex-wrap: wrap;\n align-items: center;\n width: fit-content;\n max-width: 100%;\n padding: 2px;\n gap: 3px;\n background: var(--settings-surface-strong);\n border-radius: 10px;\n}\n\n.settings-segmented__item {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-height: 28px;\n padding: 4px 14px;\n color: var(--settings-muted);\n font: inherit;\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n white-space: nowrap;\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n transition:\n color 0.15s ease,\n background-color 0.15s ease,\n box-shadow 0.15s ease;\n}\n\n.settings-segmented__item:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-segmented__item--selected,\n.settings-segmented__item[aria-selected="true"] {\n color: var(--settings-text);\n background: var(--settings-elevated);\n box-shadow: var(--settings-segmented-shadow);\n}\n\n.settings-segmented__item: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-table-header,\n.settings-connection-row {\n display: grid;\n /* Component : Status : Actions = 4 : 3 : 3 */\n grid-template-columns: minmax(0, 4fr) minmax(0, 3fr) minmax(0, 3fr);\n align-items: center;\n min-width: 0;\n column-gap: 16px;\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: var(--settings-surface);\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-rows > .settings-connection-row,\n.settings-connection-rows > .settings-connection-block {\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-rows > .settings-connection-row:last-child,\n.settings-connection-rows > .settings-connection-block:last-child {\n border-bottom: 0;\n}\n\n.settings-connection-row {\n min-height: 64px;\n padding: 10px 12px;\n cursor: pointer;\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: var(--settings-mark);\n font-size: 10px;\n font-weight: 700;\n background: var(--settings-surface-strong);\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-table-header > :last-child {\n text-align: end;\n}\n\n.settings-connection-row__status {\n display: inline-flex;\n align-items: center;\n width: fit-content;\n max-width: 100%;\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 gap: 4px;\n}\n\n.settings-connection-row__handle {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 16px;\n color: var(--settings-muted);\n cursor: grab;\n opacity: 0.6;\n}\n\n.settings-connection-row__handle:hover {\n opacity: 1;\n}\n\n.settings-connection-row[draggable="true"] {\n cursor: grab;\n}\n\n.settings-connection-row[data-connection-dragging="true"] {\n opacity: 0.4;\n}\n\n.settings-connection-row[data-connection-drop-indicator="before"] {\n box-shadow: inset 0 2px 0 0 var(--settings-focus);\n}\n\n.settings-connection-row[data-connection-drop-indicator="after"] {\n box-shadow: inset 0 -2px 0 0 var(--settings-focus);\n}\n\n.settings-connection-inline-detail {\n display: grid;\n gap: 12px;\n margin-top: 2px;\n padding: 14px 12px 16px;\n border-top: 1px solid var(--settings-divider);\n background: var(--settings-inset);\n}\n\n.settings-connection-group-divider {\n padding: 10px 12px 6px;\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 /* No border-top here: the row immediately above already carries its own\n border-bottom (it is no longer :last-child once this divider follows\n it), so adding one here would double the separator line. */\n}\n\n.settings-connection-group-divider[data-connection-drag-over="true"] {\n color: var(--settings-focus);\n background: rgb(51 156 255 / 8%);\n border-radius: 6px;\n}\n\n.settings-connection-group-more[data-connection-drag-over="true"] {\n background: rgb(51 156 255 / 8%);\n}\n\n.settings-connection-group-hint {\n display: grid;\n gap: 3px;\n margin: 0 12px 12px;\n padding: 14px 16px;\n text-align: center;\n border: 1.5px dashed var(--settings-border);\n border-radius: 10px;\n}\n\n.settings-connection-group-more[data-connection-drag-over="true"] .settings-connection-group-hint {\n border-color: var(--settings-focus);\n}\n\n.settings-connection-group-hint strong {\n color: var(--settings-text);\n font-size: 12.5px;\n font-weight: 500;\n line-height: 18px;\n}\n\n.settings-connection-group-hint span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 17px;\n}\n\n.settings-connection-group-reset {\n display: flex;\n width: 100%;\n align-items: center;\n gap: 6px;\n padding: 10px 12px;\n color: var(--settings-muted);\n font: inherit;\n font-size: 12px;\n text-align: left;\n background: transparent;\n border: 0;\n border-top: 1px solid var(--settings-divider);\n cursor: pointer;\n}\n\n.settings-connection-group-reset:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\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: var(--settings-inset);\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: var(--settings-text);\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: var(--settings-inset);\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: var(--settings-surface);\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-page {\n display: flex;\n flex-direction: column;\n gap: 18px;\n box-sizing: border-box;\n min-height: min(620px, calc(100vh - 200px));\n max-width: 720px;\n}\n\n.settings-about-page > .settings-section-label {\n padding-bottom: 10px;\n}\n\n.settings-about-panel {\n display: grid;\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-lead,\n.settings-about-extension,\n.settings-about-closing p,\n.settings-about-copy p {\n margin: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 21px;\n}\n\n.settings-about-lead {\n color: var(--settings-text);\n font-weight: 500;\n}\n\n.settings-about-agents {\n display: grid;\n gap: 10px;\n margin: 2px 0;\n padding: 0;\n list-style: none;\n}\n\n.settings-about-agent {\n display: grid;\n gap: 4px;\n padding-left: 2px;\n}\n\n.settings-about-agent-name {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 600;\n line-height: 18px;\n}\n\n.settings-about-agent-name::before {\n content: "\xB7 ";\n color: var(--settings-muted);\n font-weight: 600;\n}\n\n.settings-about-agent-description {\n display: block;\n padding-left: 0.85em;\n color: var(--settings-muted);\n font-size: 12px;\n font-weight: 400;\n line-height: 18px;\n}\n\n.settings-about-closing {\n display: grid;\n gap: 8px;\n}\n\n.settings-about-repository {\n gap: 10px;\n}\n\n.settings-about-open-source {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 0.35em;\n margin: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 21px;\n}\n\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: 4px 0 0;\n color: #f5c542;\n font-size: 14px;\n font-weight: 600;\n line-height: 22px;\n}\n\n.settings-about-repository-link {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n color: #7cb8ff;\n font-weight: 600;\n line-height: 1;\n text-decoration: none;\n}\n\n.settings-about-repository-link .codexhost-settings-icon {\n display: block;\n flex: none;\n}\n\n.settings-about-repository-link:hover {\n text-decoration: underline;\n}\n\n.settings-about-brand {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n margin-top: auto;\n padding-top: 12px;\n color: inherit;\n opacity: 0.9;\n text-decoration: none;\n transition: opacity 160ms ease;\n}\n\n.settings-about-brand:hover {\n opacity: 1;\n}\n\n.settings-about-brand-video {\n width: 40px;\n height: 40px;\n flex: none;\n overflow: hidden;\n object-fit: cover;\n border-radius: 999px;\n box-shadow: 0 1px 2px rgb(0 0 0 / 18%);\n}\n\n.settings-about-brand-copy {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 2px;\n}\n\n.settings-about-brand-name {\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 800;\n letter-spacing: 0.18em;\n line-height: 18px;\n}\n\n.settings-about-brand-tagline {\n color: var(--settings-muted);\n font-size: 12px;\n font-weight: 500;\n letter-spacing: 0.18em;\n line-height: 16px;\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/* Soft status copy (unavailable / request failure) should not sit in a framed card. */\n.settings-update-panel[data-update-state="unavailable"],\n.settings-update-panel[data-update-state="failed"],\n.settings-update-panel[data-update-state="error"] {\n padding: 4px 0 0;\n border: 0;\n border-radius: 0;\n}\n\n.settings-update-panel__status-row {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 8px;\n min-width: 0;\n}\n\n.settings-update-panel__status-row .settings-update-actions {\n flex: none;\n}\n\n.settings-update-panel__status-row .settings-update-panel__head {\n flex: 1 1 auto;\n min-width: 0;\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"]\n .settings-update-panel__head\n .codexhost-settings-icon,\n.settings-update-panel[data-update-state="downloading"]\n .settings-update-panel__head\n .codexhost-settings-icon,\n.settings-update-panel[data-update-state="installing"]\n .settings-update-panel__head\n .codexhost-settings-icon,\n.settings-update-panel[data-update-state="restarting"]\n .settings-update-panel__head\n .codexhost-settings-icon {\n color: #4aa3f0;\n}\n\n.settings-update-panel[data-update-state="current"]\n .settings-update-panel__head\n .codexhost-settings-icon {\n color: #4ade80;\n}\n\n.settings-update-panel[data-update-state="failed"]\n .settings-update-panel__head\n .codexhost-settings-icon,\n.settings-update-panel[data-update-state="error"]\n .settings-update-panel__head\n .codexhost-settings-icon {\n color: #ef4444;\n}\n\n.settings-update-panel[data-update-state="unavailable"]\n .settings-update-panel__head\n .codexhost-settings-icon {\n color: var(--settings-muted);\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: var(--settings-surface);\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: var(--settings-surface-strong);\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: var(--settings-inset);\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-muted);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button--secondary .codexhost-settings-icon,\n.settings-update-link .codexhost-settings-icon {\n color: var(--settings-muted);\n}\n\n.settings-command-button:hover:not(.settings-command-button--secondary) {\n filter: brightness(1.08);\n}\n\n.settings-command-button--secondary:hover,\n.settings-update-link:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-command-button--secondary:hover .codexhost-settings-icon,\n.settings-update-link:hover .codexhost-settings-icon {\n color: var(--settings-text);\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-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-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="light"]),\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 --settings-elevated: Canvas;\n --settings-inset: Canvas;\n --settings-surface: Canvas;\n --settings-surface-strong: Canvas;\n --settings-mark: CanvasText;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
|
|
23536
|
+
var shell_default = ':host {\n /* Inherit Codex Desktop color-scheme; light-dark() tracks the host page. */\n --settings-bg: light-dark(#ffffff, #181818);\n --settings-sidebar: light-dark(#f4f4f5, #1c1c1c);\n --settings-panel: transparent;\n --settings-text: light-dark(#171717, #f5f5f5);\n --settings-muted: light-dark(#737373, #a1a1a1);\n --settings-border: light-dark(rgb(15 23 42 / 10%), rgb(255 255 255 / 10%));\n --settings-divider: light-dark(rgb(15 23 42 / 10%), rgb(255 255 255 / 10%));\n --settings-hover: light-dark(rgb(15 23 42 / 5%), rgb(255 255 255 / 6%));\n --settings-active: light-dark(rgb(51 156 255 / 14%), rgb(51 156 255 / 12%));\n --settings-focus: #339cff;\n --settings-elevated: light-dark(#ffffff, #2c2c2e);\n --settings-inset: light-dark(rgb(15 23 42 / 4%), rgb(0 0 0 / 18%));\n --settings-surface: light-dark(rgb(15 23 42 / 3%), rgb(255 255 255 / 2%));\n --settings-surface-strong: light-dark(rgb(15 23 42 / 6%), rgb(255 255 255 / 6%));\n --settings-mark: light-dark(#52525b, #d4d8de);\n --settings-dialog-shadow: light-dark(\n 0 24px 64px rgb(15 23 42 / 16%),\n 0 24px 64px rgb(0 0 0 / 38%)\n );\n --settings-backdrop: light-dark(rgb(15 23 42 / 28%), rgb(0 0 0 / 52%));\n --settings-segmented-shadow:\n 0 0 0 0.5px light-dark(rgb(15 23 42 / 6%), rgb(0 0 0 / 4%)),\n 0 3px 1px 0 light-dark(rgb(15 23 42 / 4%), rgb(0 0 0 / 4%)),\n 0 3px 8px 0 light-dark(rgb(15 23 42 / 10%), rgb(0 0 0 / 12%));\n color: var(--settings-text);\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: var(--settings-dialog-shadow);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: var(--settings-backdrop);\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: var(--settings-muted);\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 font-weight: 600;\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-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: var(--settings-surface-strong);\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: var(--settings-surface-strong);\n border: 1px solid var(--settings-border);\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: var(--settings-surface-strong);\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-plugins-content,\n.settings-connection-list,\n.settings-connection-rows {\n min-width: 0;\n}\n\n.settings-connections-content,\n.settings-plugins-content {\n display: grid;\n gap: 12px;\n}\n\n.settings-connection-list {\n overflow: hidden;\n background: var(--settings-surface);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n}\n\n.settings-segmented {\n display: inline-flex;\n flex-wrap: wrap;\n align-items: center;\n width: fit-content;\n max-width: 100%;\n padding: 2px;\n gap: 3px;\n background: var(--settings-surface-strong);\n border-radius: 10px;\n}\n\n.settings-segmented__item {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-height: 28px;\n padding: 4px 14px;\n color: var(--settings-muted);\n font: inherit;\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n white-space: nowrap;\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n transition:\n color 0.15s ease,\n background-color 0.15s ease,\n box-shadow 0.15s ease;\n}\n\n.settings-segmented__item:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-segmented__item--selected,\n.settings-segmented__item[aria-selected="true"],\n.settings-segmented__item[aria-pressed="true"] {\n color: var(--settings-text);\n background: var(--settings-elevated);\n box-shadow: var(--settings-segmented-shadow);\n}\n\n.settings-segmented__item:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.settings-segmented__item:disabled:hover {\n color: var(--settings-muted);\n background: transparent;\n}\n\n.settings-segmented__item: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-table-header,\n.settings-connection-row {\n display: grid;\n /* Component : Status : Actions = 4 : 3 : 3 */\n grid-template-columns: minmax(0, 4fr) minmax(0, 3fr) minmax(0, 3fr);\n align-items: center;\n min-width: 0;\n column-gap: 16px;\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: var(--settings-surface);\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-rows > .settings-connection-row,\n.settings-connection-rows > .settings-connection-block {\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-rows > .settings-connection-row:last-child,\n.settings-connection-rows > .settings-connection-block:last-child {\n border-bottom: 0;\n}\n\n.settings-connection-row {\n min-height: 64px;\n padding: 10px 12px;\n cursor: pointer;\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: var(--settings-mark);\n font-size: 10px;\n font-weight: 700;\n background: var(--settings-surface-strong);\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-table-header > :last-child {\n text-align: end;\n}\n\n.settings-connection-row__status {\n display: inline-flex;\n align-items: center;\n width: fit-content;\n max-width: 100%;\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 gap: 4px;\n}\n\n.settings-connection-row__handle {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 16px;\n color: var(--settings-muted);\n cursor: grab;\n opacity: 0.6;\n}\n\n.settings-connection-row__handle:hover {\n opacity: 1;\n}\n\n.settings-connection-row[draggable="true"] {\n cursor: grab;\n}\n\n.settings-connection-row[data-connection-dragging="true"] {\n opacity: 0.4;\n}\n\n.settings-connection-row[data-connection-drop-indicator="before"] {\n box-shadow: inset 0 2px 0 0 var(--settings-focus);\n}\n\n.settings-connection-row[data-connection-drop-indicator="after"] {\n box-shadow: inset 0 -2px 0 0 var(--settings-focus);\n}\n\n.settings-connection-inline-detail {\n display: grid;\n gap: 12px;\n margin-top: 2px;\n padding: 14px 12px 16px;\n border-top: 1px solid var(--settings-divider);\n background: var(--settings-inset);\n}\n\n.settings-connection-group-divider {\n padding: 10px 12px 6px;\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 /* No border-top here: the row immediately above already carries its own\n border-bottom (it is no longer :last-child once this divider follows\n it), so adding one here would double the separator line. */\n}\n\n.settings-connection-group-divider[data-connection-drag-over="true"] {\n color: var(--settings-focus);\n background: rgb(51 156 255 / 8%);\n border-radius: 6px;\n}\n\n.settings-connection-group-more[data-connection-drag-over="true"] {\n background: rgb(51 156 255 / 8%);\n}\n\n.settings-connection-group-hint {\n display: grid;\n gap: 3px;\n margin: 0 12px 12px;\n padding: 14px 16px;\n text-align: center;\n border: 1.5px dashed var(--settings-border);\n border-radius: 10px;\n}\n\n.settings-connection-group-more[data-connection-drag-over="true"] .settings-connection-group-hint {\n border-color: var(--settings-focus);\n}\n\n.settings-connection-group-hint strong {\n color: var(--settings-text);\n font-size: 12.5px;\n font-weight: 500;\n line-height: 18px;\n}\n\n.settings-connection-group-hint span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 17px;\n}\n\n.settings-connection-group-reset {\n display: flex;\n width: 100%;\n align-items: center;\n gap: 6px;\n padding: 10px 12px;\n color: var(--settings-muted);\n font: inherit;\n font-size: 12px;\n text-align: left;\n background: transparent;\n border: 0;\n border-top: 1px solid var(--settings-divider);\n cursor: pointer;\n}\n\n.settings-connection-group-reset:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\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: var(--settings-inset);\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: var(--settings-text);\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: var(--settings-inset);\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: var(--settings-surface);\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-page {\n display: flex;\n flex-direction: column;\n gap: 18px;\n box-sizing: border-box;\n min-height: min(620px, calc(100vh - 200px));\n max-width: 720px;\n}\n\n.settings-about-page > .settings-section-label {\n padding-bottom: 10px;\n}\n\n.settings-about-panel {\n display: grid;\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-lead,\n.settings-about-extension,\n.settings-about-closing p,\n.settings-about-copy p {\n margin: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 21px;\n}\n\n.settings-about-lead {\n color: var(--settings-text);\n font-weight: 500;\n}\n\n.settings-about-agents {\n display: grid;\n gap: 10px;\n margin: 2px 0;\n padding: 0;\n list-style: none;\n}\n\n.settings-about-agent {\n display: grid;\n gap: 4px;\n padding-left: 2px;\n}\n\n.settings-about-agent-name {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 600;\n line-height: 18px;\n}\n\n.settings-about-agent-name::before {\n content: "\xB7 ";\n color: var(--settings-muted);\n font-weight: 600;\n}\n\n.settings-about-agent-description {\n display: block;\n padding-left: 0.85em;\n color: var(--settings-muted);\n font-size: 12px;\n font-weight: 400;\n line-height: 18px;\n}\n\n.settings-about-closing {\n display: grid;\n gap: 8px;\n}\n\n.settings-about-repository {\n gap: 10px;\n}\n\n.settings-about-open-source {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 0.35em;\n margin: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 21px;\n}\n\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: 4px 0 0;\n color: #f5c542;\n font-size: 14px;\n font-weight: 600;\n line-height: 22px;\n}\n\n.settings-about-repository-link {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n color: #7cb8ff;\n font-weight: 600;\n line-height: 1;\n text-decoration: none;\n}\n\n.settings-about-repository-link .codexhost-settings-icon {\n display: block;\n flex: none;\n}\n\n.settings-about-repository-link:hover {\n text-decoration: underline;\n}\n\n.settings-about-brand {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n margin-top: auto;\n padding-top: 12px;\n color: inherit;\n opacity: 0.9;\n text-decoration: none;\n transition: opacity 160ms ease;\n}\n\n.settings-about-brand:hover {\n opacity: 1;\n}\n\n.settings-about-brand-video {\n width: 40px;\n height: 40px;\n flex: none;\n overflow: hidden;\n object-fit: cover;\n border-radius: 999px;\n box-shadow: 0 1px 2px rgb(0 0 0 / 18%);\n}\n\n.settings-about-brand-copy {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 2px;\n}\n\n.settings-about-brand-name {\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 800;\n letter-spacing: 0.18em;\n line-height: 18px;\n}\n\n.settings-about-brand-tagline {\n color: var(--settings-muted);\n font-size: 12px;\n font-weight: 500;\n letter-spacing: 0.18em;\n line-height: 16px;\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/* Soft status copy (unavailable / request failure) should not sit in a framed card. */\n.settings-update-panel[data-update-state="unavailable"],\n.settings-update-panel[data-update-state="failed"],\n.settings-update-panel[data-update-state="error"] {\n padding: 4px 0 0;\n border: 0;\n border-radius: 0;\n}\n\n.settings-update-panel__status-row {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 8px;\n min-width: 0;\n}\n\n.settings-update-panel__status-row .settings-update-actions {\n flex: none;\n}\n\n.settings-update-panel__status-row .settings-update-panel__head {\n flex: 1 1 auto;\n min-width: 0;\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"]\n .settings-update-panel__head\n .codexhost-settings-icon,\n.settings-update-panel[data-update-state="downloading"]\n .settings-update-panel__head\n .codexhost-settings-icon,\n.settings-update-panel[data-update-state="installing"]\n .settings-update-panel__head\n .codexhost-settings-icon,\n.settings-update-panel[data-update-state="restarting"]\n .settings-update-panel__head\n .codexhost-settings-icon {\n color: #4aa3f0;\n}\n\n.settings-update-panel[data-update-state="current"]\n .settings-update-panel__head\n .codexhost-settings-icon {\n color: #4ade80;\n}\n\n.settings-update-panel[data-update-state="failed"]\n .settings-update-panel__head\n .codexhost-settings-icon,\n.settings-update-panel[data-update-state="error"]\n .settings-update-panel__head\n .codexhost-settings-icon {\n color: #ef4444;\n}\n\n.settings-update-panel[data-update-state="unavailable"]\n .settings-update-panel__head\n .codexhost-settings-icon {\n color: var(--settings-muted);\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: var(--settings-surface);\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: var(--settings-surface-strong);\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: var(--settings-inset);\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-muted);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button--secondary .codexhost-settings-icon,\n.settings-update-link .codexhost-settings-icon {\n color: var(--settings-muted);\n}\n\n.settings-command-button:hover:not(.settings-command-button--secondary) {\n filter: brightness(1.08);\n}\n\n.settings-command-button--secondary:hover,\n.settings-update-link:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-command-button--secondary:hover .codexhost-settings-icon,\n.settings-update-link:hover .codexhost-settings-icon {\n color: var(--settings-text);\n}\n\n.settings-command-button:disabled,\n.settings-command-button[aria-disabled="true"] {\n opacity: 0.55;\n cursor: not-allowed;\n filter: none;\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.settings-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.settings-session-import-harness {\n display: grid;\n gap: 8px;\n min-width: 0;\n}\n\n.settings-session-import-harness > span {\n color: var(--settings-muted);\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n}\n\n.settings-session-import-harness__options {\n width: 100%;\n}\n\n.settings-session-import-availability-note {\n margin: 16px 0 20px;\n}\n\n.settings-session-import-content {\n display: grid;\n min-width: 0;\n gap: 12px;\n}\n\n.settings-session-import-status {\n display: flex;\n align-items: flex-start;\n min-width: 0;\n gap: 10px;\n padding: 14px 16px;\n color: var(--settings-muted);\n background: var(--settings-surface);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n}\n\n.settings-session-import-status.is-error {\n color: #fecaca;\n background: rgb(239 68 68 / 7%);\n border-color: rgb(239 68 68 / 20%);\n}\n\n.settings-session-import-list {\n display: grid;\n min-width: 0;\n overflow: hidden;\n background: var(--settings-surface);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n}\n\n.settings-session-import-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n min-width: 0;\n gap: 16px;\n padding: 14px 16px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-session-import-row:last-child {\n border-bottom: 0;\n}\n\n.settings-session-import-row__copy {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n\n.settings-session-import-row__copy strong {\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 600;\n line-height: 20px;\n}\n\n.settings-session-import-row__copy span,\n.settings-session-import-row__cwd {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-session-import-row__cwd {\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n}\n\n.settings-session-import-row__action {\n display: flex;\n align-items: center;\n flex: none;\n gap: 8px;\n}\n\n.settings-session-import-running {\n color: #f5c542;\n font-size: 12px;\n font-weight: 500;\n line-height: 18px;\n white-space: nowrap;\n}\n\n.settings-session-import-recovery {\n display: grid;\n min-width: 0;\n gap: 12px;\n padding: 16px;\n background: var(--settings-surface);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n}\n\n.settings-session-import-recovery__copy {\n display: grid;\n gap: 6px;\n}\n\n.settings-session-import-recovery__copy strong {\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 600;\n line-height: 22px;\n}\n\n.settings-session-import-recovery__copy p {\n margin: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-session-import-recovery__path {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-session-import-recovery__path code {\n min-width: 0;\n flex: 1;\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.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-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-session-import-row {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .settings-session-import-row__action {\n justify-content: flex-start;\n flex-wrap: wrap;\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="light"]),\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 --settings-elevated: Canvas;\n --settings-inset: Canvas;\n --settings-surface: Canvas;\n --settings-surface-strong: Canvas;\n --settings-mark: CanvasText;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
|
|
22863
23537
|
|
|
22864
23538
|
// src/settings/shell.ts
|
|
22865
23539
|
var SETTINGS_SHELL_ATTRIBUTE = "data-codexhost-settings-shell";
|
|
@@ -23441,7 +24115,15 @@ ${error51.stderrTail}`] : []
|
|
|
23441
24115
|
const definitions = createDefaultRendererSettingsPages(
|
|
23442
24116
|
messages,
|
|
23443
24117
|
options.getUpdateClient ?? (() => null),
|
|
23444
|
-
options.getConnectionDiagnostics ?? (() => null)
|
|
24118
|
+
options.getConnectionDiagnostics ?? (() => null),
|
|
24119
|
+
options.getSessionImportClient ?? (() => null),
|
|
24120
|
+
async (threadId, signal) => {
|
|
24121
|
+
if (!options.openImportedThread) {
|
|
24122
|
+
throw new Error("Imported Thread navigation is unavailable");
|
|
24123
|
+
}
|
|
24124
|
+
await options.openImportedThread(threadId, signal);
|
|
24125
|
+
if (!disposed && !signal.aborted) shell?.close();
|
|
24126
|
+
}
|
|
23445
24127
|
);
|
|
23446
24128
|
const nextShell = installRendererSettingsShell(definitions, messages, ownerWindow.document);
|
|
23447
24129
|
const nextTrigger = installRendererSettingsHeaderTrigger({
|
|
@@ -23872,10 +24554,30 @@ ${error51.stderrTail}`] : []
|
|
|
23872
24554
|
getClient: (hostId) => modelClientForHost(hostId),
|
|
23873
24555
|
getLocalAgent: localAgentForSidebarThread
|
|
23874
24556
|
});
|
|
24557
|
+
const stopSidebarExternalPinning = installRendererSidebarExternalPinning({
|
|
24558
|
+
getClient: (hostId) => modelClientForHost(hostId),
|
|
24559
|
+
reportError: (error51) => {
|
|
24560
|
+
console.error(
|
|
24561
|
+
"codexhost External Thread pin update failed",
|
|
24562
|
+
error51 instanceof Error ? error51.message : String(error51)
|
|
24563
|
+
);
|
|
24564
|
+
}
|
|
24565
|
+
});
|
|
23875
24566
|
let connectionDiagnostics = null;
|
|
23876
24567
|
const settingsLifecycle = installRendererSettingsLifecycle(window, {
|
|
23877
24568
|
getUpdateClient: () => modelControl,
|
|
23878
24569
|
getConnectionDiagnostics: () => connectionDiagnostics,
|
|
24570
|
+
getSessionImportClient: () => {
|
|
24571
|
+
const client = modelClientForHost("local");
|
|
24572
|
+
const list = client?.listDeepSeekModernSessions;
|
|
24573
|
+
const importSession = client?.importDeepSeekModernSession;
|
|
24574
|
+
if (!list || !importSession) return null;
|
|
24575
|
+
return {
|
|
24576
|
+
listDeepSeekModernSessions: (input) => list(input),
|
|
24577
|
+
importDeepSeekModernSession: (input) => importSession(input)
|
|
24578
|
+
};
|
|
24579
|
+
},
|
|
24580
|
+
openImportedThread: (threadId, signal) => openRendererThread(threadId, { hostId: "local", signal }),
|
|
23879
24581
|
onLocaleChange() {
|
|
23880
24582
|
for (const mounted of mountedByComposer.values()) renderMounted(mounted);
|
|
23881
24583
|
}
|
|
@@ -23899,6 +24601,9 @@ ${error51.stderrTail}`] : []
|
|
|
23899
24601
|
omp: void 0,
|
|
23900
24602
|
antigravity: void 0
|
|
23901
24603
|
},
|
|
24604
|
+
webUi: Object.fromEntries(
|
|
24605
|
+
externalAgents.map((agent) => [agent, false])
|
|
24606
|
+
),
|
|
23902
24607
|
requestGeneration: 0,
|
|
23903
24608
|
request: null,
|
|
23904
24609
|
retryTimer: null,
|
|
@@ -24003,6 +24708,17 @@ ${error51.stderrTail}`] : []
|
|
|
24003
24708
|
mounted.control.harnessCommands.setExecuting(null);
|
|
24004
24709
|
}
|
|
24005
24710
|
};
|
|
24711
|
+
const selectCommand = (mounted, command) => {
|
|
24712
|
+
const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
|
|
24713
|
+
if (!threadId || !modelControl || controller.get(mounted.composer).agent === "codex") return;
|
|
24714
|
+
const editor = mounted.composer.querySelector(EDITOR_SELECTOR);
|
|
24715
|
+
if (routeRendererHarnessCommandSelection(editor, command, () => {
|
|
24716
|
+
void executeCommand(mounted, command);
|
|
24717
|
+
})) {
|
|
24718
|
+
return;
|
|
24719
|
+
}
|
|
24720
|
+
console.error("codexhost Harness command could not claim the current Composer editor");
|
|
24721
|
+
};
|
|
24006
24722
|
const applyThreadUsageUpdate = (update) => {
|
|
24007
24723
|
for (const mounted of mountedByComposer.values()) {
|
|
24008
24724
|
if (threadIdFromComposerModelTarget(mounted.modelTarget) !== update.threadId) continue;
|
|
@@ -24858,12 +25574,14 @@ ${error51.stderrTail}`] : []
|
|
|
24858
25574
|
agentsToInspect.map(async (agent) => {
|
|
24859
25575
|
let status = "error";
|
|
24860
25576
|
let nextError;
|
|
25577
|
+
let webUiAvailable = false;
|
|
24861
25578
|
try {
|
|
24862
25579
|
const inspection = await client.inspectHarness({
|
|
24863
25580
|
harnessId: externalHarnessIds[agent],
|
|
24864
25581
|
refresh
|
|
24865
25582
|
});
|
|
24866
25583
|
status = inspection.status === "ready" ? "ready" : inspection.status;
|
|
25584
|
+
webUiAvailable = hostId === "local" && inspection.status === "ready" && inspection.webUi?.open === true;
|
|
24867
25585
|
if (inspection.status !== "ready") {
|
|
24868
25586
|
const error51 = inspection.error;
|
|
24869
25587
|
nextError = {
|
|
@@ -24889,6 +25607,7 @@ ${error51.stderrTail}`] : []
|
|
|
24889
25607
|
const previousStatus = state.availability[agent];
|
|
24890
25608
|
state.errors[agent] = nextError;
|
|
24891
25609
|
state.availability = { ...state.availability, [agent]: status };
|
|
25610
|
+
state.webUi = { ...state.webUi, [agent]: webUiAvailable };
|
|
24892
25611
|
if (hostId !== activeAvailabilityHostId) {
|
|
24893
25612
|
publishConnectionStatus();
|
|
24894
25613
|
return;
|
|
@@ -24993,7 +25712,8 @@ ${error51.stderrTail}`] : []
|
|
|
24993
25712
|
agents: externalAgents.map((agent) => ({
|
|
24994
25713
|
agent,
|
|
24995
25714
|
availability: state.availability[agent] ?? "checking",
|
|
24996
|
-
error: state.errors[agent] ?? null
|
|
25715
|
+
error: state.errors[agent] ?? null,
|
|
25716
|
+
...state.webUi[agent] ? { webUiAvailable: true } : {}
|
|
24997
25717
|
}))
|
|
24998
25718
|
};
|
|
24999
25719
|
})
|
|
@@ -25005,6 +25725,21 @@ ${error51.stderrTail}`] : []
|
|
|
25005
25725
|
(hostId) => refreshHarnessAvailabilityForHost(hostId, true, false, true)
|
|
25006
25726
|
);
|
|
25007
25727
|
},
|
|
25728
|
+
async openWebUi(hostId, agent) {
|
|
25729
|
+
const state = hostHarnessAvailabilityState(hostId);
|
|
25730
|
+
const client = hostId === "local" ? modelClientForHost(hostId) : null;
|
|
25731
|
+
if (state.availability[agent] !== "ready" || state.webUi[agent] !== true || !client?.openHarnessWebUi) {
|
|
25732
|
+
throw new Error("Harness Web UI is unavailable");
|
|
25733
|
+
}
|
|
25734
|
+
try {
|
|
25735
|
+
await client.openHarnessWebUi({ harnessId: externalHarnessIds[agent] });
|
|
25736
|
+
} catch (error51) {
|
|
25737
|
+
state.webUi = { ...state.webUi, [agent]: false };
|
|
25738
|
+
publishConnectionStatus();
|
|
25739
|
+
void refreshHarnessAvailabilityForHost(hostId, true, false, true).catch(() => void 0);
|
|
25740
|
+
throw error51;
|
|
25741
|
+
}
|
|
25742
|
+
},
|
|
25008
25743
|
subscribe(listener) {
|
|
25009
25744
|
connectionListeners.add(listener);
|
|
25010
25745
|
return () => connectionListeners.delete(listener);
|
|
@@ -25055,7 +25790,7 @@ ${error51.stderrTail}`] : []
|
|
|
25055
25790
|
},
|
|
25056
25791
|
(command) => {
|
|
25057
25792
|
const mounted2 = mountedByComposer.get(composer);
|
|
25058
|
-
if (mounted2)
|
|
25793
|
+
if (mounted2) selectCommand(mounted2, command);
|
|
25059
25794
|
}
|
|
25060
25795
|
);
|
|
25061
25796
|
const mounted = {
|
|
@@ -25453,6 +26188,7 @@ ${error51.stderrTail}`] : []
|
|
|
25453
26188
|
modelControl = null;
|
|
25454
26189
|
mutationObserver.disconnect();
|
|
25455
26190
|
sidebarAgentIcons.dispose();
|
|
26191
|
+
stopSidebarExternalPinning();
|
|
25456
26192
|
settingsLifecycle.dispose();
|
|
25457
26193
|
document.removeEventListener("beforeinput", onBeforeInput, true);
|
|
25458
26194
|
document.removeEventListener("submit", onSubmit, true);
|