@codexhost/cli-darwin-arm64 0.2.6 → 0.3.0-test.2
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 +71 -137
- package/app/host-runtime.mjs +6838 -1627
- package/app/renderer-extension.js +777 -285
- 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;
|
|
@@ -15783,21 +15802,88 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15783
15802
|
return view;
|
|
15784
15803
|
}
|
|
15785
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
|
+
|
|
15786
15880
|
// src/renderer-model-picker.ts
|
|
15787
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";
|
|
15788
15882
|
var MENU_CLASSES = "fixed z-50 overflow-hidden rounded-xl bg-token-dropdown-background/90 text-token-foreground shadow-lg backdrop-blur-xl";
|
|
15789
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";
|
|
15790
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";
|
|
15791
15885
|
var HEADING_CLASSES = "px-2 pb-1 pt-1.5 text-sm text-token-text-tertiary";
|
|
15792
|
-
var MAIN_MENU_MIN_WIDTH = 160;
|
|
15793
|
-
var MAIN_MENU_MAX_WIDTH = 180;
|
|
15794
|
-
var MODEL_MENU_PREFERRED_WIDTH = 360;
|
|
15795
|
-
var MODEL_MENU_MAX_WIDTH = 420;
|
|
15796
|
-
var MODEL_MENU_MAX_HEIGHT = 360;
|
|
15797
15886
|
var MODEL_TRIGGER_MAX_WIDTH = "min(200px, 26vw)";
|
|
15798
|
-
var MAIN_MENU_LEFT_OFFSET = 96;
|
|
15799
|
-
var MENU_GAP = 4;
|
|
15800
|
-
var VIEWPORT_MARGIN = 8;
|
|
15801
15887
|
var MODEL_SCROLLBAR_STYLE_ATTRIBUTE = "data-codexhost-model-picker-scrollbar";
|
|
15802
15888
|
function popoverOpen2(menu) {
|
|
15803
15889
|
return menu.matches(":popover-open");
|
|
@@ -15877,47 +15963,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15877
15963
|
}
|
|
15878
15964
|
function positionMainMenu(control) {
|
|
15879
15965
|
const triggerRect = control.trigger.getBoundingClientRect();
|
|
15880
|
-
const
|
|
15881
|
-
|
|
15882
|
-
|
|
15883
|
-
|
|
15966
|
+
const placement = rendererModelPickerMainMenuPlacement(
|
|
15967
|
+
triggerRect,
|
|
15968
|
+
{ width: window.innerWidth, height: window.innerHeight },
|
|
15969
|
+
RENDERER_MODEL_PICKER_MAIN_MENU_WIDTH
|
|
15884
15970
|
);
|
|
15885
|
-
|
|
15886
|
-
|
|
15887
|
-
|
|
15888
|
-
const left = Math.max(
|
|
15889
|
-
VIEWPORT_MARGIN,
|
|
15890
|
-
Math.min(preferredLeft, Math.max(rightReservedLeft, VIEWPORT_MARGIN), maxLeft)
|
|
15891
|
-
);
|
|
15892
|
-
control.menu.style.setProperty("width", `${width}px`, "important");
|
|
15893
|
-
control.menu.style.left = `${left}px`;
|
|
15894
|
-
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`;
|
|
15895
15974
|
control.menu.style.right = "auto";
|
|
15896
15975
|
control.menu.style.top = "auto";
|
|
15897
|
-
control.menu.style.bottom = `${
|
|
15898
|
-
|
|
15899
|
-
|
|
15900
|
-
)
|
|
15901
|
-
|
|
15902
|
-
|
|
15903
|
-
|
|
15904
|
-
const
|
|
15905
|
-
const
|
|
15906
|
-
|
|
15907
|
-
|
|
15908
|
-
|
|
15909
|
-
|
|
15910
|
-
|
|
15911
|
-
|
|
15912
|
-
|
|
15913
|
-
|
|
15914
|
-
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`;
|
|
15915
15995
|
control.modelMenu.style.right = "auto";
|
|
15916
|
-
control.modelMenu.style.top = "auto"
|
|
15917
|
-
control.modelMenu.style.bottom = `${
|
|
15918
|
-
VIEWPORT_MARGIN,
|
|
15919
|
-
window.innerHeight - mainRect.bottom
|
|
15920
|
-
)}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`;
|
|
15921
15998
|
}
|
|
15922
15999
|
function syncRendererModelTriggerClass(control, nativeClassName) {
|
|
15923
16000
|
control.trigger.className = nativeClassName?.trim() || RENDERER_MODEL_TRIGGER_FALLBACK_CLASSES;
|
|
@@ -16012,7 +16089,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16012
16089
|
modelMenu.style.margin = "0";
|
|
16013
16090
|
modelMenu.style.padding = "4px";
|
|
16014
16091
|
modelMenu.style.border = "0";
|
|
16015
|
-
modelMenu.style.maxHeight =
|
|
16092
|
+
modelMenu.style.maxHeight = `min(${RENDERER_MODEL_PICKER_MODEL_MENU_MAX_HEIGHT}px, 60vh)`;
|
|
16016
16093
|
modelMenu.style.overflowY = "auto";
|
|
16017
16094
|
modelButton.setAttribute("aria-controls", modelMenu.id);
|
|
16018
16095
|
const options = /* @__PURE__ */ new Map();
|
|
@@ -16073,33 +16150,41 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16073
16150
|
applyModelSearchFilter(control);
|
|
16074
16151
|
}
|
|
16075
16152
|
};
|
|
16153
|
+
const pickerOpen = () => popoverOpen2(menu) || popoverOpen2(modelMenu);
|
|
16076
16154
|
const close = () => {
|
|
16077
16155
|
closeModelMenu();
|
|
16078
16156
|
if (popoverOpen2(menu)) menu.hidePopover();
|
|
16079
16157
|
};
|
|
16080
|
-
const openModelMenu = () => {
|
|
16081
|
-
if (!popoverOpen2(menu) || popoverOpen2(modelMenu)) return;
|
|
16158
|
+
const openModelMenu = (standalone = false) => {
|
|
16159
|
+
if (!standalone && !popoverOpen2(menu) || popoverOpen2(modelMenu)) return;
|
|
16082
16160
|
modelMenu.showPopover();
|
|
16083
|
-
positionModelMenu(control);
|
|
16161
|
+
positionModelMenu(control, standalone);
|
|
16084
16162
|
modelButton.setAttribute("aria-expanded", "true");
|
|
16085
16163
|
};
|
|
16086
16164
|
const open = () => {
|
|
16087
|
-
if (trigger.disabled ||
|
|
16165
|
+
if (trigger.disabled || pickerOpen()) return;
|
|
16166
|
+
if (control.thinkingOptions.size === 0) {
|
|
16167
|
+
openModelMenu(true);
|
|
16168
|
+
return;
|
|
16169
|
+
}
|
|
16088
16170
|
menu.showPopover();
|
|
16089
|
-
|
|
16171
|
+
positionAdvancedMenus(control);
|
|
16090
16172
|
};
|
|
16091
16173
|
const onTriggerClick = () => {
|
|
16092
|
-
if (
|
|
16174
|
+
if (pickerOpen()) close();
|
|
16093
16175
|
else open();
|
|
16094
16176
|
};
|
|
16095
16177
|
const onToggle = () => {
|
|
16096
16178
|
const openState = popoverOpen2(menu);
|
|
16097
|
-
trigger.setAttribute("aria-expanded", String(openState));
|
|
16179
|
+
trigger.setAttribute("aria-expanded", String(openState || popoverOpen2(modelMenu)));
|
|
16098
16180
|
trigger.setAttribute("data-state", openState ? "open" : "closed");
|
|
16099
16181
|
if (!openState) closeModelMenu();
|
|
16100
16182
|
};
|
|
16101
16183
|
const onModelToggle = () => {
|
|
16102
|
-
|
|
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");
|
|
16103
16188
|
};
|
|
16104
16189
|
const onRootClick = (event) => {
|
|
16105
16190
|
const target = event.target instanceof Element ? event.target.closest("button") : null;
|
|
@@ -16138,21 +16223,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16138
16223
|
trigger.focus();
|
|
16139
16224
|
};
|
|
16140
16225
|
const onViewportChange = () => {
|
|
16141
|
-
if (popoverOpen2(menu))
|
|
16142
|
-
if (popoverOpen2(modelMenu)) positionModelMenu(control);
|
|
16226
|
+
if (popoverOpen2(menu)) positionAdvancedMenus(control);
|
|
16227
|
+
else if (popoverOpen2(modelMenu)) positionModelMenu(control, true);
|
|
16143
16228
|
};
|
|
16144
16229
|
trigger.addEventListener("click", onTriggerClick);
|
|
16145
16230
|
menu.addEventListener("toggle", onToggle);
|
|
16146
16231
|
modelMenu.addEventListener("toggle", onModelToggle);
|
|
16147
16232
|
modelButton.addEventListener("mouseenter", onModelHover);
|
|
16148
|
-
|
|
16233
|
+
menu.addEventListener("click", onRootClick);
|
|
16149
16234
|
modelMenu.addEventListener("click", onModelMenuClick);
|
|
16150
16235
|
document.addEventListener("pointerdown", onDocumentPointerDown, true);
|
|
16151
16236
|
document.addEventListener("keydown", onDocumentKeyDown, true);
|
|
16152
16237
|
window.addEventListener("resize", onViewportChange);
|
|
16153
16238
|
window.addEventListener("scroll", onViewportChange, true);
|
|
16154
|
-
root.append(trigger
|
|
16155
|
-
document.body.append(modelMenu);
|
|
16239
|
+
root.append(trigger);
|
|
16240
|
+
document.body.append(menu, modelMenu);
|
|
16156
16241
|
searchHeader.append(searchInput);
|
|
16157
16242
|
modelMenu.append(searchHeader, searchEmpty);
|
|
16158
16243
|
const control = {
|
|
@@ -16175,7 +16260,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16175
16260
|
menu.removeEventListener("toggle", onToggle);
|
|
16176
16261
|
modelMenu.removeEventListener("toggle", onModelToggle);
|
|
16177
16262
|
modelButton.removeEventListener("mouseenter", onModelHover);
|
|
16178
|
-
|
|
16263
|
+
menu.removeEventListener("click", onRootClick);
|
|
16179
16264
|
modelMenu.removeEventListener("click", onModelMenuClick);
|
|
16180
16265
|
searchInput.removeEventListener("input", onSearchInput);
|
|
16181
16266
|
for (const type of silencedEventTypes) {
|
|
@@ -16186,6 +16271,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16186
16271
|
document.removeEventListener("keydown", onDocumentKeyDown, true);
|
|
16187
16272
|
window.removeEventListener("resize", onViewportChange);
|
|
16188
16273
|
window.removeEventListener("scroll", onViewportChange, true);
|
|
16274
|
+
menu.remove();
|
|
16189
16275
|
modelMenu.remove();
|
|
16190
16276
|
root.remove();
|
|
16191
16277
|
}
|
|
@@ -17138,7 +17224,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17138
17224
|
var CONTROL_ATTRIBUTE2 = "data-codexhost-harness-command-control";
|
|
17139
17225
|
var MENU_ATTRIBUTE = "data-codexhost-harness-command-menu";
|
|
17140
17226
|
var MENU_WIDTH = 320;
|
|
17141
|
-
var
|
|
17227
|
+
var VIEWPORT_MARGIN = 8;
|
|
17142
17228
|
var MENU_GAP2 = 8;
|
|
17143
17229
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
17144
17230
|
var COMMAND_ICON_PATHS = [
|
|
@@ -17254,7 +17340,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17254
17340
|
menu.style.inset = "auto";
|
|
17255
17341
|
menu.style.zIndex = "2147483647";
|
|
17256
17342
|
menu.style.width = `${MENU_WIDTH}px`;
|
|
17257
|
-
menu.style.maxWidth = `calc(100vw - ${
|
|
17343
|
+
menu.style.maxWidth = `calc(100vw - ${VIEWPORT_MARGIN * 2}px)`;
|
|
17258
17344
|
menu.style.maxHeight = "min(360px, calc(100vh - 16px))";
|
|
17259
17345
|
menu.style.overflowY = "auto";
|
|
17260
17346
|
menu.style.padding = "4px";
|
|
@@ -17275,14 +17361,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17275
17361
|
const positionMenu2 = () => {
|
|
17276
17362
|
const rect = trigger.getBoundingClientRect();
|
|
17277
17363
|
const menuHeight = menu.getBoundingClientRect().height;
|
|
17278
|
-
const opensAbove = rect.top >= menuHeight + MENU_GAP2 +
|
|
17364
|
+
const opensAbove = rect.top >= menuHeight + MENU_GAP2 + VIEWPORT_MARGIN;
|
|
17279
17365
|
const left = clamp(
|
|
17280
17366
|
rect.left,
|
|
17281
|
-
|
|
17282
|
-
window.innerWidth - MENU_WIDTH -
|
|
17367
|
+
VIEWPORT_MARGIN,
|
|
17368
|
+
window.innerWidth - MENU_WIDTH - VIEWPORT_MARGIN
|
|
17283
17369
|
);
|
|
17284
17370
|
menu.style.left = `${left}px`;
|
|
17285
|
-
menu.style.top = opensAbove ? `${Math.max(
|
|
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`;
|
|
17286
17372
|
};
|
|
17287
17373
|
const focusActive = () => {
|
|
17288
17374
|
const item = items[activeIndex];
|
|
@@ -17457,23 +17543,86 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17457
17543
|
if (target instanceof Element) return target;
|
|
17458
17544
|
return target instanceof Node ? target.parentElement : null;
|
|
17459
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
|
+
}
|
|
17460
17551
|
function buttonText(button) {
|
|
17461
|
-
return
|
|
17462
|
-
|
|
17463
|
-
|
|
17464
|
-
|
|
17465
|
-
button.getAttribute("data-testid")
|
|
17466
|
-
].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");
|
|
17467
17556
|
}
|
|
17468
17557
|
function isComposerSubmitButton(button) {
|
|
17469
17558
|
if (button.type === "submit") return true;
|
|
17470
17559
|
return /(^|\s)(send|submit|发送|提交)(\s|$)/u.test(buttonText(button));
|
|
17471
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
|
+
}
|
|
17472
17597
|
function sendButtonWithin(root) {
|
|
17473
17598
|
return [...root.querySelectorAll("button")].find(
|
|
17474
17599
|
(button) => isComposerSubmitButton(button)
|
|
17475
17600
|
) ?? null;
|
|
17476
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
|
+
}
|
|
17477
17626
|
function editorForElement(element) {
|
|
17478
17627
|
return element.matches(EDITOR_SELECTOR) ? element : element.closest(EDITOR_SELECTOR);
|
|
17479
17628
|
}
|
|
@@ -17619,7 +17768,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17619
17768
|
for (const child of parent.children) {
|
|
17620
17769
|
if (typeof child.hasAttribute !== "function") continue;
|
|
17621
17770
|
const element = child;
|
|
17622
|
-
if (element.hasAttribute("data-codexhost-credits-control") || element.hasAttribute("data-codexhost-harness-command-control")) {
|
|
17771
|
+
if (element.hasAttribute("data-codexhost-credits-control") || element.hasAttribute("data-codexhost-harness-command-control") || isTrailingActionNode(element)) {
|
|
17623
17772
|
continue;
|
|
17624
17773
|
}
|
|
17625
17774
|
return element;
|
|
@@ -17632,12 +17781,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17632
17781
|
const parent = current.parentElement;
|
|
17633
17782
|
if (!parent) break;
|
|
17634
17783
|
const first = firstMaterialChild(parent);
|
|
17635
|
-
if (first && first !== current && !first.contains(usageRoot))
|
|
17784
|
+
if (first && first !== current && !first.contains(usageRoot)) {
|
|
17785
|
+
return attachControlWithin(first) ?? first;
|
|
17786
|
+
}
|
|
17636
17787
|
if (parent === composer) break;
|
|
17637
17788
|
current = parent;
|
|
17638
17789
|
}
|
|
17639
17790
|
return null;
|
|
17640
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
|
+
}
|
|
17641
17806
|
function refreshUsagePlacement(control) {
|
|
17642
17807
|
const anchor = usagePlacementAnchor(control);
|
|
17643
17808
|
if (!anchor) {
|
|
@@ -17690,6 +17855,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17690
17855
|
}
|
|
17691
17856
|
function reconcileComposerNativeControls(control, hideModel, hidePermissionMode) {
|
|
17692
17857
|
refreshNativeModelControl(control);
|
|
17858
|
+
refreshTrailingClusterPlacement(control);
|
|
17693
17859
|
refreshUsagePlacement(control);
|
|
17694
17860
|
refreshNativePermissionModeControl(control);
|
|
17695
17861
|
setNativeControlHidden(control.nativeModelControl, hideModel);
|
|
@@ -17717,7 +17883,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17717
17883
|
const toolbar = sendButton.parentElement;
|
|
17718
17884
|
const harnessCommands = mountRendererHarnessCommandControl(
|
|
17719
17885
|
toolbar ?? composer,
|
|
17720
|
-
sendButton,
|
|
17886
|
+
trailingActionAnchor(sendButton),
|
|
17721
17887
|
onSelectCommand
|
|
17722
17888
|
);
|
|
17723
17889
|
const permissionParent = nativePermissionModeControl?.element.parentElement;
|
|
@@ -17726,12 +17892,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17726
17892
|
} else {
|
|
17727
17893
|
composer.append(permissionModePicker.root);
|
|
17728
17894
|
}
|
|
17729
|
-
if (toolbar)
|
|
17730
|
-
toolbar.insertBefore(modelPicker.root, sendButton);
|
|
17731
|
-
toolbar.insertBefore(picker.root, sendButton);
|
|
17732
|
-
} else {
|
|
17733
|
-
composer.append(modelPicker.root, picker.root);
|
|
17734
|
-
}
|
|
17895
|
+
if (!toolbar) composer.append(modelPicker.root, picker.root);
|
|
17735
17896
|
const control = {
|
|
17736
17897
|
composer,
|
|
17737
17898
|
root: picker.root,
|
|
@@ -17747,6 +17908,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17747
17908
|
sendButton,
|
|
17748
17909
|
sendDisabledBeforeSwitch: null
|
|
17749
17910
|
};
|
|
17911
|
+
refreshTrailingClusterPlacement(control);
|
|
17750
17912
|
refreshUsagePlacement(control);
|
|
17751
17913
|
return control;
|
|
17752
17914
|
}
|
|
@@ -17870,6 +18032,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17870
18032
|
isConnected() {
|
|
17871
18033
|
return this.element.isConnected;
|
|
17872
18034
|
}
|
|
18035
|
+
hostId() {
|
|
18036
|
+
return sidebarThreadAttributes(this.element)?.hostId ?? null;
|
|
18037
|
+
}
|
|
17873
18038
|
threadId() {
|
|
17874
18039
|
return threadIdFromSidebarRowElement(this.element);
|
|
17875
18040
|
}
|
|
@@ -17939,7 +18104,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17939
18104
|
const observer = new MutationObserver(onChange);
|
|
17940
18105
|
observer.observe(this.root, {
|
|
17941
18106
|
attributes: true,
|
|
17942
|
-
attributeFilter: [SIDEBAR_THREAD_ID_ATTRIBUTE],
|
|
18107
|
+
attributeFilter: [SIDEBAR_THREAD_ID_ATTRIBUTE, SIDEBAR_THREAD_HOST_ID_ATTRIBUTE],
|
|
17943
18108
|
childList: true,
|
|
17944
18109
|
subtree: true
|
|
17945
18110
|
});
|
|
@@ -17960,78 +18125,88 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17960
18125
|
const ownershipRetryTimers = /* @__PURE__ */ new Map();
|
|
17961
18126
|
let disposed = false;
|
|
17962
18127
|
let scanScheduled = false;
|
|
18128
|
+
const ownershipKey = (hostId, threadId) => JSON.stringify([hostId, threadId]);
|
|
17963
18129
|
const scheduleScan = () => {
|
|
17964
18130
|
if (disposed || scanScheduled) return;
|
|
17965
18131
|
scanScheduled = true;
|
|
17966
18132
|
queueMicrotask(scan);
|
|
17967
18133
|
};
|
|
17968
|
-
const clearOwnershipRetry = (
|
|
17969
|
-
const timer = ownershipRetryTimers.get(
|
|
18134
|
+
const clearOwnershipRetry = (key) => {
|
|
18135
|
+
const timer = ownershipRetryTimers.get(key);
|
|
17970
18136
|
if (timer !== void 0) clearTimeout(timer);
|
|
17971
|
-
ownershipRetryTimers.delete(
|
|
17972
|
-
ownershipRetryAttempts.delete(
|
|
17973
|
-
provisionalCodex.delete(
|
|
18137
|
+
ownershipRetryTimers.delete(key);
|
|
18138
|
+
ownershipRetryAttempts.delete(key);
|
|
18139
|
+
provisionalCodex.delete(key);
|
|
17974
18140
|
};
|
|
17975
|
-
const scheduleOwnershipRetry = (threadId) => {
|
|
17976
|
-
|
|
18141
|
+
const scheduleOwnershipRetry = (hostId, threadId) => {
|
|
18142
|
+
const key = ownershipKey(hostId, threadId);
|
|
18143
|
+
if (disposed || !provisionalCodex.has(key) || pending.has(key) || ownershipRetryTimers.has(key)) {
|
|
17977
18144
|
return;
|
|
17978
18145
|
}
|
|
17979
|
-
const attempt = ownershipRetryAttempts.get(
|
|
18146
|
+
const attempt = ownershipRetryAttempts.get(key) ?? 0;
|
|
17980
18147
|
const delay = OWNERSHIP_RETRY_DELAYS_MS[attempt];
|
|
17981
18148
|
if (delay === void 0) return;
|
|
17982
|
-
ownershipRetryAttempts.set(
|
|
18149
|
+
ownershipRetryAttempts.set(key, attempt + 1);
|
|
17983
18150
|
const timer = setTimeout(() => {
|
|
17984
|
-
ownershipRetryTimers.delete(
|
|
18151
|
+
ownershipRetryTimers.delete(key);
|
|
17985
18152
|
if (disposed) return;
|
|
17986
|
-
failed.delete(
|
|
17987
|
-
ownershipByThread.delete(
|
|
18153
|
+
failed.delete(key);
|
|
18154
|
+
ownershipByThread.delete(key);
|
|
17988
18155
|
scheduleScan();
|
|
17989
18156
|
}, delay);
|
|
17990
|
-
ownershipRetryTimers.set(
|
|
18157
|
+
ownershipRetryTimers.set(key, timer);
|
|
17991
18158
|
};
|
|
17992
|
-
const requestOwnership = (threadIds, client) => {
|
|
17993
|
-
for (const threadId of threadIds) pending.add(threadId);
|
|
18159
|
+
const requestOwnership = (hostId, threadIds, client) => {
|
|
18160
|
+
for (const threadId of threadIds) pending.add(ownershipKey(hostId, threadId));
|
|
17994
18161
|
let succeeded = false;
|
|
17995
18162
|
void Promise.resolve().then(() => client.listThreadOwnership({ threadIds })).then(({ threads }) => {
|
|
17996
18163
|
if (disposed) return;
|
|
17997
18164
|
for (const ownership of threads) {
|
|
17998
|
-
|
|
17999
|
-
|
|
18165
|
+
const key = ownershipKey(hostId, ownership.threadId);
|
|
18166
|
+
ownershipByThread.set(key, rendererAgentForThreadOwnership(ownership));
|
|
18167
|
+
failed.delete(key);
|
|
18000
18168
|
if (ownership.owner === "codex") {
|
|
18001
|
-
provisionalCodex.add(
|
|
18002
|
-
scheduleOwnershipRetry(ownership.threadId);
|
|
18169
|
+
provisionalCodex.add(key);
|
|
18170
|
+
scheduleOwnershipRetry(hostId, ownership.threadId);
|
|
18003
18171
|
} else {
|
|
18004
|
-
clearOwnershipRetry(
|
|
18172
|
+
clearOwnershipRetry(key);
|
|
18005
18173
|
}
|
|
18006
18174
|
}
|
|
18007
18175
|
succeeded = true;
|
|
18008
18176
|
}).catch(() => {
|
|
18009
18177
|
if (disposed) return;
|
|
18010
|
-
for (const threadId of threadIds) failed.add(threadId);
|
|
18178
|
+
for (const threadId of threadIds) failed.add(ownershipKey(hostId, threadId));
|
|
18011
18179
|
}).finally(() => {
|
|
18012
|
-
for (const threadId of threadIds) pending.delete(threadId);
|
|
18013
|
-
for (const threadId of threadIds) scheduleOwnershipRetry(threadId);
|
|
18180
|
+
for (const threadId of threadIds) pending.delete(ownershipKey(hostId, threadId));
|
|
18181
|
+
for (const threadId of threadIds) scheduleOwnershipRetry(hostId, threadId);
|
|
18014
18182
|
if (succeeded) scheduleScan();
|
|
18015
18183
|
});
|
|
18016
18184
|
};
|
|
18017
18185
|
const scan = () => {
|
|
18018
18186
|
scanScheduled = false;
|
|
18019
18187
|
if (disposed) return;
|
|
18020
|
-
const
|
|
18188
|
+
const unresolvedByHost = /* @__PURE__ */ new Map();
|
|
18021
18189
|
for (const row of dom.rows()) {
|
|
18022
18190
|
if (!row.isConnected()) {
|
|
18023
18191
|
row.clear();
|
|
18024
18192
|
continue;
|
|
18025
18193
|
}
|
|
18194
|
+
const hostId = row.hostId();
|
|
18195
|
+
if (!hostId) {
|
|
18196
|
+
row.clear();
|
|
18197
|
+
continue;
|
|
18198
|
+
}
|
|
18026
18199
|
const threadId = hostThreadIdSchema.safeParse(row.threadId());
|
|
18027
18200
|
const localAgent = options.getLocalAgent?.({
|
|
18201
|
+
hostId,
|
|
18028
18202
|
threadId: threadId.success ? threadId.data : null,
|
|
18029
18203
|
draftId: row.draftId()
|
|
18030
18204
|
});
|
|
18031
18205
|
if (localAgent !== null && localAgent !== void 0) {
|
|
18032
18206
|
if (threadId.success) {
|
|
18033
|
-
|
|
18034
|
-
|
|
18207
|
+
const key2 = ownershipKey(hostId, threadId.data);
|
|
18208
|
+
ownershipByThread.set(key2, localAgent === "codex" ? null : localAgent);
|
|
18209
|
+
clearOwnershipRetry(key2);
|
|
18035
18210
|
}
|
|
18036
18211
|
if (localAgent === "codex") row.clear();
|
|
18037
18212
|
else row.render(localAgent);
|
|
@@ -18041,22 +18216,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18041
18216
|
row.clear();
|
|
18042
18217
|
continue;
|
|
18043
18218
|
}
|
|
18044
|
-
|
|
18045
|
-
|
|
18219
|
+
const key = ownershipKey(hostId, threadId.data);
|
|
18220
|
+
if (ownershipByThread.has(key)) {
|
|
18221
|
+
const agent = ownershipByThread.get(key);
|
|
18046
18222
|
if (agent) row.render(agent);
|
|
18047
18223
|
else row.clear();
|
|
18048
18224
|
continue;
|
|
18049
18225
|
}
|
|
18050
18226
|
row.clear();
|
|
18051
|
-
if (!pending.has(
|
|
18227
|
+
if (!pending.has(key) && !failed.has(key)) {
|
|
18228
|
+
let unresolved = unresolvedByHost.get(hostId);
|
|
18229
|
+
if (!unresolved) {
|
|
18230
|
+
unresolved = /* @__PURE__ */ new Set();
|
|
18231
|
+
unresolvedByHost.set(hostId, unresolved);
|
|
18232
|
+
}
|
|
18052
18233
|
unresolved.add(threadId.data);
|
|
18053
18234
|
}
|
|
18054
18235
|
}
|
|
18055
|
-
const
|
|
18056
|
-
|
|
18057
|
-
|
|
18058
|
-
|
|
18059
|
-
|
|
18236
|
+
for (const [hostId, unresolved] of unresolvedByHost) {
|
|
18237
|
+
const client = options.getClient(hostId);
|
|
18238
|
+
if (!client) continue;
|
|
18239
|
+
const threadIds = [...unresolved];
|
|
18240
|
+
for (let index = 0; index < threadIds.length; index += THREAD_OWNERSHIP_LIST_MAX_LENGTH) {
|
|
18241
|
+
requestOwnership(
|
|
18242
|
+
hostId,
|
|
18243
|
+
threadIds.slice(index, index + THREAD_OWNERSHIP_LIST_MAX_LENGTH),
|
|
18244
|
+
client
|
|
18245
|
+
);
|
|
18246
|
+
}
|
|
18060
18247
|
}
|
|
18061
18248
|
};
|
|
18062
18249
|
const stopObserving = dom.observe(scheduleScan);
|
|
@@ -18064,12 +18251,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18064
18251
|
return {
|
|
18065
18252
|
refresh() {
|
|
18066
18253
|
failed.clear();
|
|
18067
|
-
for (const
|
|
18068
|
-
const timer = ownershipRetryTimers.get(
|
|
18254
|
+
for (const key of provisionalCodex) {
|
|
18255
|
+
const timer = ownershipRetryTimers.get(key);
|
|
18069
18256
|
if (timer !== void 0) clearTimeout(timer);
|
|
18070
|
-
ownershipRetryTimers.delete(
|
|
18071
|
-
ownershipRetryAttempts.delete(
|
|
18072
|
-
ownershipByThread.delete(
|
|
18257
|
+
ownershipRetryTimers.delete(key);
|
|
18258
|
+
ownershipRetryAttempts.delete(key);
|
|
18259
|
+
ownershipByThread.delete(key);
|
|
18073
18260
|
}
|
|
18074
18261
|
scheduleScan();
|
|
18075
18262
|
},
|
|
@@ -18467,28 +18654,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18467
18654
|
}
|
|
18468
18655
|
return `${CLAUDE_CODE_TRANSPORT_MODEL_PREFIX}${parsedModel.id}${parsedPermissionMode ? `@${parsedPermissionMode}` : ""}`;
|
|
18469
18656
|
}
|
|
18470
|
-
function grokTransportModelId(model, thinkingOptionId) {
|
|
18657
|
+
function grokTransportModelId(model, permissionModeId, thinkingOptionId) {
|
|
18471
18658
|
if (!model) {
|
|
18472
|
-
if (thinkingOptionId)
|
|
18659
|
+
if (permissionModeId || thinkingOptionId) {
|
|
18660
|
+
throw new Error("Grok transport configuration requires a Model Ref");
|
|
18661
|
+
}
|
|
18473
18662
|
return GROK_TRANSPORT_MODEL_ID;
|
|
18474
18663
|
}
|
|
18475
18664
|
const parsedModel = harnessModelRefSchema.parse(model);
|
|
18665
|
+
const parsedPermissionMode = permissionModeId ? harnessPermissionModeIdSchema.parse(permissionModeId) : void 0;
|
|
18476
18666
|
const parsedThinking = thinkingOptionId ? harnessThinkingOptionIdSchema.parse(thinkingOptionId) : void 0;
|
|
18477
|
-
|
|
18667
|
+
if (parsedThinking) {
|
|
18668
|
+
return `${GROK_TRANSPORT_MODEL_PREFIX}${parsedModel.id}@${parsedPermissionMode ?? ""}@${parsedThinking}`;
|
|
18669
|
+
}
|
|
18670
|
+
return `${GROK_TRANSPORT_MODEL_PREFIX}${parsedModel.id}${parsedPermissionMode ? `@${parsedPermissionMode}` : ""}`;
|
|
18478
18671
|
}
|
|
18479
18672
|
function decodeGrokTransportModelId(value) {
|
|
18480
18673
|
if (value === GROK_TRANSPORT_MODEL_ID) return {};
|
|
18481
18674
|
if (typeof value !== "string" || !value.startsWith(GROK_TRANSPORT_MODEL_PREFIX)) return null;
|
|
18482
18675
|
const components = value.slice(GROK_TRANSPORT_MODEL_PREFIX.length).split("@");
|
|
18483
|
-
if (components.length
|
|
18484
|
-
const [modelId,
|
|
18485
|
-
if (components.length ===
|
|
18676
|
+
if (components.length < 1 || components.length > 3) return null;
|
|
18677
|
+
const [modelId, permissionModeId, thinkingOptionId] = components;
|
|
18678
|
+
if (components.length === 2 && !permissionModeId) return null;
|
|
18679
|
+
if (components.length === 3 && !thinkingOptionId) return null;
|
|
18486
18680
|
const model = harnessModelRefSchema.safeParse({ id: modelId });
|
|
18487
18681
|
if (!model.success) return null;
|
|
18682
|
+
const permissionMode = permissionModeId ? harnessPermissionModeIdSchema.safeParse(permissionModeId) : null;
|
|
18683
|
+
if (permissionMode && !permissionMode.success) return null;
|
|
18488
18684
|
const thinking = thinkingOptionId ? harnessThinkingOptionIdSchema.safeParse(thinkingOptionId) : null;
|
|
18489
18685
|
if (thinking && !thinking.success) return null;
|
|
18490
18686
|
return {
|
|
18491
18687
|
model: model.data,
|
|
18688
|
+
...permissionMode?.success ? { permissionModeId: permissionMode.data } : {},
|
|
18492
18689
|
...thinking?.success ? { thinkingOptionId: thinking.data } : {}
|
|
18493
18690
|
};
|
|
18494
18691
|
}
|
|
@@ -18550,22 +18747,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18550
18747
|
}
|
|
18551
18748
|
return hostThreadIdSchema.parse(target[1]);
|
|
18552
18749
|
}
|
|
18553
|
-
function
|
|
18554
|
-
return (typeof value === "
|
|
18555
|
-
}
|
|
18556
|
-
function isActiveRequestManager(value) {
|
|
18557
|
-
if (!isRecord5(value) || typeof value.sendRequest !== "function") return false;
|
|
18558
|
-
const source = Function.prototype.toString.call(value.sendRequest);
|
|
18559
|
-
return source.includes("send-cli-request-for-host") && hasPrewarmMethod(value.requestClient);
|
|
18560
|
-
}
|
|
18561
|
-
function matchesCurrentPrewarmSignature(target) {
|
|
18562
|
-
const bridge = target.requestClient ?? target;
|
|
18563
|
-
const stableApiShape = bridge.hostId === "local" && typeof bridge.sendRequest === "function" && typeof bridge.prewarmThreadStart === "function" && typeof bridge.enqueueRequest === "function";
|
|
18564
|
-
if (stableApiShape) return true;
|
|
18565
|
-
const prewarm = target.prewarmThreadStart ?? target.requestClient?.prewarmThreadStart;
|
|
18566
|
-
if (!prewarm) return false;
|
|
18567
|
-
const source = Function.prototype.toString.call(prewarm);
|
|
18568
|
-
return source.includes("enqueueRequest") && source.includes("thread-prewarm-start") || source.includes("prewarm-thread-start-for-host");
|
|
18750
|
+
function isCurrentRequestBridge(value) {
|
|
18751
|
+
return isRecord5(value) && typeof value.hostId === "string" && value.hostId.length > 0 && typeof value.sendRequest === "function" && typeof value.prewarmThreadStart === "function" && typeof value.enqueueRequest === "function";
|
|
18569
18752
|
}
|
|
18570
18753
|
function findActivePrewarmTargets(root) {
|
|
18571
18754
|
const editor = root.querySelector(
|
|
@@ -18595,10 +18778,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18595
18778
|
const hookState = hook.memoizedState;
|
|
18596
18779
|
if (isRecord5(hookState)) {
|
|
18597
18780
|
const requestClient = hookState.requestClient;
|
|
18598
|
-
|
|
18599
|
-
|
|
18600
|
-
|
|
18601
|
-
targets.add(typeof hookState.sendRequest === "function" ? hookState : requestClient);
|
|
18781
|
+
const bridge = isCurrentRequestBridge(requestClient) ? requestClient : isCurrentRequestBridge(hookState) ? hookState : null;
|
|
18782
|
+
if (bridge) {
|
|
18783
|
+
targets.add(typeof hookState.sendRequest === "function" ? hookState : bridge);
|
|
18602
18784
|
}
|
|
18603
18785
|
}
|
|
18604
18786
|
hook = typeof hook.next === "object" && hook.next !== null ? hook.next : null;
|
|
@@ -18651,10 +18833,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18651
18833
|
return false;
|
|
18652
18834
|
}
|
|
18653
18835
|
}
|
|
18654
|
-
function
|
|
18655
|
-
const
|
|
18656
|
-
|
|
18657
|
-
if (
|
|
18836
|
+
function findComposerDomIdentity(composer) {
|
|
18837
|
+
const children = Array.from(composer.children ?? []);
|
|
18838
|
+
const portals = children.filter((child) => child.hasAttribute("data-above-composer-portal"));
|
|
18839
|
+
if (portals.length === 0) return { kind: "unsupported" };
|
|
18840
|
+
if (portals.length !== 1) return { kind: "ambiguous" };
|
|
18841
|
+
const value = portals[0]?.getAttribute("data-above-composer-conversation-id");
|
|
18842
|
+
if (value === null) return { kind: "draft" };
|
|
18843
|
+
const candidate = hostThreadIdSchema.safeParse(value);
|
|
18844
|
+
return candidate.success ? { kind: "conversation", threadId: candidate.data } : { kind: "ambiguous" };
|
|
18845
|
+
}
|
|
18846
|
+
function findComposerDraftIds(composer) {
|
|
18658
18847
|
const draftIds = /* @__PURE__ */ new Set();
|
|
18659
18848
|
let fiber = findComposerFiber(composer);
|
|
18660
18849
|
for (let depth = 0; fiber && depth < 120; depth += 1) {
|
|
@@ -18669,6 +18858,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18669
18858
|
const parent = fiber.return;
|
|
18670
18859
|
fiber = (typeof parent === "object" || typeof parent === "function") && parent !== null ? parent : null;
|
|
18671
18860
|
}
|
|
18861
|
+
return draftIds;
|
|
18862
|
+
}
|
|
18863
|
+
function findComposerModelTarget(composer) {
|
|
18864
|
+
const draftIds = findComposerDraftIds(composer);
|
|
18865
|
+
const domIdentity = findComposerDomIdentity(composer);
|
|
18866
|
+
if (domIdentity.kind === "ambiguous") return null;
|
|
18867
|
+
if (domIdentity.kind === "conversation") {
|
|
18868
|
+
return ["conversation", domIdentity.threadId];
|
|
18869
|
+
}
|
|
18870
|
+
if (domIdentity.kind === "draft") {
|
|
18871
|
+
return draftIds.size === 1 ? ["default", draftIds.values().next().value] : null;
|
|
18872
|
+
}
|
|
18873
|
+
const conversationThreadId = findComposerConversationThreadId(composer);
|
|
18874
|
+
if (conversationThreadId === null) return null;
|
|
18875
|
+
if (conversationThreadId !== void 0) return ["conversation", conversationThreadId];
|
|
18672
18876
|
if (draftIds.size !== 1) return null;
|
|
18673
18877
|
return ["default", draftIds.values().next().value];
|
|
18674
18878
|
}
|
|
@@ -18676,7 +18880,39 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18676
18880
|
return isRecord5(value) && value.state === "ready";
|
|
18677
18881
|
}
|
|
18678
18882
|
function isDraftPrewarmPolicyReady(value) {
|
|
18679
|
-
return isRecord5(value) && value.state === "ready" && typeof value.select === "function" && typeof value.clear === "function";
|
|
18883
|
+
return isRecord5(value) && value.state === "ready" && typeof value.hostId === "string" && value.hostId.length > 0 && typeof value.select === "function" && typeof value.clear === "function";
|
|
18884
|
+
}
|
|
18885
|
+
function prewarmTargetHostId(target) {
|
|
18886
|
+
const bridge = target.requestClient ?? target;
|
|
18887
|
+
const hostId = target.getHostId?.() ?? bridge.hostId;
|
|
18888
|
+
return typeof hostId === "string" && hostId.length > 0 ? hostId : null;
|
|
18889
|
+
}
|
|
18890
|
+
function rendererRequestTargetsForHost(targets, hostId) {
|
|
18891
|
+
const matching = targets.filter((target) => prewarmTargetHostId(target) === hostId);
|
|
18892
|
+
return matching.length === 1 ? matching : null;
|
|
18893
|
+
}
|
|
18894
|
+
function activeRendererDraftPrewarmTargets(policy, targets) {
|
|
18895
|
+
if (!isDraftPrewarmPolicyReady(policy)) return null;
|
|
18896
|
+
return rendererRequestTargetsForHost(targets, policy.hostId);
|
|
18897
|
+
}
|
|
18898
|
+
function resolveRendererRequestRoute(policy, discoveredTargets, previous) {
|
|
18899
|
+
const activeTargets = activeRendererDraftPrewarmTargets(policy, discoveredTargets);
|
|
18900
|
+
if (isDraftPrewarmPolicyReady(policy) && activeTargets) {
|
|
18901
|
+
return { policy, targets: activeTargets };
|
|
18902
|
+
}
|
|
18903
|
+
return discoveredTargets.length === 0 && isDraftPrewarmPolicyReady(policy) && previous?.policy === policy ? previous : null;
|
|
18904
|
+
}
|
|
18905
|
+
function createRendererRequestRouteResolver(readPolicy, discoverTargets) {
|
|
18906
|
+
let route = null;
|
|
18907
|
+
return {
|
|
18908
|
+
resolve() {
|
|
18909
|
+
route = resolveRendererRequestRoute(readPolicy(), discoverTargets(), route);
|
|
18910
|
+
return route;
|
|
18911
|
+
},
|
|
18912
|
+
clear() {
|
|
18913
|
+
route = null;
|
|
18914
|
+
}
|
|
18915
|
+
};
|
|
18680
18916
|
}
|
|
18681
18917
|
async function waitForRendererDraftPrewarmPolicy(target) {
|
|
18682
18918
|
const deadline = Date.now() + DRAFT_PREWARM_POLICY_WAIT_TIMEOUT_MS;
|
|
@@ -18691,7 +18927,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18691
18927
|
}
|
|
18692
18928
|
}
|
|
18693
18929
|
function modelSelectionForAgent(officialSelection, reasoningEffort, agent, model, thinkingOptionId, permissionModeId) {
|
|
18694
|
-
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);
|
|
18930
|
+
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);
|
|
18695
18931
|
return transportModelId ? { model: transportModelId, reasoningEffort } : officialSelection;
|
|
18696
18932
|
}
|
|
18697
18933
|
function installCurrentRendererAdapter() {
|
|
@@ -18717,13 +18953,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18717
18953
|
}
|
|
18718
18954
|
});
|
|
18719
18955
|
const usageSubscription = createThreadUsageSubscriptionRelay();
|
|
18956
|
+
const requestRouteResolver = createRendererRequestRouteResolver(
|
|
18957
|
+
() => window.__codexhostDraftPrewarmPolicyV1,
|
|
18958
|
+
() => findActivePrewarmTargets(document)
|
|
18959
|
+
);
|
|
18960
|
+
const currentRequestRoute = () => requestRouteResolver.resolve();
|
|
18961
|
+
const clientsByTarget = /* @__PURE__ */ new WeakMap();
|
|
18962
|
+
const modelClientForTargets = (targets) => {
|
|
18963
|
+
const target = targets[0];
|
|
18964
|
+
if (targets.length !== 1 || !target) return null;
|
|
18965
|
+
const cached2 = clientsByTarget.get(target);
|
|
18966
|
+
if (cached2) return cached2;
|
|
18967
|
+
const client = createRendererModelClient([target]);
|
|
18968
|
+
if (client) clientsByTarget.set(target, client);
|
|
18969
|
+
return client;
|
|
18970
|
+
};
|
|
18720
18971
|
const currentModelClient = () => {
|
|
18721
|
-
const client =
|
|
18972
|
+
const client = modelClientForTargets(currentRequestRoute()?.targets ?? []);
|
|
18722
18973
|
if (!client) throw new Error("Renderer Model request manager is unavailable");
|
|
18723
18974
|
usageSubscription.connect(client);
|
|
18724
18975
|
return client;
|
|
18725
18976
|
};
|
|
18726
18977
|
const modelControl = Object.freeze({
|
|
18978
|
+
currentHostId: () => currentRequestRoute()?.policy.hostId ?? null,
|
|
18979
|
+
clientForHost(hostId) {
|
|
18980
|
+
const targets = rendererRequestTargetsForHost(findActivePrewarmTargets(document), hostId);
|
|
18981
|
+
return modelClientForTargets(targets ?? []);
|
|
18982
|
+
},
|
|
18727
18983
|
forkThread: (input) => currentModelClient().forkThread(input),
|
|
18728
18984
|
inspectHarness: (input) => currentModelClient().inspectHarness(input),
|
|
18729
18985
|
inspectThread: (input) => currentModelClient().inspectThread(input),
|
|
@@ -18754,10 +19010,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18754
19010
|
});
|
|
18755
19011
|
let routingPolicy = null;
|
|
18756
19012
|
let policyTimer = null;
|
|
19013
|
+
let desiredCarrier = null;
|
|
18757
19014
|
const captureRoutingPolicy = () => {
|
|
18758
|
-
const
|
|
18759
|
-
if (!
|
|
18760
|
-
routingPolicy =
|
|
19015
|
+
const route = currentRequestRoute();
|
|
19016
|
+
if (!route) return false;
|
|
19017
|
+
routingPolicy = route.policy;
|
|
19018
|
+
routingPolicy.select(desiredCarrier);
|
|
18761
19019
|
if (policyTimer !== null) {
|
|
18762
19020
|
window.clearInterval(policyTimer);
|
|
18763
19021
|
policyTimer = null;
|
|
@@ -18769,8 +19027,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18769
19027
|
updateStatus("installing", "draft-routing-policy-unavailable", null);
|
|
18770
19028
|
policyTimer = window.setInterval(captureRoutingPolicy, DRAFT_PREWARM_POLICY_POLL_INTERVAL_MS);
|
|
18771
19029
|
}
|
|
19030
|
+
const handleRoutingPolicyChange = () => {
|
|
19031
|
+
captureRoutingPolicy();
|
|
19032
|
+
};
|
|
19033
|
+
window.addEventListener("codexhost:draft-prewarm-policy-changed", handleRoutingPolicyChange);
|
|
18772
19034
|
const applyAgent = (agent, model, thinkingOptionId, permissionModeId) => {
|
|
18773
|
-
if (disposed
|
|
19035
|
+
if (disposed) return false;
|
|
18774
19036
|
const selection = modelSelectionForAgent(
|
|
18775
19037
|
null,
|
|
18776
19038
|
null,
|
|
@@ -18781,7 +19043,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18781
19043
|
);
|
|
18782
19044
|
const carrier = selection?.model;
|
|
18783
19045
|
if (carrier !== null && carrier !== void 0 && typeof carrier !== "string") return false;
|
|
18784
|
-
|
|
19046
|
+
desiredCarrier = carrier ?? null;
|
|
19047
|
+
const route = currentRequestRoute();
|
|
19048
|
+
if (!route) return false;
|
|
19049
|
+
routingPolicy = route.policy;
|
|
19050
|
+
if (route.policy.select(desiredCarrier)) {
|
|
18785
19051
|
modelUpdates += 1;
|
|
18786
19052
|
liveStatus.modelUpdates = modelUpdates;
|
|
18787
19053
|
}
|
|
@@ -18795,8 +19061,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18795
19061
|
if (disposed) return;
|
|
18796
19062
|
disposed = true;
|
|
18797
19063
|
if (policyTimer !== null) window.clearInterval(policyTimer);
|
|
19064
|
+
window.removeEventListener(
|
|
19065
|
+
"codexhost:draft-prewarm-policy-changed",
|
|
19066
|
+
handleRoutingPolicyChange
|
|
19067
|
+
);
|
|
18798
19068
|
routingPolicy?.select(null);
|
|
18799
19069
|
routingPolicy = null;
|
|
19070
|
+
requestRouteResolver.clear();
|
|
18800
19071
|
forkControl.dispose();
|
|
18801
19072
|
usageSubscription.dispose();
|
|
18802
19073
|
}
|
|
@@ -18848,9 +19119,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18848
19119
|
const model = harnessModelRefSchema.safeParse(value.model);
|
|
18849
19120
|
if (!model.success) return void 0;
|
|
18850
19121
|
const thinkingOptionId = harnessThinkingOptionIdSchema.safeParse(value.thinkingOptionId);
|
|
19122
|
+
const permissionModeId = harnessPermissionModeIdSchema.safeParse(value.permissionModeId);
|
|
18851
19123
|
return {
|
|
18852
19124
|
model: model.data,
|
|
18853
|
-
...thinkingOptionId.success ? { thinkingOptionId: thinkingOptionId.data } : {}
|
|
19125
|
+
...thinkingOptionId.success ? { thinkingOptionId: thinkingOptionId.data } : {},
|
|
19126
|
+
...permissionModeId.success ? { permissionModeId: permissionModeId.data } : {}
|
|
18854
19127
|
};
|
|
18855
19128
|
}
|
|
18856
19129
|
function readPreference(storage) {
|
|
@@ -18890,15 +19163,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18890
19163
|
const agent = readPreference(storage)?.lastAgent;
|
|
18891
19164
|
return agent && enabledAgents.has(agent) ? agent : void 0;
|
|
18892
19165
|
}
|
|
18893
|
-
function readNewThreadExternalConfigurationPreference(agent, catalog, storage = rendererStorage2()) {
|
|
19166
|
+
function readNewThreadExternalConfigurationPreference(agent, catalog, permissionModes, storage = rendererStorage2()) {
|
|
18894
19167
|
const preference = readPreference(storage)?.externalByAgent[agent];
|
|
18895
19168
|
if (!preference) return void 0;
|
|
18896
19169
|
const catalogModel = catalog.models.find(({ ref }) => ref.id === preference.model.id);
|
|
18897
19170
|
if (!catalogModel) return void 0;
|
|
18898
19171
|
const thinkingOptionId = preference.thinkingOptionId && catalogModel.supportedThinkingOptionIds?.includes(preference.thinkingOptionId) ? preference.thinkingOptionId : void 0;
|
|
19172
|
+
const permissionModeId = preference.permissionModeId && permissionModes?.modes.some(({ id }) => id === preference.permissionModeId) ? preference.permissionModeId : void 0;
|
|
18899
19173
|
return {
|
|
18900
19174
|
model: catalogModel.ref,
|
|
18901
|
-
...thinkingOptionId ? { thinkingOptionId } : {}
|
|
19175
|
+
...thinkingOptionId ? { thinkingOptionId } : {},
|
|
19176
|
+
...permissionModeId ? { permissionModeId } : {}
|
|
18902
19177
|
};
|
|
18903
19178
|
}
|
|
18904
19179
|
function writeNewThreadAgentPreference(agent, storage = rendererStorage2()) {
|
|
@@ -18912,7 +19187,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18912
19187
|
storage
|
|
18913
19188
|
);
|
|
18914
19189
|
}
|
|
18915
|
-
function writeNewThreadExternalConfigurationPreference(agent, model, thinkingOptionId, storage = rendererStorage2()) {
|
|
19190
|
+
function writeNewThreadExternalConfigurationPreference(agent, model, thinkingOptionId, permissionModeId, storage = rendererStorage2()) {
|
|
18916
19191
|
const current = readPreference(storage);
|
|
18917
19192
|
writePreference(
|
|
18918
19193
|
{
|
|
@@ -18922,7 +19197,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18922
19197
|
...current?.externalByAgent,
|
|
18923
19198
|
[agent]: {
|
|
18924
19199
|
model: harnessModelRefSchema.parse(model),
|
|
18925
|
-
...thinkingOptionId ? { thinkingOptionId: harnessThinkingOptionIdSchema.parse(thinkingOptionId) } : {}
|
|
19200
|
+
...thinkingOptionId ? { thinkingOptionId: harnessThinkingOptionIdSchema.parse(thinkingOptionId) } : {},
|
|
19201
|
+
...permissionModeId ? { permissionModeId: harnessPermissionModeIdSchema.parse(permissionModeId) } : {}
|
|
18926
19202
|
}
|
|
18927
19203
|
}
|
|
18928
19204
|
},
|
|
@@ -19122,6 +19398,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19122
19398
|
runtimeCapabilityNotInstalled: "This runtime capability is not installed yet.",
|
|
19123
19399
|
connectionsDescription: "Inspect the adapter and each Agent runtime used by the picker. Failed checks keep their error details here.",
|
|
19124
19400
|
connectionAdapter: "Renderer adapter",
|
|
19401
|
+
connectionHosts: "Hosts",
|
|
19402
|
+
connectionLocalHost: "Local",
|
|
19403
|
+
connectionRemoteHost: "Remote Host",
|
|
19404
|
+
connectionActiveHost: "Current",
|
|
19125
19405
|
connectionReason: "Reason",
|
|
19126
19406
|
connectionRefresh: "Run connection diagnostics",
|
|
19127
19407
|
connectionRefreshing: "Running diagnostics...",
|
|
@@ -19190,6 +19470,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19190
19470
|
runtimeCapabilityNotInstalled: "\u8FD0\u884C\u65F6\u5C1A\u672A\u5B89\u88C5\u8BE5\u9879\u80FD\u529B\uFF0C\u56E0\u6B64\u6682\u4E0D\u53EF\u7528\u3002",
|
|
19191
19471
|
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",
|
|
19192
19472
|
connectionAdapter: "Renderer \u9002\u914D\u5668",
|
|
19473
|
+
connectionHosts: "Host \u5217\u8868",
|
|
19474
|
+
connectionLocalHost: "\u672C\u5730",
|
|
19475
|
+
connectionRemoteHost: "\u8FDC\u7A0B Host",
|
|
19476
|
+
connectionActiveHost: "\u5F53\u524D",
|
|
19193
19477
|
connectionReason: "\u539F\u56E0",
|
|
19194
19478
|
connectionRefresh: "\u91CD\u65B0\u8BCA\u65AD\u8FDE\u63A5",
|
|
19195
19479
|
connectionRefreshing: "\u6B63\u5728\u8BCA\u65AD...",
|
|
@@ -19833,10 +20117,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19833
20117
|
if (availability === "checking" || availability === "installing") return "checking";
|
|
19834
20118
|
return "failed";
|
|
19835
20119
|
}
|
|
19836
|
-
function diagnosticText(name, snapshot) {
|
|
20120
|
+
function diagnosticText(hostId, name, snapshot) {
|
|
19837
20121
|
const error51 = snapshot.error;
|
|
19838
20122
|
const lines = [
|
|
19839
20123
|
"codexhost connection diagnostics",
|
|
20124
|
+
`host: ${hostId}`,
|
|
19840
20125
|
`agent: ${name}`,
|
|
19841
20126
|
`status: ${snapshot.availability}`,
|
|
19842
20127
|
...error51 ? [
|
|
@@ -19882,7 +20167,7 @@ ${error51.stderrTail}`] : []
|
|
|
19882
20167
|
() => showCopyButtonFeedback(button, messages.connectionCopyFailed, restoreLabel)
|
|
19883
20168
|
);
|
|
19884
20169
|
}
|
|
19885
|
-
function appendConnectionRow(document2, parent, name, availability, detail, error51, messages, rowAttribute, diagnosticSnapshot) {
|
|
20170
|
+
function appendConnectionRow(document2, parent, name, availability, detail, error51, messages, rowAttribute, diagnosticSnapshot, diagnosticHostId) {
|
|
19886
20171
|
const row = document2.createElement("div");
|
|
19887
20172
|
row.className = "settings-connection-row";
|
|
19888
20173
|
if (rowAttribute) row.dataset.connectionAgent = rowAttribute;
|
|
@@ -19945,7 +20230,7 @@ ${error51.stderrTail}`] : []
|
|
|
19945
20230
|
copyDiagnosticsToClipboard(
|
|
19946
20231
|
document2,
|
|
19947
20232
|
copy,
|
|
19948
|
-
diagnosticText(name, diagnosticSnapshot),
|
|
20233
|
+
diagnosticText(diagnosticHostId ?? "unknown", name, diagnosticSnapshot),
|
|
19949
20234
|
messages,
|
|
19950
20235
|
messages.connectionCopyDetails
|
|
19951
20236
|
);
|
|
@@ -19961,6 +20246,18 @@ ${error51.stderrTail}`] : []
|
|
|
19961
20246
|
row.append(identity, status, detailElement, details);
|
|
19962
20247
|
parent.append(row);
|
|
19963
20248
|
}
|
|
20249
|
+
function connectionHostLabel(hostId, active, messages) {
|
|
20250
|
+
const activeLabel = active ? ` \xB7 ${messages.connectionActiveHost}` : "";
|
|
20251
|
+
if (hostId === "local") return `${messages.connectionLocalHost}${activeLabel}`;
|
|
20252
|
+
const separator = hostId.lastIndexOf(":");
|
|
20253
|
+
const encodedName = separator >= 0 ? hostId.slice(separator + 1) : hostId;
|
|
20254
|
+
let name = encodedName;
|
|
20255
|
+
try {
|
|
20256
|
+
name = decodeURIComponent(encodedName);
|
|
20257
|
+
} catch {
|
|
20258
|
+
}
|
|
20259
|
+
return `${messages.connectionRemoteHost}: ${name}${activeLabel}`;
|
|
20260
|
+
}
|
|
19964
20261
|
function connectionsPage(messages, getDiagnostics) {
|
|
19965
20262
|
return Object.freeze({
|
|
19966
20263
|
id: "connections",
|
|
@@ -19991,7 +20288,10 @@ ${error51.stderrTail}`] : []
|
|
|
19991
20288
|
content.className = "settings-connection-list";
|
|
19992
20289
|
context.content.append(heading, description, actions, content);
|
|
19993
20290
|
let pending = false;
|
|
20291
|
+
let selectedHostId = "local";
|
|
20292
|
+
let latestSnapshot = null;
|
|
19994
20293
|
const render = (snapshot) => {
|
|
20294
|
+
latestSnapshot = snapshot;
|
|
19995
20295
|
content.replaceChildren();
|
|
19996
20296
|
if (!snapshot) {
|
|
19997
20297
|
const empty = document2.createElement("div");
|
|
@@ -20010,19 +20310,50 @@ ${error51.stderrTail}`] : []
|
|
|
20010
20310
|
messages,
|
|
20011
20311
|
"renderer-adapter"
|
|
20012
20312
|
);
|
|
20013
|
-
|
|
20313
|
+
const selectedHost = snapshot.hosts.find((host) => host.hostId === selectedHostId) ?? snapshot.hosts.find((host) => host.hostId === "local") ?? snapshot.hosts[0];
|
|
20314
|
+
if (!selectedHost) return;
|
|
20315
|
+
selectedHostId = selectedHost.hostId;
|
|
20316
|
+
const tabs = document2.createElement("div");
|
|
20317
|
+
tabs.className = "settings-connection-host-tabs";
|
|
20318
|
+
tabs.setAttribute("role", "tablist");
|
|
20319
|
+
tabs.setAttribute("aria-label", messages.connectionHosts);
|
|
20320
|
+
const hostSection = document2.createElement("section");
|
|
20321
|
+
hostSection.className = "settings-connection-host";
|
|
20322
|
+
hostSection.dataset.connectionHost = selectedHost.hostId;
|
|
20323
|
+
hostSection.setAttribute("role", "tabpanel");
|
|
20324
|
+
const panelId = "codexhost-settings-connection-host-panel";
|
|
20325
|
+
hostSection.id = panelId;
|
|
20326
|
+
for (const host of snapshot.hosts) {
|
|
20327
|
+
const tab = document2.createElement("button");
|
|
20328
|
+
tab.type = "button";
|
|
20329
|
+
tab.className = "settings-connection-host-tab";
|
|
20330
|
+
tab.dataset.connectionHostTab = host.hostId;
|
|
20331
|
+
tab.setAttribute("role", "tab");
|
|
20332
|
+
tab.setAttribute("aria-controls", panelId);
|
|
20333
|
+
tab.setAttribute("aria-selected", String(host.hostId === selectedHost.hostId));
|
|
20334
|
+
tab.tabIndex = host.hostId === selectedHost.hostId ? 0 : -1;
|
|
20335
|
+
tab.textContent = connectionHostLabel(host.hostId, host.active, messages);
|
|
20336
|
+
tab.addEventListener("click", () => {
|
|
20337
|
+
selectedHostId = host.hostId;
|
|
20338
|
+
render(latestSnapshot);
|
|
20339
|
+
});
|
|
20340
|
+
tabs.append(tab);
|
|
20341
|
+
}
|
|
20342
|
+
for (const agent of selectedHost.agents) {
|
|
20014
20343
|
appendConnectionRow(
|
|
20015
20344
|
document2,
|
|
20016
|
-
|
|
20345
|
+
hostSection,
|
|
20017
20346
|
RENDERER_AGENT_LABELS[agent.agent],
|
|
20018
20347
|
agent.availability,
|
|
20019
20348
|
null,
|
|
20020
20349
|
agent.error,
|
|
20021
20350
|
messages,
|
|
20022
20351
|
agent.agent,
|
|
20023
|
-
agent
|
|
20352
|
+
agent,
|
|
20353
|
+
selectedHost.hostId
|
|
20024
20354
|
);
|
|
20025
20355
|
}
|
|
20356
|
+
content.append(tabs, hostSection);
|
|
20026
20357
|
};
|
|
20027
20358
|
const diagnostics = getDiagnostics();
|
|
20028
20359
|
render(diagnostics?.snapshot() ?? null);
|
|
@@ -20032,7 +20363,11 @@ ${error51.stderrTail}`] : []
|
|
|
20032
20363
|
}
|
|
20033
20364
|
copyAll.addEventListener("click", () => {
|
|
20034
20365
|
const snapshot = diagnostics.snapshot();
|
|
20035
|
-
const report = snapshot.
|
|
20366
|
+
const report = snapshot.hosts.flatMap(
|
|
20367
|
+
(host) => host.agents.map(
|
|
20368
|
+
(agent) => diagnosticText(host.hostId, RENDERER_AGENT_LABELS[agent.agent], agent)
|
|
20369
|
+
)
|
|
20370
|
+
).join("\n\n");
|
|
20036
20371
|
copyDiagnosticsToClipboard(document2, copyAll, report, messages, messages.connectionCopyAll);
|
|
20037
20372
|
});
|
|
20038
20373
|
const unsubscribe = diagnostics.subscribe(() => render(diagnostics.snapshot()));
|
|
@@ -20061,17 +20396,21 @@ ${error51.stderrTail}`] : []
|
|
|
20061
20396
|
createRendererSettingsIcon("diagnose", 16),
|
|
20062
20397
|
messages.connectionRefresh
|
|
20063
20398
|
);
|
|
20399
|
+
const snapshot = diagnostics.snapshot();
|
|
20064
20400
|
render({
|
|
20065
|
-
...
|
|
20066
|
-
|
|
20067
|
-
...
|
|
20068
|
-
|
|
20069
|
-
|
|
20070
|
-
|
|
20071
|
-
|
|
20072
|
-
|
|
20073
|
-
|
|
20074
|
-
|
|
20401
|
+
...snapshot,
|
|
20402
|
+
hosts: snapshot.hosts.map((host) => ({
|
|
20403
|
+
...host,
|
|
20404
|
+
agents: host.agents.map((agent) => ({
|
|
20405
|
+
...agent,
|
|
20406
|
+
availability: "error",
|
|
20407
|
+
error: {
|
|
20408
|
+
code: "internalError",
|
|
20409
|
+
message: error51 instanceof Error ? error51.message : String(error51),
|
|
20410
|
+
retryable: true,
|
|
20411
|
+
stage: "request"
|
|
20412
|
+
}
|
|
20413
|
+
}))
|
|
20075
20414
|
}))
|
|
20076
20415
|
});
|
|
20077
20416
|
}
|
|
@@ -20371,7 +20710,7 @@ ${error51.stderrTail}`] : []
|
|
|
20371
20710
|
}
|
|
20372
20711
|
|
|
20373
20712
|
// src/settings/shell.css
|
|
20374
|
-
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';
|
|
20713
|
+
var shell_default = ':host {\n --settings-bg: #181818;\n --settings-sidebar: #1c1c1c;\n --settings-panel: transparent;\n --settings-text: #f5f5f5;\n --settings-muted: #a1a1a1;\n --settings-border: rgb(255 255 255 / 10%);\n --settings-divider: rgb(255 255 255 / 10%);\n --settings-hover: rgb(255 255 255 / 6%);\n --settings-active: rgb(51 156 255 / 12%);\n --settings-focus: #339cff;\n color: var(--settings-text);\n color-scheme: dark;\n font:\n 14px/1.5 system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n letter-spacing: 0;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n letter-spacing: 0;\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\nbutton {\n color: inherit;\n}\n\n[hidden] {\n display: none !important;\n}\n\n.codexhost-settings-dialog {\n width: min(1120px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 32px));\n max-width: none;\n max-height: none;\n margin: auto;\n padding: 0;\n overflow: hidden;\n color: var(--settings-text);\n background: var(--settings-bg);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n box-shadow: 0 24px 64px rgb(0 0 0 / 38%);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: rgb(0 0 0 / 52%);\n}\n\n.settings-frame,\n.settings-layout {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n}\n\n.settings-frame {\n display: flex;\n flex-direction: column;\n}\n\n.settings-layout {\n flex: 1;\n display: grid;\n grid-template-columns: 240px minmax(0, 1fr);\n background: var(--settings-bg);\n}\n\n.settings-sidebar {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n background: var(--settings-sidebar);\n border-right: 1px solid var(--settings-border);\n padding-top: 28px;\n}\n\n.settings-header {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 64px;\n flex: none;\n padding: 0 16px;\n border-bottom: 1px solid var(--settings-border);\n}\n\n.settings-header-actions {\n display: flex;\n align-items: center;\n flex: none;\n gap: 12px;\n margin-left: auto;\n}\n\n.settings-icon-button.settings-star-link {\n width: auto;\n gap: 6px;\n padding-inline: 8px;\n font-size: 12px;\n line-height: 18px;\n text-decoration: none;\n border: 2px dashed #f5c542;\n white-space: nowrap;\n}\n\n.settings-star-link .codexhost-settings-icon {\n color: #f5c542;\n fill: currentColor;\n stroke: currentColor;\n}\n\n.settings-brand {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-brand__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n flex: none;\n color: var(--settings-text);\n}\n\n.settings-brand__mark .codexhost-settings-icon {\n width: 32px;\n height: 32px;\n object-fit: contain;\n}\n\n.settings-brand__copy {\n display: flex;\n min-width: 0;\n align-items: baseline;\n gap: 0;\n line-height: 20px;\n}\n\n.settings-brand__name {\n overflow: hidden;\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-brand__title {\n margin-left: 14px;\n padding-left: 14px;\n color: var(--settings-muted);\n font-size: 14px;\n font-weight: 400;\n border-left: 1px solid var(--settings-border);\n}\n\n.settings-nav {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 4px;\n padding: 0 12px 16px;\n overflow-y: auto;\n}\n\n.settings-nav-button {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n width: 100%;\n position: relative;\n min-height: 40px;\n flex: none;\n gap: 12px;\n padding: 8px 12px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 21px;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: 10px;\n cursor: pointer;\n}\n\n.settings-nav-button .codexhost-settings-icon {\n width: 18px;\n height: 18px;\n opacity: 0.9;\n}\n\n.settings-nav-button:hover {\n background: var(--settings-hover);\n}\n\n.settings-nav-button[aria-current="page"] {\n background: var(--settings-active);\n color: var(--settings-focus);\n}\n\n.settings-nav-button[aria-current="page"]::before {\n position: absolute;\n left: 0;\n width: 3px;\n height: 22px;\n content: "";\n background: var(--settings-focus);\n border-radius: 0 3px 3px 0;\n}\n\n.settings-nav-button span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex: none;\n padding: 0;\n color: var(--settings-muted);\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n}\n\n.settings-icon-button:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-icon-button:focus-visible,\n.settings-nav-button:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 1px;\n}\n\n.settings-page {\n display: block;\n position: relative;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n background: var(--settings-bg);\n scrollbar-gutter: stable;\n}\n\n.settings-page__content {\n width: min(930px, calc(100% - 80px));\n margin-inline: auto;\n}\n\n.settings-page__content {\n min-width: 0;\n padding: 44px 0 56px;\n}\n\n.settings-section-label {\n min-height: auto;\n padding: 0 0 28px;\n color: var(--settings-text);\n font-size: 24px;\n font-weight: 600;\n line-height: 30px;\n}\n\n.settings-status-list,\n.settings-empty {\n overflow: hidden;\n background: var(--settings-panel);\n}\n\n.settings-status-row {\n display: grid;\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\n position: relative;\n align-items: center;\n min-height: 88px;\n gap: 28px;\n padding: 16px 0;\n}\n\n.settings-status-row:not(:last-child)::after {\n content: "";\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 1px;\n background: var(--settings-divider);\n}\n\n.settings-status-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n color: var(--settings-text);\n gap: 14px;\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-status-row__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n flex: none;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 7%);\n border-radius: 50%;\n}\n\n.settings-status-badge {\n flex: none;\n padding: 5px 12px;\n color: var(--settings-muted);\n font-size: 13px;\n font-weight: 500;\n line-height: 18px;\n background: rgb(255 255 255 / 9%);\n border: 1px solid rgb(255 255 255 / 6%);\n border-radius: 6px;\n}\n\n.settings-status-row__detail {\n min-width: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-page-description {\n max-width: 760px;\n margin: -12px 0 24px;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-connection-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-bottom: 16px;\n}\n\n.settings-connection-list {\n min-width: 0;\n border-top: 1px solid var(--settings-divider);\n}\n\n.settings-connection-host-tabs {\n display: flex;\n gap: 6px;\n padding: 20px 0 8px;\n overflow-x: auto;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-host-tab {\n flex: none;\n padding: 7px 12px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: var(--settings-muted);\n font: inherit;\n font-size: 13px;\n line-height: 18px;\n cursor: pointer;\n}\n\n.settings-connection-host-tab:hover {\n background: var(--settings-hover);\n color: var(--settings-text);\n}\n\n.settings-connection-host-tab[aria-selected="true"] {\n background: var(--settings-active);\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-connection-host-tab:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: -2px;\n}\n\n.settings-connection-row {\n display: grid;\n grid-template-columns: minmax(180px, 1fr) auto minmax(260px, 1.5fr);\n align-items: center;\n min-width: 0;\n min-height: 76px;\n gap: 24px;\n padding: 14px 0;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-connection-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n gap: 10px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 20px;\n}\n\n.settings-connection-row__identity strong {\n min-width: 0;\n overflow-wrap: anywhere;\n font-weight: 500;\n}\n\n.settings-connection-row__dot {\n width: 9px;\n height: 9px;\n flex: none;\n border-radius: 50%;\n background: var(--settings-muted);\n}\n\n.settings-connection-row__dot[data-connection-tone="ready"] {\n background: #22c55e;\n}\n\n.settings-connection-row__dot[data-connection-tone="checking"] {\n background: #f5c542;\n}\n\n.settings-connection-row__dot[data-connection-tone="failed"] {\n background: #ef4444;\n}\n\n.settings-status-badge[data-connection-tone="ready"] {\n color: #4ade80;\n}\n\n.settings-status-badge[data-connection-tone="checking"] {\n color: #f5c542;\n}\n\n.settings-status-badge[data-connection-tone="failed"] {\n color: #f87171;\n}\n\n.settings-connection-row__detail {\n display: grid;\n min-width: 0;\n align-items: center;\n gap: 2px 12px;\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-connection-row__reason {\n min-width: 0;\n overflow-wrap: anywhere;\n white-space: pre-wrap;\n}\n\n.settings-connection-details-toggle {\n width: fit-content;\n padding: 0;\n color: var(--settings-focus);\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n background: transparent;\n border: 0;\n cursor: pointer;\n}\n\n.settings-connection-details-toggle:hover {\n text-decoration: underline;\n}\n\n.settings-connection-details {\n display: grid;\n grid-column: 1 / -1;\n gap: 6px;\n min-width: 0;\n margin: 4px 0 2px 32px;\n padding: 12px;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 4%);\n border-left: 2px solid #ef4444;\n border-radius: 4px;\n}\n\n.settings-connection-detail-line {\n display: grid;\n grid-template-columns: 112px minmax(0, 1fr);\n gap: 12px;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-connection-detail-line span {\n color: var(--settings-muted);\n}\n\n.settings-connection-detail-line code {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n white-space: pre-wrap;\n}\n\n.settings-connection-stderr {\n max-height: 220px;\n min-width: 0;\n margin: 4px 0 0;\n padding: 10px;\n overflow: auto;\n color: #fca5a5;\n font:\n 12px/18px ui-monospace,\n "SFMono-Regular",\n Consolas,\n "Liberation Mono",\n monospace;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n background: rgb(0 0 0 / 28%);\n border-radius: 4px;\n}\n\n.settings-connection-details .settings-command-button {\n justify-self: start;\n min-height: 30px;\n font-size: 12px;\n}\n\n.settings-connection-row__detail time {\n color: var(--settings-muted);\n opacity: 0.8;\n}\n\n.settings-empty {\n display: flex;\n align-items: center;\n min-height: 72px;\n padding: 12px 16px;\n}\n\n.settings-empty > div {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n\n.settings-empty strong {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 500;\n line-height: 19px;\n}\n\n.settings-empty span {\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 19px;\n}\n\n.settings-page-error {\n padding: 16px;\n color: var(--settings-text);\n font-size: 13px;\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 20px;\n}\n\n.settings-update-metadata {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 24px;\n margin-bottom: 24px;\n padding: 0 4px 20px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-update-metadata__item {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n\n.settings-update-metadata__item span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-metadata__item strong {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-update-panel {\n display: grid;\n gap: 16px;\n min-height: 128px;\n padding: 20px;\n color: var(--settings-text);\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n}\n\n.settings-update-panel > strong,\n.settings-update-panel > span,\n.settings-update-summary,\n.settings-update-error {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-panel > span,\n.settings-update-summary {\n color: var(--settings-muted);\n}\n\n.settings-update-error {\n color: #ef4444;\n}\n\n.settings-update-progress {\n width: 100%;\n height: 8px;\n accent-color: #238be8;\n}\n\n.settings-update-progress-detail {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-notes {\n display: grid;\n min-width: 0;\n gap: 12px;\n color: var(--settings-muted);\n font-size: 14px;\n line-height: 22px;\n overflow-wrap: anywhere;\n}\n\n.settings-update-notes > :first-child {\n margin-top: 0;\n}\n\n.settings-update-notes > :last-child {\n margin-bottom: 0;\n}\n\n.settings-update-notes h1,\n.settings-update-notes h2,\n.settings-update-notes h3,\n.settings-update-notes h4,\n.settings-update-notes h5,\n.settings-update-notes h6 {\n margin: 6px 0 0;\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-update-notes h1 {\n font-size: 18px;\n line-height: 26px;\n}\n\n.settings-update-notes h2 {\n font-size: 17px;\n line-height: 24px;\n}\n\n.settings-update-notes h3,\n.settings-update-notes h4,\n.settings-update-notes h5,\n.settings-update-notes h6 {\n font-size: 14px;\n line-height: 22px;\n}\n\n.settings-update-notes p,\n.settings-update-notes ul,\n.settings-update-notes ol,\n.settings-update-notes pre,\n.settings-update-notes blockquote {\n margin: 0;\n}\n\n.settings-update-notes ul,\n.settings-update-notes ol {\n padding-left: 24px;\n}\n\n.settings-update-notes li {\n padding-left: 4px;\n}\n\n.settings-update-notes li::marker {\n color: var(--settings-muted);\n font-size: 0.85em;\n}\n\n.settings-update-notes li + li {\n margin-top: 14px;\n}\n\n.settings-update-notes .release-note-translation {\n display: block;\n margin-top: 3px;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-notes blockquote {\n padding: 8px 12px;\n color: var(--settings-muted);\n border-left: 3px solid var(--settings-focus);\n background: rgb(255 255 255 / 4%);\n}\n\n.settings-update-notes hr {\n width: 100%;\n margin: 2px 0;\n border: 0;\n border-top: 1px solid var(--settings-divider);\n}\n\n.settings-update-notes strong {\n color: var(--settings-text);\n font-weight: 600;\n}\n\n.settings-update-notes a {\n color: #7cb8ff;\n text-decoration: none;\n}\n\n.settings-update-notes a:hover {\n text-decoration: underline;\n}\n\n.settings-update-notes code {\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 12px;\n}\n\n.settings-update-notes :not(pre) > code {\n padding: 1px 5px;\n background: rgb(255 255 255 / 8%);\n border-radius: 4px;\n}\n\n.settings-update-notes pre {\n min-width: 0;\n max-width: 100%;\n padding: 10px 12px;\n overflow-x: auto;\n overflow-y: hidden;\n background: rgb(0 0 0 / 28%);\n border-radius: 6px;\n}\n\n.settings-update-notes pre code {\n line-height: 18px;\n white-space: pre-wrap;\n}\n\n.settings-update-version-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: 20px;\n min-height: 32px;\n color: var(--settings-muted);\n font-size: 13px;\n}\n\n.settings-update-version-row strong {\n color: var(--settings-text);\n font-size: 15px;\n}\n\n.settings-update-manual {\n display: grid;\n min-width: 0;\n gap: 6px;\n margin-top: 14px;\n padding-inline: 4px;\n}\n\n.settings-update-manual[hidden] {\n display: none;\n}\n\n.settings-update-manual span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-manual code {\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-actions {\n display: flex;\n min-width: 0;\n margin-top: 16px;\n}\n\n.settings-command-button,\n.settings-update-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: fit-content;\n min-height: 36px;\n gap: 8px;\n padding: 8px 12px;\n color: white;\n font: inherit;\n font-size: 13px;\n text-decoration: none;\n background: #1677d2;\n border: 1px solid #238be8;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.settings-command-button--secondary,\n.settings-update-link {\n color: var(--settings-text);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button:hover,\n.settings-update-link:hover {\n filter: brightness(1.08);\n}\n\n.settings-command-button:focus-visible,\n.settings-update-link:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 2px;\n}\n\n.codexhost-settings-icon {\n display: block;\n flex: none;\n stroke: currentColor;\n}\n\n@media (max-width: 720px) {\n .codexhost-settings-dialog {\n width: calc(100vw - 16px);\n height: calc(100vh - 16px);\n border-radius: 10px;\n }\n\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .settings-sidebar {\n border-right: 0;\n border-bottom: 1px solid var(--settings-border);\n }\n\n .settings-header {\n height: 56px;\n padding-inline: 14px;\n }\n\n .settings-icon-button.settings-star-link {\n width: 28px;\n padding: 0;\n }\n\n .settings-star-link span {\n display: none;\n }\n\n .settings-sidebar {\n padding-top: 20px;\n }\n\n .settings-nav {\n flex: none;\n flex-direction: row;\n gap: 4px;\n padding: 7px 8px 8px;\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n .settings-nav-button {\n width: auto;\n min-width: max-content;\n min-height: 34px;\n grid-template-columns: 16px auto;\n border-radius: 10px;\n }\n\n .settings-page__content {\n width: calc(100% - 40px);\n }\n\n .settings-page__content {\n padding-top: 32px;\n padding-bottom: 32px;\n }\n\n .settings-section-label {\n padding-bottom: 20px;\n font-size: 20px;\n line-height: 26px;\n }\n\n .settings-status-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 16px;\n }\n\n .settings-connection-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 10px 16px;\n }\n\n .settings-connection-row__detail {\n grid-column: 1 / -1;\n }\n\n .settings-status-row__detail {\n grid-column: 1 / -1;\n margin: -8px 0 0 58px;\n }\n}\n\n@media (forced-colors: active) {\n :host,\n :host([data-theme="dark"]) {\n --settings-bg: Canvas;\n --settings-sidebar: Canvas;\n --settings-panel: Canvas;\n --settings-text: CanvasText;\n --settings-muted: GrayText;\n --settings-border: ButtonBorder;\n --settings-divider: ButtonBorder;\n --settings-hover: Highlight;\n --settings-active: Highlight;\n --settings-focus: Highlight;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
|
|
20375
20714
|
|
|
20376
20715
|
// src/settings/shell.ts
|
|
20377
20716
|
var SETTINGS_SHELL_ATTRIBUTE = "data-codexhost-settings-shell";
|
|
@@ -21034,6 +21373,9 @@ ${error51.stderrTail}`] : []
|
|
|
21034
21373
|
function draftPermissionMode(catalog, requested) {
|
|
21035
21374
|
return catalog.modes.find(({ id }) => id === requested)?.id ?? catalog.modes.find(({ id }) => id === catalog.defaultModeId)?.id ?? catalog.defaultModeId;
|
|
21036
21375
|
}
|
|
21376
|
+
function shouldPersistNewThreadConfigurationSelection(phase) {
|
|
21377
|
+
return phase === "draft";
|
|
21378
|
+
}
|
|
21037
21379
|
function restoredThreadOwnership(inspection) {
|
|
21038
21380
|
if (inspection.owner === "codex") return { agent: "codex" };
|
|
21039
21381
|
if (inspection.harnessId === "pi") {
|
|
@@ -21057,10 +21399,12 @@ ${error51.stderrTail}`] : []
|
|
|
21057
21399
|
}
|
|
21058
21400
|
const model = inspection.effectiveModel ?? transportSelection.model;
|
|
21059
21401
|
const thinkingOptionId = selectableThinkingOptionId(inspection) ?? transportSelection.thinkingOptionId;
|
|
21402
|
+
const permissionModeId = inspection.effectivePermissionModeId ?? transportSelection.permissionModeId;
|
|
21060
21403
|
return {
|
|
21061
21404
|
agent: "grok",
|
|
21062
21405
|
...model ? { model } : {},
|
|
21063
|
-
...thinkingOptionId ? { thinkingOptionId } : {}
|
|
21406
|
+
...thinkingOptionId ? { thinkingOptionId } : {},
|
|
21407
|
+
...permissionModeId ? { permissionModeId } : {}
|
|
21064
21408
|
};
|
|
21065
21409
|
}
|
|
21066
21410
|
if (inspection.harnessId === "claude-code") {
|
|
@@ -21091,10 +21435,10 @@ ${error51.stderrTail}`] : []
|
|
|
21091
21435
|
function isOwnershipSubmissionBlocked(status) {
|
|
21092
21436
|
return status === "loading" || status === "error";
|
|
21093
21437
|
}
|
|
21094
|
-
function shouldTransferComposerState(sourceTarget, replacementTarget, sourcePhase) {
|
|
21438
|
+
function shouldTransferComposerState(sourceTarget, replacementTarget, sourcePhase, submissionPending = false) {
|
|
21095
21439
|
if (!sourceTarget || !replacementTarget) return false;
|
|
21096
21440
|
if (sourceTarget === replacementTarget) return true;
|
|
21097
|
-
return sourcePhase === "locked" && sourceTarget[0] === "default" && replacementTarget[0] === "conversation";
|
|
21441
|
+
return (sourcePhase === "locked" || submissionPending) && sourceTarget[0] === "default" && replacementTarget[0] === "conversation";
|
|
21098
21442
|
}
|
|
21099
21443
|
function isLateConversationTarget(mountedTarget, currentTarget) {
|
|
21100
21444
|
if (currentTarget?.[0] !== "conversation") return false;
|
|
@@ -21103,13 +21447,16 @@ ${error51.stderrTail}`] : []
|
|
|
21103
21447
|
if (mountedTarget?.[0] !== "conversation") return false;
|
|
21104
21448
|
return mountedTarget.length !== currentTarget.length || mountedTarget.some((value, index) => value !== currentTarget[index]);
|
|
21105
21449
|
}
|
|
21106
|
-
function lateConversationTargetResolution(mountedTarget, currentTarget, sourcePhase) {
|
|
21450
|
+
function lateConversationTargetResolution(mountedTarget, currentTarget, sourcePhase, submissionPending = false) {
|
|
21107
21451
|
if (!isLateConversationTarget(mountedTarget, currentTarget)) return "none";
|
|
21108
|
-
return mountedTarget?.[0] === "default" && sourcePhase === "locked" ? "transfer" : "inspect";
|
|
21452
|
+
return mountedTarget?.[0] === "default" && (sourcePhase === "locked" || submissionPending) ? "transfer" : "inspect";
|
|
21109
21453
|
}
|
|
21110
21454
|
function isComposerModelWriteAllowed(target) {
|
|
21111
21455
|
return target?.[0] === "default";
|
|
21112
21456
|
}
|
|
21457
|
+
function shouldApplyDraftAgentCarrier(agent, model) {
|
|
21458
|
+
return agent === "codex" || model !== void 0;
|
|
21459
|
+
}
|
|
21113
21460
|
function applyComposerModelWrite(target, write) {
|
|
21114
21461
|
if (target?.[0] === "conversation") return true;
|
|
21115
21462
|
if (!isComposerModelWriteAllowed(target)) return false;
|
|
@@ -21159,6 +21506,8 @@ ${error51.stderrTail}`] : []
|
|
|
21159
21506
|
let modelControl = null;
|
|
21160
21507
|
let usageNotificationDispose = null;
|
|
21161
21508
|
const localAgentForSidebarThread = (input) => {
|
|
21509
|
+
const mountedHostId = modelControl?.currentHostId?.() ?? "local";
|
|
21510
|
+
if (input.hostId !== mountedHostId) return null;
|
|
21162
21511
|
for (const mounted of mountedByComposer.values()) {
|
|
21163
21512
|
const target = mounted.modelTarget;
|
|
21164
21513
|
if (target?.[0] === "default" && input.draftId !== null && target[1] === input.draftId) {
|
|
@@ -21171,7 +21520,7 @@ ${error51.stderrTail}`] : []
|
|
|
21171
21520
|
return null;
|
|
21172
21521
|
};
|
|
21173
21522
|
const sidebarAgentIcons = installRendererSidebarAgentIcons({
|
|
21174
|
-
getClient: () =>
|
|
21523
|
+
getClient: (hostId) => modelClientForHost(hostId),
|
|
21175
21524
|
getLocalAgent: localAgentForSidebarThread
|
|
21176
21525
|
});
|
|
21177
21526
|
let connectionDiagnostics = null;
|
|
@@ -21185,23 +21534,36 @@ ${error51.stderrTail}`] : []
|
|
|
21185
21534
|
modelUpdates: 0,
|
|
21186
21535
|
hook: null
|
|
21187
21536
|
};
|
|
21188
|
-
|
|
21189
|
-
|
|
21190
|
-
|
|
21191
|
-
|
|
21192
|
-
|
|
21193
|
-
|
|
21194
|
-
|
|
21195
|
-
|
|
21537
|
+
const createHostHarnessAvailabilityState = () => ({
|
|
21538
|
+
availability: Object.fromEntries(
|
|
21539
|
+
externalAgents.map((agent) => [agent, "checking"])
|
|
21540
|
+
),
|
|
21541
|
+
errors: {
|
|
21542
|
+
pi: void 0,
|
|
21543
|
+
"claude-code": void 0,
|
|
21544
|
+
"deepseek-harness": void 0,
|
|
21545
|
+
grok: void 0
|
|
21546
|
+
},
|
|
21547
|
+
requestGeneration: 0,
|
|
21548
|
+
request: null,
|
|
21549
|
+
retryTimer: null,
|
|
21550
|
+
retryAttempt: 0
|
|
21551
|
+
});
|
|
21552
|
+
const harnessAvailabilityByHost = /* @__PURE__ */ new Map();
|
|
21553
|
+
const hostHarnessAvailabilityState = (hostId) => {
|
|
21554
|
+
let state = harnessAvailabilityByHost.get(hostId);
|
|
21555
|
+
if (!state) {
|
|
21556
|
+
state = createHostHarnessAvailabilityState();
|
|
21557
|
+
harnessAvailabilityByHost.set(hostId, state);
|
|
21558
|
+
}
|
|
21559
|
+
return state;
|
|
21196
21560
|
};
|
|
21561
|
+
let activeAvailabilityHostId = "local";
|
|
21562
|
+
const activeHarnessAvailabilityState = () => hostHarnessAvailabilityState(activeAvailabilityHostId);
|
|
21197
21563
|
const connectionListeners = /* @__PURE__ */ new Set();
|
|
21198
21564
|
const publishConnectionStatus = () => {
|
|
21199
21565
|
for (const listener of connectionListeners) listener();
|
|
21200
21566
|
};
|
|
21201
|
-
let availabilityRequestGeneration = 0;
|
|
21202
|
-
let availabilityRequest = null;
|
|
21203
|
-
let availabilityRetryTimer = null;
|
|
21204
|
-
let availabilityRetryAttempt = 0;
|
|
21205
21567
|
const availabilityRetryDelays = [500, 1e3, 2e3, 4e3, 8e3];
|
|
21206
21568
|
const usageRefreshTimers = /* @__PURE__ */ new Map();
|
|
21207
21569
|
const usageRefreshAttempts = /* @__PURE__ */ new Map();
|
|
@@ -21217,7 +21579,8 @@ ${error51.stderrTail}`] : []
|
|
|
21217
21579
|
writeNewThreadExternalConfigurationPreference(
|
|
21218
21580
|
state.agent,
|
|
21219
21581
|
model,
|
|
21220
|
-
controller.thinkingOptionForAgent(composer, state.agent)
|
|
21582
|
+
controller.thinkingOptionForAgent(composer, state.agent),
|
|
21583
|
+
controller.permissionModeForAgent(composer, state.agent)
|
|
21221
21584
|
);
|
|
21222
21585
|
}
|
|
21223
21586
|
}
|
|
@@ -21237,7 +21600,7 @@ ${error51.stderrTail}`] : []
|
|
|
21237
21600
|
controller.get(mounted.composer),
|
|
21238
21601
|
adapterStatus.state,
|
|
21239
21602
|
controller.isSwitching(mounted.composer) || isOwnershipSubmissionBlocked(mounted.ownershipStatus),
|
|
21240
|
-
|
|
21603
|
+
activeHarnessAvailabilityState().availability,
|
|
21241
21604
|
mounted.modelView,
|
|
21242
21605
|
mounted.permissionModeView,
|
|
21243
21606
|
mounted.usage,
|
|
@@ -21426,7 +21789,8 @@ ${error51.stderrTail}`] : []
|
|
|
21426
21789
|
const resolution = lateConversationTargetResolution(
|
|
21427
21790
|
mounted.modelTarget,
|
|
21428
21791
|
currentTarget,
|
|
21429
|
-
controller.get(mounted.composer).phase
|
|
21792
|
+
controller.get(mounted.composer).phase,
|
|
21793
|
+
controller.isSubmissionPending(mounted.composer)
|
|
21430
21794
|
);
|
|
21431
21795
|
if (resolution === "none") return false;
|
|
21432
21796
|
const previousTarget = mounted.modelTarget;
|
|
@@ -21463,7 +21827,7 @@ ${error51.stderrTail}`] : []
|
|
|
21463
21827
|
const state = controller.get(mounted.composer);
|
|
21464
21828
|
if (state.agent === "codex") return;
|
|
21465
21829
|
const agent = state.agent;
|
|
21466
|
-
const availability =
|
|
21830
|
+
const availability = activeHarnessAvailabilityState().availability[agent];
|
|
21467
21831
|
if (availability !== "ready") {
|
|
21468
21832
|
mounted.modelView = {
|
|
21469
21833
|
status: adapterStatus.state !== "ready" || availability === "checking" ? "waitingForAdapter" : "error",
|
|
@@ -21493,6 +21857,16 @@ ${error51.stderrTail}`] : []
|
|
|
21493
21857
|
}
|
|
21494
21858
|
if (inspection.status !== "ready") throw new Error(inspection.error.message);
|
|
21495
21859
|
const current = controller.get(mounted.composer);
|
|
21860
|
+
const previousModel = controller.modelForAgent(mounted.composer, agent);
|
|
21861
|
+
const previousModelAvailable = previousModel !== void 0 && inspection.catalog.models.some((model) => model.ref.id === previousModel.id);
|
|
21862
|
+
if (current.phase === "locked" && previousModel && !previousModelAvailable) {
|
|
21863
|
+
throw new Error("Existing Thread Model is absent from the current Catalog");
|
|
21864
|
+
}
|
|
21865
|
+
const preferredConfiguration = current.phase === "draft" && !previousModelAvailable ? readNewThreadExternalConfigurationPreference(
|
|
21866
|
+
agent,
|
|
21867
|
+
inspection.catalog,
|
|
21868
|
+
inspection.permissionModes
|
|
21869
|
+
) : void 0;
|
|
21496
21870
|
const previousPermissionModeId = controller.permissionModeForAgent(mounted.composer, agent);
|
|
21497
21871
|
let selectedPermissionModeId;
|
|
21498
21872
|
if (inspection.capabilities.configuration.selectPermissionMode) {
|
|
@@ -21502,7 +21876,7 @@ ${error51.stderrTail}`] : []
|
|
|
21502
21876
|
}
|
|
21503
21877
|
mounted.permissionModeView = { status: "loading", catalog: permissionModes };
|
|
21504
21878
|
const effectivePermissionModeId = current.phase === "locked" ? mounted.threadConfiguration?.effectivePermissionModeId : void 0;
|
|
21505
|
-
const preferredPermissionModeId = agent === "claude-code" ? readClaudePermissionModePreference(permissionModes) : void 0;
|
|
21879
|
+
const preferredPermissionModeId = preferredConfiguration?.permissionModeId ?? (agent === "claude-code" ? readClaudePermissionModePreference(permissionModes) : void 0);
|
|
21506
21880
|
selectedPermissionModeId = draftPermissionMode(
|
|
21507
21881
|
permissionModes,
|
|
21508
21882
|
effectivePermissionModeId ?? previousPermissionModeId ?? preferredPermissionModeId
|
|
@@ -21531,12 +21905,6 @@ ${error51.stderrTail}`] : []
|
|
|
21531
21905
|
}
|
|
21532
21906
|
return;
|
|
21533
21907
|
}
|
|
21534
|
-
const previousModel = controller.modelForAgent(mounted.composer, agent);
|
|
21535
|
-
const previousModelAvailable = previousModel !== void 0 && inspection.catalog.models.some((model) => model.ref.id === previousModel.id);
|
|
21536
|
-
if (current.phase === "locked" && previousModel && !previousModelAvailable) {
|
|
21537
|
-
throw new Error("Existing Thread Model is absent from the current Catalog");
|
|
21538
|
-
}
|
|
21539
|
-
const preferredConfiguration = current.phase === "draft" && !previousModelAvailable ? readNewThreadExternalConfigurationPreference(agent, inspection.catalog) : void 0;
|
|
21540
21908
|
const selected = previousModelAvailable ? previousModel : preferredConfiguration?.model ?? inspection.catalog.defaultModel;
|
|
21541
21909
|
if (!selected) throw new Error("External Harness did not report its default Model");
|
|
21542
21910
|
const effectiveCatalog = current.phase === "locked" && mounted.threadConfiguration ? catalogWithConfigurationState(inspection.catalog, selected, mounted.threadConfiguration) : inspection.catalog;
|
|
@@ -21616,6 +21984,7 @@ ${error51.stderrTail}`] : []
|
|
|
21616
21984
|
}
|
|
21617
21985
|
};
|
|
21618
21986
|
const selectExternalModel = async (mounted, modelId) => {
|
|
21987
|
+
controller.clearPendingSubmission(mounted.composer);
|
|
21619
21988
|
const current = controller.get(mounted.composer);
|
|
21620
21989
|
if (current.agent === "codex") return;
|
|
21621
21990
|
const agent = current.agent;
|
|
@@ -21687,13 +22056,13 @@ ${error51.stderrTail}`] : []
|
|
|
21687
22056
|
effectiveThinkingOptionId = supportsThinkingSelection ? selectableThinkingOptionId(state) : void 0;
|
|
21688
22057
|
effectiveCatalog = supportsThinkingSelection ? catalogWithConfigurationState(catalog, effectiveModel, state) : catalog;
|
|
21689
22058
|
resolvedModelLabel = state.resolvedModelLabel;
|
|
21690
|
-
const
|
|
22059
|
+
const effectivePermissionModeId2 = state.effectivePermissionModeId ?? previousPermissionModeId;
|
|
21691
22060
|
if (!applyExternalConfiguration(
|
|
21692
22061
|
mounted,
|
|
21693
22062
|
agent,
|
|
21694
22063
|
effectiveModel,
|
|
21695
22064
|
effectiveThinkingOptionId,
|
|
21696
|
-
|
|
22065
|
+
effectivePermissionModeId2
|
|
21697
22066
|
)) {
|
|
21698
22067
|
throw new Error("Confirmed external Model could not be applied to the Composer");
|
|
21699
22068
|
}
|
|
@@ -21702,11 +22071,18 @@ ${error51.stderrTail}`] : []
|
|
|
21702
22071
|
if (!isCurrentModelRequest(mounted, generation)) return;
|
|
21703
22072
|
controller.setExternalModel(mounted.composer, agent, effectiveModel);
|
|
21704
22073
|
controller.setExternalThinkingOption(mounted.composer, agent, effectiveThinkingOptionId);
|
|
21705
|
-
|
|
21706
|
-
|
|
21707
|
-
|
|
21708
|
-
|
|
21709
|
-
)
|
|
22074
|
+
const effectivePermissionModeId = mounted.threadConfiguration?.effectivePermissionModeId ?? previousPermissionModeId;
|
|
22075
|
+
if (effectivePermissionModeId) {
|
|
22076
|
+
controller.setExternalPermissionMode(mounted.composer, agent, effectivePermissionModeId);
|
|
22077
|
+
}
|
|
22078
|
+
if (shouldPersistNewThreadConfigurationSelection(current.phase)) {
|
|
22079
|
+
writeNewThreadExternalConfigurationPreference(
|
|
22080
|
+
agent,
|
|
22081
|
+
effectiveModel,
|
|
22082
|
+
effectiveThinkingOptionId,
|
|
22083
|
+
effectivePermissionModeId
|
|
22084
|
+
);
|
|
22085
|
+
}
|
|
21710
22086
|
mounted.modelView = {
|
|
21711
22087
|
status: "ready",
|
|
21712
22088
|
catalog: effectiveCatalog,
|
|
@@ -21739,6 +22115,7 @@ ${error51.stderrTail}`] : []
|
|
|
21739
22115
|
}
|
|
21740
22116
|
};
|
|
21741
22117
|
const selectPermissionMode = async (mounted, permissionModeId) => {
|
|
22118
|
+
controller.clearPendingSubmission(mounted.composer);
|
|
21742
22119
|
const current = controller.get(mounted.composer);
|
|
21743
22120
|
if (current.agent === "codex") return;
|
|
21744
22121
|
const agent = current.agent;
|
|
@@ -21747,9 +22124,6 @@ ${error51.stderrTail}`] : []
|
|
|
21747
22124
|
const model = controller.modelForAgent(mounted.composer, agent);
|
|
21748
22125
|
if (!catalog || !selectedPermissionModeId || !model || !modelControl) return;
|
|
21749
22126
|
const previousPermissionModeId = controller.permissionModeForAgent(mounted.composer, agent);
|
|
21750
|
-
if (agent === "claude-code") {
|
|
21751
|
-
writeClaudePermissionModePreference(selectedPermissionModeId);
|
|
21752
|
-
}
|
|
21753
22127
|
const thinkingOptionId = controller.thinkingOptionForAgent(mounted.composer, agent);
|
|
21754
22128
|
const generation = controller.beginModelRequest(mounted.composer);
|
|
21755
22129
|
mounted.permissionModeView = {
|
|
@@ -21814,6 +22188,17 @@ ${error51.stderrTail}`] : []
|
|
|
21814
22188
|
}
|
|
21815
22189
|
if (!isCurrentModelRequest(mounted, generation)) return;
|
|
21816
22190
|
controller.setExternalPermissionMode(mounted.composer, agent, effectivePermissionModeId);
|
|
22191
|
+
if (shouldPersistNewThreadConfigurationSelection(current.phase)) {
|
|
22192
|
+
writeNewThreadExternalConfigurationPreference(
|
|
22193
|
+
agent,
|
|
22194
|
+
model,
|
|
22195
|
+
thinkingOptionId,
|
|
22196
|
+
effectivePermissionModeId
|
|
22197
|
+
);
|
|
22198
|
+
if (agent === "claude-code") {
|
|
22199
|
+
writeClaudePermissionModePreference(effectivePermissionModeId);
|
|
22200
|
+
}
|
|
22201
|
+
}
|
|
21817
22202
|
mounted.permissionModeView = {
|
|
21818
22203
|
status: "ready",
|
|
21819
22204
|
catalog,
|
|
@@ -21841,6 +22226,7 @@ ${error51.stderrTail}`] : []
|
|
|
21841
22226
|
}
|
|
21842
22227
|
};
|
|
21843
22228
|
const selectExternalThinking = async (mounted, thinkingOptionId) => {
|
|
22229
|
+
controller.clearPendingSubmission(mounted.composer);
|
|
21844
22230
|
const current = controller.get(mounted.composer);
|
|
21845
22231
|
if (current.agent === "codex") return;
|
|
21846
22232
|
const agent = current.agent;
|
|
@@ -21919,7 +22305,18 @@ ${error51.stderrTail}`] : []
|
|
|
21919
22305
|
}
|
|
21920
22306
|
if (!isCurrentModelRequest(mounted, generation)) return;
|
|
21921
22307
|
controller.setExternalThinkingOption(mounted.composer, agent, effectiveThinkingOptionId);
|
|
21922
|
-
|
|
22308
|
+
const effectivePermissionModeId = mounted.threadConfiguration?.effectivePermissionModeId ?? permissionModeId;
|
|
22309
|
+
if (effectivePermissionModeId) {
|
|
22310
|
+
controller.setExternalPermissionMode(mounted.composer, agent, effectivePermissionModeId);
|
|
22311
|
+
}
|
|
22312
|
+
if (shouldPersistNewThreadConfigurationSelection(current.phase)) {
|
|
22313
|
+
writeNewThreadExternalConfigurationPreference(
|
|
22314
|
+
agent,
|
|
22315
|
+
model,
|
|
22316
|
+
effectiveThinkingOptionId,
|
|
22317
|
+
effectivePermissionModeId
|
|
22318
|
+
);
|
|
22319
|
+
}
|
|
21923
22320
|
mounted.modelView = {
|
|
21924
22321
|
status: "ready",
|
|
21925
22322
|
catalog: effectiveCatalog,
|
|
@@ -21943,14 +22340,19 @@ ${error51.stderrTail}`] : []
|
|
|
21943
22340
|
}
|
|
21944
22341
|
};
|
|
21945
22342
|
const switchComposerAgent = async (mounted, agent) => {
|
|
21946
|
-
if (agent !== "codex" &&
|
|
22343
|
+
if (agent !== "codex" && activeHarnessAvailabilityState().availability[agent] !== "ready") {
|
|
22344
|
+
return false;
|
|
22345
|
+
}
|
|
22346
|
+
controller.clearPendingSubmission(mounted.composer);
|
|
21947
22347
|
const composerId = controller.get(mounted.composer).composerId;
|
|
21948
22348
|
controller.invalidateModelRequests(mounted.composer);
|
|
21949
22349
|
const switching = controller.switchAgent(mounted.composer, agent, {
|
|
21950
22350
|
applyAgent(nextAgent) {
|
|
22351
|
+
const model = controller.modelForAgent(mounted.composer, nextAgent);
|
|
22352
|
+
if (!shouldApplyDraftAgentCarrier(nextAgent, model)) return true;
|
|
21951
22353
|
return applyAdapterAgent?.(
|
|
21952
22354
|
nextAgent,
|
|
21953
|
-
|
|
22355
|
+
model,
|
|
21954
22356
|
nextAgent !== "codex" ? controller.thinkingOptionForAgent(mounted.composer, nextAgent) : void 0,
|
|
21955
22357
|
nextAgent !== "codex" ? controller.permissionModeForAgent(mounted.composer, nextAgent) : void 0,
|
|
21956
22358
|
mounted.composer
|
|
@@ -21987,53 +22389,67 @@ ${error51.stderrTail}`] : []
|
|
|
21987
22389
|
const url2 = RENDERER_AGENT_INSTALL_URLS[agent];
|
|
21988
22390
|
window.open(url2, "_blank", "noopener,noreferrer");
|
|
21989
22391
|
};
|
|
21990
|
-
|
|
21991
|
-
|
|
21992
|
-
|
|
21993
|
-
|
|
22392
|
+
function resetHarnessAvailabilityRetry(hostId) {
|
|
22393
|
+
const state = hostHarnessAvailabilityState(hostId);
|
|
22394
|
+
if (state.retryTimer !== null) {
|
|
22395
|
+
window.clearTimeout(state.retryTimer);
|
|
22396
|
+
state.retryTimer = null;
|
|
21994
22397
|
}
|
|
21995
|
-
|
|
21996
|
-
}
|
|
21997
|
-
|
|
21998
|
-
|
|
22398
|
+
state.retryAttempt = 0;
|
|
22399
|
+
}
|
|
22400
|
+
function scheduleHarnessAvailabilityRetry(hostId) {
|
|
22401
|
+
const state = hostHarnessAvailabilityState(hostId);
|
|
22402
|
+
if (disposed || state.retryTimer !== null || state.retryAttempt >= availabilityRetryDelays.length) {
|
|
21999
22403
|
return;
|
|
22000
22404
|
}
|
|
22001
|
-
const delay = availabilityRetryDelays[
|
|
22002
|
-
|
|
22003
|
-
|
|
22004
|
-
|
|
22005
|
-
void
|
|
22405
|
+
const delay = availabilityRetryDelays[state.retryAttempt];
|
|
22406
|
+
state.retryAttempt += 1;
|
|
22407
|
+
state.retryTimer = window.setTimeout(() => {
|
|
22408
|
+
state.retryTimer = null;
|
|
22409
|
+
void refreshHarnessAvailabilityForHost(hostId, true, true);
|
|
22006
22410
|
}, delay);
|
|
22007
|
-
}
|
|
22008
|
-
|
|
22009
|
-
if (!
|
|
22010
|
-
|
|
22011
|
-
|
|
22012
|
-
|
|
22013
|
-
|
|
22411
|
+
}
|
|
22412
|
+
function modelClientForHost(hostId) {
|
|
22413
|
+
if (!modelControl) return null;
|
|
22414
|
+
const selected = modelControl.clientForHost?.(hostId);
|
|
22415
|
+
if (selected) return selected;
|
|
22416
|
+
const currentHostId = modelControl.currentHostId?.() ?? "local";
|
|
22417
|
+
return currentHostId === hostId ? modelControl : null;
|
|
22418
|
+
}
|
|
22419
|
+
function refreshHarnessAvailabilityForHost(hostId, refresh = false, retry = false) {
|
|
22420
|
+
const state = hostHarnessAvailabilityState(hostId);
|
|
22421
|
+
if (!retry) resetHarnessAvailabilityRetry(hostId);
|
|
22422
|
+
const client = modelClientForHost(hostId);
|
|
22423
|
+
if (!client) {
|
|
22424
|
+
scheduleHarnessAvailabilityRetry(hostId);
|
|
22425
|
+
return Promise.resolve();
|
|
22426
|
+
}
|
|
22427
|
+
if (state.request?.client === client) return state.request.promise;
|
|
22428
|
+
state.availability = Object.fromEntries(
|
|
22014
22429
|
externalAgents.map((agent) => [
|
|
22015
22430
|
agent,
|
|
22016
|
-
|
|
22431
|
+
state.availability[agent] === "ready" ? "ready" : "checking"
|
|
22017
22432
|
])
|
|
22018
22433
|
);
|
|
22019
|
-
|
|
22020
|
-
|
|
22021
|
-
|
|
22434
|
+
if (hostId === activeAvailabilityHostId) {
|
|
22435
|
+
publishConnectionStatus();
|
|
22436
|
+
for (const mounted of mountedByComposer.values()) renderMounted(mounted);
|
|
22437
|
+
}
|
|
22438
|
+
const generation = ++state.requestGeneration;
|
|
22022
22439
|
const promise2 = (async () => {
|
|
22023
22440
|
await Promise.all(
|
|
22024
22441
|
externalAgents.map(async (agent) => {
|
|
22025
22442
|
let status = "error";
|
|
22443
|
+
let nextError;
|
|
22026
22444
|
try {
|
|
22027
22445
|
const inspection = await client.inspectHarness({
|
|
22028
22446
|
harnessId: externalHarnessIds[agent],
|
|
22029
22447
|
refresh
|
|
22030
22448
|
});
|
|
22031
22449
|
status = inspection.status === "ready" ? "ready" : inspection.status;
|
|
22032
|
-
if (inspection.status
|
|
22033
|
-
harnessAvailabilityErrors[agent] = void 0;
|
|
22034
|
-
} else {
|
|
22450
|
+
if (inspection.status !== "ready") {
|
|
22035
22451
|
const error51 = inspection.error;
|
|
22036
|
-
|
|
22452
|
+
nextError = {
|
|
22037
22453
|
code: error51.code,
|
|
22038
22454
|
message: error51.message,
|
|
22039
22455
|
retryable: error51.retryable,
|
|
@@ -22045,24 +22461,29 @@ ${error51.stderrTail}`] : []
|
|
|
22045
22461
|
}
|
|
22046
22462
|
} catch (error51) {
|
|
22047
22463
|
status = "error";
|
|
22048
|
-
|
|
22464
|
+
nextError = {
|
|
22049
22465
|
code: "internalError",
|
|
22050
22466
|
message: error51 instanceof Error ? error51.message : String(error51),
|
|
22051
22467
|
retryable: true,
|
|
22052
22468
|
stage: "request"
|
|
22053
22469
|
};
|
|
22054
22470
|
}
|
|
22055
|
-
if (generation !==
|
|
22056
|
-
|
|
22471
|
+
if (generation !== state.requestGeneration || disposed) return;
|
|
22472
|
+
state.errors[agent] = nextError;
|
|
22473
|
+
state.availability = { ...state.availability, [agent]: status };
|
|
22474
|
+
if (hostId !== activeAvailabilityHostId) {
|
|
22475
|
+
publishConnectionStatus();
|
|
22476
|
+
return;
|
|
22477
|
+
}
|
|
22057
22478
|
for (const mounted of mountedByComposer.values()) {
|
|
22058
|
-
const
|
|
22059
|
-
if (adapterStatus.state === "ready" &&
|
|
22479
|
+
const composerState = controller.get(mounted.composer);
|
|
22480
|
+
if (adapterStatus.state === "ready" && composerState.phase === "draft" && composerState.agent === agent && status !== "ready") {
|
|
22060
22481
|
await switchComposerAgent(mounted, "codex");
|
|
22061
22482
|
}
|
|
22062
22483
|
}
|
|
22063
22484
|
for (const mounted of mountedByComposer.values()) {
|
|
22064
|
-
const
|
|
22065
|
-
if (
|
|
22485
|
+
const composerState = controller.get(mounted.composer);
|
|
22486
|
+
if (composerState.agent === agent) {
|
|
22066
22487
|
void loadExternalCatalog(mounted);
|
|
22067
22488
|
}
|
|
22068
22489
|
renderMounted(mounted);
|
|
@@ -22070,37 +22491,66 @@ ${error51.stderrTail}`] : []
|
|
|
22070
22491
|
publishConnectionStatus();
|
|
22071
22492
|
})
|
|
22072
22493
|
);
|
|
22073
|
-
if (
|
|
22074
|
-
|
|
22494
|
+
if (generation !== state.requestGeneration || disposed) return;
|
|
22495
|
+
if (externalAgents.every((agent) => state.availability[agent] === "ready")) {
|
|
22496
|
+
resetHarnessAvailabilityRetry(hostId);
|
|
22075
22497
|
} else {
|
|
22076
|
-
scheduleHarnessAvailabilityRetry();
|
|
22498
|
+
scheduleHarnessAvailabilityRetry(hostId);
|
|
22077
22499
|
}
|
|
22078
22500
|
})();
|
|
22079
22501
|
const request = { client, promise: promise2 };
|
|
22080
|
-
|
|
22502
|
+
state.request = request;
|
|
22081
22503
|
void promise2.then(
|
|
22082
22504
|
() => {
|
|
22083
|
-
if (
|
|
22505
|
+
if (state.request === request) state.request = null;
|
|
22084
22506
|
},
|
|
22085
22507
|
() => {
|
|
22086
|
-
if (
|
|
22508
|
+
if (state.request === request) state.request = null;
|
|
22087
22509
|
}
|
|
22088
22510
|
);
|
|
22089
22511
|
return promise2;
|
|
22512
|
+
}
|
|
22513
|
+
function reconcileHarnessAvailabilityHost() {
|
|
22514
|
+
const reportedHostId = modelControl?.currentHostId?.();
|
|
22515
|
+
const hostId = reportedHostId ?? (modelControl?.currentHostId ? activeAvailabilityHostId : "local");
|
|
22516
|
+
if (hostId === activeAvailabilityHostId) return;
|
|
22517
|
+
activeAvailabilityHostId = hostId;
|
|
22518
|
+
hostHarnessAvailabilityState(hostId);
|
|
22519
|
+
publishConnectionStatus();
|
|
22520
|
+
for (const mounted of mountedByComposer.values()) renderMounted(mounted);
|
|
22521
|
+
void refreshHarnessAvailabilityForHost(hostId);
|
|
22522
|
+
}
|
|
22523
|
+
const refreshHarnessAvailability = (refresh = false) => {
|
|
22524
|
+
reconcileHarnessAvailabilityHost();
|
|
22525
|
+
return refreshHarnessAvailabilityForHost(activeAvailabilityHostId, refresh);
|
|
22090
22526
|
};
|
|
22091
22527
|
connectionDiagnostics = {
|
|
22092
22528
|
snapshot() {
|
|
22529
|
+
const hostIds = [
|
|
22530
|
+
"local",
|
|
22531
|
+
...[...harnessAvailabilityByHost.keys()].filter((hostId) => hostId !== "local").sort()
|
|
22532
|
+
];
|
|
22093
22533
|
return {
|
|
22094
22534
|
adapter: { ...adapterStatus },
|
|
22095
|
-
|
|
22096
|
-
|
|
22097
|
-
|
|
22098
|
-
|
|
22099
|
-
|
|
22535
|
+
hosts: hostIds.map((hostId) => {
|
|
22536
|
+
const state = hostHarnessAvailabilityState(hostId);
|
|
22537
|
+
return {
|
|
22538
|
+
hostId,
|
|
22539
|
+
active: hostId === activeAvailabilityHostId,
|
|
22540
|
+
agents: externalAgents.map((agent) => ({
|
|
22541
|
+
agent,
|
|
22542
|
+
availability: state.availability[agent] ?? "checking",
|
|
22543
|
+
error: state.errors[agent] ?? null
|
|
22544
|
+
}))
|
|
22545
|
+
};
|
|
22546
|
+
})
|
|
22100
22547
|
};
|
|
22101
22548
|
},
|
|
22102
22549
|
refresh() {
|
|
22103
|
-
|
|
22550
|
+
for (const hostId of harnessAvailabilityByHost.keys()) {
|
|
22551
|
+
void refreshHarnessAvailabilityForHost(hostId, true);
|
|
22552
|
+
}
|
|
22553
|
+
return Promise.resolve();
|
|
22104
22554
|
},
|
|
22105
22555
|
subscribe(listener) {
|
|
22106
22556
|
connectionListeners.add(listener);
|
|
@@ -22169,13 +22619,16 @@ ${error51.stderrTail}`] : []
|
|
|
22169
22619
|
};
|
|
22170
22620
|
mountedByComposer.set(composer, mounted);
|
|
22171
22621
|
if (isComposerModelWriteAllowed(modelTarget)) {
|
|
22172
|
-
|
|
22173
|
-
|
|
22174
|
-
|
|
22175
|
-
|
|
22176
|
-
|
|
22177
|
-
|
|
22178
|
-
|
|
22622
|
+
const model = controller.modelForAgent(composer, state.agent);
|
|
22623
|
+
if (shouldApplyDraftAgentCarrier(state.agent, model)) {
|
|
22624
|
+
applyAdapterAgent?.(
|
|
22625
|
+
state.agent,
|
|
22626
|
+
model,
|
|
22627
|
+
state.agent !== "codex" ? controller.thinkingOptionForAgent(composer, state.agent) : void 0,
|
|
22628
|
+
state.agent !== "codex" ? controller.permissionModeForAgent(composer, state.agent) : void 0,
|
|
22629
|
+
composer
|
|
22630
|
+
);
|
|
22631
|
+
}
|
|
22179
22632
|
}
|
|
22180
22633
|
renderMounted(mounted);
|
|
22181
22634
|
sidebarAgentIcons.refresh();
|
|
@@ -22200,7 +22653,8 @@ ${error51.stderrTail}`] : []
|
|
|
22200
22653
|
if (!shouldTransferComposerState(
|
|
22201
22654
|
replacement.sourceModelTarget,
|
|
22202
22655
|
replacementTarget,
|
|
22203
|
-
sourceState.phase
|
|
22656
|
+
sourceState.phase,
|
|
22657
|
+
controller.isSubmissionPending(replacement.source.composer)
|
|
22204
22658
|
) || !controller.transfer(replacement.source.composer, target, replacementTarget)) {
|
|
22205
22659
|
pendingReplacements.delete(target);
|
|
22206
22660
|
}
|
|
@@ -22227,6 +22681,16 @@ ${error51.stderrTail}`] : []
|
|
|
22227
22681
|
const composer = composerForEditor(editor);
|
|
22228
22682
|
if (composer) mount(composer);
|
|
22229
22683
|
}
|
|
22684
|
+
const localAvailability = hostHarnessAvailabilityState("local").availability;
|
|
22685
|
+
if (externalAgents.some((agent) => localAvailability[agent] === "checking")) {
|
|
22686
|
+
void refreshHarnessAvailabilityForHost("local");
|
|
22687
|
+
}
|
|
22688
|
+
reconcileHarnessAvailabilityHost();
|
|
22689
|
+
if (externalAgents.some(
|
|
22690
|
+
(agent) => activeHarnessAvailabilityState().availability[agent] === "checking"
|
|
22691
|
+
)) {
|
|
22692
|
+
void refreshHarnessAvailability();
|
|
22693
|
+
}
|
|
22230
22694
|
pendingReplacements.clear();
|
|
22231
22695
|
};
|
|
22232
22696
|
const scheduleScan = (refreshTargets = false) => {
|
|
@@ -22282,11 +22746,13 @@ ${error51.stderrTail}`] : []
|
|
|
22282
22746
|
return state.phase === "locked" && mounted.ownershipStatus === "ready";
|
|
22283
22747
|
}
|
|
22284
22748
|
if (!mounted || !isComposerModelWriteAllowed(mounted.modelTarget)) return false;
|
|
22749
|
+
const model = controller.modelForAgent(composer, state.agent);
|
|
22750
|
+
if (!shouldApplyDraftAgentCarrier(state.agent, model)) return false;
|
|
22285
22751
|
return applyComposerModelWrite(
|
|
22286
22752
|
mounted.modelTarget,
|
|
22287
22753
|
() => applyAdapterAgent?.(
|
|
22288
22754
|
state.agent,
|
|
22289
|
-
|
|
22755
|
+
model,
|
|
22290
22756
|
state.agent !== "codex" ? controller.thinkingOptionForAgent(composer, state.agent) : void 0,
|
|
22291
22757
|
state.agent !== "codex" ? controller.permissionModeForAgent(composer, state.agent) : void 0,
|
|
22292
22758
|
composer
|
|
@@ -22308,7 +22774,7 @@ ${error51.stderrTail}`] : []
|
|
|
22308
22774
|
if (!isExternalConfigurationReady(mounted)) return false;
|
|
22309
22775
|
if (current.phase === "locked") return true;
|
|
22310
22776
|
if (!applyComposerAgent(composer)) return false;
|
|
22311
|
-
controller.
|
|
22777
|
+
controller.markSubmissionPending(composer);
|
|
22312
22778
|
renderMounted(mounted);
|
|
22313
22779
|
return true;
|
|
22314
22780
|
};
|
|
@@ -22321,6 +22787,7 @@ ${error51.stderrTail}`] : []
|
|
|
22321
22787
|
const onBeforeInput = (event) => {
|
|
22322
22788
|
const composer = composerForTarget(event.target);
|
|
22323
22789
|
if (!composer) return;
|
|
22790
|
+
controller.clearPendingSubmission(composer);
|
|
22324
22791
|
const mounted = mountedByComposer.get(composer);
|
|
22325
22792
|
if (mounted && isOwnershipSubmissionBlocked(mounted.ownershipStatus)) return;
|
|
22326
22793
|
if (controller.isSwitching(composer) || !applyComposerAgent(composer)) blockEvent(event);
|
|
@@ -22378,10 +22845,15 @@ ${error51.stderrTail}`] : []
|
|
|
22378
22845
|
transferReplacedComposers(mutations);
|
|
22379
22846
|
scheduleScan(mutations.some(mutationMayChangeComposerTarget));
|
|
22380
22847
|
});
|
|
22848
|
+
const onHostRouteChange = () => {
|
|
22849
|
+
reconcileHarnessAvailabilityHost();
|
|
22850
|
+
void refreshHarnessAvailability();
|
|
22851
|
+
};
|
|
22381
22852
|
const onAdapterStatus = () => {
|
|
22382
22853
|
publishConnectionStatus();
|
|
22383
22854
|
if (adapterStatus.state === "ready") {
|
|
22384
22855
|
sidebarAgentIcons.refresh();
|
|
22856
|
+
void refreshHarnessAvailabilityForHost("local");
|
|
22385
22857
|
void refreshHarnessAvailability();
|
|
22386
22858
|
for (const mounted of mountedByComposer.values()) {
|
|
22387
22859
|
if (mounted.modelView.status === "waitingForAdapter" && mounted.composer.isConnected && applyComposerAgent(mounted.composer)) {
|
|
@@ -22403,10 +22875,17 @@ ${error51.stderrTail}`] : []
|
|
|
22403
22875
|
document.addEventListener("keydown", onKeyDown, true);
|
|
22404
22876
|
document.addEventListener("click", onClick, true);
|
|
22405
22877
|
const onWindowFocus = () => {
|
|
22406
|
-
|
|
22878
|
+
reconcileHarnessAvailabilityHost();
|
|
22879
|
+
const local = hostHarnessAvailabilityState("local");
|
|
22880
|
+
if (externalAgents.some((agent) => local.availability[agent] !== "ready")) {
|
|
22881
|
+
void refreshHarnessAvailabilityForHost("local", true);
|
|
22882
|
+
}
|
|
22883
|
+
const active = activeHarnessAvailabilityState();
|
|
22884
|
+
if (externalAgents.some((agent) => active.availability[agent] !== "ready")) {
|
|
22407
22885
|
void refreshHarnessAvailability(true);
|
|
22408
22886
|
}
|
|
22409
22887
|
};
|
|
22888
|
+
window.addEventListener("codexhost:draft-prewarm-policy-changed", onHostRouteChange);
|
|
22410
22889
|
window.addEventListener("codexhost:renderer-adapter-status", onAdapterStatus);
|
|
22411
22890
|
window.addEventListener("focus", onWindowFocus);
|
|
22412
22891
|
const connectedComposers = () => [...mountedByComposer.values()].filter(
|
|
@@ -22423,7 +22902,7 @@ ${error51.stderrTail}`] : []
|
|
|
22423
22902
|
version: 2,
|
|
22424
22903
|
mountedComposers: selections.length,
|
|
22425
22904
|
enabledAgents: [...enabledAgents],
|
|
22426
|
-
availability: { ...
|
|
22905
|
+
availability: { ...activeHarnessAvailabilityState().availability },
|
|
22427
22906
|
selections,
|
|
22428
22907
|
adapter: { ...adapterStatus }
|
|
22429
22908
|
};
|
|
@@ -22470,8 +22949,16 @@ ${error51.stderrTail}`] : []
|
|
|
22470
22949
|
} catch {
|
|
22471
22950
|
}
|
|
22472
22951
|
});
|
|
22952
|
+
for (const state of harnessAvailabilityByHost.values()) {
|
|
22953
|
+
state.requestGeneration += 1;
|
|
22954
|
+
state.request = null;
|
|
22955
|
+
if (state.retryTimer !== null) window.clearTimeout(state.retryTimer);
|
|
22956
|
+
}
|
|
22957
|
+
harnessAvailabilityByHost.clear();
|
|
22958
|
+
activeAvailabilityHostId = "local";
|
|
22473
22959
|
sidebarAgentIcons.refresh();
|
|
22474
|
-
void
|
|
22960
|
+
void refreshHarnessAvailabilityForHost("local");
|
|
22961
|
+
reconcileHarnessAvailabilityHost();
|
|
22475
22962
|
const connected = connectedComposers();
|
|
22476
22963
|
if (connected.length === 1) {
|
|
22477
22964
|
const mounted = connected[0];
|
|
@@ -22504,9 +22991,14 @@ ${error51.stderrTail}`] : []
|
|
|
22504
22991
|
document.removeEventListener("submit", onSubmit, true);
|
|
22505
22992
|
document.removeEventListener("keydown", onKeyDown, true);
|
|
22506
22993
|
document.removeEventListener("click", onClick, true);
|
|
22994
|
+
window.removeEventListener("codexhost:draft-prewarm-policy-changed", onHostRouteChange);
|
|
22507
22995
|
window.removeEventListener("codexhost:renderer-adapter-status", onAdapterStatus);
|
|
22508
22996
|
window.removeEventListener("focus", onWindowFocus);
|
|
22509
|
-
|
|
22997
|
+
for (const state of harnessAvailabilityByHost.values()) {
|
|
22998
|
+
state.requestGeneration += 1;
|
|
22999
|
+
if (state.retryTimer !== null) window.clearTimeout(state.retryTimer);
|
|
23000
|
+
}
|
|
23001
|
+
harnessAvailabilityByHost.clear();
|
|
22510
23002
|
for (const timer of usageRefreshTimers.values()) window.clearTimeout(timer);
|
|
22511
23003
|
usageRefreshTimers.clear();
|
|
22512
23004
|
for (const mounted of mountedByComposer.values()) {
|