@codexhost/cli-linux-x64 0.2.5 → 0.3.0-test.1
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 +4 -1
- package/THIRD_PARTY_NOTICES.txt +4 -0
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +59 -25
- package/app/host-runtime.mjs +7788 -1768
- package/app/renderer-extension.js +1487 -188
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/licenses/ws-LICENSE.txt +20 -0
- package/package.json +1 -1
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
#ownershipRequestGenerations = /* @__PURE__ */ new WeakMap();
|
|
37
37
|
#states = /* @__PURE__ */ new WeakMap();
|
|
38
38
|
#switching = /* @__PURE__ */ new Set();
|
|
39
|
+
#pendingSubmissions = /* @__PURE__ */ new Set();
|
|
39
40
|
#composerSequence = 0;
|
|
40
41
|
#modelRequestSequence = 0;
|
|
41
42
|
#ownershipRequestSequence = 0;
|
|
@@ -95,6 +96,7 @@
|
|
|
95
96
|
rebindConversation(composer, target) {
|
|
96
97
|
if (!isConversationTarget(target)) return null;
|
|
97
98
|
const previous = this.#state(composer);
|
|
99
|
+
this.#pendingSubmissions.delete(previous);
|
|
98
100
|
this.#modelRequestGenerations.set(previous, ++this.#modelRequestSequence);
|
|
99
101
|
this.#ownershipRequestGenerations.set(previous, ++this.#ownershipRequestSequence);
|
|
100
102
|
let state = this.#conversationState(target);
|
|
@@ -114,6 +116,7 @@
|
|
|
114
116
|
restore(composer, agent, model, thinkingOptionId, permissionModeId) {
|
|
115
117
|
if (!this.#enabledAgents.has(agent)) return null;
|
|
116
118
|
const state = this.#state(composer);
|
|
119
|
+
this.#pendingSubmissions.delete(state);
|
|
117
120
|
state.agent = agent;
|
|
118
121
|
state.phase = "locked";
|
|
119
122
|
if (agent === "pi" && model) state.piModel = model;
|
|
@@ -204,9 +207,21 @@
|
|
|
204
207
|
}
|
|
205
208
|
lock(composer) {
|
|
206
209
|
const state = this.#state(composer);
|
|
210
|
+
this.#pendingSubmissions.delete(state);
|
|
207
211
|
state.phase = "locked";
|
|
208
212
|
return state;
|
|
209
213
|
}
|
|
214
|
+
markSubmissionPending(composer) {
|
|
215
|
+
const state = this.#state(composer);
|
|
216
|
+
if (state.phase === "draft") this.#pendingSubmissions.add(state);
|
|
217
|
+
return state;
|
|
218
|
+
}
|
|
219
|
+
isSubmissionPending(composer) {
|
|
220
|
+
return this.#pendingSubmissions.has(this.#state(composer));
|
|
221
|
+
}
|
|
222
|
+
clearPendingSubmission(composer) {
|
|
223
|
+
this.#pendingSubmissions.delete(this.#state(composer));
|
|
224
|
+
}
|
|
210
225
|
recordSubmission(composer) {
|
|
211
226
|
const state = this.#state(composer);
|
|
212
227
|
this.#lastSubmittedAgent = state.agent;
|
|
@@ -224,6 +239,9 @@
|
|
|
224
239
|
if (isConversationTarget(target) && !bound) {
|
|
225
240
|
this.#conversationStates.push({ target, state });
|
|
226
241
|
}
|
|
242
|
+
if (isConversationTarget(target) && this.#pendingSubmissions.delete(state)) {
|
|
243
|
+
state.phase = "locked";
|
|
244
|
+
}
|
|
227
245
|
return true;
|
|
228
246
|
}
|
|
229
247
|
async switchAgent(composer, nextAgent, operations) {
|
|
@@ -231,6 +249,7 @@
|
|
|
231
249
|
if (!this.#enabledAgents.has(nextAgent)) return false;
|
|
232
250
|
if (state.phase !== "draft" || this.#switching.has(state)) return false;
|
|
233
251
|
if (state.agent === nextAgent) return true;
|
|
252
|
+
this.#pendingSubmissions.delete(state);
|
|
234
253
|
this.#switching.add(state);
|
|
235
254
|
try {
|
|
236
255
|
if (!operations.applyAgent(nextAgent)) return false;
|
|
@@ -14848,8 +14867,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14848
14867
|
code: external_exports.string().min(1),
|
|
14849
14868
|
message: external_exports.string().min(1),
|
|
14850
14869
|
retryable: external_exports.boolean(),
|
|
14851
|
-
diagnostic: external_exports.string().min(1).optional()
|
|
14852
|
-
|
|
14870
|
+
diagnostic: external_exports.string().min(1).optional(),
|
|
14871
|
+
stage: external_exports.string().min(1).optional(),
|
|
14872
|
+
durationMs: external_exports.number().int().nonnegative().optional(),
|
|
14873
|
+
stderrTail: external_exports.string().min(1).optional()
|
|
14874
|
+
}).superRefine(rejectExplicitUndefined(["diagnostic", "stage", "durationMs", "stderrTail"]));
|
|
14853
14875
|
|
|
14854
14876
|
// ../shared-contracts/dist/ids.js
|
|
14855
14877
|
var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
|
|
@@ -15194,6 +15216,47 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15194
15216
|
}
|
|
15195
15217
|
});
|
|
15196
15218
|
|
|
15219
|
+
// ../shared-contracts/dist/harness-commands.js
|
|
15220
|
+
var commandIdSchema = external_exports.string().trim().min(1).max(128).regex(/^[A-Za-z0-9._:-]+$/u).brand();
|
|
15221
|
+
var commandInvocationSchema = external_exports.string().min(1).max(128);
|
|
15222
|
+
var commandLabelSchema = external_exports.string().trim().min(1).max(128);
|
|
15223
|
+
var commandDescriptionSchema = external_exports.string().trim().min(1).max(512);
|
|
15224
|
+
var harnessCommandDescriptorSchema = external_exports.object({
|
|
15225
|
+
id: commandIdSchema,
|
|
15226
|
+
invocation: commandInvocationSchema,
|
|
15227
|
+
label: commandLabelSchema,
|
|
15228
|
+
description: commandDescriptionSchema.optional(),
|
|
15229
|
+
argumentMode: external_exports.enum(["none", "text"])
|
|
15230
|
+
}).strict();
|
|
15231
|
+
var harnessCommandCatalogSchema = external_exports.object({
|
|
15232
|
+
commands: external_exports.array(harnessCommandDescriptorSchema)
|
|
15233
|
+
}).strict().superRefine((catalog, context) => {
|
|
15234
|
+
const ids = /* @__PURE__ */ new Set();
|
|
15235
|
+
for (const [index, command] of catalog.commands.entries()) {
|
|
15236
|
+
if (ids.has(command.id)) {
|
|
15237
|
+
context.addIssue({
|
|
15238
|
+
code: "custom",
|
|
15239
|
+
message: "Harness command IDs must be unique",
|
|
15240
|
+
path: ["commands", index, "id"]
|
|
15241
|
+
});
|
|
15242
|
+
}
|
|
15243
|
+
ids.add(command.id);
|
|
15244
|
+
}
|
|
15245
|
+
});
|
|
15246
|
+
var threadCommandsInspectParamsSchema = external_exports.object({
|
|
15247
|
+
threadId: hostThreadIdSchema
|
|
15248
|
+
}).strict();
|
|
15249
|
+
var threadCommandExecuteParamsSchema = external_exports.object({
|
|
15250
|
+
threadId: hostThreadIdSchema,
|
|
15251
|
+
commandId: commandIdSchema,
|
|
15252
|
+
turnId: hostTurnIdSchema.optional(),
|
|
15253
|
+
arguments: jsonObjectSchema.optional()
|
|
15254
|
+
}).strict();
|
|
15255
|
+
var threadCommandExecuteResultSchema = external_exports.object({
|
|
15256
|
+
accepted: external_exports.literal(true),
|
|
15257
|
+
turnId: hostTurnIdSchema
|
|
15258
|
+
}).strict();
|
|
15259
|
+
|
|
15197
15260
|
// ../shared-contracts/dist/json-rpc.js
|
|
15198
15261
|
var jsonRpcVersionSchema = external_exports.literal("2.0").optional();
|
|
15199
15262
|
var absentSchema = external_exports.never().optional();
|
|
@@ -15405,6 +15468,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15405
15468
|
grok: "https://grok.com/"
|
|
15406
15469
|
};
|
|
15407
15470
|
var CONTROL_ATTRIBUTE = "data-codexhost-agent-control";
|
|
15471
|
+
var AGENT_MENU_WIDTH = 200;
|
|
15408
15472
|
function rendererAgentPickerView(state, adapterState, switching, agents, availability = {}) {
|
|
15409
15473
|
const optionDisabled = Object.fromEntries(
|
|
15410
15474
|
agents.map((agent) => [
|
|
@@ -15425,7 +15489,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15425
15489
|
}
|
|
15426
15490
|
function setMenuPosition(control) {
|
|
15427
15491
|
const rect = control.trigger.getBoundingClientRect();
|
|
15428
|
-
const width =
|
|
15492
|
+
const width = AGENT_MENU_WIDTH;
|
|
15429
15493
|
const left = Math.max(8, Math.min(rect.right - width, window.innerWidth - width - 8));
|
|
15430
15494
|
control.menu.style.left = `${left}px`;
|
|
15431
15495
|
control.menu.style.bottom = `${Math.max(8, window.innerHeight - rect.top + 6)}px`;
|
|
@@ -15495,13 +15559,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15495
15559
|
menu.hidden = typeof menu.showPopover !== "function";
|
|
15496
15560
|
menu.style.position = "fixed";
|
|
15497
15561
|
menu.style.inset = "auto";
|
|
15498
|
-
menu.style.width =
|
|
15562
|
+
menu.style.width = `${AGENT_MENU_WIDTH}px`;
|
|
15499
15563
|
menu.style.padding = "4px";
|
|
15500
15564
|
menu.style.border = "0";
|
|
15501
15565
|
menu.style.borderRadius = "6px";
|
|
15502
15566
|
menu.style.background = "Canvas";
|
|
15503
15567
|
menu.style.color = "CanvasText";
|
|
15504
15568
|
menu.style.boxShadow = "0 8px 24px rgba(0, 0, 0, 0.28)";
|
|
15569
|
+
menu.style.boxSizing = "border-box";
|
|
15570
|
+
menu.style.overflowX = "hidden";
|
|
15571
|
+
menu.style.overflowY = "auto";
|
|
15505
15572
|
menu.style.zIndex = "2147483647";
|
|
15506
15573
|
trigger.setAttribute("aria-controls", menu.id);
|
|
15507
15574
|
const options = {};
|
|
@@ -15533,6 +15600,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15533
15600
|
button.style.display = "flex";
|
|
15534
15601
|
button.style.alignItems = "center";
|
|
15535
15602
|
button.style.gap = "8px";
|
|
15603
|
+
button.style.minWidth = "0";
|
|
15536
15604
|
button.style.width = "100%";
|
|
15537
15605
|
button.style.flex = "1 1 auto";
|
|
15538
15606
|
button.style.height = "36px";
|
|
@@ -15556,8 +15624,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15556
15624
|
const check2 = document.createElement("span");
|
|
15557
15625
|
check2.textContent = "\u2713";
|
|
15558
15626
|
check2.setAttribute("aria-hidden", "true");
|
|
15559
|
-
check2.style.width = "
|
|
15627
|
+
check2.style.width = "24px";
|
|
15560
15628
|
check2.style.flex = "none";
|
|
15629
|
+
check2.style.textAlign = "center";
|
|
15561
15630
|
check2.style.visibility = "hidden";
|
|
15562
15631
|
const label = document.createElement("span");
|
|
15563
15632
|
label.textContent = RENDERER_AGENT_LABELS[agent];
|
|
@@ -15566,7 +15635,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15566
15635
|
label.style.overflow = "hidden";
|
|
15567
15636
|
label.style.textOverflow = "ellipsis";
|
|
15568
15637
|
label.style.whiteSpace = "nowrap";
|
|
15569
|
-
button.append(
|
|
15638
|
+
button.append(createRendererAgentIcon(agent), label);
|
|
15570
15639
|
button.addEventListener("click", () => {
|
|
15571
15640
|
const selected = button.getAttribute("aria-pressed") === "true";
|
|
15572
15641
|
close();
|
|
@@ -15576,9 +15645,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15576
15645
|
const download = agent === "codex" ? null : (() => {
|
|
15577
15646
|
const control2 = document.createElement("button");
|
|
15578
15647
|
control2.type = "button";
|
|
15579
|
-
control2.textContent = "
|
|
15648
|
+
control2.textContent = "+";
|
|
15580
15649
|
control2.setAttribute("aria-label", `Install ${RENDERER_AGENT_LABELS[agent]}`);
|
|
15581
|
-
control2.title = `
|
|
15650
|
+
control2.title = `Install ${RENDERER_AGENT_LABELS[agent]}`;
|
|
15651
|
+
control2.style.position = "absolute";
|
|
15652
|
+
control2.style.inset = "0";
|
|
15582
15653
|
control2.style.display = "inline-flex";
|
|
15583
15654
|
control2.style.alignItems = "center";
|
|
15584
15655
|
control2.style.justifyContent = "center";
|
|
@@ -15591,7 +15662,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15591
15662
|
control2.style.background = "transparent";
|
|
15592
15663
|
control2.style.color = "inherit";
|
|
15593
15664
|
control2.style.cursor = "pointer";
|
|
15594
|
-
control2.style.font = "600
|
|
15665
|
+
control2.style.font = "600 18px/1 system-ui, sans-serif";
|
|
15595
15666
|
control2.style.opacity = "0.72";
|
|
15596
15667
|
control2.addEventListener("pointerenter", () => {
|
|
15597
15668
|
if (!control2.disabled) control2.style.background = "rgba(127, 127, 127, 0.16)";
|
|
@@ -15606,16 +15677,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15606
15677
|
return control2;
|
|
15607
15678
|
})();
|
|
15608
15679
|
options[agent] = { button, check: check2, download };
|
|
15609
|
-
|
|
15610
|
-
|
|
15611
|
-
|
|
15612
|
-
|
|
15613
|
-
|
|
15614
|
-
|
|
15615
|
-
|
|
15616
|
-
|
|
15617
|
-
|
|
15618
|
-
|
|
15680
|
+
const row = document.createElement("div");
|
|
15681
|
+
row.style.display = "flex";
|
|
15682
|
+
row.style.alignItems = "center";
|
|
15683
|
+
row.style.gap = "2px";
|
|
15684
|
+
const actionSlot = document.createElement("span");
|
|
15685
|
+
actionSlot.style.position = "relative";
|
|
15686
|
+
actionSlot.style.display = "inline-block";
|
|
15687
|
+
actionSlot.style.width = "24px";
|
|
15688
|
+
actionSlot.style.height = "24px";
|
|
15689
|
+
actionSlot.style.flex = "none";
|
|
15690
|
+
actionSlot.append(check2);
|
|
15691
|
+
if (download) actionSlot.append(download);
|
|
15692
|
+
row.append(actionSlot, button);
|
|
15693
|
+
menu.append(row);
|
|
15619
15694
|
}
|
|
15620
15695
|
root.append(trigger, menu);
|
|
15621
15696
|
const onTriggerClick = () => {
|
|
@@ -15716,30 +15791,138 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15716
15791
|
option.check.style.visibility = selected ? "visible" : "hidden";
|
|
15717
15792
|
if (option.download) {
|
|
15718
15793
|
const visible = view.downloadVisible[agent] === true;
|
|
15719
|
-
option.download.hidden =
|
|
15794
|
+
option.download.hidden = false;
|
|
15720
15795
|
option.download.disabled = !visible;
|
|
15721
|
-
option.download.
|
|
15796
|
+
option.download.setAttribute("aria-hidden", String(!visible));
|
|
15797
|
+
option.download.style.display = "inline-flex";
|
|
15798
|
+
option.download.style.visibility = visible ? "visible" : "hidden";
|
|
15799
|
+
option.download.style.pointerEvents = visible ? "auto" : "none";
|
|
15722
15800
|
}
|
|
15723
15801
|
}
|
|
15724
15802
|
return view;
|
|
15725
15803
|
}
|
|
15726
15804
|
|
|
15805
|
+
// src/renderer-model-picker-positioning.ts
|
|
15806
|
+
var MENU_GAP = 4;
|
|
15807
|
+
var MAIN_MENU_SIDE_OFFSET = 8;
|
|
15808
|
+
var COLLISION_PADDING = 8;
|
|
15809
|
+
var RENDERER_MODEL_PICKER_MAIN_MENU_WIDTH = 260;
|
|
15810
|
+
var RENDERER_MODEL_PICKER_MODEL_MENU_WIDTH = 280;
|
|
15811
|
+
var RENDERER_MODEL_PICKER_MODEL_MENU_MAX_HEIGHT = 360;
|
|
15812
|
+
function clampPosition(value, minimum, maximum) {
|
|
15813
|
+
return Math.min(Math.max(value, minimum), Math.max(minimum, maximum));
|
|
15814
|
+
}
|
|
15815
|
+
function fitWidth(preferredWidth, viewportWidth) {
|
|
15816
|
+
return Math.max(
|
|
15817
|
+
COLLISION_PADDING,
|
|
15818
|
+
Math.min(preferredWidth, viewportWidth - COLLISION_PADDING * 2)
|
|
15819
|
+
);
|
|
15820
|
+
}
|
|
15821
|
+
function fitHeight(viewport, top = COLLISION_PADDING) {
|
|
15822
|
+
return Math.max(
|
|
15823
|
+
COLLISION_PADDING,
|
|
15824
|
+
Math.min(
|
|
15825
|
+
RENDERER_MODEL_PICKER_MODEL_MENU_MAX_HEIGHT,
|
|
15826
|
+
viewport.height * 0.6,
|
|
15827
|
+
viewport.height - top - COLLISION_PADDING
|
|
15828
|
+
)
|
|
15829
|
+
);
|
|
15830
|
+
}
|
|
15831
|
+
function rendererModelPickerMainMenuPlacement(triggerRect, viewport, width = RENDERER_MODEL_PICKER_MAIN_MENU_WIDTH) {
|
|
15832
|
+
const maxLeft = viewport.width - COLLISION_PADDING - width;
|
|
15833
|
+
return {
|
|
15834
|
+
left: clampPosition(triggerRect.right - width, COLLISION_PADDING, maxLeft),
|
|
15835
|
+
width,
|
|
15836
|
+
bottom: Math.max(COLLISION_PADDING, viewport.height - triggerRect.top + MAIN_MENU_SIDE_OFFSET)
|
|
15837
|
+
};
|
|
15838
|
+
}
|
|
15839
|
+
function rendererModelPickerStandaloneModelMenuPlacement(triggerRect, viewport) {
|
|
15840
|
+
const width = fitWidth(RENDERER_MODEL_PICKER_MODEL_MENU_WIDTH, viewport.width);
|
|
15841
|
+
const maxLeft = viewport.width - COLLISION_PADDING - width;
|
|
15842
|
+
return {
|
|
15843
|
+
left: clampPosition(triggerRect.right - width, COLLISION_PADDING, maxLeft),
|
|
15844
|
+
width,
|
|
15845
|
+
maxHeight: fitHeight(viewport),
|
|
15846
|
+
bottom: Math.max(COLLISION_PADDING, viewport.height - triggerRect.top + MAIN_MENU_SIDE_OFFSET)
|
|
15847
|
+
};
|
|
15848
|
+
}
|
|
15849
|
+
function rendererModelPickerModelMenuPlacement(mainRect, viewport) {
|
|
15850
|
+
const preferredWidth = fitWidth(RENDERER_MODEL_PICKER_MODEL_MENU_WIDTH, viewport.width);
|
|
15851
|
+
const rightLeft = mainRect.right + MENU_GAP;
|
|
15852
|
+
const leftLeft = mainRect.left - MENU_GAP - preferredWidth;
|
|
15853
|
+
const rightAvailable = viewport.width - rightLeft - COLLISION_PADDING;
|
|
15854
|
+
const leftAvailable = mainRect.left - MENU_GAP - COLLISION_PADDING;
|
|
15855
|
+
let width;
|
|
15856
|
+
let left;
|
|
15857
|
+
if (rightAvailable >= preferredWidth) {
|
|
15858
|
+
width = preferredWidth;
|
|
15859
|
+
left = rightLeft;
|
|
15860
|
+
} else if (leftAvailable >= preferredWidth) {
|
|
15861
|
+
width = preferredWidth;
|
|
15862
|
+
left = leftLeft;
|
|
15863
|
+
} else if (rightAvailable >= leftAvailable) {
|
|
15864
|
+
width = Math.max(COLLISION_PADDING, rightAvailable);
|
|
15865
|
+
left = rightLeft;
|
|
15866
|
+
} else {
|
|
15867
|
+
width = Math.max(COLLISION_PADDING, leftAvailable);
|
|
15868
|
+
left = mainRect.left - MENU_GAP - width;
|
|
15869
|
+
}
|
|
15870
|
+
const top = clampPosition(mainRect.top, COLLISION_PADDING, viewport.height - COLLISION_PADDING);
|
|
15871
|
+
const maxHeight = fitHeight(viewport, top);
|
|
15872
|
+
return {
|
|
15873
|
+
left: clampPosition(left, COLLISION_PADDING, viewport.width - COLLISION_PADDING - width),
|
|
15874
|
+
top,
|
|
15875
|
+
width,
|
|
15876
|
+
maxHeight
|
|
15877
|
+
};
|
|
15878
|
+
}
|
|
15879
|
+
|
|
15727
15880
|
// src/renderer-model-picker.ts
|
|
15728
15881
|
var RENDERER_MODEL_TRIGGER_FALLBACK_CLASSES = "border-token-border no-drag cursor-interaction items-center gap-1 border whitespace-nowrap select-none focus:outline-none disabled:cursor-not-allowed disabled:opacity-40 flex rounded-full text-token-text-tertiary enabled:hover:bg-token-list-hover-background enabled:active:bg-token-foreground/15 data-[state=open]:bg-token-list-hover-background border-transparent h-token-button-composer px-2 py-0 text-sm leading-[18px] min-w-0";
|
|
15729
15882
|
var MENU_CLASSES = "fixed z-50 overflow-hidden rounded-xl bg-token-dropdown-background/90 text-token-foreground shadow-lg backdrop-blur-xl";
|
|
15883
|
+
var SEARCH_INPUT_CLASSES = "mb-1 w-full shrink-0 rounded-lg border border-token-border bg-token-dropdown-background/95 px-2 py-1.5 text-sm text-token-foreground outline-none placeholder:text-token-text-tertiary disabled:cursor-not-allowed disabled:opacity-40";
|
|
15730
15884
|
var OPTION_CLASSES = "flex w-full cursor-interaction items-center gap-2 rounded-lg px-2 py-2 text-left text-sm text-token-foreground outline-none enabled:hover:bg-token-list-hover-background enabled:active:bg-token-foreground/15 disabled:cursor-not-allowed disabled:opacity-40";
|
|
15731
15885
|
var HEADING_CLASSES = "px-2 pb-1 pt-1.5 text-sm text-token-text-tertiary";
|
|
15732
|
-
var
|
|
15733
|
-
var
|
|
15734
|
-
var MODEL_MENU_PREFERRED_WIDTH = 320;
|
|
15735
|
-
var MODEL_MENU_MAX_WIDTH = 380;
|
|
15736
|
-
var MODEL_MENU_MAX_HEIGHT = 360;
|
|
15737
|
-
var MAIN_MENU_LEFT_OFFSET = 96;
|
|
15738
|
-
var MENU_GAP = 4;
|
|
15739
|
-
var VIEWPORT_MARGIN = 8;
|
|
15886
|
+
var MODEL_TRIGGER_MAX_WIDTH = "min(200px, 26vw)";
|
|
15887
|
+
var MODEL_SCROLLBAR_STYLE_ATTRIBUTE = "data-codexhost-model-picker-scrollbar";
|
|
15740
15888
|
function popoverOpen2(menu) {
|
|
15741
15889
|
return menu.matches(":popover-open");
|
|
15742
15890
|
}
|
|
15891
|
+
function ensureModelScrollbarStyle(ownerDocument) {
|
|
15892
|
+
if (ownerDocument.querySelector(`style[${MODEL_SCROLLBAR_STYLE_ATTRIBUTE}]`)) return;
|
|
15893
|
+
const style = ownerDocument.createElement("style");
|
|
15894
|
+
style.setAttribute(MODEL_SCROLLBAR_STYLE_ATTRIBUTE, "true");
|
|
15895
|
+
style.textContent = `
|
|
15896
|
+
[data-codexhost-model-scrollable] {
|
|
15897
|
+
scrollbar-width: thin;
|
|
15898
|
+
scrollbar-color: rgba(255, 255, 255, 0.28) transparent;
|
|
15899
|
+
}
|
|
15900
|
+
[data-codexhost-model-scrollable]::-webkit-scrollbar {
|
|
15901
|
+
width: 6px;
|
|
15902
|
+
height: 6px;
|
|
15903
|
+
}
|
|
15904
|
+
[data-codexhost-model-scrollable]::-webkit-scrollbar-track {
|
|
15905
|
+
background: transparent;
|
|
15906
|
+
}
|
|
15907
|
+
[data-codexhost-model-scrollable]::-webkit-scrollbar-thumb {
|
|
15908
|
+
min-height: 28px;
|
|
15909
|
+
border: 1px solid transparent;
|
|
15910
|
+
border-radius: 999px;
|
|
15911
|
+
background: rgba(255, 255, 255, 0.28);
|
|
15912
|
+
background-clip: padding-box;
|
|
15913
|
+
}
|
|
15914
|
+
[data-codexhost-model-scrollable]::-webkit-scrollbar-thumb:hover {
|
|
15915
|
+
background: rgba(255, 255, 255, 0.42);
|
|
15916
|
+
background-clip: padding-box;
|
|
15917
|
+
}
|
|
15918
|
+
[data-codexhost-model-scrollable]::-webkit-scrollbar-button {
|
|
15919
|
+
display: none;
|
|
15920
|
+
width: 0;
|
|
15921
|
+
height: 0;
|
|
15922
|
+
}
|
|
15923
|
+
`;
|
|
15924
|
+
(ownerDocument.head ?? ownerDocument.documentElement).append(style);
|
|
15925
|
+
}
|
|
15743
15926
|
function thinkingOptionsForModel(catalog, selected) {
|
|
15744
15927
|
const supported = catalog?.models.find(
|
|
15745
15928
|
(model) => model.ref.id === selected?.id
|
|
@@ -15753,6 +15936,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15753
15936
|
function shouldCloseRendererModelPicker(view) {
|
|
15754
15937
|
return isRendererModelPickerDisabled(view) && view.status !== "selecting";
|
|
15755
15938
|
}
|
|
15939
|
+
function isTransientPickerState(view) {
|
|
15940
|
+
return view.status === "idle" || view.status === "loading";
|
|
15941
|
+
}
|
|
15756
15942
|
function rendererModelPickerPresentation(view) {
|
|
15757
15943
|
const selectedModel = view.catalog?.models.find((model) => model.ref.id === view.selected?.id);
|
|
15758
15944
|
const thinkingOptions = view.thinkingSelectionSupported === false ? [] : thinkingOptionsForModel(view.catalog, view.selected);
|
|
@@ -15777,52 +15963,43 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15777
15963
|
}
|
|
15778
15964
|
function positionMainMenu(control) {
|
|
15779
15965
|
const triggerRect = control.trigger.getBoundingClientRect();
|
|
15780
|
-
const
|
|
15781
|
-
|
|
15782
|
-
|
|
15783
|
-
|
|
15966
|
+
const placement = rendererModelPickerMainMenuPlacement(
|
|
15967
|
+
triggerRect,
|
|
15968
|
+
{ width: window.innerWidth, height: window.innerHeight },
|
|
15969
|
+
RENDERER_MODEL_PICKER_MAIN_MENU_WIDTH
|
|
15784
15970
|
);
|
|
15785
|
-
|
|
15786
|
-
|
|
15787
|
-
|
|
15788
|
-
const left = Math.max(
|
|
15789
|
-
VIEWPORT_MARGIN,
|
|
15790
|
-
Math.min(preferredLeft, Math.max(rightReservedLeft, VIEWPORT_MARGIN), maxLeft)
|
|
15791
|
-
);
|
|
15792
|
-
control.menu.style.setProperty("width", `${width}px`, "important");
|
|
15793
|
-
control.menu.style.left = `${left}px`;
|
|
15794
|
-
control.menu.style.maxWidth = `${width}px`;
|
|
15971
|
+
control.menu.style.setProperty("width", `${placement.width}px`, "important");
|
|
15972
|
+
control.menu.style.left = `${placement.left}px`;
|
|
15973
|
+
control.menu.style.maxWidth = `${placement.width}px`;
|
|
15795
15974
|
control.menu.style.right = "auto";
|
|
15796
15975
|
control.menu.style.top = "auto";
|
|
15797
|
-
control.menu.style.bottom = `${
|
|
15798
|
-
|
|
15799
|
-
|
|
15800
|
-
)
|
|
15801
|
-
|
|
15802
|
-
|
|
15803
|
-
|
|
15804
|
-
const
|
|
15805
|
-
const
|
|
15806
|
-
|
|
15807
|
-
|
|
15808
|
-
|
|
15809
|
-
|
|
15810
|
-
|
|
15811
|
-
|
|
15812
|
-
|
|
15813
|
-
|
|
15814
|
-
control.modelMenu.style.
|
|
15976
|
+
control.menu.style.bottom = `${placement.bottom}px`;
|
|
15977
|
+
}
|
|
15978
|
+
function positionAdvancedMenus(control) {
|
|
15979
|
+
positionMainMenu(control);
|
|
15980
|
+
positionModelMenu(control);
|
|
15981
|
+
}
|
|
15982
|
+
function positionModelMenu(control, standalone = false) {
|
|
15983
|
+
const anchorRect = standalone ? control.trigger.getBoundingClientRect() : control.menu.getBoundingClientRect();
|
|
15984
|
+
const placement = standalone ? rendererModelPickerStandaloneModelMenuPlacement(anchorRect, {
|
|
15985
|
+
width: window.innerWidth,
|
|
15986
|
+
height: window.innerHeight
|
|
15987
|
+
}) : rendererModelPickerModelMenuPlacement(anchorRect, {
|
|
15988
|
+
width: window.innerWidth,
|
|
15989
|
+
height: window.innerHeight
|
|
15990
|
+
});
|
|
15991
|
+
control.modelMenu.style.setProperty("width", `${placement.width}px`, "important");
|
|
15992
|
+
control.modelMenu.style.left = `${placement.left}px`;
|
|
15993
|
+
control.modelMenu.style.maxWidth = `${placement.width}px`;
|
|
15994
|
+
control.modelMenu.style.maxHeight = `${placement.maxHeight}px`;
|
|
15815
15995
|
control.modelMenu.style.right = "auto";
|
|
15816
|
-
control.modelMenu.style.top = "auto"
|
|
15817
|
-
control.modelMenu.style.bottom = `${
|
|
15818
|
-
VIEWPORT_MARGIN,
|
|
15819
|
-
window.innerHeight - mainRect.bottom
|
|
15820
|
-
)}px`;
|
|
15996
|
+
control.modelMenu.style.top = placement.top === void 0 ? "auto" : `${placement.top}px`;
|
|
15997
|
+
control.modelMenu.style.bottom = placement.bottom === void 0 ? "auto" : `${placement.bottom}px`;
|
|
15821
15998
|
}
|
|
15822
15999
|
function syncRendererModelTriggerClass(control, nativeClassName) {
|
|
15823
16000
|
control.trigger.className = nativeClassName?.trim() || RENDERER_MODEL_TRIGGER_FALLBACK_CLASSES;
|
|
15824
16001
|
control.trigger.style.width = "fit-content";
|
|
15825
|
-
control.trigger.style.maxWidth =
|
|
16002
|
+
control.trigger.style.maxWidth = MODEL_TRIGGER_MAX_WIDTH;
|
|
15826
16003
|
}
|
|
15827
16004
|
function createCheck() {
|
|
15828
16005
|
const check2 = document.createElement("span");
|
|
@@ -15845,6 +16022,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15845
16022
|
element.textContent = text;
|
|
15846
16023
|
return true;
|
|
15847
16024
|
}
|
|
16025
|
+
function applyModelSearchFilter(control) {
|
|
16026
|
+
const query = control.searchInput.value.trim().toLowerCase();
|
|
16027
|
+
let visibleCount = 0;
|
|
16028
|
+
for (const option of control.options.values()) {
|
|
16029
|
+
const matches = query.length === 0 || option.searchText.includes(query);
|
|
16030
|
+
option.button.hidden = !matches;
|
|
16031
|
+
if (matches) visibleCount += 1;
|
|
16032
|
+
}
|
|
16033
|
+
control.searchEmpty.hidden = query.length === 0 || visibleCount > 0;
|
|
16034
|
+
}
|
|
15848
16035
|
function mountRendererModelPicker(composerId, nativeClassName, onSelectModel, onSelectThinking) {
|
|
15849
16036
|
const root = document.createElement("div");
|
|
15850
16037
|
root.setAttribute("data-codexhost-model-control", composerId);
|
|
@@ -15874,7 +16061,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15874
16061
|
menu.id = `${composerId}-model-menu`;
|
|
15875
16062
|
menu.setAttribute("role", "menu");
|
|
15876
16063
|
menu.setAttribute("aria-label", "Model and Thinking");
|
|
15877
|
-
menu.setAttribute("popover", "
|
|
16064
|
+
menu.setAttribute("popover", "manual");
|
|
15878
16065
|
menu.className = MENU_CLASSES;
|
|
15879
16066
|
menu.style.position = "fixed";
|
|
15880
16067
|
menu.style.inset = "auto";
|
|
@@ -15895,52 +16082,115 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15895
16082
|
modelMenu.setAttribute("aria-label", "Model");
|
|
15896
16083
|
modelMenu.setAttribute("popover", "manual");
|
|
15897
16084
|
modelMenu.className = MENU_CLASSES;
|
|
16085
|
+
modelMenu.dataset.codexhostModelScrollable = "true";
|
|
16086
|
+
ensureModelScrollbarStyle(document);
|
|
15898
16087
|
modelMenu.style.position = "fixed";
|
|
15899
16088
|
modelMenu.style.inset = "auto";
|
|
15900
16089
|
modelMenu.style.margin = "0";
|
|
15901
16090
|
modelMenu.style.padding = "4px";
|
|
15902
16091
|
modelMenu.style.border = "0";
|
|
15903
|
-
modelMenu.style.maxHeight =
|
|
16092
|
+
modelMenu.style.maxHeight = `min(${RENDERER_MODEL_PICKER_MODEL_MENU_MAX_HEIGHT}px, 60vh)`;
|
|
15904
16093
|
modelMenu.style.overflowY = "auto";
|
|
15905
16094
|
modelButton.setAttribute("aria-controls", modelMenu.id);
|
|
15906
16095
|
const options = /* @__PURE__ */ new Map();
|
|
15907
16096
|
const thinkingOptions = /* @__PURE__ */ new Map();
|
|
16097
|
+
const searchInput = document.createElement("input");
|
|
16098
|
+
searchInput.type = "search";
|
|
16099
|
+
searchInput.placeholder = "Search models";
|
|
16100
|
+
searchInput.setAttribute("aria-label", "Search models");
|
|
16101
|
+
searchInput.autocomplete = "off";
|
|
16102
|
+
searchInput.spellcheck = false;
|
|
16103
|
+
searchInput.className = SEARCH_INPUT_CLASSES;
|
|
16104
|
+
const searchHeader = document.createElement("div");
|
|
16105
|
+
searchHeader.style.position = "sticky";
|
|
16106
|
+
searchHeader.style.top = "0";
|
|
16107
|
+
searchHeader.style.zIndex = "2";
|
|
16108
|
+
searchHeader.style.margin = "-4px";
|
|
16109
|
+
searchHeader.style.padding = "4px";
|
|
16110
|
+
searchHeader.style.backgroundColor = "Canvas";
|
|
16111
|
+
const searchEmpty = document.createElement("div");
|
|
16112
|
+
searchEmpty.dataset.codexhostModelSearchEmpty = "true";
|
|
16113
|
+
searchEmpty.textContent = "No matching models";
|
|
16114
|
+
searchEmpty.className = "block px-2 py-2 text-sm text-token-text-tertiary";
|
|
16115
|
+
searchEmpty.hidden = true;
|
|
16116
|
+
const onSearchInput = () => applyModelSearchFilter(control);
|
|
16117
|
+
searchInput.addEventListener("input", onSearchInput);
|
|
16118
|
+
const silencedEventTypes = [
|
|
16119
|
+
"keydown",
|
|
16120
|
+
"keypress",
|
|
16121
|
+
"keyup",
|
|
16122
|
+
"beforeinput",
|
|
16123
|
+
"input",
|
|
16124
|
+
"compositionstart",
|
|
16125
|
+
"compositionupdate",
|
|
16126
|
+
"compositionend",
|
|
16127
|
+
"change"
|
|
16128
|
+
];
|
|
16129
|
+
const silenceForHarness = (event) => {
|
|
16130
|
+
event.stopPropagation();
|
|
16131
|
+
};
|
|
16132
|
+
for (const type of silencedEventTypes) {
|
|
16133
|
+
searchInput.addEventListener(type, silenceForHarness);
|
|
16134
|
+
}
|
|
16135
|
+
const onSearchBlur = () => {
|
|
16136
|
+
if (!popoverOpen2(modelMenu)) return;
|
|
16137
|
+
const active = document.activeElement;
|
|
16138
|
+
const movedToComposer = active === document.body || active instanceof Element && (active.matches('textarea, [contenteditable="true"], [role="textbox"]') || active.closest('textarea, [contenteditable="true"], [role="textbox"]') !== null);
|
|
16139
|
+
if (!movedToComposer) return;
|
|
16140
|
+
requestAnimationFrame(() => {
|
|
16141
|
+
if (popoverOpen2(modelMenu) && searchInput.isConnected) searchInput.focus();
|
|
16142
|
+
});
|
|
16143
|
+
};
|
|
16144
|
+
searchInput.addEventListener("blur", onSearchBlur);
|
|
15908
16145
|
const closeModelMenu = () => {
|
|
15909
16146
|
if (popoverOpen2(modelMenu)) modelMenu.hidePopover();
|
|
15910
16147
|
modelButton.setAttribute("aria-expanded", "false");
|
|
16148
|
+
if (searchInput.value !== "") {
|
|
16149
|
+
searchInput.value = "";
|
|
16150
|
+
applyModelSearchFilter(control);
|
|
16151
|
+
}
|
|
15911
16152
|
};
|
|
16153
|
+
const pickerOpen = () => popoverOpen2(menu) || popoverOpen2(modelMenu);
|
|
15912
16154
|
const close = () => {
|
|
15913
16155
|
closeModelMenu();
|
|
15914
16156
|
if (popoverOpen2(menu)) menu.hidePopover();
|
|
15915
16157
|
};
|
|
15916
|
-
const openModelMenu = () => {
|
|
15917
|
-
if (!popoverOpen2(menu) || popoverOpen2(modelMenu)) return;
|
|
16158
|
+
const openModelMenu = (standalone = false) => {
|
|
16159
|
+
if (!standalone && !popoverOpen2(menu) || popoverOpen2(modelMenu)) return;
|
|
15918
16160
|
modelMenu.showPopover();
|
|
15919
|
-
positionModelMenu(control);
|
|
16161
|
+
positionModelMenu(control, standalone);
|
|
15920
16162
|
modelButton.setAttribute("aria-expanded", "true");
|
|
15921
16163
|
};
|
|
15922
16164
|
const open = () => {
|
|
15923
|
-
if (trigger.disabled ||
|
|
16165
|
+
if (trigger.disabled || pickerOpen()) return;
|
|
16166
|
+
if (control.thinkingOptions.size === 0) {
|
|
16167
|
+
openModelMenu(true);
|
|
16168
|
+
return;
|
|
16169
|
+
}
|
|
15924
16170
|
menu.showPopover();
|
|
15925
|
-
|
|
16171
|
+
positionAdvancedMenus(control);
|
|
15926
16172
|
};
|
|
15927
16173
|
const onTriggerClick = () => {
|
|
15928
|
-
if (
|
|
16174
|
+
if (pickerOpen()) close();
|
|
15929
16175
|
else open();
|
|
15930
16176
|
};
|
|
15931
16177
|
const onToggle = () => {
|
|
15932
16178
|
const openState = popoverOpen2(menu);
|
|
15933
|
-
trigger.setAttribute("aria-expanded", String(openState));
|
|
16179
|
+
trigger.setAttribute("aria-expanded", String(openState || popoverOpen2(modelMenu)));
|
|
15934
16180
|
trigger.setAttribute("data-state", openState ? "open" : "closed");
|
|
15935
16181
|
if (!openState) closeModelMenu();
|
|
15936
16182
|
};
|
|
15937
16183
|
const onModelToggle = () => {
|
|
15938
|
-
|
|
16184
|
+
const openState = popoverOpen2(modelMenu);
|
|
16185
|
+
modelButton.setAttribute("aria-expanded", String(openState));
|
|
16186
|
+
trigger.setAttribute("aria-expanded", String(openState || popoverOpen2(menu)));
|
|
16187
|
+
trigger.setAttribute("data-state", openState || popoverOpen2(menu) ? "open" : "closed");
|
|
15939
16188
|
};
|
|
15940
16189
|
const onRootClick = (event) => {
|
|
15941
16190
|
const target = event.target instanceof Element ? event.target.closest("button") : null;
|
|
15942
16191
|
if (target?.dataset.openModelMenu) {
|
|
15943
16192
|
openModelMenu();
|
|
16193
|
+
control.searchInput.focus();
|
|
15944
16194
|
return;
|
|
15945
16195
|
}
|
|
15946
16196
|
if (target?.dataset.thinkingOptionId) {
|
|
@@ -15952,25 +16202,44 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15952
16202
|
const onModelMenuClick = (event) => {
|
|
15953
16203
|
const target = event.target instanceof Element ? event.target.closest("button[data-model-id]") : null;
|
|
15954
16204
|
if (!target?.dataset.modelId) return;
|
|
15955
|
-
|
|
15956
|
-
|
|
16205
|
+
close();
|
|
16206
|
+
trigger.focus();
|
|
15957
16207
|
onSelectModel(target.dataset.modelId);
|
|
15958
16208
|
};
|
|
15959
16209
|
const onModelHover = () => openModelMenu();
|
|
16210
|
+
const onDocumentPointerDown = (event) => {
|
|
16211
|
+
if (!popoverOpen2(menu) && !popoverOpen2(modelMenu)) return;
|
|
16212
|
+
const target = event.target instanceof Node ? event.target : null;
|
|
16213
|
+
if (target && (root.contains(target) || menu.contains(target) || modelMenu.contains(target))) {
|
|
16214
|
+
return;
|
|
16215
|
+
}
|
|
16216
|
+
close();
|
|
16217
|
+
};
|
|
16218
|
+
const onDocumentKeyDown = (event) => {
|
|
16219
|
+
if (event.key !== "Escape") return;
|
|
16220
|
+
if (!popoverOpen2(menu) && !popoverOpen2(modelMenu)) return;
|
|
16221
|
+
event.preventDefault();
|
|
16222
|
+
close();
|
|
16223
|
+
trigger.focus();
|
|
16224
|
+
};
|
|
15960
16225
|
const onViewportChange = () => {
|
|
15961
|
-
if (popoverOpen2(menu))
|
|
15962
|
-
if (popoverOpen2(modelMenu)) positionModelMenu(control);
|
|
16226
|
+
if (popoverOpen2(menu)) positionAdvancedMenus(control);
|
|
16227
|
+
else if (popoverOpen2(modelMenu)) positionModelMenu(control, true);
|
|
15963
16228
|
};
|
|
15964
16229
|
trigger.addEventListener("click", onTriggerClick);
|
|
15965
16230
|
menu.addEventListener("toggle", onToggle);
|
|
15966
16231
|
modelMenu.addEventListener("toggle", onModelToggle);
|
|
15967
16232
|
modelButton.addEventListener("mouseenter", onModelHover);
|
|
15968
|
-
|
|
16233
|
+
menu.addEventListener("click", onRootClick);
|
|
15969
16234
|
modelMenu.addEventListener("click", onModelMenuClick);
|
|
16235
|
+
document.addEventListener("pointerdown", onDocumentPointerDown, true);
|
|
16236
|
+
document.addEventListener("keydown", onDocumentKeyDown, true);
|
|
15970
16237
|
window.addEventListener("resize", onViewportChange);
|
|
15971
16238
|
window.addEventListener("scroll", onViewportChange, true);
|
|
15972
|
-
root.append(trigger
|
|
15973
|
-
document.body.append(modelMenu);
|
|
16239
|
+
root.append(trigger);
|
|
16240
|
+
document.body.append(menu, modelMenu);
|
|
16241
|
+
searchHeader.append(searchInput);
|
|
16242
|
+
modelMenu.append(searchHeader, searchEmpty);
|
|
15974
16243
|
const control = {
|
|
15975
16244
|
root,
|
|
15976
16245
|
trigger,
|
|
@@ -15979,6 +16248,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15979
16248
|
menu,
|
|
15980
16249
|
modelMenu,
|
|
15981
16250
|
modelButton,
|
|
16251
|
+
searchInput,
|
|
16252
|
+
searchHeader,
|
|
16253
|
+
searchEmpty,
|
|
15982
16254
|
options,
|
|
15983
16255
|
thinkingOptions,
|
|
15984
16256
|
close,
|
|
@@ -15988,10 +16260,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15988
16260
|
menu.removeEventListener("toggle", onToggle);
|
|
15989
16261
|
modelMenu.removeEventListener("toggle", onModelToggle);
|
|
15990
16262
|
modelButton.removeEventListener("mouseenter", onModelHover);
|
|
15991
|
-
|
|
16263
|
+
menu.removeEventListener("click", onRootClick);
|
|
15992
16264
|
modelMenu.removeEventListener("click", onModelMenuClick);
|
|
16265
|
+
searchInput.removeEventListener("input", onSearchInput);
|
|
16266
|
+
for (const type of silencedEventTypes) {
|
|
16267
|
+
searchInput.removeEventListener(type, silenceForHarness);
|
|
16268
|
+
}
|
|
16269
|
+
searchInput.removeEventListener("blur", onSearchBlur);
|
|
16270
|
+
document.removeEventListener("pointerdown", onDocumentPointerDown, true);
|
|
16271
|
+
document.removeEventListener("keydown", onDocumentKeyDown, true);
|
|
15993
16272
|
window.removeEventListener("resize", onViewportChange);
|
|
15994
16273
|
window.removeEventListener("scroll", onViewportChange, true);
|
|
16274
|
+
menu.remove();
|
|
15995
16275
|
modelMenu.remove();
|
|
15996
16276
|
root.remove();
|
|
15997
16277
|
}
|
|
@@ -16004,7 +16284,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16004
16284
|
control.options.clear();
|
|
16005
16285
|
control.thinkingOptions.clear();
|
|
16006
16286
|
control.menu.replaceChildren();
|
|
16007
|
-
control.modelMenu.replaceChildren(
|
|
16287
|
+
control.modelMenu.replaceChildren(
|
|
16288
|
+
createHeading("Model"),
|
|
16289
|
+
control.searchHeader,
|
|
16290
|
+
control.searchEmpty
|
|
16291
|
+
);
|
|
16008
16292
|
if (presentation.showThinkingSection) {
|
|
16009
16293
|
control.menu.append(createHeading("Thinking"));
|
|
16010
16294
|
for (const option of presentation.thinkingOptions) {
|
|
@@ -16048,9 +16332,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16048
16332
|
text.title = model.label;
|
|
16049
16333
|
const check2 = createCheck();
|
|
16050
16334
|
button.append(text, check2);
|
|
16051
|
-
control.options.set(model.ref.id, {
|
|
16335
|
+
control.options.set(model.ref.id, {
|
|
16336
|
+
button,
|
|
16337
|
+
check: check2,
|
|
16338
|
+
searchText: `${model.label} ${model.ref.id}`.toLowerCase()
|
|
16339
|
+
});
|
|
16052
16340
|
control.modelMenu.append(button);
|
|
16053
16341
|
}
|
|
16342
|
+
applyModelSearchFilter(control);
|
|
16343
|
+
if (popoverOpen2(control.modelMenu)) control.searchInput.focus();
|
|
16054
16344
|
}
|
|
16055
16345
|
function renderRendererModelPicker(control, view, visible) {
|
|
16056
16346
|
control.root.style.display = visible ? "block" : "none";
|
|
@@ -16065,11 +16355,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16065
16355
|
showThinkingSection: presentation.showThinkingSection,
|
|
16066
16356
|
modelLabel: presentation.modelLabel
|
|
16067
16357
|
});
|
|
16068
|
-
|
|
16358
|
+
const keepOpenMenu = popoverOpen2(control.menu) && isTransientPickerState(view);
|
|
16359
|
+
if (control.root.dataset.catalogSignature !== catalogSignature && !keepOpenMenu) {
|
|
16069
16360
|
rebuildOptions(control, view);
|
|
16070
16361
|
control.root.dataset.catalogSignature = catalogSignature;
|
|
16071
16362
|
}
|
|
16072
16363
|
syncRendererLabelText(control.label, presentation.modelLabel);
|
|
16364
|
+
control.label.title = presentation.modelLabel;
|
|
16073
16365
|
const secondaryLabel = presentation.thinkingLabel ?? presentation.resolvedModelLabel;
|
|
16074
16366
|
syncRendererLabelText(control.thinkingLabel, secondaryLabel ?? "");
|
|
16075
16367
|
control.thinkingLabel.hidden = secondaryLabel === void 0;
|
|
@@ -16081,7 +16373,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16081
16373
|
String(view.status === "loading" || view.status === "selecting")
|
|
16082
16374
|
);
|
|
16083
16375
|
control.trigger.disabled = isRendererModelPickerDisabled(view);
|
|
16084
|
-
if (shouldCloseRendererModelPicker(view)) control.close();
|
|
16376
|
+
if (shouldCloseRendererModelPicker(view) && !keepOpenMenu) control.close();
|
|
16085
16377
|
control.modelButton.disabled = control.trigger.disabled;
|
|
16086
16378
|
for (const [modelId, option] of control.options) {
|
|
16087
16379
|
const selected = modelId === view.selected?.id;
|
|
@@ -16928,6 +17220,322 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16928
17220
|
return true;
|
|
16929
17221
|
}
|
|
16930
17222
|
|
|
17223
|
+
// src/renderer-harness-command-control.ts
|
|
17224
|
+
var CONTROL_ATTRIBUTE2 = "data-codexhost-harness-command-control";
|
|
17225
|
+
var MENU_ATTRIBUTE = "data-codexhost-harness-command-menu";
|
|
17226
|
+
var MENU_WIDTH = 320;
|
|
17227
|
+
var VIEWPORT_MARGIN = 8;
|
|
17228
|
+
var MENU_GAP2 = 8;
|
|
17229
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
17230
|
+
var COMMAND_ICON_PATHS = [
|
|
17231
|
+
"M409.6 377.6h204.8a32 32 0 0 1 32 32v204.8a32 32 0 0 1-32 32H409.6a32 32 0 0 1-32-32V409.6a32 32 0 0 1 32-32z m172.8 64h-140.8v140.8h140.8z",
|
|
17232
|
+
"M332.8 800a108.8 108.8 0 0 1 0-217.6h76.8a32 32 0 0 1 32 32v76.8a108.928 108.928 0 0 1-108.8 108.8z m0-153.6a44.8 44.8 0 1 0 44.8 44.8v-44.8zM409.6 441.6H332.8a108.8 108.8 0 1 1 108.8-108.8v76.8a32 32 0 0 1-32 32z m-76.8-153.6a44.8 44.8 0 0 0 0 89.6h44.8V332.8A44.842667 44.842667 0 0 0 332.8 288zM691.2 441.6h-76.8a32 32 0 0 1-32-32V332.8a108.8 108.8 0 1 1 108.8 108.8z m-44.8-64h44.8a44.8 44.8 0 1 0-44.8-44.8zM691.2 800a108.928 108.928 0 0 1-108.8-108.8v-76.8a32 32 0 0 1 32-32h76.8a108.8 108.8 0 0 1 0 217.6z m-44.8-153.6v44.8a44.8 44.8 0 1 0 44.8-44.8z",
|
|
17233
|
+
"M640 970.666667H384c-118.186667 0-198.272-25.002667-251.946667-78.72S53.333333 758.186667 53.333333 640V384c0-118.186667 25.002667-198.272 78.72-251.946667S265.813333 53.333333 384 53.333333h256c118.186667 0 198.272 25.002667 251.946667 78.72S970.666667 265.813333 970.666667 384v256c0 118.186667-25.002667 198.272-78.72 251.946667S758.186667 970.666667 640 970.666667z m-256-853.333334c-100.096 0-165.802667 19.2-206.72 59.946667S117.333333 283.904 117.333333 384v256c0 100.096 19.072 165.802667 59.946667 206.72S283.904 906.666667 384 906.666667h256c100.096 0 165.802667-19.072 206.72-59.946667S906.666667 740.096 906.666667 640V384c0-100.096-19.072-165.802667-59.946667-206.72S740.096 117.333333 640 117.333333z"
|
|
17234
|
+
];
|
|
17235
|
+
function commandIcon(ownerDocument) {
|
|
17236
|
+
const svg = ownerDocument.createElementNS(SVG_NS, "svg");
|
|
17237
|
+
svg.setAttribute("viewBox", "0 0 1024 1024");
|
|
17238
|
+
svg.setAttribute("width", "15");
|
|
17239
|
+
svg.setAttribute("height", "15");
|
|
17240
|
+
svg.setAttribute("fill", "currentColor");
|
|
17241
|
+
svg.setAttribute("aria-hidden", "true");
|
|
17242
|
+
for (const path of COMMAND_ICON_PATHS) {
|
|
17243
|
+
const element = ownerDocument.createElementNS(SVG_NS, "path");
|
|
17244
|
+
element.setAttribute("d", path);
|
|
17245
|
+
svg.append(element);
|
|
17246
|
+
}
|
|
17247
|
+
return svg;
|
|
17248
|
+
}
|
|
17249
|
+
function menuItem(ownerDocument, command, onSelect) {
|
|
17250
|
+
const item = ownerDocument.createElement("button");
|
|
17251
|
+
item.type = "button";
|
|
17252
|
+
item.setAttribute("role", "menuitem");
|
|
17253
|
+
item.setAttribute("data-command-id", command.id);
|
|
17254
|
+
item.setAttribute("aria-label", `${command.invocation} ${command.label}`);
|
|
17255
|
+
item.style.display = "flex";
|
|
17256
|
+
item.style.alignItems = "center";
|
|
17257
|
+
item.style.width = "100%";
|
|
17258
|
+
item.style.minHeight = "38px";
|
|
17259
|
+
item.style.gap = "8px";
|
|
17260
|
+
item.style.padding = "6px 8px";
|
|
17261
|
+
item.style.border = "0";
|
|
17262
|
+
item.style.borderRadius = "6px";
|
|
17263
|
+
item.style.background = "transparent";
|
|
17264
|
+
item.style.color = "inherit";
|
|
17265
|
+
item.style.textAlign = "left";
|
|
17266
|
+
item.style.cursor = "pointer";
|
|
17267
|
+
const updateHighlight = (active) => {
|
|
17268
|
+
item.style.background = active ? "rgba(127, 127, 127, 0.12)" : "transparent";
|
|
17269
|
+
};
|
|
17270
|
+
item.addEventListener("pointerenter", () => updateHighlight(true));
|
|
17271
|
+
item.addEventListener("pointerleave", () => updateHighlight(false));
|
|
17272
|
+
item.addEventListener("focus", () => updateHighlight(true));
|
|
17273
|
+
item.addEventListener("blur", () => updateHighlight(false));
|
|
17274
|
+
item.addEventListener("click", onSelect);
|
|
17275
|
+
const copy = ownerDocument.createElement("span");
|
|
17276
|
+
copy.style.display = "flex";
|
|
17277
|
+
copy.style.flexDirection = "column";
|
|
17278
|
+
copy.style.minWidth = "0";
|
|
17279
|
+
copy.style.flex = "1 1 auto";
|
|
17280
|
+
const title = ownerDocument.createElement("span");
|
|
17281
|
+
title.textContent = command.invocation;
|
|
17282
|
+
title.style.font = "600 13px/18px system-ui, sans-serif";
|
|
17283
|
+
title.style.whiteSpace = "nowrap";
|
|
17284
|
+
const description = ownerDocument.createElement("span");
|
|
17285
|
+
description.textContent = command.description ?? command.label;
|
|
17286
|
+
description.style.overflow = "hidden";
|
|
17287
|
+
description.style.color = "rgba(127, 127, 127, 0.9)";
|
|
17288
|
+
description.style.font = "400 11px/16px system-ui, sans-serif";
|
|
17289
|
+
description.style.textOverflow = "ellipsis";
|
|
17290
|
+
description.style.whiteSpace = "nowrap";
|
|
17291
|
+
const hint = ownerDocument.createElement("span");
|
|
17292
|
+
hint.textContent = command.argumentMode === "text" ? "Text" : "\u21B5";
|
|
17293
|
+
hint.style.flex = "0 0 auto";
|
|
17294
|
+
hint.style.color = "rgba(127, 127, 127, 0.75)";
|
|
17295
|
+
hint.style.font = "400 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace";
|
|
17296
|
+
copy.append(title, description);
|
|
17297
|
+
item.append(copy, hint);
|
|
17298
|
+
return item;
|
|
17299
|
+
}
|
|
17300
|
+
function clamp(value, minimum, maximum) {
|
|
17301
|
+
return Math.max(minimum, Math.min(value, maximum));
|
|
17302
|
+
}
|
|
17303
|
+
function setButtonClass(button) {
|
|
17304
|
+
button.style.display = "inline-flex";
|
|
17305
|
+
button.style.alignItems = "center";
|
|
17306
|
+
button.style.justifyContent = "center";
|
|
17307
|
+
button.style.gap = "0";
|
|
17308
|
+
button.style.width = "28px";
|
|
17309
|
+
button.style.height = "28px";
|
|
17310
|
+
button.style.padding = "0";
|
|
17311
|
+
button.style.border = "0";
|
|
17312
|
+
button.style.borderRadius = "8px";
|
|
17313
|
+
button.style.background = "transparent";
|
|
17314
|
+
button.style.color = "inherit";
|
|
17315
|
+
button.style.cursor = "pointer";
|
|
17316
|
+
button.style.whiteSpace = "nowrap";
|
|
17317
|
+
}
|
|
17318
|
+
function mountRendererHarnessCommandControl(parent, insertBefore, onCommandSelected) {
|
|
17319
|
+
const ownerDocument = parent.ownerDocument;
|
|
17320
|
+
const root = ownerDocument.createElement("div");
|
|
17321
|
+
root.setAttribute(CONTROL_ATTRIBUTE2, "true");
|
|
17322
|
+
root.style.display = "inline-flex";
|
|
17323
|
+
root.style.alignItems = "center";
|
|
17324
|
+
root.style.minWidth = "0";
|
|
17325
|
+
const trigger = ownerDocument.createElement("button");
|
|
17326
|
+
trigger.type = "button";
|
|
17327
|
+
trigger.setAttribute("aria-haspopup", "menu");
|
|
17328
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
17329
|
+
trigger.setAttribute("aria-label", "Harness commands");
|
|
17330
|
+
trigger.title = "Harness commands";
|
|
17331
|
+
setButtonClass(trigger);
|
|
17332
|
+
trigger.append(commandIcon(ownerDocument));
|
|
17333
|
+
root.append(trigger);
|
|
17334
|
+
const menu = ownerDocument.createElement("div");
|
|
17335
|
+
menu.setAttribute(MENU_ATTRIBUTE, "true");
|
|
17336
|
+
menu.setAttribute("role", "menu");
|
|
17337
|
+
menu.setAttribute("aria-label", "Harness commands");
|
|
17338
|
+
menu.hidden = true;
|
|
17339
|
+
menu.style.position = "fixed";
|
|
17340
|
+
menu.style.inset = "auto";
|
|
17341
|
+
menu.style.zIndex = "2147483647";
|
|
17342
|
+
menu.style.width = `${MENU_WIDTH}px`;
|
|
17343
|
+
menu.style.maxWidth = `calc(100vw - ${VIEWPORT_MARGIN * 2}px)`;
|
|
17344
|
+
menu.style.maxHeight = "min(360px, calc(100vh - 16px))";
|
|
17345
|
+
menu.style.overflowY = "auto";
|
|
17346
|
+
menu.style.padding = "4px";
|
|
17347
|
+
menu.style.border = "1px solid rgba(127, 127, 127, 0.24)";
|
|
17348
|
+
menu.style.borderRadius = "10px";
|
|
17349
|
+
menu.style.background = "Canvas";
|
|
17350
|
+
menu.style.color = "CanvasText";
|
|
17351
|
+
menu.style.boxShadow = "0 12px 32px rgba(0, 0, 0, 0.22)";
|
|
17352
|
+
ownerDocument.body.append(menu);
|
|
17353
|
+
if (insertBefore?.parentElement === parent) parent.insertBefore(root, insertBefore);
|
|
17354
|
+
else parent.append(root);
|
|
17355
|
+
let commands = [];
|
|
17356
|
+
let items = [];
|
|
17357
|
+
let activeIndex = 0;
|
|
17358
|
+
let executingCommandId = null;
|
|
17359
|
+
let triggerHovered = false;
|
|
17360
|
+
let disposed = false;
|
|
17361
|
+
const positionMenu2 = () => {
|
|
17362
|
+
const rect = trigger.getBoundingClientRect();
|
|
17363
|
+
const menuHeight = menu.getBoundingClientRect().height;
|
|
17364
|
+
const opensAbove = rect.top >= menuHeight + MENU_GAP2 + VIEWPORT_MARGIN;
|
|
17365
|
+
const left = clamp(
|
|
17366
|
+
rect.left,
|
|
17367
|
+
VIEWPORT_MARGIN,
|
|
17368
|
+
window.innerWidth - MENU_WIDTH - VIEWPORT_MARGIN
|
|
17369
|
+
);
|
|
17370
|
+
menu.style.left = `${left}px`;
|
|
17371
|
+
menu.style.top = opensAbove ? `${Math.max(VIEWPORT_MARGIN, rect.top - menuHeight - MENU_GAP2)}px` : `${Math.min(window.innerHeight - menuHeight - VIEWPORT_MARGIN, rect.bottom + MENU_GAP2)}px`;
|
|
17372
|
+
};
|
|
17373
|
+
const focusActive = () => {
|
|
17374
|
+
const item = items[activeIndex];
|
|
17375
|
+
if (!item || item.disabled) return;
|
|
17376
|
+
item.focus();
|
|
17377
|
+
item.scrollIntoView({ block: "nearest" });
|
|
17378
|
+
};
|
|
17379
|
+
const syncTriggerBackground = () => {
|
|
17380
|
+
trigger.style.background = !trigger.disabled && (triggerHovered || !menu.hidden) ? "rgba(127, 127, 127, 0.16)" : "transparent";
|
|
17381
|
+
};
|
|
17382
|
+
const close = () => {
|
|
17383
|
+
menu.hidden = true;
|
|
17384
|
+
trigger.setAttribute("aria-expanded", "false");
|
|
17385
|
+
syncTriggerBackground();
|
|
17386
|
+
};
|
|
17387
|
+
const open = (shouldFocus = true) => {
|
|
17388
|
+
if (commands.length === 0 || executingCommandId !== null) return;
|
|
17389
|
+
menu.hidden = false;
|
|
17390
|
+
positionMenu2();
|
|
17391
|
+
trigger.setAttribute("aria-expanded", "true");
|
|
17392
|
+
syncTriggerBackground();
|
|
17393
|
+
if (shouldFocus) queueMicrotask(focusActive);
|
|
17394
|
+
};
|
|
17395
|
+
let closeTimer = null;
|
|
17396
|
+
const cancelClose = () => {
|
|
17397
|
+
if (closeTimer === null) return;
|
|
17398
|
+
window.clearTimeout(closeTimer);
|
|
17399
|
+
closeTimer = null;
|
|
17400
|
+
};
|
|
17401
|
+
const scheduleClose = () => {
|
|
17402
|
+
cancelClose();
|
|
17403
|
+
closeTimer = window.setTimeout(() => {
|
|
17404
|
+
closeTimer = null;
|
|
17405
|
+
if (!trigger.matches(":hover") && !menu.matches(":hover")) close();
|
|
17406
|
+
}, 140);
|
|
17407
|
+
};
|
|
17408
|
+
const select = (command) => {
|
|
17409
|
+
close();
|
|
17410
|
+
onCommandSelected(command);
|
|
17411
|
+
};
|
|
17412
|
+
const renderItems = () => {
|
|
17413
|
+
menu.replaceChildren();
|
|
17414
|
+
const header = ownerDocument.createElement("div");
|
|
17415
|
+
header.textContent = "Commands";
|
|
17416
|
+
header.style.padding = "5px 8px 4px";
|
|
17417
|
+
header.style.color = "rgba(127, 127, 127, 0.75)";
|
|
17418
|
+
header.style.font = "600 11px/16px system-ui, sans-serif";
|
|
17419
|
+
menu.append(header);
|
|
17420
|
+
items = commands.map((command) => menuItem(ownerDocument, command, () => select(command)));
|
|
17421
|
+
menu.append(...items);
|
|
17422
|
+
activeIndex = Math.min(activeIndex, Math.max(0, items.length - 1));
|
|
17423
|
+
if (executingCommandId !== null) {
|
|
17424
|
+
for (const item of items) {
|
|
17425
|
+
const isExecuting = item.dataset.commandId === executingCommandId;
|
|
17426
|
+
item.disabled = true;
|
|
17427
|
+
item.style.opacity = isExecuting ? "1" : "0.5";
|
|
17428
|
+
if (isExecuting) item.setAttribute("aria-busy", "true");
|
|
17429
|
+
}
|
|
17430
|
+
}
|
|
17431
|
+
};
|
|
17432
|
+
const onTriggerKeyDown = (event) => {
|
|
17433
|
+
if (event.key === "ArrowDown" || event.key === "Enter" || event.key === " ") {
|
|
17434
|
+
event.preventDefault();
|
|
17435
|
+
open();
|
|
17436
|
+
}
|
|
17437
|
+
};
|
|
17438
|
+
const onMenuKeyDown = (event) => {
|
|
17439
|
+
if (event.key === "Escape") {
|
|
17440
|
+
event.preventDefault();
|
|
17441
|
+
close();
|
|
17442
|
+
trigger.focus();
|
|
17443
|
+
return;
|
|
17444
|
+
}
|
|
17445
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
17446
|
+
event.preventDefault();
|
|
17447
|
+
const delta = event.key === "ArrowDown" ? 1 : -1;
|
|
17448
|
+
activeIndex = (activeIndex + delta + items.length) % items.length;
|
|
17449
|
+
focusActive();
|
|
17450
|
+
return;
|
|
17451
|
+
}
|
|
17452
|
+
if (event.key === "Enter") {
|
|
17453
|
+
event.preventDefault();
|
|
17454
|
+
items[activeIndex]?.click();
|
|
17455
|
+
}
|
|
17456
|
+
};
|
|
17457
|
+
const onDocumentPointerDown = (event) => {
|
|
17458
|
+
if (!menu.hidden && !root.contains(event.target) && !menu.contains(event.target)) {
|
|
17459
|
+
close();
|
|
17460
|
+
}
|
|
17461
|
+
};
|
|
17462
|
+
const onViewportChange = () => {
|
|
17463
|
+
if (!menu.hidden) positionMenu2();
|
|
17464
|
+
};
|
|
17465
|
+
trigger.addEventListener("click", () => {
|
|
17466
|
+
cancelClose();
|
|
17467
|
+
open(true);
|
|
17468
|
+
});
|
|
17469
|
+
trigger.addEventListener("pointerenter", () => {
|
|
17470
|
+
triggerHovered = true;
|
|
17471
|
+
syncTriggerBackground();
|
|
17472
|
+
cancelClose();
|
|
17473
|
+
if (menu.hidden) open(false);
|
|
17474
|
+
});
|
|
17475
|
+
trigger.addEventListener("pointerleave", () => {
|
|
17476
|
+
triggerHovered = false;
|
|
17477
|
+
syncTriggerBackground();
|
|
17478
|
+
scheduleClose();
|
|
17479
|
+
});
|
|
17480
|
+
trigger.addEventListener("keydown", onTriggerKeyDown);
|
|
17481
|
+
menu.addEventListener("pointerenter", cancelClose);
|
|
17482
|
+
menu.addEventListener("pointerleave", scheduleClose);
|
|
17483
|
+
menu.addEventListener("keydown", onMenuKeyDown);
|
|
17484
|
+
ownerDocument.addEventListener("pointerdown", onDocumentPointerDown, true);
|
|
17485
|
+
ownerDocument.defaultView?.addEventListener("resize", onViewportChange);
|
|
17486
|
+
ownerDocument.defaultView?.addEventListener("scroll", onViewportChange, true);
|
|
17487
|
+
const control = {
|
|
17488
|
+
root,
|
|
17489
|
+
trigger,
|
|
17490
|
+
menu,
|
|
17491
|
+
placeBefore(reference) {
|
|
17492
|
+
if (!reference?.parentElement) return false;
|
|
17493
|
+
if (root.parentElement === reference.parentElement && root.nextElementSibling === reference) {
|
|
17494
|
+
return true;
|
|
17495
|
+
}
|
|
17496
|
+
reference.parentElement.insertBefore(root, reference);
|
|
17497
|
+
return true;
|
|
17498
|
+
},
|
|
17499
|
+
setCommands(nextCommands) {
|
|
17500
|
+
commands = [...nextCommands];
|
|
17501
|
+
root.hidden = commands.length === 0;
|
|
17502
|
+
if (commands.length === 0) close();
|
|
17503
|
+
renderItems();
|
|
17504
|
+
},
|
|
17505
|
+
setExecuting(commandId) {
|
|
17506
|
+
executingCommandId = commandId;
|
|
17507
|
+
for (const item of items) {
|
|
17508
|
+
const isExecuting = item.dataset.commandId === commandId;
|
|
17509
|
+
item.disabled = commandId !== null;
|
|
17510
|
+
item.style.opacity = commandId !== null && !isExecuting ? "0.5" : "1";
|
|
17511
|
+
if (isExecuting) item.setAttribute("aria-busy", "true");
|
|
17512
|
+
else item.removeAttribute("aria-busy");
|
|
17513
|
+
}
|
|
17514
|
+
trigger.disabled = commandId !== null;
|
|
17515
|
+
trigger.style.opacity = commandId !== null ? "0.65" : "1";
|
|
17516
|
+
syncTriggerBackground();
|
|
17517
|
+
},
|
|
17518
|
+
close,
|
|
17519
|
+
dispose() {
|
|
17520
|
+
if (disposed) return;
|
|
17521
|
+
disposed = true;
|
|
17522
|
+
cancelClose();
|
|
17523
|
+
close();
|
|
17524
|
+
ownerDocument.removeEventListener("pointerdown", onDocumentPointerDown, true);
|
|
17525
|
+
ownerDocument.defaultView?.removeEventListener("resize", onViewportChange);
|
|
17526
|
+
ownerDocument.defaultView?.removeEventListener("scroll", onViewportChange, true);
|
|
17527
|
+
trigger.removeEventListener("keydown", onTriggerKeyDown);
|
|
17528
|
+
menu.removeEventListener("pointerenter", cancelClose);
|
|
17529
|
+
menu.removeEventListener("pointerleave", scheduleClose);
|
|
17530
|
+
menu.removeEventListener("keydown", onMenuKeyDown);
|
|
17531
|
+
menu.remove();
|
|
17532
|
+
root.remove();
|
|
17533
|
+
}
|
|
17534
|
+
};
|
|
17535
|
+
root.hidden = true;
|
|
17536
|
+
return control;
|
|
17537
|
+
}
|
|
17538
|
+
|
|
16931
17539
|
// src/renderer-composer-dom.ts
|
|
16932
17540
|
var CODEX_COMPOSER_SELECTOR = "[data-codex-composer-root]";
|
|
16933
17541
|
var EDITOR_SELECTOR = 'textarea, [contenteditable="true"], [role="textbox"]';
|
|
@@ -16935,23 +17543,86 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16935
17543
|
if (target instanceof Element) return target;
|
|
16936
17544
|
return target instanceof Node ? target.parentElement : null;
|
|
16937
17545
|
}
|
|
17546
|
+
function controlDescription(element) {
|
|
17547
|
+
const typed = element;
|
|
17548
|
+
const read = (name) => typeof element.getAttribute === "function" ? element.getAttribute(name) : null;
|
|
17549
|
+
return [typed.type, read("aria-label"), read("title"), read("data-testid")].filter((value) => typeof value === "string").join(" ").toLowerCase();
|
|
17550
|
+
}
|
|
16938
17551
|
function buttonText(button) {
|
|
16939
|
-
return
|
|
16940
|
-
|
|
16941
|
-
|
|
16942
|
-
|
|
16943
|
-
button.getAttribute("data-testid")
|
|
16944
|
-
].filter((value) => typeof value === "string").join(" ").toLowerCase();
|
|
17552
|
+
return controlDescription(button);
|
|
17553
|
+
}
|
|
17554
|
+
function isOwnedRendererControl(element) {
|
|
17555
|
+
return element.hasAttribute(CONTROL_ATTRIBUTE) || element.hasAttribute("data-codexhost-model-control") || element.hasAttribute("data-codexhost-permission-mode-control") || element.hasAttribute("data-codexhost-usage-control") || element.hasAttribute("data-codexhost-credits-control") || element.hasAttribute("data-codexhost-harness-command-control");
|
|
16945
17556
|
}
|
|
16946
17557
|
function isComposerSubmitButton(button) {
|
|
16947
17558
|
if (button.type === "submit") return true;
|
|
16948
17559
|
return /(^|\s)(send|submit|发送|提交)(\s|$)/u.test(buttonText(button));
|
|
16949
17560
|
}
|
|
17561
|
+
var VOICE_CONTROL_PATTERN = /(dictat|microphone|speech(?:[-_\s]?to[-_\s]?text)?|voice[-_\s]?input|(^|\s)voice(\s|$)|composer[-_](?:speech|dictat|mic)|语音|听写|麦克风|pause|暂停|stop recording|stop dictation|停止录音|停止听写|(^|\s)stop(\s|$))/iu;
|
|
17562
|
+
var CANCEL_CONTROL_PATTERN = /(cancel|discard|close|dismiss|取消|关闭|丢弃)/iu;
|
|
17563
|
+
var ATTACH_CONTROL_PATTERN = /(add files|attach files|attach file|attachment|composer[-_]attach|添加文件|附件)/iu;
|
|
17564
|
+
var TRAILING_ACTION_WALK_DEPTH = 3;
|
|
17565
|
+
function isComposerCancelButton(element) {
|
|
17566
|
+
if (isOwnedRendererControl(element)) return false;
|
|
17567
|
+
return CANCEL_CONTROL_PATTERN.test(controlDescription(element));
|
|
17568
|
+
}
|
|
17569
|
+
function isComposerVoiceButton(element) {
|
|
17570
|
+
if (isOwnedRendererControl(element) || isComposerCancelButton(element)) return false;
|
|
17571
|
+
const description = controlDescription(element);
|
|
17572
|
+
if (/(^|\s)(send|submit|发送|提交)(\s|$)/u.test(description)) return false;
|
|
17573
|
+
return VOICE_CONTROL_PATTERN.test(description);
|
|
17574
|
+
}
|
|
17575
|
+
function isComposerAttachButton(element) {
|
|
17576
|
+
if (isOwnedRendererControl(element)) return false;
|
|
17577
|
+
return ATTACH_CONTROL_PATTERN.test(controlDescription(element));
|
|
17578
|
+
}
|
|
17579
|
+
function isComposerTrailingActionButton(element) {
|
|
17580
|
+
return isComposerVoiceButton(element) || isComposerSubmitButton(element);
|
|
17581
|
+
}
|
|
17582
|
+
function isTrailingActionNode(element) {
|
|
17583
|
+
if (isComposerCancelButton(element)) return false;
|
|
17584
|
+
if (isComposerTrailingActionButton(element)) return true;
|
|
17585
|
+
if (typeof element.querySelectorAll !== "function") return false;
|
|
17586
|
+
const buttons = [...element.querySelectorAll("button")];
|
|
17587
|
+
return buttons.length > 0 && buttons.every((button) => isComposerTrailingActionButton(button));
|
|
17588
|
+
}
|
|
17589
|
+
function attachControlWithin(root) {
|
|
17590
|
+
if (isComposerAttachButton(root)) return root;
|
|
17591
|
+
if (typeof root.querySelectorAll !== "function") return null;
|
|
17592
|
+
const matches = [
|
|
17593
|
+
...root.querySelectorAll("button, [aria-label], [title], [data-testid]")
|
|
17594
|
+
].filter(isComposerAttachButton);
|
|
17595
|
+
return matches.length === 1 ? matches[0] ?? null : null;
|
|
17596
|
+
}
|
|
16950
17597
|
function sendButtonWithin(root) {
|
|
16951
17598
|
return [...root.querySelectorAll("button")].find(
|
|
16952
17599
|
(button) => isComposerSubmitButton(button)
|
|
16953
17600
|
) ?? null;
|
|
16954
17601
|
}
|
|
17602
|
+
function leftmostTrailingSibling(container, before) {
|
|
17603
|
+
for (const child of container.children) {
|
|
17604
|
+
if (child === before) break;
|
|
17605
|
+
if (typeof child.hasAttribute !== "function") continue;
|
|
17606
|
+
const element = child;
|
|
17607
|
+
if (isOwnedRendererControl(element) || isComposerCancelButton(element)) continue;
|
|
17608
|
+
if (isTrailingActionNode(element)) return element;
|
|
17609
|
+
}
|
|
17610
|
+
return null;
|
|
17611
|
+
}
|
|
17612
|
+
function trailingActionAnchor(sendButton) {
|
|
17613
|
+
let container = sendButton.parentElement;
|
|
17614
|
+
let before = sendButton;
|
|
17615
|
+
for (let depth = 0; container && depth < TRAILING_ACTION_WALK_DEPTH; depth += 1) {
|
|
17616
|
+
if (typeof container.matches === "function" && container.matches(CODEX_COMPOSER_SELECTOR)) {
|
|
17617
|
+
break;
|
|
17618
|
+
}
|
|
17619
|
+
const candidate = leftmostTrailingSibling(container, before);
|
|
17620
|
+
if (candidate) return candidate;
|
|
17621
|
+
before = container;
|
|
17622
|
+
container = container.parentElement;
|
|
17623
|
+
}
|
|
17624
|
+
return sendButton;
|
|
17625
|
+
}
|
|
16955
17626
|
function editorForElement(element) {
|
|
16956
17627
|
return element.matches(EDITOR_SELECTOR) ? element : element.closest(EDITOR_SELECTOR);
|
|
16957
17628
|
}
|
|
@@ -17097,7 +17768,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17097
17768
|
for (const child of parent.children) {
|
|
17098
17769
|
if (typeof child.hasAttribute !== "function") continue;
|
|
17099
17770
|
const element = child;
|
|
17100
|
-
if (element.hasAttribute("data-codexhost-credits-control"))
|
|
17771
|
+
if (element.hasAttribute("data-codexhost-credits-control") || element.hasAttribute("data-codexhost-harness-command-control") || isTrailingActionNode(element)) {
|
|
17772
|
+
continue;
|
|
17773
|
+
}
|
|
17101
17774
|
return element;
|
|
17102
17775
|
}
|
|
17103
17776
|
return null;
|
|
@@ -17108,12 +17781,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17108
17781
|
const parent = current.parentElement;
|
|
17109
17782
|
if (!parent) break;
|
|
17110
17783
|
const first = firstMaterialChild(parent);
|
|
17111
|
-
if (first && first !== current && !first.contains(usageRoot))
|
|
17784
|
+
if (first && first !== current && !first.contains(usageRoot)) {
|
|
17785
|
+
return attachControlWithin(first) ?? first;
|
|
17786
|
+
}
|
|
17112
17787
|
if (parent === composer) break;
|
|
17113
17788
|
current = parent;
|
|
17114
17789
|
}
|
|
17115
17790
|
return null;
|
|
17116
17791
|
}
|
|
17792
|
+
function refreshTrailingClusterPlacement(control) {
|
|
17793
|
+
const sendButton = control.sendButton;
|
|
17794
|
+
const modelRoot = control.modelPicker?.root;
|
|
17795
|
+
const agentRoot = control.root ?? control.picker?.root;
|
|
17796
|
+
if (!sendButton || !modelRoot || !agentRoot) return;
|
|
17797
|
+
const anchor = trailingActionAnchor(sendButton);
|
|
17798
|
+
const parent = anchor.parentElement;
|
|
17799
|
+
if (!parent || typeof parent.insertBefore !== "function") return;
|
|
17800
|
+
if (modelRoot.parentElement === parent && agentRoot.parentElement === parent && modelRoot.nextElementSibling === agentRoot && agentRoot.nextElementSibling === anchor) {
|
|
17801
|
+
return;
|
|
17802
|
+
}
|
|
17803
|
+
parent.insertBefore(modelRoot, anchor);
|
|
17804
|
+
parent.insertBefore(agentRoot, anchor);
|
|
17805
|
+
}
|
|
17117
17806
|
function refreshUsagePlacement(control) {
|
|
17118
17807
|
const anchor = usagePlacementAnchor(control);
|
|
17119
17808
|
if (!anchor) {
|
|
@@ -17123,7 +17812,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17123
17812
|
control.credits.anchor = null;
|
|
17124
17813
|
return;
|
|
17125
17814
|
}
|
|
17815
|
+
const previousUsageParent = control.usage.root.parentElement;
|
|
17816
|
+
const previousUsageNextSibling = control.usage.root.nextElementSibling;
|
|
17126
17817
|
control.usage.place(anchor);
|
|
17818
|
+
const usagePositionChanged = previousUsageParent !== control.usage.root.parentElement || previousUsageNextSibling !== control.usage.root.nextElementSibling;
|
|
17819
|
+
if (usagePositionChanged) control.harnessCommands?.placeBefore(control.usage.root);
|
|
17127
17820
|
const leading = creditsPlacementAnchor(control.composer, control.usage.root);
|
|
17128
17821
|
if (!leading) {
|
|
17129
17822
|
if (control.credits.anchor) control.credits.root.remove();
|
|
@@ -17162,12 +17855,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17162
17855
|
}
|
|
17163
17856
|
function reconcileComposerNativeControls(control, hideModel, hidePermissionMode) {
|
|
17164
17857
|
refreshNativeModelControl(control);
|
|
17858
|
+
refreshTrailingClusterPlacement(control);
|
|
17165
17859
|
refreshUsagePlacement(control);
|
|
17166
17860
|
refreshNativePermissionModeControl(control);
|
|
17167
17861
|
setNativeControlHidden(control.nativeModelControl, hideModel);
|
|
17168
17862
|
setNativeControlHidden(control.nativePermissionModeControl, hidePermissionMode);
|
|
17169
17863
|
}
|
|
17170
|
-
function mountComposerAgentControl(composer, composerId, sendButton, enabledAgents, onSelect, onDownload, onSelectModel, onSelectThinking, onSelectPermissionMode) {
|
|
17864
|
+
function mountComposerAgentControl(composer, composerId, sendButton, enabledAgents, onSelect, onDownload, onSelectModel, onSelectThinking, onSelectPermissionMode, onSelectCommand) {
|
|
17171
17865
|
const nativeModelControl = captureNativeControl(nativeModelControlForComposer(composer));
|
|
17172
17866
|
const semanticNativePermissionModeControl = semanticNativePermissionModeControlForComposer(composer);
|
|
17173
17867
|
const nativePermissionModeControl = captureNativeControl(semanticNativePermissionModeControl);
|
|
@@ -17186,19 +17880,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17186
17880
|
);
|
|
17187
17881
|
const usage = mountRendererUsageControl(composerId, nativeModelControl?.element.className);
|
|
17188
17882
|
const credits = mountRendererCreditsControl(composerId, nativeModelControl?.element.className);
|
|
17883
|
+
const toolbar = sendButton.parentElement;
|
|
17884
|
+
const harnessCommands = mountRendererHarnessCommandControl(
|
|
17885
|
+
toolbar ?? composer,
|
|
17886
|
+
trailingActionAnchor(sendButton),
|
|
17887
|
+
onSelectCommand
|
|
17888
|
+
);
|
|
17189
17889
|
const permissionParent = nativePermissionModeControl?.element.parentElement;
|
|
17190
17890
|
if (permissionParent && nativePermissionModeControl && nativePermissionModeControlVerified) {
|
|
17191
17891
|
permissionParent.insertBefore(permissionModePicker.root, nativePermissionModeControl.element);
|
|
17192
17892
|
} else {
|
|
17193
17893
|
composer.append(permissionModePicker.root);
|
|
17194
17894
|
}
|
|
17195
|
-
|
|
17196
|
-
if (toolbar) {
|
|
17197
|
-
toolbar.insertBefore(modelPicker.root, sendButton);
|
|
17198
|
-
toolbar.insertBefore(picker.root, sendButton);
|
|
17199
|
-
} else {
|
|
17200
|
-
composer.append(modelPicker.root, picker.root);
|
|
17201
|
-
}
|
|
17895
|
+
if (!toolbar) composer.append(modelPicker.root, picker.root);
|
|
17202
17896
|
const control = {
|
|
17203
17897
|
composer,
|
|
17204
17898
|
root: picker.root,
|
|
@@ -17210,9 +17904,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17210
17904
|
nativePermissionModeControlVerified,
|
|
17211
17905
|
credits,
|
|
17212
17906
|
usage,
|
|
17907
|
+
harnessCommands,
|
|
17213
17908
|
sendButton,
|
|
17214
17909
|
sendDisabledBeforeSwitch: null
|
|
17215
17910
|
};
|
|
17911
|
+
refreshTrailingClusterPlacement(control);
|
|
17216
17912
|
refreshUsagePlacement(control);
|
|
17217
17913
|
return control;
|
|
17218
17914
|
}
|
|
@@ -17264,6 +17960,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17264
17960
|
restoreNativeControl(control.nativePermissionModeControl);
|
|
17265
17961
|
control.credits.dispose();
|
|
17266
17962
|
control.usage.dispose();
|
|
17963
|
+
control.harnessCommands.dispose();
|
|
17267
17964
|
control.permissionModePicker.dispose();
|
|
17268
17965
|
control.modelPicker.dispose();
|
|
17269
17966
|
control.picker.dispose();
|
|
@@ -17701,6 +18398,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17701
18398
|
var HARNESS_INSPECT_METHOD = "codexhost/harness/inspect";
|
|
17702
18399
|
var THREAD_FORK_METHOD = "codexhost/thread/fork";
|
|
17703
18400
|
var THREAD_INSPECT_METHOD = "codexhost/thread/inspect";
|
|
18401
|
+
var THREAD_COMMANDS_INSPECT_METHOD = "codexhost/thread/commands/inspect";
|
|
18402
|
+
var THREAD_COMMAND_EXECUTE_METHOD = "codexhost/thread/command/execute";
|
|
17704
18403
|
var THREAD_MODEL_SELECT_METHOD = "codexhost/thread/model/select";
|
|
17705
18404
|
var THREAD_THINKING_SELECT_METHOD = "codexhost/thread/thinking/select";
|
|
17706
18405
|
var THREAD_PERMISSION_MODE_SELECT_METHOD = "codexhost/thread/permission-mode/select";
|
|
@@ -17722,6 +18421,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17722
18421
|
const parsed = hostThreadIdSchema.safeParse(params.threadId);
|
|
17723
18422
|
return parsed.success ? parsed.data : null;
|
|
17724
18423
|
}
|
|
18424
|
+
function usageNotificationTarget(manager) {
|
|
18425
|
+
if (typeof manager.addNotificationCallback === "function") return manager;
|
|
18426
|
+
const nested = manager.requestClient;
|
|
18427
|
+
return nested && typeof nested.addNotificationCallback === "function" ? nested : null;
|
|
18428
|
+
}
|
|
17725
18429
|
function createThreadUsageSubscriptionRelay() {
|
|
17726
18430
|
const listeners = /* @__PURE__ */ new Set();
|
|
17727
18431
|
let removeNotificationCallback = null;
|
|
@@ -17763,6 +18467,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17763
18467
|
const result = await manager.sendRequest(HARNESS_INSPECT_METHOD, params);
|
|
17764
18468
|
return harnessInspectionSchema.parse(result);
|
|
17765
18469
|
};
|
|
18470
|
+
const inspectThreadCommands = async (input) => {
|
|
18471
|
+
const params = threadCommandsInspectParamsSchema.parse(input);
|
|
18472
|
+
const result = await manager.sendRequest(THREAD_COMMANDS_INSPECT_METHOD, params);
|
|
18473
|
+
return harnessCommandCatalogSchema.parse(result);
|
|
18474
|
+
};
|
|
18475
|
+
const executeThreadCommand = async (input) => {
|
|
18476
|
+
const params = threadCommandExecuteParamsSchema.parse(input);
|
|
18477
|
+
const result = await manager.sendRequest(THREAD_COMMAND_EXECUTE_METHOD, params);
|
|
18478
|
+
return threadCommandExecuteResultSchema.parse(result);
|
|
18479
|
+
};
|
|
17766
18480
|
const inspectThreadUsage = async (input) => {
|
|
17767
18481
|
const params = threadUsageInspectionParamsSchema.parse(input);
|
|
17768
18482
|
const result = await manager.sendRequest(THREAD_USAGE_INSPECT_METHOD, params);
|
|
@@ -17795,6 +18509,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17795
18509
|
const result = await manager.sendRequest(THREAD_INSPECT_METHOD, params);
|
|
17796
18510
|
return threadInspectionSchema.parse(result);
|
|
17797
18511
|
},
|
|
18512
|
+
inspectThreadCommands,
|
|
18513
|
+
executeThreadCommand,
|
|
17798
18514
|
async listThreadOwnership(input) {
|
|
17799
18515
|
const params = threadOwnershipListParamsSchema.parse(input);
|
|
17800
18516
|
const value = await manager.sendRequest(THREAD_OWNERSHIP_LIST_METHOD, params);
|
|
@@ -17806,10 +18522,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17806
18522
|
},
|
|
17807
18523
|
inspectThreadUsage,
|
|
17808
18524
|
subscribeThreadUsage(listener) {
|
|
17809
|
-
|
|
18525
|
+
const notifications = usageNotificationTarget(manager);
|
|
18526
|
+
if (!notifications?.addNotificationCallback) {
|
|
18527
|
+
throw new Error("Renderer Usage notification callback is unavailable");
|
|
18528
|
+
}
|
|
17810
18529
|
let disposed = false;
|
|
17811
18530
|
const generations = /* @__PURE__ */ new Map();
|
|
17812
|
-
const removeNotificationCallback =
|
|
18531
|
+
const removeNotificationCallback = notifications.addNotificationCallback(
|
|
17813
18532
|
THREAD_TOKEN_USAGE_UPDATED_METHOD,
|
|
17814
18533
|
(notification) => {
|
|
17815
18534
|
const threadId = notifiedThreadId(notification);
|
|
@@ -17910,28 +18629,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17910
18629
|
}
|
|
17911
18630
|
return `${CLAUDE_CODE_TRANSPORT_MODEL_PREFIX}${parsedModel.id}${parsedPermissionMode ? `@${parsedPermissionMode}` : ""}`;
|
|
17912
18631
|
}
|
|
17913
|
-
function grokTransportModelId(model, thinkingOptionId) {
|
|
18632
|
+
function grokTransportModelId(model, permissionModeId, thinkingOptionId) {
|
|
17914
18633
|
if (!model) {
|
|
17915
|
-
if (thinkingOptionId)
|
|
18634
|
+
if (permissionModeId || thinkingOptionId) {
|
|
18635
|
+
throw new Error("Grok transport configuration requires a Model Ref");
|
|
18636
|
+
}
|
|
17916
18637
|
return GROK_TRANSPORT_MODEL_ID;
|
|
17917
18638
|
}
|
|
17918
18639
|
const parsedModel = harnessModelRefSchema.parse(model);
|
|
18640
|
+
const parsedPermissionMode = permissionModeId ? harnessPermissionModeIdSchema.parse(permissionModeId) : void 0;
|
|
17919
18641
|
const parsedThinking = thinkingOptionId ? harnessThinkingOptionIdSchema.parse(thinkingOptionId) : void 0;
|
|
17920
|
-
|
|
18642
|
+
if (parsedThinking) {
|
|
18643
|
+
return `${GROK_TRANSPORT_MODEL_PREFIX}${parsedModel.id}@${parsedPermissionMode ?? ""}@${parsedThinking}`;
|
|
18644
|
+
}
|
|
18645
|
+
return `${GROK_TRANSPORT_MODEL_PREFIX}${parsedModel.id}${parsedPermissionMode ? `@${parsedPermissionMode}` : ""}`;
|
|
17921
18646
|
}
|
|
17922
18647
|
function decodeGrokTransportModelId(value) {
|
|
17923
18648
|
if (value === GROK_TRANSPORT_MODEL_ID) return {};
|
|
17924
18649
|
if (typeof value !== "string" || !value.startsWith(GROK_TRANSPORT_MODEL_PREFIX)) return null;
|
|
17925
18650
|
const components = value.slice(GROK_TRANSPORT_MODEL_PREFIX.length).split("@");
|
|
17926
|
-
if (components.length
|
|
17927
|
-
const [modelId,
|
|
17928
|
-
if (components.length ===
|
|
18651
|
+
if (components.length < 1 || components.length > 3) return null;
|
|
18652
|
+
const [modelId, permissionModeId, thinkingOptionId] = components;
|
|
18653
|
+
if (components.length === 2 && !permissionModeId) return null;
|
|
18654
|
+
if (components.length === 3 && !thinkingOptionId) return null;
|
|
17929
18655
|
const model = harnessModelRefSchema.safeParse({ id: modelId });
|
|
17930
18656
|
if (!model.success) return null;
|
|
18657
|
+
const permissionMode = permissionModeId ? harnessPermissionModeIdSchema.safeParse(permissionModeId) : null;
|
|
18658
|
+
if (permissionMode && !permissionMode.success) return null;
|
|
17931
18659
|
const thinking = thinkingOptionId ? harnessThinkingOptionIdSchema.safeParse(thinkingOptionId) : null;
|
|
17932
18660
|
if (thinking && !thinking.success) return null;
|
|
17933
18661
|
return {
|
|
17934
18662
|
model: model.data,
|
|
18663
|
+
...permissionMode?.success ? { permissionModeId: permissionMode.data } : {},
|
|
17935
18664
|
...thinking?.success ? { thinkingOptionId: thinking.data } : {}
|
|
17936
18665
|
};
|
|
17937
18666
|
}
|
|
@@ -17971,14 +18700,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17971
18700
|
});
|
|
17972
18701
|
return model.success ? { model: model.data } : null;
|
|
17973
18702
|
}
|
|
17974
|
-
function
|
|
17975
|
-
if (value === PI_TRANSPORT_MODEL_ID) return
|
|
17976
|
-
if (typeof value !== "string" || !value.startsWith(PI_TRANSPORT_MODEL_PREFIX)) return
|
|
18703
|
+
function decodePiTransportModelId(value) {
|
|
18704
|
+
if (value === PI_TRANSPORT_MODEL_ID) return {};
|
|
18705
|
+
if (typeof value !== "string" || !value.startsWith(PI_TRANSPORT_MODEL_PREFIX)) return null;
|
|
17977
18706
|
const components = value.slice(PI_TRANSPORT_MODEL_PREFIX.length).split("@");
|
|
17978
|
-
if (components.length < 1 || components.length > 2) return
|
|
18707
|
+
if (components.length < 1 || components.length > 2) return null;
|
|
17979
18708
|
const [modelId, thinkingOptionId] = components;
|
|
17980
|
-
if (
|
|
17981
|
-
|
|
18709
|
+
if (components.length === 2 && !thinkingOptionId) return null;
|
|
18710
|
+
const model = harnessModelRefSchema.safeParse({ id: modelId });
|
|
18711
|
+
if (!model.success) return null;
|
|
18712
|
+
const thinking = thinkingOptionId ? harnessThinkingOptionIdSchema.safeParse(thinkingOptionId) : null;
|
|
18713
|
+
if (thinking && !thinking.success) return null;
|
|
18714
|
+
return {
|
|
18715
|
+
model: model.data,
|
|
18716
|
+
...thinking?.success ? { thinkingOptionId: thinking.data } : {}
|
|
18717
|
+
};
|
|
17982
18718
|
}
|
|
17983
18719
|
function threadIdFromComposerModelTarget(target) {
|
|
17984
18720
|
if (target?.[0] !== "conversation" || typeof target[1] !== "string" || target[1].trim().length === 0) {
|
|
@@ -17996,7 +18732,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17996
18732
|
}
|
|
17997
18733
|
function matchesCurrentPrewarmSignature(target) {
|
|
17998
18734
|
const bridge = target.requestClient ?? target;
|
|
17999
|
-
const stableApiShape = bridge.hostId === "
|
|
18735
|
+
const stableApiShape = typeof bridge.hostId === "string" && bridge.hostId.length > 0 && typeof bridge.sendRequest === "function" && typeof bridge.prewarmThreadStart === "function" && typeof bridge.enqueueRequest === "function";
|
|
18000
18736
|
if (stableApiShape) return true;
|
|
18001
18737
|
const prewarm = target.prewarmThreadStart ?? target.requestClient?.prewarmThreadStart;
|
|
18002
18738
|
if (!prewarm) return false;
|
|
@@ -18034,7 +18770,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18034
18770
|
if (isActiveRequestManager(hookState) && matchesCurrentPrewarmSignature(hookState)) {
|
|
18035
18771
|
targets.add(hookState);
|
|
18036
18772
|
} else if (hasPrewarmMethod(requestClient) && matchesCurrentPrewarmSignature(requestClient)) {
|
|
18037
|
-
targets.add(requestClient);
|
|
18773
|
+
targets.add(typeof hookState.sendRequest === "function" ? hookState : requestClient);
|
|
18038
18774
|
}
|
|
18039
18775
|
}
|
|
18040
18776
|
hook = typeof hook.next === "object" && hook.next !== null ? hook.next : null;
|
|
@@ -18087,10 +18823,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18087
18823
|
return false;
|
|
18088
18824
|
}
|
|
18089
18825
|
}
|
|
18090
|
-
function
|
|
18091
|
-
const
|
|
18092
|
-
|
|
18093
|
-
if (
|
|
18826
|
+
function findComposerDomIdentity(composer) {
|
|
18827
|
+
const children = Array.from(composer.children ?? []);
|
|
18828
|
+
const portals = children.filter((child) => child.hasAttribute("data-above-composer-portal"));
|
|
18829
|
+
if (portals.length === 0) return { kind: "unsupported" };
|
|
18830
|
+
if (portals.length !== 1) return { kind: "ambiguous" };
|
|
18831
|
+
const value = portals[0]?.getAttribute("data-above-composer-conversation-id");
|
|
18832
|
+
if (value === null) return { kind: "draft" };
|
|
18833
|
+
const candidate = hostThreadIdSchema.safeParse(value);
|
|
18834
|
+
return candidate.success ? { kind: "conversation", threadId: candidate.data } : { kind: "ambiguous" };
|
|
18835
|
+
}
|
|
18836
|
+
function findComposerDraftIds(composer) {
|
|
18094
18837
|
const draftIds = /* @__PURE__ */ new Set();
|
|
18095
18838
|
let fiber = findComposerFiber(composer);
|
|
18096
18839
|
for (let depth = 0; fiber && depth < 120; depth += 1) {
|
|
@@ -18105,6 +18848,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18105
18848
|
const parent = fiber.return;
|
|
18106
18849
|
fiber = (typeof parent === "object" || typeof parent === "function") && parent !== null ? parent : null;
|
|
18107
18850
|
}
|
|
18851
|
+
return draftIds;
|
|
18852
|
+
}
|
|
18853
|
+
function findComposerModelTarget(composer) {
|
|
18854
|
+
const draftIds = findComposerDraftIds(composer);
|
|
18855
|
+
const domIdentity = findComposerDomIdentity(composer);
|
|
18856
|
+
if (domIdentity.kind === "ambiguous") return null;
|
|
18857
|
+
if (domIdentity.kind === "conversation") {
|
|
18858
|
+
return ["conversation", domIdentity.threadId];
|
|
18859
|
+
}
|
|
18860
|
+
if (domIdentity.kind === "draft") {
|
|
18861
|
+
return draftIds.size === 1 ? ["default", draftIds.values().next().value] : null;
|
|
18862
|
+
}
|
|
18863
|
+
const conversationThreadId = findComposerConversationThreadId(composer);
|
|
18864
|
+
if (conversationThreadId === null) return null;
|
|
18865
|
+
if (conversationThreadId !== void 0) return ["conversation", conversationThreadId];
|
|
18108
18866
|
if (draftIds.size !== 1) return null;
|
|
18109
18867
|
return ["default", draftIds.values().next().value];
|
|
18110
18868
|
}
|
|
@@ -18112,7 +18870,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18112
18870
|
return isRecord5(value) && value.state === "ready";
|
|
18113
18871
|
}
|
|
18114
18872
|
function isDraftPrewarmPolicyReady(value) {
|
|
18115
|
-
return isRecord5(value) && value.state === "ready" && typeof value.select === "function" && typeof value.clear === "function";
|
|
18873
|
+
return isRecord5(value) && value.state === "ready" && typeof value.hostId === "string" && value.hostId.length > 0 && typeof value.select === "function" && typeof value.clear === "function";
|
|
18874
|
+
}
|
|
18875
|
+
function activeRendererDraftPrewarmTargets(policy, targets) {
|
|
18876
|
+
if (!isDraftPrewarmPolicyReady(policy)) return null;
|
|
18877
|
+
const activeTargets = targets.filter((target) => {
|
|
18878
|
+
const bridge = target.requestClient ?? target;
|
|
18879
|
+
return (target.getHostId?.() ?? bridge.hostId) === policy.hostId;
|
|
18880
|
+
});
|
|
18881
|
+
return activeTargets.length === 1 ? activeTargets : null;
|
|
18882
|
+
}
|
|
18883
|
+
function resolveRendererRequestRoute(policy, discoveredTargets, previous) {
|
|
18884
|
+
const activeTargets = activeRendererDraftPrewarmTargets(policy, discoveredTargets);
|
|
18885
|
+
if (isDraftPrewarmPolicyReady(policy) && activeTargets) {
|
|
18886
|
+
return { policy, targets: activeTargets };
|
|
18887
|
+
}
|
|
18888
|
+
return discoveredTargets.length === 0 && isDraftPrewarmPolicyReady(policy) && previous?.policy === policy ? previous : null;
|
|
18889
|
+
}
|
|
18890
|
+
function createRendererRequestRouteResolver(readPolicy, discoverTargets) {
|
|
18891
|
+
let route = null;
|
|
18892
|
+
return {
|
|
18893
|
+
resolve() {
|
|
18894
|
+
route = resolveRendererRequestRoute(readPolicy(), discoverTargets(), route);
|
|
18895
|
+
return route;
|
|
18896
|
+
},
|
|
18897
|
+
clear() {
|
|
18898
|
+
route = null;
|
|
18899
|
+
}
|
|
18900
|
+
};
|
|
18116
18901
|
}
|
|
18117
18902
|
async function waitForRendererDraftPrewarmPolicy(target) {
|
|
18118
18903
|
const deadline = Date.now() + DRAFT_PREWARM_POLICY_WAIT_TIMEOUT_MS;
|
|
@@ -18127,7 +18912,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18127
18912
|
}
|
|
18128
18913
|
}
|
|
18129
18914
|
function modelSelectionForAgent(officialSelection, reasoningEffort, agent, model, thinkingOptionId, permissionModeId) {
|
|
18130
|
-
const transportModelId = agent === "pi" ? piTransportModelId(model, thinkingOptionId) : agent === "claude-code" ? claudeTransportModelId(model, permissionModeId, thinkingOptionId) : agent === "deepseek-harness" ? deepSeekHarnessTransportModelId(model) : agent === "grok" ? grokTransportModelId(model, thinkingOptionId) : transportModelIdForAgent(agent);
|
|
18915
|
+
const transportModelId = agent === "pi" ? piTransportModelId(model, thinkingOptionId) : agent === "claude-code" ? claudeTransportModelId(model, permissionModeId, thinkingOptionId) : agent === "deepseek-harness" ? deepSeekHarnessTransportModelId(model) : agent === "grok" ? grokTransportModelId(model, permissionModeId, thinkingOptionId) : transportModelIdForAgent(agent);
|
|
18131
18916
|
return transportModelId ? { model: transportModelId, reasoningEffort } : officialSelection;
|
|
18132
18917
|
}
|
|
18133
18918
|
function installCurrentRendererAdapter() {
|
|
@@ -18153,8 +18938,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18153
18938
|
}
|
|
18154
18939
|
});
|
|
18155
18940
|
const usageSubscription = createThreadUsageSubscriptionRelay();
|
|
18941
|
+
const requestRouteResolver = createRendererRequestRouteResolver(
|
|
18942
|
+
() => window.__codexhostDraftPrewarmPolicyV1,
|
|
18943
|
+
() => findActivePrewarmTargets(document)
|
|
18944
|
+
);
|
|
18945
|
+
const currentRequestRoute = () => requestRouteResolver.resolve();
|
|
18156
18946
|
const currentModelClient = () => {
|
|
18157
|
-
const client = createRendererModelClient(
|
|
18947
|
+
const client = createRendererModelClient(currentRequestRoute()?.targets ?? []);
|
|
18158
18948
|
if (!client) throw new Error("Renderer Model request manager is unavailable");
|
|
18159
18949
|
usageSubscription.connect(client);
|
|
18160
18950
|
return client;
|
|
@@ -18163,6 +18953,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18163
18953
|
forkThread: (input) => currentModelClient().forkThread(input),
|
|
18164
18954
|
inspectHarness: (input) => currentModelClient().inspectHarness(input),
|
|
18165
18955
|
inspectThread: (input) => currentModelClient().inspectThread(input),
|
|
18956
|
+
inspectThreadCommands: (input) => currentModelClient().inspectThreadCommands(input),
|
|
18957
|
+
executeThreadCommand: (input) => currentModelClient().executeThreadCommand(input),
|
|
18166
18958
|
inspectThreadUsage: (input) => currentModelClient().inspectThreadUsage(input),
|
|
18167
18959
|
subscribeThreadUsage: (listener) => usageSubscription.subscribe(listener),
|
|
18168
18960
|
listThreadOwnership: (input) => currentModelClient().listThreadOwnership(input),
|
|
@@ -18188,10 +18980,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18188
18980
|
});
|
|
18189
18981
|
let routingPolicy = null;
|
|
18190
18982
|
let policyTimer = null;
|
|
18983
|
+
let desiredCarrier = null;
|
|
18191
18984
|
const captureRoutingPolicy = () => {
|
|
18192
|
-
const
|
|
18193
|
-
if (!
|
|
18194
|
-
routingPolicy =
|
|
18985
|
+
const route = currentRequestRoute();
|
|
18986
|
+
if (!route) return false;
|
|
18987
|
+
routingPolicy = route.policy;
|
|
18988
|
+
routingPolicy.select(desiredCarrier);
|
|
18195
18989
|
if (policyTimer !== null) {
|
|
18196
18990
|
window.clearInterval(policyTimer);
|
|
18197
18991
|
policyTimer = null;
|
|
@@ -18203,8 +18997,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18203
18997
|
updateStatus("installing", "draft-routing-policy-unavailable", null);
|
|
18204
18998
|
policyTimer = window.setInterval(captureRoutingPolicy, DRAFT_PREWARM_POLICY_POLL_INTERVAL_MS);
|
|
18205
18999
|
}
|
|
19000
|
+
const handleRoutingPolicyChange = () => {
|
|
19001
|
+
captureRoutingPolicy();
|
|
19002
|
+
};
|
|
19003
|
+
window.addEventListener("codexhost:draft-prewarm-policy-changed", handleRoutingPolicyChange);
|
|
18206
19004
|
const applyAgent = (agent, model, thinkingOptionId, permissionModeId) => {
|
|
18207
|
-
if (disposed
|
|
19005
|
+
if (disposed) return false;
|
|
18208
19006
|
const selection = modelSelectionForAgent(
|
|
18209
19007
|
null,
|
|
18210
19008
|
null,
|
|
@@ -18215,7 +19013,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18215
19013
|
);
|
|
18216
19014
|
const carrier = selection?.model;
|
|
18217
19015
|
if (carrier !== null && carrier !== void 0 && typeof carrier !== "string") return false;
|
|
18218
|
-
|
|
19016
|
+
desiredCarrier = carrier ?? null;
|
|
19017
|
+
const route = currentRequestRoute();
|
|
19018
|
+
if (!route) return false;
|
|
19019
|
+
routingPolicy = route.policy;
|
|
19020
|
+
if (route.policy.select(desiredCarrier)) {
|
|
18219
19021
|
modelUpdates += 1;
|
|
18220
19022
|
liveStatus.modelUpdates = modelUpdates;
|
|
18221
19023
|
}
|
|
@@ -18229,8 +19031,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18229
19031
|
if (disposed) return;
|
|
18230
19032
|
disposed = true;
|
|
18231
19033
|
if (policyTimer !== null) window.clearInterval(policyTimer);
|
|
19034
|
+
window.removeEventListener(
|
|
19035
|
+
"codexhost:draft-prewarm-policy-changed",
|
|
19036
|
+
handleRoutingPolicyChange
|
|
19037
|
+
);
|
|
18232
19038
|
routingPolicy?.select(null);
|
|
18233
19039
|
routingPolicy = null;
|
|
19040
|
+
requestRouteResolver.clear();
|
|
18234
19041
|
forkControl.dispose();
|
|
18235
19042
|
usageSubscription.dispose();
|
|
18236
19043
|
}
|
|
@@ -18282,9 +19089,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18282
19089
|
const model = harnessModelRefSchema.safeParse(value.model);
|
|
18283
19090
|
if (!model.success) return void 0;
|
|
18284
19091
|
const thinkingOptionId = harnessThinkingOptionIdSchema.safeParse(value.thinkingOptionId);
|
|
19092
|
+
const permissionModeId = harnessPermissionModeIdSchema.safeParse(value.permissionModeId);
|
|
18285
19093
|
return {
|
|
18286
19094
|
model: model.data,
|
|
18287
|
-
...thinkingOptionId.success ? { thinkingOptionId: thinkingOptionId.data } : {}
|
|
19095
|
+
...thinkingOptionId.success ? { thinkingOptionId: thinkingOptionId.data } : {},
|
|
19096
|
+
...permissionModeId.success ? { permissionModeId: permissionModeId.data } : {}
|
|
18288
19097
|
};
|
|
18289
19098
|
}
|
|
18290
19099
|
function readPreference(storage) {
|
|
@@ -18324,15 +19133,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18324
19133
|
const agent = readPreference(storage)?.lastAgent;
|
|
18325
19134
|
return agent && enabledAgents.has(agent) ? agent : void 0;
|
|
18326
19135
|
}
|
|
18327
|
-
function readNewThreadExternalConfigurationPreference(agent, catalog, storage = rendererStorage2()) {
|
|
19136
|
+
function readNewThreadExternalConfigurationPreference(agent, catalog, permissionModes, storage = rendererStorage2()) {
|
|
18328
19137
|
const preference = readPreference(storage)?.externalByAgent[agent];
|
|
18329
19138
|
if (!preference) return void 0;
|
|
18330
19139
|
const catalogModel = catalog.models.find(({ ref }) => ref.id === preference.model.id);
|
|
18331
19140
|
if (!catalogModel) return void 0;
|
|
18332
19141
|
const thinkingOptionId = preference.thinkingOptionId && catalogModel.supportedThinkingOptionIds?.includes(preference.thinkingOptionId) ? preference.thinkingOptionId : void 0;
|
|
19142
|
+
const permissionModeId = preference.permissionModeId && permissionModes?.modes.some(({ id }) => id === preference.permissionModeId) ? preference.permissionModeId : void 0;
|
|
18333
19143
|
return {
|
|
18334
19144
|
model: catalogModel.ref,
|
|
18335
|
-
...thinkingOptionId ? { thinkingOptionId } : {}
|
|
19145
|
+
...thinkingOptionId ? { thinkingOptionId } : {},
|
|
19146
|
+
...permissionModeId ? { permissionModeId } : {}
|
|
18336
19147
|
};
|
|
18337
19148
|
}
|
|
18338
19149
|
function writeNewThreadAgentPreference(agent, storage = rendererStorage2()) {
|
|
@@ -18346,7 +19157,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18346
19157
|
storage
|
|
18347
19158
|
);
|
|
18348
19159
|
}
|
|
18349
|
-
function writeNewThreadExternalConfigurationPreference(agent, model, thinkingOptionId, storage = rendererStorage2()) {
|
|
19160
|
+
function writeNewThreadExternalConfigurationPreference(agent, model, thinkingOptionId, permissionModeId, storage = rendererStorage2()) {
|
|
18350
19161
|
const current = readPreference(storage);
|
|
18351
19162
|
writePreference(
|
|
18352
19163
|
{
|
|
@@ -18356,7 +19167,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18356
19167
|
...current?.externalByAgent,
|
|
18357
19168
|
[agent]: {
|
|
18358
19169
|
model: harnessModelRefSchema.parse(model),
|
|
18359
|
-
...thinkingOptionId ? { thinkingOptionId: harnessThinkingOptionIdSchema.parse(thinkingOptionId) } : {}
|
|
19170
|
+
...thinkingOptionId ? { thinkingOptionId: harnessThinkingOptionIdSchema.parse(thinkingOptionId) } : {},
|
|
19171
|
+
...permissionModeId ? { permissionModeId: harnessPermissionModeIdSchema.parse(permissionModeId) } : {}
|
|
18360
19172
|
}
|
|
18361
19173
|
}
|
|
18362
19174
|
},
|
|
@@ -18554,6 +19366,30 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18554
19366
|
inDevelopment: "In development",
|
|
18555
19367
|
notAvailable: "Not available",
|
|
18556
19368
|
runtimeCapabilityNotInstalled: "This runtime capability is not installed yet.",
|
|
19369
|
+
connectionsDescription: "Inspect the adapter and each Agent runtime used by the picker. Failed checks keep their error details here.",
|
|
19370
|
+
connectionAdapter: "Renderer adapter",
|
|
19371
|
+
connectionReason: "Reason",
|
|
19372
|
+
connectionRefresh: "Run connection diagnostics",
|
|
19373
|
+
connectionRefreshing: "Running diagnostics...",
|
|
19374
|
+
connectionViewDetails: "View details",
|
|
19375
|
+
connectionCopyDetails: "Copy diagnostics",
|
|
19376
|
+
connectionCopyAll: "Copy all diagnostics",
|
|
19377
|
+
connectionCopied: "Copied",
|
|
19378
|
+
connectionCopyFailed: "Copy failed",
|
|
19379
|
+
connectionErrorCode: "Error code",
|
|
19380
|
+
connectionErrorMessage: "Error message",
|
|
19381
|
+
connectionRetryable: "Retryable",
|
|
19382
|
+
connectionFailureStage: "Failure stage",
|
|
19383
|
+
connectionDuration: "Duration",
|
|
19384
|
+
connectionDiagnostic: "Diagnostic",
|
|
19385
|
+
connectionNoRuntime: "The renderer request bridge is not available yet.",
|
|
19386
|
+
connectionStatusReady: "Ready",
|
|
19387
|
+
connectionStatusChecking: "Checking",
|
|
19388
|
+
connectionStatusNotInstalled: "Not installed",
|
|
19389
|
+
connectionStatusUnavailable: "Unavailable",
|
|
19390
|
+
connectionStatusError: "Error",
|
|
19391
|
+
connectionStatusInstalling: "Installing",
|
|
19392
|
+
connectionStatusUnsupported: "Unsupported",
|
|
18557
19393
|
openSettings: "Open codexhost settings",
|
|
18558
19394
|
settingsButtonTitle: "codexhost settings",
|
|
18559
19395
|
settingsUnavailableTitle: "codexhost settings unavailable",
|
|
@@ -18598,6 +19434,30 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18598
19434
|
inDevelopment: "\u5F00\u53D1\u4E2D",
|
|
18599
19435
|
notAvailable: "\u6682\u4E0D\u53EF\u7528",
|
|
18600
19436
|
runtimeCapabilityNotInstalled: "\u8FD0\u884C\u65F6\u5C1A\u672A\u5B89\u88C5\u8BE5\u9879\u80FD\u529B\uFF0C\u56E0\u6B64\u6682\u4E0D\u53EF\u7528\u3002",
|
|
19437
|
+
connectionsDescription: "\u67E5\u770B\u9002\u914D\u5668\u548C Agent \u8FD0\u884C\u65F6\u7684\u771F\u5B9E\u68C0\u67E5\u7ED3\u679C\u3002\u5931\u8D25\u68C0\u67E5\u4F1A\u4FDD\u7559\u9519\u8BEF\u8BE6\u60C5\uFF0C\u65B9\u4FBF\u6392\u67E5\u65E0\u6CD5\u9009\u62E9\u7684\u95EE\u9898\u3002",
|
|
19438
|
+
connectionAdapter: "Renderer \u9002\u914D\u5668",
|
|
19439
|
+
connectionReason: "\u539F\u56E0",
|
|
19440
|
+
connectionRefresh: "\u91CD\u65B0\u8BCA\u65AD\u8FDE\u63A5",
|
|
19441
|
+
connectionRefreshing: "\u6B63\u5728\u8BCA\u65AD...",
|
|
19442
|
+
connectionViewDetails: "\u67E5\u770B\u8BE6\u60C5",
|
|
19443
|
+
connectionCopyDetails: "\u590D\u5236\u8BCA\u65AD\u4FE1\u606F",
|
|
19444
|
+
connectionCopyAll: "\u590D\u5236\u5168\u90E8\u8BCA\u65AD\u4FE1\u606F",
|
|
19445
|
+
connectionCopied: "\u5DF2\u590D\u5236",
|
|
19446
|
+
connectionCopyFailed: "\u590D\u5236\u5931\u8D25",
|
|
19447
|
+
connectionErrorCode: "\u9519\u8BEF\u7801",
|
|
19448
|
+
connectionErrorMessage: "\u9519\u8BEF\u4FE1\u606F",
|
|
19449
|
+
connectionRetryable: "\u53EF\u91CD\u8BD5",
|
|
19450
|
+
connectionFailureStage: "\u5931\u8D25\u9636\u6BB5",
|
|
19451
|
+
connectionDuration: "\u68C0\u67E5\u8017\u65F6",
|
|
19452
|
+
connectionDiagnostic: "\u8BCA\u65AD\u4FE1\u606F",
|
|
19453
|
+
connectionNoRuntime: "Renderer \u8BF7\u6C42\u6865\u5C1A\u672A\u53EF\u7528\u3002",
|
|
19454
|
+
connectionStatusReady: "\u6B63\u5E38",
|
|
19455
|
+
connectionStatusChecking: "\u68C0\u67E5\u4E2D",
|
|
19456
|
+
connectionStatusNotInstalled: "\u672A\u5B89\u88C5",
|
|
19457
|
+
connectionStatusUnavailable: "\u4E0D\u53EF\u7528",
|
|
19458
|
+
connectionStatusError: "\u9519\u8BEF",
|
|
19459
|
+
connectionStatusInstalling: "\u5B89\u88C5\u4E2D",
|
|
19460
|
+
connectionStatusUnsupported: "\u4E0D\u652F\u6301",
|
|
18601
19461
|
openSettings: "\u6253\u5F00 codexhost \u8BBE\u7F6E",
|
|
18602
19462
|
settingsButtonTitle: "codexhost \u8BBE\u7F6E",
|
|
18603
19463
|
settingsUnavailableTitle: "codexhost \u8BBE\u7F6E\u4E0D\u53EF\u7528",
|
|
@@ -18690,6 +19550,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18690
19550
|
["path", { d: "M19.08 19.08A10 10 0 1 1 4.92 4.92" }]
|
|
18691
19551
|
];
|
|
18692
19552
|
|
|
19553
|
+
// ../../node_modules/lucide/dist/esm/icons/copy.mjs
|
|
19554
|
+
var Copy = [
|
|
19555
|
+
["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2" }],
|
|
19556
|
+
["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" }]
|
|
19557
|
+
];
|
|
19558
|
+
|
|
18693
19559
|
// ../../node_modules/lucide/dist/esm/icons/download.mjs
|
|
18694
19560
|
var Download = [
|
|
18695
19561
|
["path", { d: "M12 15V3" }],
|
|
@@ -18758,6 +19624,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18758
19624
|
["circle", { cx: "12", cy: "12", r: "3" }]
|
|
18759
19625
|
];
|
|
18760
19626
|
|
|
19627
|
+
// ../../node_modules/lucide/dist/esm/icons/stethoscope.mjs
|
|
19628
|
+
var Stethoscope = [
|
|
19629
|
+
["path", { d: "M11 2v2" }],
|
|
19630
|
+
["path", { d: "M5 2v2" }],
|
|
19631
|
+
["path", { d: "M5 3H4a2 2 0 0 0-2 2v4a6 6 0 0 0 12 0V5a2 2 0 0 0-2-2h-1" }],
|
|
19632
|
+
["path", { d: "M8 15a6 6 0 0 0 12 0v-3" }],
|
|
19633
|
+
["circle", { cx: "20", cy: "10", r: "2" }]
|
|
19634
|
+
];
|
|
19635
|
+
|
|
18761
19636
|
// ../../node_modules/lucide/dist/esm/icons/star.mjs
|
|
18762
19637
|
var Star = [
|
|
18763
19638
|
[
|
|
@@ -18790,7 +19665,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18790
19665
|
"updates",
|
|
18791
19666
|
"external-link",
|
|
18792
19667
|
"refresh",
|
|
18793
|
-
"unavailable"
|
|
19668
|
+
"unavailable",
|
|
19669
|
+
"diagnose",
|
|
19670
|
+
"copy"
|
|
18794
19671
|
];
|
|
18795
19672
|
var iconNodes = {
|
|
18796
19673
|
settings: Settings,
|
|
@@ -18804,7 +19681,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18804
19681
|
updates: Download,
|
|
18805
19682
|
"external-link": ExternalLink,
|
|
18806
19683
|
refresh: RefreshCw,
|
|
18807
|
-
unavailable: CircleOff
|
|
19684
|
+
unavailable: CircleOff,
|
|
19685
|
+
diagnose: Stethoscope,
|
|
19686
|
+
copy: Copy
|
|
18808
19687
|
};
|
|
18809
19688
|
function isRendererSettingsIconName(value) {
|
|
18810
19689
|
return RENDERER_SETTINGS_ICON_NAMES.includes(value);
|
|
@@ -19186,6 +20065,268 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19186
20065
|
}
|
|
19187
20066
|
});
|
|
19188
20067
|
}
|
|
20068
|
+
function connectionStatusLabel(availability, messages) {
|
|
20069
|
+
if (availability === "ready") return messages.connectionStatusReady;
|
|
20070
|
+
if (availability === "checking") return messages.connectionStatusChecking;
|
|
20071
|
+
if (availability === "notInstalled") return messages.connectionStatusNotInstalled;
|
|
20072
|
+
if (availability === "unavailable" || availability === "error") {
|
|
20073
|
+
return availability === "error" ? messages.connectionStatusError : messages.connectionStatusUnavailable;
|
|
20074
|
+
}
|
|
20075
|
+
return availability === "installing" ? messages.connectionStatusInstalling : messages.connectionStatusUnsupported;
|
|
20076
|
+
}
|
|
20077
|
+
function connectionStatusTone(availability) {
|
|
20078
|
+
if (availability === "ready") return "ready";
|
|
20079
|
+
if (availability === "checking" || availability === "installing") return "checking";
|
|
20080
|
+
return "failed";
|
|
20081
|
+
}
|
|
20082
|
+
function diagnosticText(name, snapshot) {
|
|
20083
|
+
const error51 = snapshot.error;
|
|
20084
|
+
const lines = [
|
|
20085
|
+
"codexhost connection diagnostics",
|
|
20086
|
+
`agent: ${name}`,
|
|
20087
|
+
`status: ${snapshot.availability}`,
|
|
20088
|
+
...error51 ? [
|
|
20089
|
+
`error.code: ${error51.code}`,
|
|
20090
|
+
`error.message: ${error51.message}`,
|
|
20091
|
+
`retryable: ${error51.retryable}`,
|
|
20092
|
+
...error51.stage ? [`stage: ${error51.stage}`] : [],
|
|
20093
|
+
...error51.durationMs !== void 0 ? [`durationMs: ${error51.durationMs}`] : [],
|
|
20094
|
+
...error51.diagnostic ? [`diagnostic: ${error51.diagnostic}`] : [],
|
|
20095
|
+
...error51.stderrTail ? [`stderr:
|
|
20096
|
+
${error51.stderrTail}`] : []
|
|
20097
|
+
] : []
|
|
20098
|
+
];
|
|
20099
|
+
return lines.join("\n");
|
|
20100
|
+
}
|
|
20101
|
+
function detailLine(document2, label, value) {
|
|
20102
|
+
const line = document2.createElement("div");
|
|
20103
|
+
line.className = "settings-connection-detail-line";
|
|
20104
|
+
const name = document2.createElement("span");
|
|
20105
|
+
name.textContent = label;
|
|
20106
|
+
const content = document2.createElement("code");
|
|
20107
|
+
content.textContent = value;
|
|
20108
|
+
line.append(name, content);
|
|
20109
|
+
return line;
|
|
20110
|
+
}
|
|
20111
|
+
function setCopyButtonLabel(button, label) {
|
|
20112
|
+
button.replaceChildren(createRendererSettingsIcon("copy", 16), label);
|
|
20113
|
+
}
|
|
20114
|
+
function showCopyButtonFeedback(button, label, restoreLabel) {
|
|
20115
|
+
setCopyButtonLabel(button, label);
|
|
20116
|
+
button.ownerDocument.defaultView?.setTimeout(() => {
|
|
20117
|
+
setCopyButtonLabel(button, restoreLabel);
|
|
20118
|
+
}, 2e3);
|
|
20119
|
+
}
|
|
20120
|
+
function copyDiagnosticsToClipboard(document2, button, report, messages, restoreLabel) {
|
|
20121
|
+
const clipboard = document2.defaultView?.navigator.clipboard;
|
|
20122
|
+
if (!clipboard) {
|
|
20123
|
+
showCopyButtonFeedback(button, messages.connectionCopyFailed, restoreLabel);
|
|
20124
|
+
return;
|
|
20125
|
+
}
|
|
20126
|
+
void clipboard.writeText(report).then(
|
|
20127
|
+
() => showCopyButtonFeedback(button, messages.connectionCopied, restoreLabel),
|
|
20128
|
+
() => showCopyButtonFeedback(button, messages.connectionCopyFailed, restoreLabel)
|
|
20129
|
+
);
|
|
20130
|
+
}
|
|
20131
|
+
function appendConnectionRow(document2, parent, name, availability, detail, error51, messages, rowAttribute, diagnosticSnapshot) {
|
|
20132
|
+
const row = document2.createElement("div");
|
|
20133
|
+
row.className = "settings-connection-row";
|
|
20134
|
+
if (rowAttribute) row.dataset.connectionAgent = rowAttribute;
|
|
20135
|
+
const identity = document2.createElement("div");
|
|
20136
|
+
identity.className = "settings-connection-row__identity";
|
|
20137
|
+
const dot = document2.createElement("span");
|
|
20138
|
+
dot.className = "settings-connection-row__dot";
|
|
20139
|
+
dot.dataset.connectionTone = connectionStatusTone(availability);
|
|
20140
|
+
dot.setAttribute("aria-hidden", "true");
|
|
20141
|
+
const label = document2.createElement("strong");
|
|
20142
|
+
label.textContent = name;
|
|
20143
|
+
identity.append(dot, label);
|
|
20144
|
+
const status = document2.createElement("span");
|
|
20145
|
+
status.className = "settings-status-badge";
|
|
20146
|
+
status.dataset.connectionTone = connectionStatusTone(availability);
|
|
20147
|
+
status.textContent = connectionStatusLabel(availability, messages);
|
|
20148
|
+
const detailElement = document2.createElement("div");
|
|
20149
|
+
detailElement.className = "settings-connection-row__detail";
|
|
20150
|
+
const summary = document2.createElement("span");
|
|
20151
|
+
summary.className = "settings-connection-row__reason";
|
|
20152
|
+
summary.textContent = error51 ? `${messages.connectionReason}: ${error51.code}: ${error51.message}` : detail ? `${messages.connectionReason}: ${detail}` : "";
|
|
20153
|
+
detailElement.append(summary);
|
|
20154
|
+
let toggle = null;
|
|
20155
|
+
if (error51) {
|
|
20156
|
+
toggle = document2.createElement("button");
|
|
20157
|
+
toggle.type = "button";
|
|
20158
|
+
toggle.className = "settings-connection-details-toggle";
|
|
20159
|
+
toggle.textContent = messages.connectionViewDetails;
|
|
20160
|
+
toggle.setAttribute("aria-expanded", "true");
|
|
20161
|
+
detailElement.append(toggle);
|
|
20162
|
+
}
|
|
20163
|
+
const details = document2.createElement("div");
|
|
20164
|
+
details.className = "settings-connection-details";
|
|
20165
|
+
details.hidden = !error51;
|
|
20166
|
+
if (error51) {
|
|
20167
|
+
details.append(
|
|
20168
|
+
detailLine(document2, messages.connectionErrorCode, error51.code),
|
|
20169
|
+
detailLine(document2, messages.connectionErrorMessage, error51.message),
|
|
20170
|
+
detailLine(document2, messages.connectionRetryable, String(error51.retryable))
|
|
20171
|
+
);
|
|
20172
|
+
if (error51.stage)
|
|
20173
|
+
details.append(detailLine(document2, messages.connectionFailureStage, error51.stage));
|
|
20174
|
+
if (error51.durationMs !== void 0) {
|
|
20175
|
+
details.append(detailLine(document2, messages.connectionDuration, `${error51.durationMs} ms`));
|
|
20176
|
+
}
|
|
20177
|
+
if (error51.diagnostic)
|
|
20178
|
+
details.append(detailLine(document2, messages.connectionDiagnostic, error51.diagnostic));
|
|
20179
|
+
if (error51.stderrTail) {
|
|
20180
|
+
const stderr = document2.createElement("pre");
|
|
20181
|
+
stderr.className = "settings-connection-stderr";
|
|
20182
|
+
stderr.textContent = error51.stderrTail;
|
|
20183
|
+
details.append(stderr);
|
|
20184
|
+
}
|
|
20185
|
+
const copy = document2.createElement("button");
|
|
20186
|
+
copy.type = "button";
|
|
20187
|
+
copy.className = "settings-command-button settings-command-button--secondary";
|
|
20188
|
+
setCopyButtonLabel(copy, messages.connectionCopyDetails);
|
|
20189
|
+
copy.addEventListener("click", () => {
|
|
20190
|
+
if (!diagnosticSnapshot) return;
|
|
20191
|
+
copyDiagnosticsToClipboard(
|
|
20192
|
+
document2,
|
|
20193
|
+
copy,
|
|
20194
|
+
diagnosticText(name, diagnosticSnapshot),
|
|
20195
|
+
messages,
|
|
20196
|
+
messages.connectionCopyDetails
|
|
20197
|
+
);
|
|
20198
|
+
});
|
|
20199
|
+
details.append(copy);
|
|
20200
|
+
}
|
|
20201
|
+
if (toggle) {
|
|
20202
|
+
toggle.addEventListener("click", () => {
|
|
20203
|
+
details.hidden = !details.hidden;
|
|
20204
|
+
toggle?.setAttribute("aria-expanded", String(!details.hidden));
|
|
20205
|
+
});
|
|
20206
|
+
}
|
|
20207
|
+
row.append(identity, status, detailElement, details);
|
|
20208
|
+
parent.append(row);
|
|
20209
|
+
}
|
|
20210
|
+
function connectionsPage(messages, getDiagnostics) {
|
|
20211
|
+
return Object.freeze({
|
|
20212
|
+
id: "connections",
|
|
20213
|
+
label: messages.pageLabels.connections,
|
|
20214
|
+
icon: "connections",
|
|
20215
|
+
mount(context) {
|
|
20216
|
+
const document2 = context.content.ownerDocument;
|
|
20217
|
+
const heading = document2.createElement("div");
|
|
20218
|
+
heading.className = "settings-section-label";
|
|
20219
|
+
heading.textContent = messages.pageLabels.connections;
|
|
20220
|
+
const description = document2.createElement("p");
|
|
20221
|
+
description.className = "settings-page-description";
|
|
20222
|
+
description.textContent = messages.connectionsDescription;
|
|
20223
|
+
const actions = document2.createElement("div");
|
|
20224
|
+
actions.className = "settings-connection-actions";
|
|
20225
|
+
const refresh = document2.createElement("button");
|
|
20226
|
+
refresh.type = "button";
|
|
20227
|
+
refresh.className = "settings-command-button settings-command-button--secondary";
|
|
20228
|
+
refresh.dataset.connectionAction = "refresh";
|
|
20229
|
+
refresh.append(createRendererSettingsIcon("diagnose", 16), messages.connectionRefresh);
|
|
20230
|
+
const copyAll = document2.createElement("button");
|
|
20231
|
+
copyAll.type = "button";
|
|
20232
|
+
copyAll.className = "settings-command-button settings-command-button--secondary";
|
|
20233
|
+
copyAll.dataset.connectionAction = "copy-all";
|
|
20234
|
+
copyAll.append(createRendererSettingsIcon("copy", 16), messages.connectionCopyAll);
|
|
20235
|
+
actions.append(refresh, copyAll);
|
|
20236
|
+
const content = document2.createElement("div");
|
|
20237
|
+
content.className = "settings-connection-list";
|
|
20238
|
+
context.content.append(heading, description, actions, content);
|
|
20239
|
+
let pending = false;
|
|
20240
|
+
const render = (snapshot) => {
|
|
20241
|
+
content.replaceChildren();
|
|
20242
|
+
if (!snapshot) {
|
|
20243
|
+
const empty = document2.createElement("div");
|
|
20244
|
+
empty.className = "settings-empty";
|
|
20245
|
+
empty.textContent = messages.connectionNoRuntime;
|
|
20246
|
+
content.append(empty);
|
|
20247
|
+
return;
|
|
20248
|
+
}
|
|
20249
|
+
appendConnectionRow(
|
|
20250
|
+
document2,
|
|
20251
|
+
content,
|
|
20252
|
+
messages.connectionAdapter,
|
|
20253
|
+
snapshot.adapter.state,
|
|
20254
|
+
`reason=${snapshot.adapter.reason}, hook=${snapshot.adapter.hook ?? "none"}`,
|
|
20255
|
+
null,
|
|
20256
|
+
messages,
|
|
20257
|
+
"renderer-adapter"
|
|
20258
|
+
);
|
|
20259
|
+
for (const agent of snapshot.agents) {
|
|
20260
|
+
appendConnectionRow(
|
|
20261
|
+
document2,
|
|
20262
|
+
content,
|
|
20263
|
+
RENDERER_AGENT_LABELS[agent.agent],
|
|
20264
|
+
agent.availability,
|
|
20265
|
+
null,
|
|
20266
|
+
agent.error,
|
|
20267
|
+
messages,
|
|
20268
|
+
agent.agent,
|
|
20269
|
+
agent
|
|
20270
|
+
);
|
|
20271
|
+
}
|
|
20272
|
+
};
|
|
20273
|
+
const diagnostics = getDiagnostics();
|
|
20274
|
+
render(diagnostics?.snapshot() ?? null);
|
|
20275
|
+
if (!diagnostics) {
|
|
20276
|
+
copyAll.disabled = true;
|
|
20277
|
+
return void 0;
|
|
20278
|
+
}
|
|
20279
|
+
copyAll.addEventListener("click", () => {
|
|
20280
|
+
const snapshot = diagnostics.snapshot();
|
|
20281
|
+
const report = snapshot.agents.map((agent) => diagnosticText(RENDERER_AGENT_LABELS[agent.agent], agent)).join("\n\n");
|
|
20282
|
+
copyDiagnosticsToClipboard(document2, copyAll, report, messages, messages.connectionCopyAll);
|
|
20283
|
+
});
|
|
20284
|
+
const unsubscribe = diagnostics.subscribe(() => render(diagnostics.snapshot()));
|
|
20285
|
+
refresh.addEventListener("click", () => {
|
|
20286
|
+
if (pending) return;
|
|
20287
|
+
pending = true;
|
|
20288
|
+
refresh.disabled = true;
|
|
20289
|
+
refresh.replaceChildren(
|
|
20290
|
+
createRendererSettingsIcon("diagnose", 16),
|
|
20291
|
+
messages.connectionRefreshing
|
|
20292
|
+
);
|
|
20293
|
+
void context.runLatest(() => diagnostics.refresh(), {
|
|
20294
|
+
success() {
|
|
20295
|
+
pending = false;
|
|
20296
|
+
refresh.disabled = false;
|
|
20297
|
+
refresh.replaceChildren(
|
|
20298
|
+
createRendererSettingsIcon("diagnose", 16),
|
|
20299
|
+
messages.connectionRefresh
|
|
20300
|
+
);
|
|
20301
|
+
render(diagnostics.snapshot());
|
|
20302
|
+
},
|
|
20303
|
+
failure(error51) {
|
|
20304
|
+
pending = false;
|
|
20305
|
+
refresh.disabled = false;
|
|
20306
|
+
refresh.replaceChildren(
|
|
20307
|
+
createRendererSettingsIcon("diagnose", 16),
|
|
20308
|
+
messages.connectionRefresh
|
|
20309
|
+
);
|
|
20310
|
+
render({
|
|
20311
|
+
...diagnostics.snapshot(),
|
|
20312
|
+
agents: diagnostics.snapshot().agents.map((agent) => ({
|
|
20313
|
+
...agent,
|
|
20314
|
+
availability: "error",
|
|
20315
|
+
error: {
|
|
20316
|
+
code: "internalError",
|
|
20317
|
+
message: error51 instanceof Error ? error51.message : String(error51),
|
|
20318
|
+
retryable: true,
|
|
20319
|
+
stage: "request"
|
|
20320
|
+
}
|
|
20321
|
+
}))
|
|
20322
|
+
});
|
|
20323
|
+
}
|
|
20324
|
+
});
|
|
20325
|
+
});
|
|
20326
|
+
return unsubscribe;
|
|
20327
|
+
}
|
|
20328
|
+
});
|
|
20329
|
+
}
|
|
19189
20330
|
function versionRow(context, label, version2) {
|
|
19190
20331
|
const row = context.content.ownerDocument.createElement("div");
|
|
19191
20332
|
row.className = "settings-update-version-row";
|
|
@@ -19459,23 +20600,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19459
20600
|
}
|
|
19460
20601
|
});
|
|
19461
20602
|
}
|
|
19462
|
-
function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null) {
|
|
20603
|
+
function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null) {
|
|
19463
20604
|
const unavailableIds = DEFAULT_RENDERER_SETTINGS_PAGE_IDS.filter(
|
|
19464
|
-
(id) => id !== "updates"
|
|
20605
|
+
(id) => id !== "updates" && id !== "connections"
|
|
19465
20606
|
);
|
|
19466
20607
|
return Object.freeze([
|
|
20608
|
+
connectionsPage(messages, getDiagnostics),
|
|
19467
20609
|
...unavailableIds.map((id) => unavailablePage(id, messages)),
|
|
19468
20610
|
updatesPage(messages, getUpdateClient)
|
|
19469
20611
|
]);
|
|
19470
20612
|
}
|
|
19471
|
-
function createDefaultRendererSettingsRegistry(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null) {
|
|
20613
|
+
function createDefaultRendererSettingsRegistry(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null) {
|
|
19472
20614
|
return createRendererSettingsPageRegistry(
|
|
19473
|
-
createDefaultRendererSettingsPages(messages, getUpdateClient)
|
|
20615
|
+
createDefaultRendererSettingsPages(messages, getUpdateClient, getDiagnostics)
|
|
19474
20616
|
);
|
|
19475
20617
|
}
|
|
19476
20618
|
|
|
19477
20619
|
// src/settings/shell.css
|
|
19478
|
-
var shell_default = ':host {\n --settings-bg: #181818;\n --settings-sidebar: #1c1c1c;\n --settings-panel: transparent;\n --settings-text: #f5f5f5;\n --settings-muted: #a1a1a1;\n --settings-border: rgb(255 255 255 / 10%);\n --settings-divider: rgb(255 255 255 / 10%);\n --settings-hover: rgb(255 255 255 / 6%);\n --settings-active: rgb(51 156 255 / 12%);\n --settings-focus: #339cff;\n color: var(--settings-text);\n color-scheme: dark;\n font:\n 14px/1.5 system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n letter-spacing: 0;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n letter-spacing: 0;\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\nbutton {\n color: inherit;\n}\n\n[hidden] {\n display: none !important;\n}\n\n.codexhost-settings-dialog {\n width: min(1120px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 32px));\n max-width: none;\n max-height: none;\n margin: auto;\n padding: 0;\n overflow: hidden;\n color: var(--settings-text);\n background: var(--settings-bg);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n box-shadow: 0 24px 64px rgb(0 0 0 / 38%);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: rgb(0 0 0 / 52%);\n}\n\n.settings-frame,\n.settings-layout {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n}\n\n.settings-frame {\n display: flex;\n flex-direction: column;\n}\n\n.settings-layout {\n flex: 1;\n display: grid;\n grid-template-columns: 240px minmax(0, 1fr);\n background: var(--settings-bg);\n}\n\n.settings-sidebar {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n background: var(--settings-sidebar);\n border-right: 1px solid var(--settings-border);\n padding-top: 28px;\n}\n\n.settings-header {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 64px;\n flex: none;\n padding: 0 16px;\n border-bottom: 1px solid var(--settings-border);\n}\n\n.settings-header-actions {\n display: flex;\n align-items: center;\n flex: none;\n gap: 12px;\n margin-left: auto;\n}\n\n.settings-icon-button.settings-star-link {\n width: auto;\n gap: 6px;\n padding-inline: 8px;\n font-size: 12px;\n line-height: 18px;\n text-decoration: none;\n border: 2px dashed #f5c542;\n white-space: nowrap;\n}\n\n.settings-star-link .codexhost-settings-icon {\n color: #f5c542;\n fill: currentColor;\n stroke: currentColor;\n}\n\n.settings-brand {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-brand__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n flex: none;\n color: var(--settings-text);\n}\n\n.settings-brand__mark .codexhost-settings-icon {\n width: 32px;\n height: 32px;\n object-fit: contain;\n}\n\n.settings-brand__copy {\n display: flex;\n min-width: 0;\n align-items: baseline;\n gap: 0;\n line-height: 20px;\n}\n\n.settings-brand__name {\n overflow: hidden;\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-brand__title {\n margin-left: 14px;\n padding-left: 14px;\n color: var(--settings-muted);\n font-size: 14px;\n font-weight: 400;\n border-left: 1px solid var(--settings-border);\n}\n\n.settings-nav {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 4px;\n padding: 0 12px 16px;\n overflow-y: auto;\n}\n\n.settings-nav-button {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n width: 100%;\n position: relative;\n min-height: 40px;\n flex: none;\n gap: 12px;\n padding: 8px 12px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 21px;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: 10px;\n cursor: pointer;\n}\n\n.settings-nav-button .codexhost-settings-icon {\n width: 18px;\n height: 18px;\n opacity: 0.9;\n}\n\n.settings-nav-button:hover {\n background: var(--settings-hover);\n}\n\n.settings-nav-button[aria-current="page"] {\n background: var(--settings-active);\n color: var(--settings-focus);\n}\n\n.settings-nav-button[aria-current="page"]::before {\n position: absolute;\n left: 0;\n width: 3px;\n height: 22px;\n content: "";\n background: var(--settings-focus);\n border-radius: 0 3px 3px 0;\n}\n\n.settings-nav-button span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex: none;\n padding: 0;\n color: var(--settings-muted);\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n}\n\n.settings-icon-button:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-icon-button:focus-visible,\n.settings-nav-button:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 1px;\n}\n\n.settings-page {\n display: block;\n position: relative;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n background: var(--settings-bg);\n scrollbar-gutter: stable;\n}\n\n.settings-page__content {\n width: min(930px, calc(100% - 80px));\n margin-inline: auto;\n}\n\n.settings-page__content {\n min-width: 0;\n padding: 44px 0 56px;\n}\n\n.settings-section-label {\n min-height: auto;\n padding: 0 0 28px;\n color: var(--settings-text);\n font-size: 24px;\n font-weight: 600;\n line-height: 30px;\n}\n\n.settings-status-list,\n.settings-empty {\n overflow: hidden;\n background: var(--settings-panel);\n}\n\n.settings-status-row {\n display: grid;\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\n position: relative;\n align-items: center;\n min-height: 88px;\n gap: 28px;\n padding: 16px 0;\n}\n\n.settings-status-row:not(:last-child)::after {\n content: "";\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 1px;\n background: var(--settings-divider);\n}\n\n.settings-status-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n color: var(--settings-text);\n gap: 14px;\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-status-row__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n flex: none;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 7%);\n border-radius: 50%;\n}\n\n.settings-status-badge {\n flex: none;\n padding: 5px 12px;\n color: var(--settings-muted);\n font-size: 13px;\n font-weight: 500;\n line-height: 18px;\n background: rgb(255 255 255 / 9%);\n border: 1px solid rgb(255 255 255 / 6%);\n border-radius: 6px;\n}\n\n.settings-status-row__detail {\n min-width: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-empty {\n display: flex;\n align-items: center;\n min-height: 72px;\n padding: 12px 16px;\n}\n\n.settings-empty > div {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n\n.settings-empty strong {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 500;\n line-height: 19px;\n}\n\n.settings-empty span {\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 19px;\n}\n\n.settings-page-error {\n padding: 16px;\n color: var(--settings-text);\n font-size: 13px;\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 20px;\n}\n\n.settings-update-metadata {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 24px;\n margin-bottom: 24px;\n padding: 0 4px 20px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-update-metadata__item {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n\n.settings-update-metadata__item span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-metadata__item strong {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-update-panel {\n display: grid;\n gap: 16px;\n min-height: 128px;\n padding: 20px;\n color: var(--settings-text);\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n}\n\n.settings-update-panel > strong,\n.settings-update-panel > span,\n.settings-update-summary,\n.settings-update-error {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-panel > span,\n.settings-update-summary {\n color: var(--settings-muted);\n}\n\n.settings-update-error {\n color: #ef4444;\n}\n\n.settings-update-progress {\n width: 100%;\n height: 8px;\n accent-color: #238be8;\n}\n\n.settings-update-progress-detail {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-notes {\n display: grid;\n min-width: 0;\n gap: 12px;\n color: var(--settings-muted);\n font-size: 14px;\n line-height: 22px;\n overflow-wrap: anywhere;\n}\n\n.settings-update-notes > :first-child {\n margin-top: 0;\n}\n\n.settings-update-notes > :last-child {\n margin-bottom: 0;\n}\n\n.settings-update-notes h1,\n.settings-update-notes h2,\n.settings-update-notes h3,\n.settings-update-notes h4,\n.settings-update-notes h5,\n.settings-update-notes h6 {\n margin: 6px 0 0;\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-update-notes h1 {\n font-size: 18px;\n line-height: 26px;\n}\n\n.settings-update-notes h2 {\n font-size: 17px;\n line-height: 24px;\n}\n\n.settings-update-notes h3,\n.settings-update-notes h4,\n.settings-update-notes h5,\n.settings-update-notes h6 {\n font-size: 14px;\n line-height: 22px;\n}\n\n.settings-update-notes p,\n.settings-update-notes ul,\n.settings-update-notes ol,\n.settings-update-notes pre,\n.settings-update-notes blockquote {\n margin: 0;\n}\n\n.settings-update-notes ul,\n.settings-update-notes ol {\n padding-left: 24px;\n}\n\n.settings-update-notes li {\n padding-left: 4px;\n}\n\n.settings-update-notes li::marker {\n color: var(--settings-muted);\n font-size: 0.85em;\n}\n\n.settings-update-notes li + li {\n margin-top: 14px;\n}\n\n.settings-update-notes .release-note-translation {\n display: block;\n margin-top: 3px;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-notes blockquote {\n padding: 8px 12px;\n color: var(--settings-muted);\n border-left: 3px solid var(--settings-focus);\n background: rgb(255 255 255 / 4%);\n}\n\n.settings-update-notes hr {\n width: 100%;\n margin: 2px 0;\n border: 0;\n border-top: 1px solid var(--settings-divider);\n}\n\n.settings-update-notes strong {\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-update-notes a {\n color: #7cb8ff;\n text-decoration: none;\n}\n\n.settings-update-notes a:hover {\n text-decoration: underline;\n}\n\n.settings-update-notes code {\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 12px;\n}\n\n.settings-update-notes :not(pre) > code {\n padding: 1px 5px;\n background: rgb(255 255 255 / 8%);\n border-radius: 4px;\n}\n\n.settings-update-notes pre {\n min-width: 0;\n max-width: 100%;\n padding: 10px 12px;\n overflow-x: auto;\n overflow-y: hidden;\n background: rgb(0 0 0 / 28%);\n border-radius: 6px;\n}\n\n.settings-update-notes pre code {\n line-height: 18px;\n white-space: pre-wrap;\n}\n\n.settings-update-version-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: 20px;\n min-height: 32px;\n color: var(--settings-muted);\n font-size: 13px;\n}\n\n.settings-update-version-row strong {\n color: var(--settings-text);\n font-size: 15px;\n}\n\n.settings-update-manual {\n display: grid;\n min-width: 0;\n gap: 6px;\n margin-top: 14px;\n padding-inline: 4px;\n}\n\n.settings-update-manual[hidden] {\n display: none;\n}\n\n.settings-update-manual span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-manual code {\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-actions {\n display: flex;\n min-width: 0;\n margin-top: 16px;\n}\n\n.settings-command-button,\n.settings-update-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: fit-content;\n min-height: 36px;\n gap: 8px;\n padding: 8px 12px;\n color: white;\n font: inherit;\n font-size: 13px;\n text-decoration: none;\n background: #1677d2;\n border: 1px solid #238be8;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.settings-command-button--secondary,\n.settings-update-link {\n color: var(--settings-text);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button:hover,\n.settings-update-link:hover {\n filter: brightness(1.08);\n}\n\n.settings-command-button:focus-visible,\n.settings-update-link:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 2px;\n}\n\n.codexhost-settings-icon {\n display: block;\n flex: none;\n stroke: currentColor;\n}\n\n@media (max-width: 720px) {\n .codexhost-settings-dialog {\n width: calc(100vw - 16px);\n height: calc(100vh - 16px);\n border-radius: 10px;\n }\n\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .settings-sidebar {\n border-right: 0;\n border-bottom: 1px solid var(--settings-border);\n }\n\n .settings-header {\n height: 56px;\n padding-inline: 14px;\n }\n\n .settings-icon-button.settings-star-link {\n width: 28px;\n padding: 0;\n }\n\n .settings-star-link span {\n display: none;\n }\n\n .settings-sidebar {\n padding-top: 20px;\n }\n\n .settings-nav {\n flex: none;\n flex-direction: row;\n gap: 4px;\n padding: 7px 8px 8px;\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n .settings-nav-button {\n width: auto;\n min-width: max-content;\n min-height: 34px;\n grid-template-columns: 16px auto;\n border-radius: 10px;\n }\n\n .settings-page__content {\n width: calc(100% - 40px);\n }\n\n .settings-page__content {\n padding-top: 32px;\n padding-bottom: 32px;\n }\n\n .settings-section-label {\n padding-bottom: 20px;\n font-size: 20px;\n line-height: 26px;\n }\n\n .settings-status-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 16px;\n }\n\n .settings-status-row__detail {\n grid-column: 1 / -1;\n margin: -8px 0 0 58px;\n }\n}\n\n@media (forced-colors: active) {\n :host,\n :host([data-theme="dark"]) {\n --settings-bg: Canvas;\n --settings-sidebar: Canvas;\n --settings-panel: Canvas;\n --settings-text: CanvasText;\n --settings-muted: GrayText;\n --settings-border: ButtonBorder;\n --settings-divider: ButtonBorder;\n --settings-hover: Highlight;\n --settings-active: Highlight;\n --settings-focus: Highlight;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
|
|
20620
|
+
var shell_default = ':host {\n --settings-bg: #181818;\n --settings-sidebar: #1c1c1c;\n --settings-panel: transparent;\n --settings-text: #f5f5f5;\n --settings-muted: #a1a1a1;\n --settings-border: rgb(255 255 255 / 10%);\n --settings-divider: rgb(255 255 255 / 10%);\n --settings-hover: rgb(255 255 255 / 6%);\n --settings-active: rgb(51 156 255 / 12%);\n --settings-focus: #339cff;\n color: var(--settings-text);\n color-scheme: dark;\n font:\n 14px/1.5 system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n letter-spacing: 0;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n letter-spacing: 0;\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\nbutton {\n color: inherit;\n}\n\n[hidden] {\n display: none !important;\n}\n\n.codexhost-settings-dialog {\n width: min(1120px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 32px));\n max-width: none;\n max-height: none;\n margin: auto;\n padding: 0;\n overflow: hidden;\n color: var(--settings-text);\n background: var(--settings-bg);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n box-shadow: 0 24px 64px rgb(0 0 0 / 38%);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: rgb(0 0 0 / 52%);\n}\n\n.settings-frame,\n.settings-layout {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n}\n\n.settings-frame {\n display: flex;\n flex-direction: column;\n}\n\n.settings-layout {\n flex: 1;\n display: grid;\n grid-template-columns: 240px minmax(0, 1fr);\n background: var(--settings-bg);\n}\n\n.settings-sidebar {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n background: var(--settings-sidebar);\n border-right: 1px solid var(--settings-border);\n padding-top: 28px;\n}\n\n.settings-header {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 64px;\n flex: none;\n padding: 0 16px;\n border-bottom: 1px solid var(--settings-border);\n}\n\n.settings-header-actions {\n display: flex;\n align-items: center;\n flex: none;\n gap: 12px;\n margin-left: auto;\n}\n\n.settings-icon-button.settings-star-link {\n width: auto;\n gap: 6px;\n padding-inline: 8px;\n font-size: 12px;\n line-height: 18px;\n text-decoration: none;\n border: 2px dashed #f5c542;\n white-space: nowrap;\n}\n\n.settings-star-link .codexhost-settings-icon {\n color: #f5c542;\n fill: currentColor;\n stroke: currentColor;\n}\n\n.settings-brand {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-brand__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n flex: none;\n color: var(--settings-text);\n}\n\n.settings-brand__mark .codexhost-settings-icon {\n width: 32px;\n height: 32px;\n object-fit: contain;\n}\n\n.settings-brand__copy {\n display: flex;\n min-width: 0;\n align-items: baseline;\n gap: 0;\n line-height: 20px;\n}\n\n.settings-brand__name {\n overflow: hidden;\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-brand__title {\n margin-left: 14px;\n padding-left: 14px;\n color: var(--settings-muted);\n font-size: 14px;\n font-weight: 400;\n border-left: 1px solid var(--settings-border);\n}\n\n.settings-nav {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 4px;\n padding: 0 12px 16px;\n overflow-y: auto;\n}\n\n.settings-nav-button {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n width: 100%;\n position: relative;\n min-height: 40px;\n flex: none;\n gap: 12px;\n padding: 8px 12px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 21px;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: 10px;\n cursor: pointer;\n}\n\n.settings-nav-button .codexhost-settings-icon {\n width: 18px;\n height: 18px;\n opacity: 0.9;\n}\n\n.settings-nav-button:hover {\n background: var(--settings-hover);\n}\n\n.settings-nav-button[aria-current="page"] {\n background: var(--settings-active);\n color: var(--settings-focus);\n}\n\n.settings-nav-button[aria-current="page"]::before {\n position: absolute;\n left: 0;\n width: 3px;\n height: 22px;\n content: "";\n background: var(--settings-focus);\n border-radius: 0 3px 3px 0;\n}\n\n.settings-nav-button span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex: none;\n padding: 0;\n color: var(--settings-muted);\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n}\n\n.settings-icon-button:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-icon-button:focus-visible,\n.settings-nav-button:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 1px;\n}\n\n.settings-page {\n display: block;\n position: relative;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n background: var(--settings-bg);\n scrollbar-gutter: stable;\n}\n\n.settings-page__content {\n width: min(930px, calc(100% - 80px));\n margin-inline: auto;\n}\n\n.settings-page__content {\n min-width: 0;\n padding: 44px 0 56px;\n}\n\n.settings-section-label {\n min-height: auto;\n padding: 0 0 28px;\n color: var(--settings-text);\n font-size: 24px;\n font-weight: 600;\n line-height: 30px;\n}\n\n.settings-status-list,\n.settings-empty {\n overflow: hidden;\n background: var(--settings-panel);\n}\n\n.settings-status-row {\n display: grid;\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\n position: relative;\n align-items: center;\n min-height: 88px;\n gap: 28px;\n padding: 16px 0;\n}\n\n.settings-status-row:not(:last-child)::after {\n content: "";\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 1px;\n background: var(--settings-divider);\n}\n\n.settings-status-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n color: var(--settings-text);\n gap: 14px;\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-status-row__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n flex: none;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 7%);\n border-radius: 50%;\n}\n\n.settings-status-badge {\n flex: none;\n padding: 5px 12px;\n color: var(--settings-muted);\n font-size: 13px;\n font-weight: 500;\n line-height: 18px;\n background: rgb(255 255 255 / 9%);\n border: 1px solid rgb(255 255 255 / 6%);\n border-radius: 6px;\n}\n\n.settings-status-row__detail {\n min-width: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-page-description {\n max-width: 760px;\n margin: -12px 0 24px;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-connection-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.settings-connection-list {\n min-width: 0;\n border-top: 1px solid var(--settings-divider);\n}\n\n.settings-connection-row {\n display: grid;\n grid-template-columns: minmax(180px, 1fr) auto minmax(260px, 1.5fr);\n align-items: center;\n min-width: 0;\n min-height: 76px;\n gap: 24px;\n padding: 14px 0;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n gap: 10px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 20px;\n}\n\n.settings-connection-row__identity strong {\n min-width: 0;\n overflow-wrap: anywhere;\n font-weight: 500;\n}\n\n.settings-connection-row__dot {\n width: 9px;\n height: 9px;\n flex: none;\n border-radius: 50%;\n background: var(--settings-muted);\n}\n\n.settings-connection-row__dot[data-connection-tone="ready"] {\n background: #22c55e;\n}\n\n.settings-connection-row__dot[data-connection-tone="checking"] {\n background: #f5c542;\n}\n\n.settings-connection-row__dot[data-connection-tone="failed"] {\n background: #ef4444;\n}\n\n.settings-status-badge[data-connection-tone="ready"] {\n color: #4ade80;\n}\n\n.settings-status-badge[data-connection-tone="checking"] {\n color: #f5c542;\n}\n\n.settings-status-badge[data-connection-tone="failed"] {\n color: #f87171;\n}\n\n.settings-connection-row__detail {\n display: grid;\n min-width: 0;\n align-items: center;\n gap: 2px 12px;\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-connection-row__reason {\n min-width: 0;\n overflow-wrap: anywhere;\n white-space: pre-wrap;\n}\n\n.settings-connection-details-toggle {\n width: fit-content;\n padding: 0;\n color: var(--settings-focus);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n background: transparent;\n border: 0;\n cursor: pointer;\n}\n\n.settings-connection-details-toggle:hover {\n text-decoration: underline;\n}\n\n.settings-connection-details {\n display: grid;\n grid-column: 1 / -1;\n gap: 6px;\n min-width: 0;\n margin: 4px 0 2px 32px;\n padding: 12px;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 4%);\n border-left: 2px solid #ef4444;\n border-radius: 4px;\n}\n\n.settings-connection-detail-line {\n display: grid;\n grid-template-columns: 112px minmax(0, 1fr);\n gap: 12px;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-connection-detail-line span {\n color: var(--settings-muted);\n}\n\n.settings-connection-detail-line code {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n white-space: pre-wrap;\n}\n\n.settings-connection-stderr {\n max-height: 220px;\n min-width: 0;\n margin: 4px 0 0;\n padding: 10px;\n overflow: auto;\n color: #fca5a5;\n font:\n 12px/18px ui-monospace,\n "SFMono-Regular",\n Consolas,\n "Liberation Mono",\n monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n background: rgb(0 0 0 / 28%);\n border-radius: 4px;\n}\n\n.settings-connection-details .settings-command-button {\n justify-self: start;\n min-height: 30px;\n font-size: 12px;\n}\n\n.settings-connection-row__detail time {\n color: var(--settings-muted);\n opacity: 0.8;\n}\n\n.settings-empty {\n display: flex;\n align-items: center;\n min-height: 72px;\n padding: 12px 16px;\n}\n\n.settings-empty > div {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n\n.settings-empty strong {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 500;\n line-height: 19px;\n}\n\n.settings-empty span {\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 19px;\n}\n\n.settings-page-error {\n padding: 16px;\n color: var(--settings-text);\n font-size: 13px;\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 20px;\n}\n\n.settings-update-metadata {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 24px;\n margin-bottom: 24px;\n padding: 0 4px 20px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-update-metadata__item {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n\n.settings-update-metadata__item span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-metadata__item strong {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-update-panel {\n display: grid;\n gap: 16px;\n min-height: 128px;\n padding: 20px;\n color: var(--settings-text);\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n}\n\n.settings-update-panel > strong,\n.settings-update-panel > span,\n.settings-update-summary,\n.settings-update-error {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-panel > span,\n.settings-update-summary {\n color: var(--settings-muted);\n}\n\n.settings-update-error {\n color: #ef4444;\n}\n\n.settings-update-progress {\n width: 100%;\n height: 8px;\n accent-color: #238be8;\n}\n\n.settings-update-progress-detail {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-notes {\n display: grid;\n min-width: 0;\n gap: 12px;\n color: var(--settings-muted);\n font-size: 14px;\n line-height: 22px;\n overflow-wrap: anywhere;\n}\n\n.settings-update-notes > :first-child {\n margin-top: 0;\n}\n\n.settings-update-notes > :last-child {\n margin-bottom: 0;\n}\n\n.settings-update-notes h1,\n.settings-update-notes h2,\n.settings-update-notes h3,\n.settings-update-notes h4,\n.settings-update-notes h5,\n.settings-update-notes h6 {\n margin: 6px 0 0;\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-update-notes h1 {\n font-size: 18px;\n line-height: 26px;\n}\n\n.settings-update-notes h2 {\n font-size: 17px;\n line-height: 24px;\n}\n\n.settings-update-notes h3,\n.settings-update-notes h4,\n.settings-update-notes h5,\n.settings-update-notes h6 {\n font-size: 14px;\n line-height: 22px;\n}\n\n.settings-update-notes p,\n.settings-update-notes ul,\n.settings-update-notes ol,\n.settings-update-notes pre,\n.settings-update-notes blockquote {\n margin: 0;\n}\n\n.settings-update-notes ul,\n.settings-update-notes ol {\n padding-left: 24px;\n}\n\n.settings-update-notes li {\n padding-left: 4px;\n}\n\n.settings-update-notes li::marker {\n color: var(--settings-muted);\n font-size: 0.85em;\n}\n\n.settings-update-notes li + li {\n margin-top: 14px;\n}\n\n.settings-update-notes .release-note-translation {\n display: block;\n margin-top: 3px;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-notes blockquote {\n padding: 8px 12px;\n color: var(--settings-muted);\n border-left: 3px solid var(--settings-focus);\n background: rgb(255 255 255 / 4%);\n}\n\n.settings-update-notes hr {\n width: 100%;\n margin: 2px 0;\n border: 0;\n border-top: 1px solid var(--settings-divider);\n}\n\n.settings-update-notes strong {\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-update-notes a {\n color: #7cb8ff;\n text-decoration: none;\n}\n\n.settings-update-notes a:hover {\n text-decoration: underline;\n}\n\n.settings-update-notes code {\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 12px;\n}\n\n.settings-update-notes :not(pre) > code {\n padding: 1px 5px;\n background: rgb(255 255 255 / 8%);\n border-radius: 4px;\n}\n\n.settings-update-notes pre {\n min-width: 0;\n max-width: 100%;\n padding: 10px 12px;\n overflow-x: auto;\n overflow-y: hidden;\n background: rgb(0 0 0 / 28%);\n border-radius: 6px;\n}\n\n.settings-update-notes pre code {\n line-height: 18px;\n white-space: pre-wrap;\n}\n\n.settings-update-version-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: 20px;\n min-height: 32px;\n color: var(--settings-muted);\n font-size: 13px;\n}\n\n.settings-update-version-row strong {\n color: var(--settings-text);\n font-size: 15px;\n}\n\n.settings-update-manual {\n display: grid;\n min-width: 0;\n gap: 6px;\n margin-top: 14px;\n padding-inline: 4px;\n}\n\n.settings-update-manual[hidden] {\n display: none;\n}\n\n.settings-update-manual span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-manual code {\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-actions {\n display: flex;\n min-width: 0;\n margin-top: 16px;\n}\n\n.settings-command-button,\n.settings-update-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: fit-content;\n min-height: 36px;\n gap: 8px;\n padding: 8px 12px;\n color: white;\n font: inherit;\n font-size: 13px;\n text-decoration: none;\n background: #1677d2;\n border: 1px solid #238be8;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.settings-command-button--secondary,\n.settings-update-link {\n color: var(--settings-text);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button:hover,\n.settings-update-link:hover {\n filter: brightness(1.08);\n}\n\n.settings-command-button:focus-visible,\n.settings-update-link:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 2px;\n}\n\n.codexhost-settings-icon {\n display: block;\n flex: none;\n stroke: currentColor;\n}\n\n@media (max-width: 720px) {\n .codexhost-settings-dialog {\n width: calc(100vw - 16px);\n height: calc(100vh - 16px);\n border-radius: 10px;\n }\n\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .settings-sidebar {\n border-right: 0;\n border-bottom: 1px solid var(--settings-border);\n }\n\n .settings-header {\n height: 56px;\n padding-inline: 14px;\n }\n\n .settings-icon-button.settings-star-link {\n width: 28px;\n padding: 0;\n }\n\n .settings-star-link span {\n display: none;\n }\n\n .settings-sidebar {\n padding-top: 20px;\n }\n\n .settings-nav {\n flex: none;\n flex-direction: row;\n gap: 4px;\n padding: 7px 8px 8px;\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n .settings-nav-button {\n width: auto;\n min-width: max-content;\n min-height: 34px;\n grid-template-columns: 16px auto;\n border-radius: 10px;\n }\n\n .settings-page__content {\n width: calc(100% - 40px);\n }\n\n .settings-page__content {\n padding-top: 32px;\n padding-bottom: 32px;\n }\n\n .settings-section-label {\n padding-bottom: 20px;\n font-size: 20px;\n line-height: 26px;\n }\n\n .settings-status-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 16px;\n }\n\n .settings-connection-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 10px 16px;\n }\n\n .settings-connection-row__detail {\n grid-column: 1 / -1;\n }\n\n .settings-status-row__detail {\n grid-column: 1 / -1;\n margin: -8px 0 0 58px;\n }\n}\n\n@media (forced-colors: active) {\n :host,\n :host([data-theme="dark"]) {\n --settings-bg: Canvas;\n --settings-sidebar: Canvas;\n --settings-panel: Canvas;\n --settings-text: CanvasText;\n --settings-muted: GrayText;\n --settings-border: ButtonBorder;\n --settings-divider: ButtonBorder;\n --settings-hover: Highlight;\n --settings-active: Highlight;\n --settings-focus: Highlight;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
|
|
19479
20621
|
|
|
19480
20622
|
// src/settings/shell.ts
|
|
19481
20623
|
var SETTINGS_SHELL_ATTRIBUTE = "data-codexhost-settings-shell";
|
|
@@ -19945,7 +21087,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19945
21087
|
const messages = rendererSettingsMessages(locale);
|
|
19946
21088
|
const definitions = createDefaultRendererSettingsPages(
|
|
19947
21089
|
messages,
|
|
19948
|
-
options.getUpdateClient ?? (() => null)
|
|
21090
|
+
options.getUpdateClient ?? (() => null),
|
|
21091
|
+
options.getConnectionDiagnostics ?? (() => null)
|
|
19949
21092
|
);
|
|
19950
21093
|
const nextShell = installRendererSettingsShell(definitions, messages, ownerWindow.document);
|
|
19951
21094
|
const nextTrigger = installRendererSettingsHeaderTrigger({
|
|
@@ -20137,17 +21280,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20137
21280
|
function draftPermissionMode(catalog, requested) {
|
|
20138
21281
|
return catalog.modes.find(({ id }) => id === requested)?.id ?? catalog.modes.find(({ id }) => id === catalog.defaultModeId)?.id ?? catalog.defaultModeId;
|
|
20139
21282
|
}
|
|
21283
|
+
function shouldPersistNewThreadConfigurationSelection(phase) {
|
|
21284
|
+
return phase === "draft";
|
|
21285
|
+
}
|
|
20140
21286
|
function restoredThreadOwnership(inspection) {
|
|
20141
21287
|
if (inspection.owner === "codex") return { agent: "codex" };
|
|
20142
21288
|
if (inspection.harnessId === "pi") {
|
|
20143
|
-
|
|
21289
|
+
const transportSelection = decodePiTransportModelId(inspection.transportModelId);
|
|
21290
|
+
if (!transportSelection) {
|
|
20144
21291
|
throw new Error("Pi Thread reported an incompatible transport Model");
|
|
20145
21292
|
}
|
|
20146
|
-
const
|
|
21293
|
+
const model = inspection.effectiveModel ?? transportSelection.model;
|
|
21294
|
+
const thinkingOptionId = selectableThinkingOptionId(inspection) ?? transportSelection.thinkingOptionId;
|
|
20147
21295
|
return {
|
|
20148
21296
|
agent: "pi",
|
|
20149
|
-
...
|
|
20150
|
-
...
|
|
21297
|
+
...model ? { model } : {},
|
|
21298
|
+
...thinkingOptionId ? { thinkingOptionId } : {},
|
|
20151
21299
|
...inspection.effectivePermissionModeId ? { permissionModeId: inspection.effectivePermissionModeId } : {}
|
|
20152
21300
|
};
|
|
20153
21301
|
}
|
|
@@ -20158,10 +21306,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20158
21306
|
}
|
|
20159
21307
|
const model = inspection.effectiveModel ?? transportSelection.model;
|
|
20160
21308
|
const thinkingOptionId = selectableThinkingOptionId(inspection) ?? transportSelection.thinkingOptionId;
|
|
21309
|
+
const permissionModeId = inspection.effectivePermissionModeId ?? transportSelection.permissionModeId;
|
|
20161
21310
|
return {
|
|
20162
21311
|
agent: "grok",
|
|
20163
21312
|
...model ? { model } : {},
|
|
20164
|
-
...thinkingOptionId ? { thinkingOptionId } : {}
|
|
21313
|
+
...thinkingOptionId ? { thinkingOptionId } : {},
|
|
21314
|
+
...permissionModeId ? { permissionModeId } : {}
|
|
20165
21315
|
};
|
|
20166
21316
|
}
|
|
20167
21317
|
if (inspection.harnessId === "claude-code") {
|
|
@@ -20192,10 +21342,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20192
21342
|
function isOwnershipSubmissionBlocked(status) {
|
|
20193
21343
|
return status === "loading" || status === "error";
|
|
20194
21344
|
}
|
|
20195
|
-
function shouldTransferComposerState(sourceTarget, replacementTarget, sourcePhase) {
|
|
21345
|
+
function shouldTransferComposerState(sourceTarget, replacementTarget, sourcePhase, submissionPending = false) {
|
|
20196
21346
|
if (!sourceTarget || !replacementTarget) return false;
|
|
20197
21347
|
if (sourceTarget === replacementTarget) return true;
|
|
20198
|
-
return sourcePhase === "locked" && sourceTarget[0] === "default" && replacementTarget[0] === "conversation";
|
|
21348
|
+
return (sourcePhase === "locked" || submissionPending) && sourceTarget[0] === "default" && replacementTarget[0] === "conversation";
|
|
20199
21349
|
}
|
|
20200
21350
|
function isLateConversationTarget(mountedTarget, currentTarget) {
|
|
20201
21351
|
if (currentTarget?.[0] !== "conversation") return false;
|
|
@@ -20204,13 +21354,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20204
21354
|
if (mountedTarget?.[0] !== "conversation") return false;
|
|
20205
21355
|
return mountedTarget.length !== currentTarget.length || mountedTarget.some((value, index) => value !== currentTarget[index]);
|
|
20206
21356
|
}
|
|
20207
|
-
function lateConversationTargetResolution(mountedTarget, currentTarget, sourcePhase) {
|
|
21357
|
+
function lateConversationTargetResolution(mountedTarget, currentTarget, sourcePhase, submissionPending = false) {
|
|
20208
21358
|
if (!isLateConversationTarget(mountedTarget, currentTarget)) return "none";
|
|
20209
|
-
return mountedTarget?.[0] === "default" && sourcePhase === "locked" ? "transfer" : "inspect";
|
|
21359
|
+
return mountedTarget?.[0] === "default" && (sourcePhase === "locked" || submissionPending) ? "transfer" : "inspect";
|
|
20210
21360
|
}
|
|
20211
21361
|
function isComposerModelWriteAllowed(target) {
|
|
20212
21362
|
return target?.[0] === "default";
|
|
20213
21363
|
}
|
|
21364
|
+
function shouldApplyDraftAgentCarrier(agent, model) {
|
|
21365
|
+
return agent === "codex" || model !== void 0;
|
|
21366
|
+
}
|
|
20214
21367
|
function applyComposerModelWrite(target, write) {
|
|
20215
21368
|
if (target?.[0] === "conversation") return true;
|
|
20216
21369
|
if (!isComposerModelWriteAllowed(target)) return false;
|
|
@@ -20275,8 +21428,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20275
21428
|
getClient: () => modelControl,
|
|
20276
21429
|
getLocalAgent: localAgentForSidebarThread
|
|
20277
21430
|
});
|
|
21431
|
+
let connectionDiagnostics = null;
|
|
20278
21432
|
const settingsLifecycle = installRendererSettingsLifecycle(window, {
|
|
20279
|
-
getUpdateClient: () => modelControl
|
|
21433
|
+
getUpdateClient: () => modelControl,
|
|
21434
|
+
getConnectionDiagnostics: () => connectionDiagnostics
|
|
20280
21435
|
});
|
|
20281
21436
|
let adapterStatus = {
|
|
20282
21437
|
state: "installing",
|
|
@@ -20287,6 +21442,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20287
21442
|
let harnessAvailability = Object.fromEntries(
|
|
20288
21443
|
externalAgents.map((agent) => [agent, "checking"])
|
|
20289
21444
|
);
|
|
21445
|
+
const harnessAvailabilityErrors = {
|
|
21446
|
+
pi: void 0,
|
|
21447
|
+
"claude-code": void 0,
|
|
21448
|
+
"deepseek-harness": void 0,
|
|
21449
|
+
grok: void 0
|
|
21450
|
+
};
|
|
21451
|
+
const connectionListeners = /* @__PURE__ */ new Set();
|
|
21452
|
+
const publishConnectionStatus = () => {
|
|
21453
|
+
for (const listener of connectionListeners) listener();
|
|
21454
|
+
};
|
|
20290
21455
|
let availabilityRequestGeneration = 0;
|
|
20291
21456
|
let availabilityRequest = null;
|
|
20292
21457
|
let availabilityRetryTimer = null;
|
|
@@ -20306,7 +21471,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20306
21471
|
writeNewThreadExternalConfigurationPreference(
|
|
20307
21472
|
state.agent,
|
|
20308
21473
|
model,
|
|
20309
|
-
controller.thinkingOptionForAgent(composer, state.agent)
|
|
21474
|
+
controller.thinkingOptionForAgent(composer, state.agent),
|
|
21475
|
+
controller.permissionModeForAgent(composer, state.agent)
|
|
20310
21476
|
);
|
|
20311
21477
|
}
|
|
20312
21478
|
}
|
|
@@ -20333,6 +21499,40 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20333
21499
|
mounted.accountCredits
|
|
20334
21500
|
);
|
|
20335
21501
|
};
|
|
21502
|
+
const refreshCommands = async (mounted) => {
|
|
21503
|
+
const state = controller.get(mounted.composer);
|
|
21504
|
+
const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
|
|
21505
|
+
if (state.agent === "codex" || !threadId || !modelControl) {
|
|
21506
|
+
mounted.control.harnessCommands.setCommands([]);
|
|
21507
|
+
return;
|
|
21508
|
+
}
|
|
21509
|
+
try {
|
|
21510
|
+
const catalog = await modelControl.inspectThreadCommands({ threadId });
|
|
21511
|
+
if (disposed || mountedByComposer.get(mounted.composer) !== mounted || threadIdFromComposerModelTarget(mounted.modelTarget) !== threadId || controller.get(mounted.composer).agent === "codex") {
|
|
21512
|
+
return;
|
|
21513
|
+
}
|
|
21514
|
+
mounted.control.harnessCommands.setCommands(catalog.commands);
|
|
21515
|
+
} catch {
|
|
21516
|
+
if (mountedByComposer.get(mounted.composer) === mounted) {
|
|
21517
|
+
mounted.control.harnessCommands.setCommands([]);
|
|
21518
|
+
}
|
|
21519
|
+
}
|
|
21520
|
+
};
|
|
21521
|
+
const executeCommand = async (mounted, command) => {
|
|
21522
|
+
const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
|
|
21523
|
+
if (!threadId || !modelControl || controller.get(mounted.composer).agent === "codex") return;
|
|
21524
|
+
mounted.control.harnessCommands.setExecuting(command.id);
|
|
21525
|
+
try {
|
|
21526
|
+
await modelControl.executeThreadCommand({ threadId, commandId: command.id });
|
|
21527
|
+
} catch (error51) {
|
|
21528
|
+
console.error(
|
|
21529
|
+
"codexhost Harness command failed",
|
|
21530
|
+
error51 instanceof Error ? error51.message : String(error51)
|
|
21531
|
+
);
|
|
21532
|
+
} finally {
|
|
21533
|
+
mounted.control.harnessCommands.setExecuting(null);
|
|
21534
|
+
}
|
|
21535
|
+
};
|
|
20336
21536
|
const applyThreadUsageUpdate = (update) => {
|
|
20337
21537
|
for (const mounted of mountedByComposer.values()) {
|
|
20338
21538
|
if (threadIdFromComposerModelTarget(mounted.modelTarget) !== update.threadId) continue;
|
|
@@ -20464,6 +21664,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20464
21664
|
} finally {
|
|
20465
21665
|
if (isCurrentOwnershipRequest(mounted, generation)) {
|
|
20466
21666
|
renderMounted(mounted);
|
|
21667
|
+
if (mounted.ownershipStatus !== "error") void refreshCommands(mounted);
|
|
20467
21668
|
sidebarAgentIcons.refresh();
|
|
20468
21669
|
if (mounted.ownershipStatus !== "error" && shouldRetryExternalThreadUsage(
|
|
20469
21670
|
controller.get(mounted.composer).agent,
|
|
@@ -20480,7 +21681,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20480
21681
|
const resolution = lateConversationTargetResolution(
|
|
20481
21682
|
mounted.modelTarget,
|
|
20482
21683
|
currentTarget,
|
|
20483
|
-
controller.get(mounted.composer).phase
|
|
21684
|
+
controller.get(mounted.composer).phase,
|
|
21685
|
+
controller.isSubmissionPending(mounted.composer)
|
|
20484
21686
|
);
|
|
20485
21687
|
if (resolution === "none") return false;
|
|
20486
21688
|
const previousTarget = mounted.modelTarget;
|
|
@@ -20547,6 +21749,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20547
21749
|
}
|
|
20548
21750
|
if (inspection.status !== "ready") throw new Error(inspection.error.message);
|
|
20549
21751
|
const current = controller.get(mounted.composer);
|
|
21752
|
+
const previousModel = controller.modelForAgent(mounted.composer, agent);
|
|
21753
|
+
const previousModelAvailable = previousModel !== void 0 && inspection.catalog.models.some((model) => model.ref.id === previousModel.id);
|
|
21754
|
+
if (current.phase === "locked" && previousModel && !previousModelAvailable) {
|
|
21755
|
+
throw new Error("Existing Thread Model is absent from the current Catalog");
|
|
21756
|
+
}
|
|
21757
|
+
const preferredConfiguration = current.phase === "draft" && !previousModelAvailable ? readNewThreadExternalConfigurationPreference(
|
|
21758
|
+
agent,
|
|
21759
|
+
inspection.catalog,
|
|
21760
|
+
inspection.permissionModes
|
|
21761
|
+
) : void 0;
|
|
20550
21762
|
const previousPermissionModeId = controller.permissionModeForAgent(mounted.composer, agent);
|
|
20551
21763
|
let selectedPermissionModeId;
|
|
20552
21764
|
if (inspection.capabilities.configuration.selectPermissionMode) {
|
|
@@ -20556,7 +21768,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20556
21768
|
}
|
|
20557
21769
|
mounted.permissionModeView = { status: "loading", catalog: permissionModes };
|
|
20558
21770
|
const effectivePermissionModeId = current.phase === "locked" ? mounted.threadConfiguration?.effectivePermissionModeId : void 0;
|
|
20559
|
-
const preferredPermissionModeId = agent === "claude-code" ? readClaudePermissionModePreference(permissionModes) : void 0;
|
|
21771
|
+
const preferredPermissionModeId = preferredConfiguration?.permissionModeId ?? (agent === "claude-code" ? readClaudePermissionModePreference(permissionModes) : void 0);
|
|
20560
21772
|
selectedPermissionModeId = draftPermissionMode(
|
|
20561
21773
|
permissionModes,
|
|
20562
21774
|
effectivePermissionModeId ?? previousPermissionModeId ?? preferredPermissionModeId
|
|
@@ -20585,12 +21797,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20585
21797
|
}
|
|
20586
21798
|
return;
|
|
20587
21799
|
}
|
|
20588
|
-
const previousModel = controller.modelForAgent(mounted.composer, agent);
|
|
20589
|
-
const previousModelAvailable = previousModel !== void 0 && inspection.catalog.models.some((model) => model.ref.id === previousModel.id);
|
|
20590
|
-
if (current.phase === "locked" && previousModel && !previousModelAvailable) {
|
|
20591
|
-
throw new Error("Existing Thread Model is absent from the current Catalog");
|
|
20592
|
-
}
|
|
20593
|
-
const preferredConfiguration = current.phase === "draft" && !previousModelAvailable ? readNewThreadExternalConfigurationPreference(agent, inspection.catalog) : void 0;
|
|
20594
21800
|
const selected = previousModelAvailable ? previousModel : preferredConfiguration?.model ?? inspection.catalog.defaultModel;
|
|
20595
21801
|
if (!selected) throw new Error("External Harness did not report its default Model");
|
|
20596
21802
|
const effectiveCatalog = current.phase === "locked" && mounted.threadConfiguration ? catalogWithConfigurationState(inspection.catalog, selected, mounted.threadConfiguration) : inspection.catalog;
|
|
@@ -20670,6 +21876,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20670
21876
|
}
|
|
20671
21877
|
};
|
|
20672
21878
|
const selectExternalModel = async (mounted, modelId) => {
|
|
21879
|
+
controller.clearPendingSubmission(mounted.composer);
|
|
20673
21880
|
const current = controller.get(mounted.composer);
|
|
20674
21881
|
if (current.agent === "codex") return;
|
|
20675
21882
|
const agent = current.agent;
|
|
@@ -20741,13 +21948,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20741
21948
|
effectiveThinkingOptionId = supportsThinkingSelection ? selectableThinkingOptionId(state) : void 0;
|
|
20742
21949
|
effectiveCatalog = supportsThinkingSelection ? catalogWithConfigurationState(catalog, effectiveModel, state) : catalog;
|
|
20743
21950
|
resolvedModelLabel = state.resolvedModelLabel;
|
|
20744
|
-
const
|
|
21951
|
+
const effectivePermissionModeId2 = state.effectivePermissionModeId ?? previousPermissionModeId;
|
|
20745
21952
|
if (!applyExternalConfiguration(
|
|
20746
21953
|
mounted,
|
|
20747
21954
|
agent,
|
|
20748
21955
|
effectiveModel,
|
|
20749
21956
|
effectiveThinkingOptionId,
|
|
20750
|
-
|
|
21957
|
+
effectivePermissionModeId2
|
|
20751
21958
|
)) {
|
|
20752
21959
|
throw new Error("Confirmed external Model could not be applied to the Composer");
|
|
20753
21960
|
}
|
|
@@ -20756,11 +21963,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20756
21963
|
if (!isCurrentModelRequest(mounted, generation)) return;
|
|
20757
21964
|
controller.setExternalModel(mounted.composer, agent, effectiveModel);
|
|
20758
21965
|
controller.setExternalThinkingOption(mounted.composer, agent, effectiveThinkingOptionId);
|
|
20759
|
-
|
|
20760
|
-
|
|
20761
|
-
|
|
20762
|
-
|
|
20763
|
-
)
|
|
21966
|
+
const effectivePermissionModeId = mounted.threadConfiguration?.effectivePermissionModeId ?? previousPermissionModeId;
|
|
21967
|
+
if (effectivePermissionModeId) {
|
|
21968
|
+
controller.setExternalPermissionMode(mounted.composer, agent, effectivePermissionModeId);
|
|
21969
|
+
}
|
|
21970
|
+
if (shouldPersistNewThreadConfigurationSelection(current.phase)) {
|
|
21971
|
+
writeNewThreadExternalConfigurationPreference(
|
|
21972
|
+
agent,
|
|
21973
|
+
effectiveModel,
|
|
21974
|
+
effectiveThinkingOptionId,
|
|
21975
|
+
effectivePermissionModeId
|
|
21976
|
+
);
|
|
21977
|
+
}
|
|
20764
21978
|
mounted.modelView = {
|
|
20765
21979
|
status: "ready",
|
|
20766
21980
|
catalog: effectiveCatalog,
|
|
@@ -20793,6 +22007,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20793
22007
|
}
|
|
20794
22008
|
};
|
|
20795
22009
|
const selectPermissionMode = async (mounted, permissionModeId) => {
|
|
22010
|
+
controller.clearPendingSubmission(mounted.composer);
|
|
20796
22011
|
const current = controller.get(mounted.composer);
|
|
20797
22012
|
if (current.agent === "codex") return;
|
|
20798
22013
|
const agent = current.agent;
|
|
@@ -20801,9 +22016,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20801
22016
|
const model = controller.modelForAgent(mounted.composer, agent);
|
|
20802
22017
|
if (!catalog || !selectedPermissionModeId || !model || !modelControl) return;
|
|
20803
22018
|
const previousPermissionModeId = controller.permissionModeForAgent(mounted.composer, agent);
|
|
20804
|
-
if (agent === "claude-code") {
|
|
20805
|
-
writeClaudePermissionModePreference(selectedPermissionModeId);
|
|
20806
|
-
}
|
|
20807
22019
|
const thinkingOptionId = controller.thinkingOptionForAgent(mounted.composer, agent);
|
|
20808
22020
|
const generation = controller.beginModelRequest(mounted.composer);
|
|
20809
22021
|
mounted.permissionModeView = {
|
|
@@ -20868,6 +22080,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20868
22080
|
}
|
|
20869
22081
|
if (!isCurrentModelRequest(mounted, generation)) return;
|
|
20870
22082
|
controller.setExternalPermissionMode(mounted.composer, agent, effectivePermissionModeId);
|
|
22083
|
+
if (shouldPersistNewThreadConfigurationSelection(current.phase)) {
|
|
22084
|
+
writeNewThreadExternalConfigurationPreference(
|
|
22085
|
+
agent,
|
|
22086
|
+
model,
|
|
22087
|
+
thinkingOptionId,
|
|
22088
|
+
effectivePermissionModeId
|
|
22089
|
+
);
|
|
22090
|
+
if (agent === "claude-code") {
|
|
22091
|
+
writeClaudePermissionModePreference(effectivePermissionModeId);
|
|
22092
|
+
}
|
|
22093
|
+
}
|
|
20871
22094
|
mounted.permissionModeView = {
|
|
20872
22095
|
status: "ready",
|
|
20873
22096
|
catalog,
|
|
@@ -20895,6 +22118,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20895
22118
|
}
|
|
20896
22119
|
};
|
|
20897
22120
|
const selectExternalThinking = async (mounted, thinkingOptionId) => {
|
|
22121
|
+
controller.clearPendingSubmission(mounted.composer);
|
|
20898
22122
|
const current = controller.get(mounted.composer);
|
|
20899
22123
|
if (current.agent === "codex") return;
|
|
20900
22124
|
const agent = current.agent;
|
|
@@ -20973,7 +22197,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20973
22197
|
}
|
|
20974
22198
|
if (!isCurrentModelRequest(mounted, generation)) return;
|
|
20975
22199
|
controller.setExternalThinkingOption(mounted.composer, agent, effectiveThinkingOptionId);
|
|
20976
|
-
|
|
22200
|
+
const effectivePermissionModeId = mounted.threadConfiguration?.effectivePermissionModeId ?? permissionModeId;
|
|
22201
|
+
if (effectivePermissionModeId) {
|
|
22202
|
+
controller.setExternalPermissionMode(mounted.composer, agent, effectivePermissionModeId);
|
|
22203
|
+
}
|
|
22204
|
+
if (shouldPersistNewThreadConfigurationSelection(current.phase)) {
|
|
22205
|
+
writeNewThreadExternalConfigurationPreference(
|
|
22206
|
+
agent,
|
|
22207
|
+
model,
|
|
22208
|
+
effectiveThinkingOptionId,
|
|
22209
|
+
effectivePermissionModeId
|
|
22210
|
+
);
|
|
22211
|
+
}
|
|
20977
22212
|
mounted.modelView = {
|
|
20978
22213
|
status: "ready",
|
|
20979
22214
|
catalog: effectiveCatalog,
|
|
@@ -20998,13 +22233,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20998
22233
|
};
|
|
20999
22234
|
const switchComposerAgent = async (mounted, agent) => {
|
|
21000
22235
|
if (agent !== "codex" && harnessAvailability[agent] !== "ready") return false;
|
|
22236
|
+
controller.clearPendingSubmission(mounted.composer);
|
|
21001
22237
|
const composerId = controller.get(mounted.composer).composerId;
|
|
21002
22238
|
controller.invalidateModelRequests(mounted.composer);
|
|
21003
22239
|
const switching = controller.switchAgent(mounted.composer, agent, {
|
|
21004
22240
|
applyAgent(nextAgent) {
|
|
22241
|
+
const model = controller.modelForAgent(mounted.composer, nextAgent);
|
|
22242
|
+
if (!shouldApplyDraftAgentCarrier(nextAgent, model)) return true;
|
|
21005
22243
|
return applyAdapterAgent?.(
|
|
21006
22244
|
nextAgent,
|
|
21007
|
-
|
|
22245
|
+
model,
|
|
21008
22246
|
nextAgent !== "codex" ? controller.thinkingOptionForAgent(mounted.composer, nextAgent) : void 0,
|
|
21009
22247
|
nextAgent !== "codex" ? controller.permissionModeForAgent(mounted.composer, nextAgent) : void 0,
|
|
21010
22248
|
mounted.composer
|
|
@@ -21070,6 +22308,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21070
22308
|
harnessAvailability[agent] === "ready" ? "ready" : "checking"
|
|
21071
22309
|
])
|
|
21072
22310
|
);
|
|
22311
|
+
publishConnectionStatus();
|
|
21073
22312
|
for (const mounted of mountedByComposer.values()) renderMounted(mounted);
|
|
21074
22313
|
const generation = ++availabilityRequestGeneration;
|
|
21075
22314
|
const promise2 = (async () => {
|
|
@@ -21082,8 +22321,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21082
22321
|
refresh
|
|
21083
22322
|
});
|
|
21084
22323
|
status = inspection.status === "ready" ? "ready" : inspection.status;
|
|
21085
|
-
|
|
22324
|
+
if (inspection.status === "ready") {
|
|
22325
|
+
harnessAvailabilityErrors[agent] = void 0;
|
|
22326
|
+
} else {
|
|
22327
|
+
const error51 = inspection.error;
|
|
22328
|
+
harnessAvailabilityErrors[agent] = {
|
|
22329
|
+
code: error51.code,
|
|
22330
|
+
message: error51.message,
|
|
22331
|
+
retryable: error51.retryable,
|
|
22332
|
+
...error51.diagnostic ? { diagnostic: error51.diagnostic } : {},
|
|
22333
|
+
...error51.stage ? { stage: error51.stage } : {},
|
|
22334
|
+
...error51.durationMs !== void 0 ? { durationMs: error51.durationMs } : {},
|
|
22335
|
+
...error51.stderrTail ? { stderrTail: error51.stderrTail } : {}
|
|
22336
|
+
};
|
|
22337
|
+
}
|
|
22338
|
+
} catch (error51) {
|
|
21086
22339
|
status = "error";
|
|
22340
|
+
harnessAvailabilityErrors[agent] = {
|
|
22341
|
+
code: "internalError",
|
|
22342
|
+
message: error51 instanceof Error ? error51.message : String(error51),
|
|
22343
|
+
retryable: true,
|
|
22344
|
+
stage: "request"
|
|
22345
|
+
};
|
|
21087
22346
|
}
|
|
21088
22347
|
if (generation !== availabilityRequestGeneration || disposed) return;
|
|
21089
22348
|
harnessAvailability = { ...harnessAvailability, [agent]: status };
|
|
@@ -21100,6 +22359,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21100
22359
|
}
|
|
21101
22360
|
renderMounted(mounted);
|
|
21102
22361
|
}
|
|
22362
|
+
publishConnectionStatus();
|
|
21103
22363
|
})
|
|
21104
22364
|
);
|
|
21105
22365
|
if (externalAgents.every((agent) => harnessAvailability[agent] === "ready")) {
|
|
@@ -21120,6 +22380,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21120
22380
|
);
|
|
21121
22381
|
return promise2;
|
|
21122
22382
|
};
|
|
22383
|
+
connectionDiagnostics = {
|
|
22384
|
+
snapshot() {
|
|
22385
|
+
return {
|
|
22386
|
+
adapter: { ...adapterStatus },
|
|
22387
|
+
agents: externalAgents.map((agent) => ({
|
|
22388
|
+
agent,
|
|
22389
|
+
availability: harnessAvailability[agent] ?? "checking",
|
|
22390
|
+
error: harnessAvailabilityErrors[agent] ?? null
|
|
22391
|
+
}))
|
|
22392
|
+
};
|
|
22393
|
+
},
|
|
22394
|
+
refresh() {
|
|
22395
|
+
return refreshHarnessAvailability(true);
|
|
22396
|
+
},
|
|
22397
|
+
subscribe(listener) {
|
|
22398
|
+
connectionListeners.add(listener);
|
|
22399
|
+
return () => connectionListeners.delete(listener);
|
|
22400
|
+
}
|
|
22401
|
+
};
|
|
21123
22402
|
const mount = (composer) => {
|
|
21124
22403
|
if (mountedByComposer.has(composer) || !composer.isConnected || !composer.matches(CODEX_COMPOSER_SELECTOR)) {
|
|
21125
22404
|
return;
|
|
@@ -21128,6 +22407,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21128
22407
|
const sendButton = sendButtonWithin(composer) ?? allButtons.at(-1) ?? null;
|
|
21129
22408
|
if (!sendButton) return;
|
|
21130
22409
|
const modelTarget = findComposerModelTarget(composer);
|
|
22410
|
+
const editor = composer.querySelector(EDITOR_SELECTOR);
|
|
22411
|
+
if (!editor) return;
|
|
21131
22412
|
const state = controller.mount(
|
|
21132
22413
|
composer,
|
|
21133
22414
|
modelTarget,
|
|
@@ -21159,6 +22440,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21159
22440
|
const mounted2 = mountedByComposer.get(composer);
|
|
21160
22441
|
if (!composer.isConnected || !mounted2) return;
|
|
21161
22442
|
void selectPermissionMode(mounted2, permissionModeId);
|
|
22443
|
+
},
|
|
22444
|
+
(command) => {
|
|
22445
|
+
const mounted2 = mountedByComposer.get(composer);
|
|
22446
|
+
if (mounted2) void executeCommand(mounted2, command);
|
|
21162
22447
|
}
|
|
21163
22448
|
);
|
|
21164
22449
|
const mounted = {
|
|
@@ -21176,13 +22461,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21176
22461
|
};
|
|
21177
22462
|
mountedByComposer.set(composer, mounted);
|
|
21178
22463
|
if (isComposerModelWriteAllowed(modelTarget)) {
|
|
21179
|
-
|
|
21180
|
-
|
|
21181
|
-
|
|
21182
|
-
|
|
21183
|
-
|
|
21184
|
-
|
|
21185
|
-
|
|
22464
|
+
const model = controller.modelForAgent(composer, state.agent);
|
|
22465
|
+
if (shouldApplyDraftAgentCarrier(state.agent, model)) {
|
|
22466
|
+
applyAdapterAgent?.(
|
|
22467
|
+
state.agent,
|
|
22468
|
+
model,
|
|
22469
|
+
state.agent !== "codex" ? controller.thinkingOptionForAgent(composer, state.agent) : void 0,
|
|
22470
|
+
state.agent !== "codex" ? controller.permissionModeForAgent(composer, state.agent) : void 0,
|
|
22471
|
+
composer
|
|
22472
|
+
);
|
|
22473
|
+
}
|
|
21186
22474
|
}
|
|
21187
22475
|
renderMounted(mounted);
|
|
21188
22476
|
sidebarAgentIcons.refresh();
|
|
@@ -21193,6 +22481,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21193
22481
|
} else if (state.agent !== "codex" && !isExternalConfigurationReady(mounted)) {
|
|
21194
22482
|
void loadExternalCatalog(mounted);
|
|
21195
22483
|
}
|
|
22484
|
+
void refreshCommands(mounted);
|
|
21196
22485
|
};
|
|
21197
22486
|
const scan = () => {
|
|
21198
22487
|
scanScheduled = false;
|
|
@@ -21206,7 +22495,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21206
22495
|
if (!shouldTransferComposerState(
|
|
21207
22496
|
replacement.sourceModelTarget,
|
|
21208
22497
|
replacementTarget,
|
|
21209
|
-
sourceState.phase
|
|
22498
|
+
sourceState.phase,
|
|
22499
|
+
controller.isSubmissionPending(replacement.source.composer)
|
|
21210
22500
|
) || !controller.transfer(replacement.source.composer, target, replacementTarget)) {
|
|
21211
22501
|
pendingReplacements.delete(target);
|
|
21212
22502
|
}
|
|
@@ -21288,11 +22578,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21288
22578
|
return state.phase === "locked" && mounted.ownershipStatus === "ready";
|
|
21289
22579
|
}
|
|
21290
22580
|
if (!mounted || !isComposerModelWriteAllowed(mounted.modelTarget)) return false;
|
|
22581
|
+
const model = controller.modelForAgent(composer, state.agent);
|
|
22582
|
+
if (!shouldApplyDraftAgentCarrier(state.agent, model)) return false;
|
|
21291
22583
|
return applyComposerModelWrite(
|
|
21292
22584
|
mounted.modelTarget,
|
|
21293
22585
|
() => applyAdapterAgent?.(
|
|
21294
22586
|
state.agent,
|
|
21295
|
-
|
|
22587
|
+
model,
|
|
21296
22588
|
state.agent !== "codex" ? controller.thinkingOptionForAgent(composer, state.agent) : void 0,
|
|
21297
22589
|
state.agent !== "codex" ? controller.permissionModeForAgent(composer, state.agent) : void 0,
|
|
21298
22590
|
composer
|
|
@@ -21314,7 +22606,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21314
22606
|
if (!isExternalConfigurationReady(mounted)) return false;
|
|
21315
22607
|
if (current.phase === "locked") return true;
|
|
21316
22608
|
if (!applyComposerAgent(composer)) return false;
|
|
21317
|
-
controller.
|
|
22609
|
+
controller.markSubmissionPending(composer);
|
|
21318
22610
|
renderMounted(mounted);
|
|
21319
22611
|
return true;
|
|
21320
22612
|
};
|
|
@@ -21327,6 +22619,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21327
22619
|
const onBeforeInput = (event) => {
|
|
21328
22620
|
const composer = composerForTarget(event.target);
|
|
21329
22621
|
if (!composer) return;
|
|
22622
|
+
controller.clearPendingSubmission(composer);
|
|
21330
22623
|
const mounted = mountedByComposer.get(composer);
|
|
21331
22624
|
if (mounted && isOwnershipSubmissionBlocked(mounted.ownershipStatus)) return;
|
|
21332
22625
|
if (controller.isSwitching(composer) || !applyComposerAgent(composer)) blockEvent(event);
|
|
@@ -21385,6 +22678,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21385
22678
|
scheduleScan(mutations.some(mutationMayChangeComposerTarget));
|
|
21386
22679
|
});
|
|
21387
22680
|
const onAdapterStatus = () => {
|
|
22681
|
+
publishConnectionStatus();
|
|
21388
22682
|
if (adapterStatus.state === "ready") {
|
|
21389
22683
|
sidebarAgentIcons.refresh();
|
|
21390
22684
|
void refreshHarnessAvailability();
|
|
@@ -21466,6 +22760,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21466
22760
|
usageNotificationDispose = null;
|
|
21467
22761
|
}
|
|
21468
22762
|
adapterStatus = status;
|
|
22763
|
+
publishConnectionStatus();
|
|
21469
22764
|
const installedModelControl = modelControl;
|
|
21470
22765
|
queueMicrotask(() => {
|
|
21471
22766
|
if (disposed || modelControl !== installedModelControl) return;
|
|
@@ -21520,6 +22815,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
21520
22815
|
}
|
|
21521
22816
|
mountedByComposer.clear();
|
|
21522
22817
|
pendingReplacements.clear();
|
|
22818
|
+
connectionListeners.clear();
|
|
22819
|
+
connectionDiagnostics = null;
|
|
21523
22820
|
delete window.__codexhostRendererBindingProbeV1;
|
|
21524
22821
|
}
|
|
21525
22822
|
};
|
|
@@ -21565,6 +22862,7 @@ lucide/dist/esm/icons/shield.mjs:
|
|
|
21565
22862
|
lucide/dist/esm/icons/shield-alert.mjs:
|
|
21566
22863
|
lucide/dist/esm/icons/boxes.mjs:
|
|
21567
22864
|
lucide/dist/esm/icons/circle-off.mjs:
|
|
22865
|
+
lucide/dist/esm/icons/copy.mjs:
|
|
21568
22866
|
lucide/dist/esm/icons/download.mjs:
|
|
21569
22867
|
lucide/dist/esm/icons/external-link.mjs:
|
|
21570
22868
|
lucide/dist/esm/icons/languages.mjs:
|
|
@@ -21573,6 +22871,7 @@ lucide/dist/esm/icons/plug-zap.mjs:
|
|
|
21573
22871
|
lucide/dist/esm/icons/refresh-cw.mjs:
|
|
21574
22872
|
lucide/dist/esm/icons/route.mjs:
|
|
21575
22873
|
lucide/dist/esm/icons/settings.mjs:
|
|
22874
|
+
lucide/dist/esm/icons/stethoscope.mjs:
|
|
21576
22875
|
lucide/dist/esm/icons/star.mjs:
|
|
21577
22876
|
lucide/dist/esm/icons/x.mjs:
|
|
21578
22877
|
(**
|