@codexhost/cli-darwin-arm64 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,8 +7,14 @@
7
7
  };
8
8
 
9
9
  // src/agent-selection-state.ts
10
- var KNOWN_RENDERER_AGENTS = ["codex", "pi", "claude-code"];
11
- var DEFAULT_RENDERER_AGENTS = ["codex", "pi", "claude-code"];
10
+ var KNOWN_RENDERER_AGENTS = [
11
+ "codex",
12
+ "pi",
13
+ "claude-code",
14
+ "deepseek-harness",
15
+ "grok"
16
+ ];
17
+ var DEFAULT_RENDERER_AGENTS = KNOWN_RENDERER_AGENTS;
12
18
  function defaultIdFactory(sequence) {
13
19
  return `codexhost-composer-${Date.now().toString(36)}-${sequence.toString(36)}`;
14
20
  }
@@ -112,19 +118,18 @@
112
118
  state.phase = "locked";
113
119
  if (agent === "pi" && model) state.piModel = model;
114
120
  if (agent === "claude-code" && model) state.claudeModel = model;
115
- if (agent === "pi" && thinkingOptionId) {
116
- state.piThinkingOptionId = thinkingOptionId;
117
- } else if (agent === "pi") {
118
- delete state.piThinkingOptionId;
119
- }
121
+ if (agent === "deepseek-harness" && model) state.deepSeekHarnessModel = model;
122
+ if (agent === "grok" && model) state.grokModel = model;
123
+ if (agent === "pi" && thinkingOptionId) state.piThinkingOptionId = thinkingOptionId;
124
+ else if (agent === "pi") delete state.piThinkingOptionId;
120
125
  if (agent === "claude-code" && thinkingOptionId) {
121
126
  state.claudeThinkingOptionId = thinkingOptionId;
122
- } else if (agent === "claude-code") {
123
- delete state.claudeThinkingOptionId;
124
- }
127
+ } else if (agent === "claude-code") delete state.claudeThinkingOptionId;
128
+ if (agent === "grok" && thinkingOptionId) state.grokThinkingOptionId = thinkingOptionId;
129
+ else if (agent === "grok") delete state.grokThinkingOptionId;
125
130
  if (agent !== "codex") {
126
131
  const permissionModeByAgent = {};
127
- for (const candidate of ["pi", "claude-code"]) {
132
+ for (const candidate of ["pi", "claude-code", "deepseek-harness", "grok"]) {
128
133
  const current = state.permissionModeByAgent?.[candidate];
129
134
  if (candidate !== agent && current) permissionModeByAgent[candidate] = current;
130
135
  }
@@ -139,11 +144,16 @@
139
144
  }
140
145
  modelForAgent(composer, agent) {
141
146
  const state = this.#state(composer);
142
- return agent === "pi" ? state.piModel : agent === "claude-code" ? state.claudeModel : void 0;
147
+ if (agent === "pi") return state.piModel;
148
+ if (agent === "claude-code") return state.claudeModel;
149
+ if (agent === "deepseek-harness") return state.deepSeekHarnessModel;
150
+ return agent === "grok" ? state.grokModel : void 0;
143
151
  }
144
152
  thinkingOptionForAgent(composer, agent) {
145
153
  const state = this.#state(composer);
146
- return agent === "pi" ? state.piThinkingOptionId : state.claudeThinkingOptionId;
154
+ if (agent === "pi") return state.piThinkingOptionId;
155
+ if (agent === "claude-code") return state.claudeThinkingOptionId;
156
+ return agent === "grok" ? state.grokThinkingOptionId : void 0;
147
157
  }
148
158
  permissionModeForAgent(composer, agent) {
149
159
  return this.#state(composer).permissionModeByAgent?.[agent];
@@ -159,7 +169,9 @@
159
169
  setExternalModel(composer, agent, model) {
160
170
  const state = this.#state(composer);
161
171
  if (agent === "pi") state.piModel = model;
162
- else state.claudeModel = model;
172
+ else if (agent === "claude-code") state.claudeModel = model;
173
+ else if (agent === "deepseek-harness") state.deepSeekHarnessModel = model;
174
+ else state.grokModel = model;
163
175
  return state;
164
176
  }
165
177
  setPiConfiguration(composer, model, thinkingOptionId) {
@@ -176,8 +188,15 @@
176
188
  const state = this.#state(composer);
177
189
  if (agent === "pi" && thinkingOptionId) state.piThinkingOptionId = thinkingOptionId;
178
190
  else if (agent === "pi") delete state.piThinkingOptionId;
179
- else if (thinkingOptionId) state.claudeThinkingOptionId = thinkingOptionId;
180
- else delete state.claudeThinkingOptionId;
191
+ else if (agent === "claude-code" && thinkingOptionId) {
192
+ state.claudeThinkingOptionId = thinkingOptionId;
193
+ } else if (agent === "claude-code") {
194
+ delete state.claudeThinkingOptionId;
195
+ } else if (agent === "grok" && thinkingOptionId) {
196
+ state.grokThinkingOptionId = thinkingOptionId;
197
+ } else if (agent === "grok") {
198
+ delete state.grokThinkingOptionId;
199
+ }
181
200
  return state;
182
201
  }
183
202
  setPiThinkingOption(composer, thinkingOptionId) {
@@ -14903,6 +14922,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14903
14922
  cachedInputTokens: nonNegativeSafeIntegerSchema.optional(),
14904
14923
  cacheWriteInputTokens: nonNegativeSafeIntegerSchema.optional(),
14905
14924
  outputTokens: nonNegativeSafeIntegerSchema.optional(),
14925
+ outputTokensPerSecond: finiteNonNegativeNumberSchema.optional(),
14906
14926
  reasoningOutputTokens: nonNegativeSafeIntegerSchema.optional(),
14907
14927
  totalTokens: nonNegativeSafeIntegerSchema.optional(),
14908
14928
  totalCostUsd: finiteNonNegativeNumberSchema.optional(),
@@ -15292,11 +15312,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15292
15312
  // src/assets/codex-agent.png
15293
15313
  var codex_agent_default = "data:image/png;base64,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";
15294
15314
 
15315
+ // src/assets/grok-agent.png
15316
+ var grok_agent_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAAXNSR0IArs4c6QAAEk9JREFUeNrtnQdsHEUXx5fee40xnQiQ6b23IAiJAWHACV10AQHRRG8GDJgSOggEGAEBg6gGhAIBQknoppjeezGE3kybb3+je6f1fVdm93Z2Zy870iPmfN67mffmzSv/98bzLIxZZpml2ad2n7p86vWp36cBnwZ9UjlVpcHCWvUX1q6rsJbNnsvD/4ItPnX41Jcz0Rr1Fda4xSXGt/k0MWdO4sSat6XJ+FafpuaMSJ3gQWuSjG/yaUK+8M4RPGmyzfyxPk3LF9tZgjdjbTG/M1/gzFBn3Mzvzhc1c9QdF/N78sXMLPXkO386o5lnnllT3ZogP/OzRzPNNJOac8451bBhw0qFoDOKtZ8vasZ2Pv/uuOOOaoklltDCUPKesWH8/NzVyxjzfdapcePGqa222kr/XMFFbDIRgDzIkzGC4Yceeqg6/fTTKzG/GCwyCe/mi5ox5u+3337q4YcfVvPNN1851V9KrdUEII/tZ4z5e++9t/rmm2/UeuutV2v3F3MH1bJ6+cJmiPnt7e3q77//VieccIIp84XayglAntLNEPO33XZb9dtvv2nVP9tss5mo/iGp5HJgjnxxM8L8TTbZRKv9adOmqVVWWSXs7hdqCQpAR7642WD+hhtuqD777DPFOProo6MyH+oICkAO48oY8ydNmqTmmmuusKp/CLwsCOCcbgImLBg044wz6kUtpRlmmKH4npJwaqrMX3PNNdXHH3+smf/zzz+HsfqrUbNXQJw2dIQsyFx2zSKLLKKWWWYZtfrqq+uFFFpttdXUsssuqxZeeGE199xz6/cH/z4NgeBzV1hhBfX2228rGeecc04czIfavQLsuKESIsIwmI2RNGbMGHX++eere++9V73wwgvq888/Vz/88IP69ddf1e+//16kX375Rb+Omn3xxRf1+y+44AK1++67q1VXXVU/T55dh+oNxfyll15avfzyy0XmIwiLLbaY1mAxfEaXV8CeN8QZCS244IJq9OjR6tJLL1V9fX2aqeXGf//9p+nff/8tkrxWbvCcV155RV1++eVq1KhR+nPkM23NZ6mlllLPPfec/nz5fvvvv3+cn9nrFQoQMq3iUdXrrLOOuuiii9S77747hIn8/M8//9RNpc9855139Oet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";
15317
+
15295
15318
  // src/renderer-agent-icon.ts
15296
15319
  var RENDERER_AGENT_LABELS = {
15297
15320
  codex: "Codex",
15298
15321
  pi: "Pi",
15299
- "claude-code": "Claude Code"
15322
+ "claude-code": "Claude Code",
15323
+ "deepseek-harness": "DeepSeek Harness",
15324
+ grok: "Grok"
15300
15325
  };
15301
15326
  var PI_PATHS = [
15302
15327
  {
@@ -15305,10 +15330,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15305
15330
  },
15306
15331
  { d: "M17.5 12H23v11h-5.5V12z" }
15307
15332
  ];
15333
+ var DEEPSEEK_HARNESS_WHALE_PATH = "M22.9168 1.43018C22.6713 1.31018 22.5658 1.53918 22.4223 1.65519C22.3733 1.69269 22.3318 1.74169 22.2903 1.78669C21.9317 2.1697 21.5127 2.42121 20.9657 2.39121C20.1657 2.34621 19.4827 2.59771 18.8787 3.20973C18.7502 2.45521 18.3236 2.0047 17.6746 1.71569C17.3351 1.56568 16.9916 1.41518 16.7536 1.08867C16.5876 0.856163 16.5421 0.597155 16.4591 0.341647C16.4061 0.187643 16.3536 0.0301382 16.1761 0.00363739C15.9836 -0.0263635 15.9081 0.135141 15.8326 0.270145C15.5306 0.822162 15.4136 1.43018 15.4251 2.0462C15.4516 3.43174 16.0366 4.53527 17.1991 5.3203C17.3311 5.4103 17.3651 5.5003 17.3236 5.63181C17.2441 5.90231 17.1501 6.16482 17.0671 6.43533C17.0141 6.60784 16.9351 6.64584 16.7501 6.57033C16.1121 6.30383 15.5611 5.90931 15.074 5.4328C14.2475 4.63328 13.5 3.75075 12.568 3.05973C12.349 2.89822 12.13 2.74822 11.9034 2.60522C10.9524 1.68169 12.028 0.923165 12.277 0.833162C12.5375 0.739159 12.3675 0.41615 11.5259 0.42015C10.6844 0.42365 9.91439 0.705658 8.93286 1.08117C8.78935 1.13767 8.63835 1.17867 8.48384 1.21267C7.59332 1.04367 6.66829 1.00617 5.70226 1.11517C3.88321 1.31768 2.43016 2.1777 1.36213 3.64575C0.0790928 5.4103 -0.222916 7.41536 0.146595 9.50642C0.535106 11.7105 1.66014 13.535 3.38869 14.9616C5.18125 16.4406 7.24581 17.1657 9.60138 17.0266C11.0319 16.9441 12.6245 16.7526 14.421 15.2321C14.874 15.4576 15.3496 15.5476 16.1381 15.6151C16.7456 15.6716 17.3306 15.5851 17.7836 15.4911C18.4931 15.3411 18.4441 14.6841 18.1876 14.5636C16.1081 13.595 16.5646 13.9891 16.1496 13.67C17.2061 12.42 18.8202 10.1979 19.3182 7.17235C19.3672 6.83834 19.4297 6.36783 19.4222 6.09732C19.4182 5.93231 19.4562 5.86831 19.6447 5.84931C20.1657 5.78931 20.6712 5.64681 21.1357 5.3913C22.4833 4.65528 23.0268 3.44624 23.1548 1.9972C23.1738 1.77569 23.1508 1.54668 22.9168 1.43018ZM11.1749 14.4736C9.15936 12.889 8.18184 12.3675 7.77832 12.39C7.40081 12.4125 7.46881 12.8445 7.55182 13.126C7.63882 13.404 7.75182 13.5955 7.91033 13.8396C8.01983 14.0011 8.09533 14.2411 7.80083 14.4216C7.15181 14.8231 6.02327 14.2866 5.97027 14.2601C4.65673 13.4865 3.5587 12.4655 2.78467 11.069C2.03715 9.72493 1.60314 8.28289 1.53164 6.74384C1.51264 6.37233 1.62214 6.24082 1.99215 6.17332C2.47916 6.08332 2.98118 6.06432 3.46769 6.13582C5.52476 6.43633 7.27581 7.35586 8.74385 8.8129C9.58188 9.64243 10.2159 10.634 10.8689 11.6025C11.5634 12.631 12.3105 13.611 13.262 14.4146C13.598 14.6961 13.866 14.9101 14.1225 15.0681C13.349 15.1546 12.058 15.1731 11.1749 14.4746L11.1749 14.4736ZM12.141 8.25988C12.141 8.09488 12.273 7.96338 12.439 7.96338C12.4765 7.96338 12.5105 7.97088 12.541 7.98188C12.5825 7.99688 12.6205 8.01938 12.6505 8.05338C12.7035 8.10588 12.7335 8.18088 12.7335 8.25988C12.7335 8.42489 12.6015 8.55639 12.4355 8.55639C12.2695 8.55639 12.141 8.42489 12.141 8.25988ZM15.1415 9.79893C14.949 9.87793 14.7565 9.94544 14.5715 9.95294C14.2845 9.96794 13.9715 9.85143 13.8015 9.70893C13.5375 9.48742 13.3485 9.36342 13.2695 8.97691C13.2355 8.8119 13.2545 8.55639 13.2845 8.40989C13.3525 8.09438 13.277 7.89187 13.0545 7.70787C12.8735 7.55786 12.643 7.51636 12.39 7.51636C12.2955 7.51636 12.209 7.47486 12.1445 7.44136C12.039 7.38886 11.9519 7.25735 12.035 7.09585C12.0615 7.04335 12.19 6.91584 12.22 6.89334C12.5635 6.69784 12.9595 6.76184 13.326 6.90834C13.6655 7.04735 13.9225 7.30236 14.292 7.66287C14.6695 8.09838 14.7375 8.21838 14.9525 8.54539C15.1225 8.8009 15.277 9.06341 15.3831 9.36392C15.4471 9.55142 15.3641 9.70493 15.1415 9.79893Z";
15308
15334
  var CLAUDE_PATH = "M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z";
15309
- function createSvgIcon(paths, color, size, ownerDocument) {
15335
+ function createSvgIcon(paths, color, size, ownerDocument, viewBox = "0 0 24 24") {
15310
15336
  const svg = ownerDocument.createElementNS("http://www.w3.org/2000/svg", "svg");
15311
- svg.setAttribute("viewBox", "0 0 24 24");
15337
+ svg.setAttribute("viewBox", viewBox);
15312
15338
  svg.setAttribute("aria-hidden", "true");
15313
15339
  svg.style.width = `${size}px`;
15314
15340
  svg.style.height = `${size}px`;
@@ -15335,13 +15361,36 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15335
15361
  return image;
15336
15362
  }
15337
15363
  if (agent === "pi") return createSvgIcon(PI_PATHS, "currentColor", size, ownerDocument);
15338
- return createSvgIcon([{ d: CLAUDE_PATH }], "#d97757", size, ownerDocument);
15364
+ if (agent === "claude-code") {
15365
+ return createSvgIcon([{ d: CLAUDE_PATH }], "#d97757", size, ownerDocument);
15366
+ }
15367
+ if (agent === "deepseek-harness") {
15368
+ return createSvgIcon(
15369
+ [{ d: DEEPSEEK_HARNESS_WHALE_PATH }],
15370
+ "#4D6BFE",
15371
+ size,
15372
+ ownerDocument,
15373
+ "0 0 23.16 17.04"
15374
+ );
15375
+ }
15376
+ const mark = ownerDocument.createElement("img");
15377
+ mark.src = grok_agent_default;
15378
+ mark.alt = "";
15379
+ mark.draggable = false;
15380
+ mark.style.width = `${size}px`;
15381
+ mark.style.height = `${size}px`;
15382
+ mark.style.objectFit = "contain";
15383
+ mark.style.borderRadius = "22.37%";
15384
+ mark.style.flex = "none";
15385
+ return mark;
15339
15386
  }
15340
15387
 
15341
15388
  // src/renderer-agent-picker.ts
15342
15389
  var RENDERER_AGENT_INSTALL_URLS = {
15343
15390
  pi: "https://pi.dev/",
15344
- "claude-code": "https://code.claude.com/docs/en/quickstart"
15391
+ "claude-code": "https://code.claude.com/docs/en/quickstart",
15392
+ "deepseek-harness": "https://github.com/deepseek-ai/deepseek-harness",
15393
+ grok: "https://grok.com/"
15345
15394
  };
15346
15395
  var CONTROL_ATTRIBUTE = "data-codexhost-agent-control";
15347
15396
  function rendererAgentPickerView(state, adapterState, switching, agents, availability = {}) {
@@ -15396,7 +15445,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15396
15445
  trigger.style.width = "30px";
15397
15446
  trigger.style.height = "28px";
15398
15447
  trigger.style.padding = "0";
15399
- trigger.style.border = "1px solid rgba(127, 127, 127, 0.28)";
15448
+ trigger.style.border = "0";
15400
15449
  trigger.style.borderRadius = "6px";
15401
15450
  trigger.style.background = "rgba(127, 127, 127, 0.08)";
15402
15451
  trigger.style.color = "inherit";
@@ -15436,7 +15485,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15436
15485
  menu.style.inset = "auto";
15437
15486
  menu.style.width = "190px";
15438
15487
  menu.style.padding = "4px";
15439
- menu.style.border = "1px solid rgba(127, 127, 127, 0.35)";
15488
+ menu.style.border = "0";
15440
15489
  menu.style.borderRadius = "6px";
15441
15490
  menu.style.background = "Canvas";
15442
15491
  menu.style.color = "CanvasText";
@@ -15665,9 +15714,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15665
15714
 
15666
15715
  // src/renderer-model-picker.ts
15667
15716
  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";
15668
- var MENU_CLASSES = "fixed z-50 overflow-hidden rounded-xl bg-token-dropdown-background/90 text-token-foreground shadow-lg ring-[0.5px] ring-token-border backdrop-blur-xl";
15717
+ var MENU_CLASSES = "fixed z-50 overflow-hidden rounded-xl bg-token-dropdown-background/90 text-token-foreground shadow-lg backdrop-blur-xl";
15669
15718
  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";
15670
15719
  var HEADING_CLASSES = "px-2 pb-1 pt-1.5 text-sm text-token-text-tertiary";
15720
+ var MAIN_MENU_MIN_WIDTH = 180;
15721
+ var MAIN_MENU_MAX_WIDTH = 210;
15722
+ var MODEL_MENU_PREFERRED_WIDTH = 320;
15723
+ var MODEL_MENU_MAX_WIDTH = 380;
15724
+ var MODEL_MENU_MAX_HEIGHT = 360;
15725
+ var MAIN_MENU_LEFT_OFFSET = 96;
15726
+ var MENU_GAP = 4;
15727
+ var VIEWPORT_MARGIN = 8;
15671
15728
  function popoverOpen2(menu) {
15672
15729
  return menu.matches(":popover-open");
15673
15730
  }
@@ -15707,24 +15764,47 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15707
15764
  };
15708
15765
  }
15709
15766
  function positionMainMenu(control) {
15710
- const rect = control.trigger.getBoundingClientRect();
15711
- const width = Math.min(280, Math.max(220, rect.width));
15712
- const left = Math.max(8, Math.min(rect.right - width, window.innerWidth - width - 8));
15713
- control.menu.style.width = `${width}px`;
15767
+ const triggerRect = control.trigger.getBoundingClientRect();
15768
+ const width = Math.min(MAIN_MENU_MAX_WIDTH, Math.max(MAIN_MENU_MIN_WIDTH, triggerRect.width));
15769
+ const modelMenuWidth = Math.min(
15770
+ MODEL_MENU_MAX_WIDTH,
15771
+ Math.min(MODEL_MENU_PREFERRED_WIDTH, window.innerWidth - VIEWPORT_MARGIN * 2)
15772
+ );
15773
+ const preferredLeft = triggerRect.right - width - MAIN_MENU_LEFT_OFFSET;
15774
+ const rightReservedLeft = window.innerWidth - VIEWPORT_MARGIN - modelMenuWidth - MENU_GAP - width;
15775
+ const maxLeft = window.innerWidth - VIEWPORT_MARGIN - width;
15776
+ const left = Math.max(
15777
+ VIEWPORT_MARGIN,
15778
+ Math.min(preferredLeft, Math.max(rightReservedLeft, VIEWPORT_MARGIN), maxLeft)
15779
+ );
15780
+ control.menu.style.setProperty("width", `${width}px`, "important");
15714
15781
  control.menu.style.left = `${left}px`;
15715
- control.menu.style.bottom = `${Math.max(8, window.innerHeight - rect.top + 6)}px`;
15782
+ control.menu.style.maxWidth = `${width}px`;
15783
+ control.menu.style.right = "auto";
15784
+ control.menu.style.top = "auto";
15785
+ control.menu.style.bottom = `${Math.max(
15786
+ VIEWPORT_MARGIN,
15787
+ window.innerHeight - triggerRect.top + 6
15788
+ )}px`;
15716
15789
  }
15717
15790
  function positionModelMenu(control) {
15718
- const rect = control.menu.getBoundingClientRect();
15719
- const width = Math.min(360, Math.max(280, rect.width));
15720
- const rightCandidate = rect.right + 4;
15721
- const left = rightCandidate + width <= window.innerWidth - 8 ? rightCandidate : Math.max(8, rect.left - width - 4);
15722
- control.modelMenu.style.width = `${width}px`;
15791
+ const mainRect = control.menu.getBoundingClientRect();
15792
+ const availableRight = window.innerWidth - mainRect.right - VIEWPORT_MARGIN;
15793
+ const width = Math.min(MODEL_MENU_MAX_WIDTH, Math.max(VIEWPORT_MARGIN, availableRight));
15794
+ const left = mainRect.right + MENU_GAP;
15795
+ control.modelMenu.style.setProperty("width", `${width}px`, "important");
15723
15796
  control.modelMenu.style.left = `${left}px`;
15724
- const height = control.modelMenu.getBoundingClientRect().height;
15725
- control.modelMenu.style.top = `${Math.max(
15726
- 8,
15727
- Math.min(rect.top, window.innerHeight - height - 8)
15797
+ control.modelMenu.style.maxWidth = `${width}px`;
15798
+ const maxHeight = Math.max(
15799
+ VIEWPORT_MARGIN,
15800
+ Math.min(MODEL_MENU_MAX_HEIGHT, window.innerHeight * 0.6, mainRect.bottom - VIEWPORT_MARGIN)
15801
+ );
15802
+ control.modelMenu.style.maxHeight = `${maxHeight}px`;
15803
+ control.modelMenu.style.right = "auto";
15804
+ control.modelMenu.style.top = "auto";
15805
+ control.modelMenu.style.bottom = `${Math.max(
15806
+ VIEWPORT_MARGIN,
15807
+ window.innerHeight - mainRect.bottom
15728
15808
  )}px`;
15729
15809
  }
15730
15810
  function syncRendererModelTriggerClass(control, nativeClassName) {
@@ -15784,9 +15864,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15784
15864
  menu.setAttribute("aria-label", "Model and Thinking");
15785
15865
  menu.setAttribute("popover", "auto");
15786
15866
  menu.className = MENU_CLASSES;
15867
+ menu.style.position = "fixed";
15787
15868
  menu.style.inset = "auto";
15788
15869
  menu.style.margin = "0";
15789
15870
  menu.style.padding = "4px";
15871
+ menu.style.border = "0";
15790
15872
  trigger.setAttribute("aria-controls", menu.id);
15791
15873
  const modelButton = document.createElement("button");
15792
15874
  modelButton.type = "button";
@@ -15801,9 +15883,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15801
15883
  modelMenu.setAttribute("aria-label", "Model");
15802
15884
  modelMenu.setAttribute("popover", "manual");
15803
15885
  modelMenu.className = MENU_CLASSES;
15886
+ modelMenu.style.position = "fixed";
15804
15887
  modelMenu.style.inset = "auto";
15805
15888
  modelMenu.style.margin = "0";
15806
15889
  modelMenu.style.padding = "4px";
15890
+ modelMenu.style.border = "0";
15807
15891
  modelMenu.style.maxHeight = "min(360px, 60vh)";
15808
15892
  modelMenu.style.overflowY = "auto";
15809
15893
  modelButton.setAttribute("aria-controls", modelMenu.id);
@@ -15825,8 +15909,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15825
15909
  };
15826
15910
  const open = () => {
15827
15911
  if (trigger.disabled || popoverOpen2(menu)) return;
15828
- positionMainMenu(control);
15829
15912
  menu.showPopover();
15913
+ positionMainMenu(control);
15830
15914
  };
15831
15915
  const onTriggerClick = () => {
15832
15916
  if (popoverOpen2(menu)) close();
@@ -15847,26 +15931,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15847
15931
  openModelMenu();
15848
15932
  return;
15849
15933
  }
15850
- if (target?.dataset.modelId) {
15851
- closeModelMenu();
15852
- modelButton.focus();
15853
- onSelectModel(target.dataset.modelId);
15854
- return;
15855
- }
15856
15934
  if (target?.dataset.thinkingOptionId) {
15857
15935
  close();
15858
15936
  trigger.focus();
15859
15937
  onSelectThinking(target.dataset.thinkingOptionId);
15860
15938
  }
15861
15939
  };
15940
+ const onModelMenuClick = (event) => {
15941
+ const target = event.target instanceof Element ? event.target.closest("button[data-model-id]") : null;
15942
+ if (!target?.dataset.modelId) return;
15943
+ closeModelMenu();
15944
+ modelButton.focus();
15945
+ onSelectModel(target.dataset.modelId);
15946
+ };
15862
15947
  const onModelHover = () => openModelMenu();
15948
+ const onViewportChange = () => {
15949
+ if (popoverOpen2(menu)) positionMainMenu(control);
15950
+ if (popoverOpen2(modelMenu)) positionModelMenu(control);
15951
+ };
15863
15952
  trigger.addEventListener("click", onTriggerClick);
15864
15953
  menu.addEventListener("toggle", onToggle);
15865
15954
  modelMenu.addEventListener("toggle", onModelToggle);
15866
15955
  modelButton.addEventListener("mouseenter", onModelHover);
15867
15956
  root.addEventListener("click", onRootClick);
15868
- menu.append(modelMenu);
15957
+ modelMenu.addEventListener("click", onModelMenuClick);
15958
+ window.addEventListener("resize", onViewportChange);
15959
+ window.addEventListener("scroll", onViewportChange, true);
15869
15960
  root.append(trigger, menu);
15961
+ document.body.append(modelMenu);
15870
15962
  const control = {
15871
15963
  root,
15872
15964
  trigger,
@@ -15885,6 +15977,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15885
15977
  modelMenu.removeEventListener("toggle", onModelToggle);
15886
15978
  modelButton.removeEventListener("mouseenter", onModelHover);
15887
15979
  root.removeEventListener("click", onRootClick);
15980
+ modelMenu.removeEventListener("click", onModelMenuClick);
15981
+ window.removeEventListener("resize", onViewportChange);
15982
+ window.removeEventListener("scroll", onViewportChange, true);
15983
+ modelMenu.remove();
15888
15984
  root.remove();
15889
15985
  }
15890
15986
  };
@@ -15943,7 +16039,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15943
16039
  control.options.set(model.ref.id, { button, check: check2 });
15944
16040
  control.modelMenu.append(button);
15945
16041
  }
15946
- control.menu.append(control.modelMenu);
15947
16042
  }
15948
16043
  function renderRendererModelPicker(control, view, visible) {
15949
16044
  control.root.style.display = visible ? "block" : "none";
@@ -16310,6 +16405,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16310
16405
  function formatRendererCost(value) {
16311
16406
  return `$${value.toFixed(3)}`;
16312
16407
  }
16408
+ function formatRendererTokenRate(value) {
16409
+ return `${decimal(value, 1)} tok/s`;
16410
+ }
16313
16411
  function formatRendererTokenCount(value) {
16314
16412
  const sign = value < 0 ? "-" : "";
16315
16413
  const absolute = Math.abs(value);
@@ -16354,12 +16452,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16354
16452
  formatRendererCacheHitRate(usage.cacheHitRatePercent)
16355
16453
  );
16356
16454
  }
16455
+ if (usage.outputTokensPerSecond !== void 0) {
16456
+ addDetailRow(popover, "Output speed", formatRendererTokenRate(usage.outputTokensPerSecond));
16457
+ }
16357
16458
  if (usage.cachedInputTokens !== void 0) {
16358
16459
  addDetailRow(popover, "Cache read", formatRendererTokenCount(usage.cachedInputTokens));
16359
16460
  }
16360
16461
  if (usage.cacheWriteInputTokens !== void 0) {
16361
16462
  addDetailRow(popover, "Cache write", formatRendererTokenCount(usage.cacheWriteInputTokens));
16362
16463
  }
16464
+ if (usage.reasoningOutputTokens !== void 0) {
16465
+ addDetailRow(popover, "Reasoning", formatRendererTokenCount(usage.reasoningOutputTokens));
16466
+ }
16363
16467
  if (usage.inputTokens !== void 0 || usage.outputTokens !== void 0) {
16364
16468
  addDetailRow(
16365
16469
  popover,
@@ -16530,10 +16634,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16530
16634
  }
16531
16635
  function renderRendererUsageControl(control, usage) {
16532
16636
  const cacheHitRatePercent = usage?.cacheHitRatePercent;
16637
+ const outputTokensPerSecond = usage?.outputTokensPerSecond;
16533
16638
  const totalCostUsd = usage?.totalCostUsd;
16534
16639
  const hasCacheHitRate = cacheHitRatePercent !== void 0;
16640
+ const hasOutputSpeed = outputTokensPerSecond !== void 0;
16535
16641
  const hasCost = totalCostUsd !== void 0;
16536
- const visible = hasCacheHitRate || hasCost;
16642
+ const visible = hasCacheHitRate || hasOutputSpeed || hasCost;
16537
16643
  control.root.style.display = visible ? "inline-flex" : "none";
16538
16644
  if (!visible || !usage) {
16539
16645
  closePopover(control);
@@ -16541,6 +16647,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16541
16647
  }
16542
16648
  const summary = [
16543
16649
  cacheHitRatePercent !== void 0 ? formatRendererCacheHitRate(cacheHitRatePercent) : null,
16650
+ outputTokensPerSecond !== void 0 ? formatRendererTokenRate(outputTokensPerSecond) : null,
16544
16651
  totalCostUsd !== void 0 ? formatRendererCost(totalCostUsd) : null
16545
16652
  ].filter((value) => value !== null);
16546
16653
  const compactSummary = summary.join(" \xB7 ");
@@ -16589,30 +16696,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16589
16696
  return event.key === "Enter" && !event.shiftKey && !event.isComposing;
16590
16697
  }
16591
16698
  function composerForEditor(editor) {
16592
- const codexComposer = editor.closest(CODEX_COMPOSER_SELECTOR);
16593
- if (codexComposer) return codexComposer;
16594
- const form = editor.closest("form");
16595
- if (form && sendButtonWithin(form)) return form;
16596
- let candidate = editor.parentElement;
16597
- for (let depth = 0; candidate && candidate !== document.body && depth < 8; depth += 1) {
16598
- if (sendButtonWithin(candidate)) return candidate;
16599
- candidate = candidate.parentElement;
16600
- }
16601
- return null;
16699
+ return editor.closest(CODEX_COMPOSER_SELECTOR);
16602
16700
  }
16603
16701
  function composerForElement(element) {
16604
- const codexComposer = element.closest(CODEX_COMPOSER_SELECTOR);
16605
- if (codexComposer) return codexComposer;
16606
- const mounted = element.closest(`[${CONTROL_ATTRIBUTE}]`);
16607
- if (mounted) return mounted.parentElement;
16608
- const editor = editorForElement(element);
16609
- if (editor) return composerForEditor(editor);
16610
- let candidate = element;
16611
- for (let depth = 0; candidate && candidate !== document.body && depth < 8; depth += 1) {
16612
- if (candidate.querySelector(`[${CONTROL_ATTRIBUTE}]`)) return candidate;
16613
- candidate = candidate.parentElement;
16614
- }
16615
- return null;
16702
+ return element.closest(CODEX_COMPOSER_SELECTOR);
16616
16703
  }
16617
16704
  function isRecord(value) {
16618
16705
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -16907,6 +16994,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16907
16994
  if (ownership.owner === "codex") return null;
16908
16995
  if (ownership.harnessId === "pi") return "pi";
16909
16996
  if (ownership.harnessId === "claude-code") return "claude-code";
16997
+ if (ownership.harnessId === "deepseek-harness") return "deepseek-harness";
16998
+ if (ownership.harnessId === "grok") return "grok";
16910
16999
  return null;
16911
17000
  }
16912
17001
  var BrowserSidebarAgentIconRow = class {
@@ -17009,7 +17098,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17009
17098
  const requestOwnership = (threadIds, client) => {
17010
17099
  for (const threadId of threadIds) pending.add(threadId);
17011
17100
  let succeeded = false;
17012
- void client.listThreadOwnership({ threadIds }).then(({ threads }) => {
17101
+ void Promise.resolve().then(() => client.listThreadOwnership({ threadIds })).then(({ threads }) => {
17013
17102
  if (disposed) return;
17014
17103
  for (const ownership of threads) {
17015
17104
  ownershipByThread.set(ownership.threadId, rendererAgentForThreadOwnership(ownership));
@@ -17377,6 +17466,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17377
17466
  var PI_TRANSPORT_MODEL_PREFIX = `${PI_TRANSPORT_MODEL_ID}@`;
17378
17467
  var CLAUDE_CODE_TRANSPORT_MODEL_ID = "codexhost/claude-code-native";
17379
17468
  var CLAUDE_CODE_TRANSPORT_MODEL_PREFIX = `${CLAUDE_CODE_TRANSPORT_MODEL_ID}@`;
17469
+ var DEEPSEEK_HARNESS_TRANSPORT_MODEL_ID = "codexhost/deepseek-harness-native";
17470
+ var DEEPSEEK_HARNESS_TRANSPORT_MODEL_PREFIX = `${DEEPSEEK_HARNESS_TRANSPORT_MODEL_ID}@`;
17471
+ var GROK_TRANSPORT_MODEL_ID = "codexhost/grok-native";
17472
+ var GROK_TRANSPORT_MODEL_PREFIX = `${GROK_TRANSPORT_MODEL_ID}@`;
17380
17473
  function transitionRendererAdapterStatus(current, next, publish) {
17381
17474
  if (current.state === next.state && current.reason === next.reason && current.hook === next.hook) {
17382
17475
  return false;
@@ -17392,11 +17485,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17392
17485
  function transportModelIdForAgent(agent) {
17393
17486
  if (agent === "pi") return PI_TRANSPORT_MODEL_ID;
17394
17487
  if (agent === "claude-code") return CLAUDE_CODE_TRANSPORT_MODEL_ID;
17488
+ if (agent === "deepseek-harness") return DEEPSEEK_HARNESS_TRANSPORT_MODEL_ID;
17489
+ if (agent === "grok") return GROK_TRANSPORT_MODEL_ID;
17395
17490
  return null;
17396
17491
  }
17397
- function isTransportModelId(model) {
17398
- return isPiTransportModelId(model) || isClaudeTransportModelId(model);
17399
- }
17400
17492
  function isRecord5(value) {
17401
17493
  return typeof value === "object" && value !== null && !Array.isArray(value);
17402
17494
  }
@@ -17424,6 +17516,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17424
17516
  }
17425
17517
  return `${CLAUDE_CODE_TRANSPORT_MODEL_PREFIX}${parsedModel.id}${parsedPermissionMode ? `@${parsedPermissionMode}` : ""}`;
17426
17518
  }
17519
+ function grokTransportModelId(model, thinkingOptionId) {
17520
+ if (!model) {
17521
+ if (thinkingOptionId) throw new Error("Grok transport Thinking requires a Model Ref");
17522
+ return GROK_TRANSPORT_MODEL_ID;
17523
+ }
17524
+ const parsedModel = harnessModelRefSchema.parse(model);
17525
+ const parsedThinking = thinkingOptionId ? harnessThinkingOptionIdSchema.parse(thinkingOptionId) : void 0;
17526
+ return `${GROK_TRANSPORT_MODEL_PREFIX}${parsedModel.id}${parsedThinking ? `@@${parsedThinking}` : ""}`;
17527
+ }
17528
+ function decodeGrokTransportModelId(value) {
17529
+ if (value === GROK_TRANSPORT_MODEL_ID) return {};
17530
+ if (typeof value !== "string" || !value.startsWith(GROK_TRANSPORT_MODEL_PREFIX)) return null;
17531
+ const components = value.slice(GROK_TRANSPORT_MODEL_PREFIX.length).split("@");
17532
+ if (components.length !== 1 && components.length !== 3) return null;
17533
+ const [modelId, emptyPermissionMode, thinkingOptionId] = components;
17534
+ if (components.length === 3 && (emptyPermissionMode !== "" || !thinkingOptionId)) return null;
17535
+ const model = harnessModelRefSchema.safeParse({ id: modelId });
17536
+ if (!model.success) return null;
17537
+ const thinking = thinkingOptionId ? harnessThinkingOptionIdSchema.safeParse(thinkingOptionId) : null;
17538
+ if (thinking && !thinking.success) return null;
17539
+ return {
17540
+ model: model.data,
17541
+ ...thinking?.success ? { thinkingOptionId: thinking.data } : {}
17542
+ };
17543
+ }
17427
17544
  function decodeClaudeTransportModelId(value) {
17428
17545
  if (value === CLAUDE_CODE_TRANSPORT_MODEL_ID) return {};
17429
17546
  if (typeof value !== "string" || !value.startsWith(CLAUDE_CODE_TRANSPORT_MODEL_PREFIX)) {
@@ -17446,8 +17563,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17446
17563
  ...thinking?.success ? { thinkingOptionId: thinking.data } : {}
17447
17564
  };
17448
17565
  }
17449
- function isClaudeTransportModelId(value) {
17450
- return decodeClaudeTransportModelId(value) !== null;
17566
+ function deepSeekHarnessTransportModelId(model) {
17567
+ if (!model) return DEEPSEEK_HARNESS_TRANSPORT_MODEL_ID;
17568
+ return `${DEEPSEEK_HARNESS_TRANSPORT_MODEL_PREFIX}${harnessModelRefSchema.parse(model).id}`;
17569
+ }
17570
+ function decodeDeepSeekHarnessTransportModelId(value) {
17571
+ if (value === DEEPSEEK_HARNESS_TRANSPORT_MODEL_ID) return {};
17572
+ if (typeof value !== "string" || !value.startsWith(DEEPSEEK_HARNESS_TRANSPORT_MODEL_PREFIX)) {
17573
+ return null;
17574
+ }
17575
+ const model = harnessModelRefSchema.safeParse({
17576
+ id: value.slice(DEEPSEEK_HARNESS_TRANSPORT_MODEL_PREFIX.length)
17577
+ });
17578
+ return model.success ? { model: model.data } : null;
17451
17579
  }
17452
17580
  function isPiTransportModelId(value) {
17453
17581
  if (value === PI_TRANSPORT_MODEL_ID) return true;
@@ -17520,31 +17648,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17520
17648
  }
17521
17649
  return [...targets];
17522
17650
  }
17523
- function isModelAtomState(value) {
17524
- return isRecord5(value) && isRecord5(value.atom) && typeof value.get === "function" && typeof value.set === "function";
17525
- }
17526
- function isModelSelection(value) {
17527
- return value === null || isRecord5(value) && "model" in value && "reasoningEffort" in value;
17528
- }
17529
- function sameModelPowerSelection(left, right) {
17530
- return left === right || left !== null && right !== null && left.model === right.model && left.reasoningEffort === right.reasoningEffort;
17531
- }
17532
- function sameTarget2(left, right) {
17533
- return left.length === right.length && left.every((value, index) => value === right[index]);
17534
- }
17535
- function selectOptimisticModelAtom(pairs) {
17536
- const first = pairs[0];
17537
- if (!first) return null;
17538
- const value = first.optimistic.get();
17539
- if (isRecord5(value) && "modelSettings" in value) return first.optimistic;
17540
- if (first.optimistic.atom === first.committed.atom) return null;
17541
- if (!pairs.every(
17542
- (pair) => pair.optimistic.atom === first.optimistic.atom && pair.committed.atom === first.committed.atom && sameTarget2(pair.target, first.target)
17543
- )) {
17544
- return null;
17545
- }
17546
- return first.optimistic;
17547
- }
17548
17651
  function findComposerFiber(composer) {
17549
17652
  const selector = '[data-codex-composer], [contenteditable="true"][role="textbox"]';
17550
17653
  const editor = composer?.matches(selector) === true ? composer : (composer ?? document).querySelector(selector);
@@ -17559,165 +17662,60 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17559
17662
  }
17560
17663
  return fiberElement && fiberName ? Object.getOwnPropertyDescriptor(fiberElement, fiberName)?.value : null;
17561
17664
  }
17562
- function findReasoningEffort() {
17563
- const matches = [];
17564
- for (const button of document.querySelectorAll(
17565
- '[data-codex-composer-root] button[aria-haspopup="menu"]'
17566
- )) {
17567
- const fiberName = Object.getOwnPropertyNames(button).find(
17568
- (name) => name.startsWith("__reactFiber$")
17569
- );
17570
- let fiber = fiberName ? Object.getOwnPropertyDescriptor(button, fiberName)?.value : null;
17571
- for (let depth = 0; fiber && depth < 60; depth += 1) {
17572
- const props = fiber.memoizedProps;
17573
- if (isRecord5(props) && typeof props.onSelectModel === "function" && typeof props.onSelectReasoningEffort === "function" && "reasoningEffort" in props && isRecord5(props.fallbackPowerSelection)) {
17574
- matches.push({ callback: props.onSelectModel, value: props.reasoningEffort });
17665
+ function findComposerConversationThreadId(composer) {
17666
+ let threadId;
17667
+ let fiber = findComposerFiber(composer);
17668
+ for (let depth = 0; fiber && depth < 120; depth += 1) {
17669
+ const props = fiber.memoizedProps;
17670
+ if (isRecord5(props) && "conversationId" in props && props.conversationId != null) {
17671
+ const candidate = hostThreadIdSchema.safeParse(props.conversationId);
17672
+ if (!candidate.success || threadId !== void 0 && threadId !== candidate.data) {
17673
+ return null;
17575
17674
  }
17576
- const parent = fiber.return;
17577
- fiber = (typeof parent === "object" || typeof parent === "function") && parent !== null ? parent : null;
17675
+ threadId = candidate.data;
17578
17676
  }
17677
+ const parent = fiber.return;
17678
+ fiber = (typeof parent === "object" || typeof parent === "function") && parent !== null ? parent : null;
17579
17679
  }
17580
- const uniqueCallbacks = new Set(matches.map((match) => match.callback));
17581
- const first = matches[0];
17582
- return {
17583
- found: first !== void 0 && uniqueCallbacks.size === 1 && matches.every((match) => match.value === first.value),
17584
- value: first?.value
17585
- };
17680
+ return threadId;
17586
17681
  }
17587
- function findModelPickerControl(composer) {
17588
- let control;
17589
- for (const button of (composer ?? document).querySelectorAll(
17590
- 'button[aria-haspopup="menu"]'
17591
- )) {
17592
- const fiberName = Object.getOwnPropertyNames(button).find(
17593
- (name) => name.startsWith("__reactFiber$")
17594
- );
17595
- let fiber = fiberName ? Object.getOwnPropertyDescriptor(button, fiberName)?.value : null;
17596
- for (let depth = 0; fiber && depth < 60; depth += 1) {
17597
- const props = fiber.memoizedProps;
17598
- if (!control && isRecord5(props) && "model" in props && "reasoningEffort" in props && typeof props.onSelectModel === "function") {
17599
- const selection = { model: props.model, reasoningEffort: props.reasoningEffort };
17600
- const fallbackSelection = isRecord5(props.fallbackPowerSelection) ? props.fallbackPowerSelection : null;
17601
- control = {
17602
- codexSelection: isTransportModelId(selection.model) ? fallbackSelection : selection,
17603
- selection,
17604
- selectModel: props.onSelectModel
17605
- };
17606
- }
17607
- const parent = fiber.return;
17608
- fiber = (typeof parent === "object" || typeof parent === "function") && parent !== null ? parent : null;
17609
- }
17682
+ function isCurrentDraftWrapper(value) {
17683
+ if (!Array.isArray(value) || value.length !== 7 || value[3] !== value[5] || value[3] !== value[6] || !isRecord5(value[3]) || typeof value[3].get !== "function" || typeof value[2] !== "string" && value[2] !== null) {
17684
+ return false;
17685
+ }
17686
+ try {
17687
+ const draft = value[3].get();
17688
+ return isRecord5(draft) && "modelSettings" in draft && "isManuallyChanged" in draft;
17689
+ } catch {
17690
+ return false;
17610
17691
  }
17611
- return {
17612
- codexSelection: control?.codexSelection ?? null,
17613
- found: control !== void 0,
17614
- selection: control?.selection ?? { model: void 0, reasoningEffort: void 0 },
17615
- selectModel(model, reasoningEffort) {
17616
- control?.selectModel(model, reasoningEffort);
17617
- }
17618
- };
17619
17692
  }
17620
- function findModelAtomPairs(composer) {
17621
- const pairs = [];
17622
- const compactPairs = [];
17693
+ function findComposerModelTarget(composer) {
17694
+ const conversationThreadId = findComposerConversationThreadId(composer);
17695
+ if (conversationThreadId === null) return null;
17696
+ if (conversationThreadId !== void 0) return ["conversation", conversationThreadId];
17697
+ const draftIds = /* @__PURE__ */ new Set();
17623
17698
  let fiber = findComposerFiber(composer);
17624
17699
  for (let depth = 0; fiber && depth < 120; depth += 1) {
17625
17700
  const updateQueue = fiber.updateQueue;
17626
17701
  const memoCache = isRecord5(updateQueue) ? updateQueue.memoCache : null;
17627
17702
  const data = isRecord5(memoCache) && Array.isArray(memoCache.data) ? memoCache.data : [];
17628
- for (let index = 0; index + 1 < data.length; index += 1) {
17629
- const compact = data[index];
17630
- const resolved = data[index + 1];
17631
- if (!Array.isArray(compact) || !isModelAtomState(compact[1]) || !Array.isArray(resolved) || !isModelAtomState(resolved[3]) || resolved[2] !== null && typeof resolved[2] !== "string") {
17632
- continue;
17633
- }
17634
- let value;
17635
- try {
17636
- value = compact[1].get();
17637
- } catch {
17638
- continue;
17639
- }
17640
- if (!isRecord5(value) || !("modelSettings" in value)) continue;
17641
- const target = resolved[2] === null || resolved[2].startsWith("client-new-thread:") ? ["default", resolved[2]] : ["conversation", resolved[2]];
17642
- compactPairs.push({ optimistic: compact[1], committed: resolved[3], target });
17643
- }
17644
- for (let index = 0; index + 3 < data.length; index += 1) {
17645
- const first = data[index];
17646
- const firstResolved = data[index + 1];
17647
- const second = data[index + 2];
17648
- const secondResolved = data[index + 3];
17649
- if (!Array.isArray(first) || first.length !== 3 || !Array.isArray(firstResolved) || firstResolved.length !== 4 || !Array.isArray(second) || second.length !== 3 || !Array.isArray(secondResolved) || secondResolved.length !== 4) {
17650
- continue;
17651
- }
17652
- const target = firstResolved[2];
17653
- const secondTarget = secondResolved[2];
17654
- const optimistic = firstResolved[3];
17655
- const committed = secondResolved[3];
17656
- if (!Array.isArray(target) || !Array.isArray(secondTarget) || target !== secondTarget || target[0] !== "default" && target[0] !== "conversation" || !isModelAtomState(optimistic) || !isModelAtomState(committed)) {
17657
- continue;
17658
- }
17659
- let optimisticValue;
17660
- let committedValue;
17661
- try {
17662
- optimisticValue = optimistic.get();
17663
- committedValue = committed.get();
17664
- } catch {
17665
- continue;
17703
+ for (const value of data) {
17704
+ if (isCurrentDraftWrapper(value) && typeof value[2] === "string" && value[2].startsWith("client-new-thread:")) {
17705
+ draftIds.add(value[2]);
17666
17706
  }
17667
- if (!isModelSelection(optimisticValue) || !isModelSelection(committedValue)) continue;
17668
- pairs.push({ optimistic, committed, target });
17669
17707
  }
17670
17708
  const parent = fiber.return;
17671
17709
  fiber = (typeof parent === "object" || typeof parent === "function") && parent !== null ? parent : null;
17672
17710
  }
17673
- return pairs.length > 0 ? pairs : compactPairs;
17674
- }
17675
- function findComposerModelTarget(composer) {
17676
- const pairs = findModelAtomPairs(composer);
17677
- if (!selectOptimisticModelAtom(pairs)) return null;
17678
- return pairs[0]?.target ?? null;
17679
- }
17680
- function findModelStateController(composer) {
17681
- const pairs = findModelAtomPairs(composer);
17682
- const optimistic = selectOptimisticModelAtom(pairs);
17683
- if (!optimistic) return null;
17684
- const current = optimistic.get();
17685
- if (isModelSelection(current)) {
17686
- const reasoningEffort = findReasoningEffort();
17687
- const picker2 = findModelPickerControl(composer);
17688
- if (!reasoningEffort.found) return null;
17689
- return {
17690
- apply(selection) {
17691
- optimistic.set(selection);
17692
- },
17693
- codexSelection: current === null ? picker2.codexSelection : !isTransportModelId(current.model) ? current : picker2.codexSelection,
17694
- get current() {
17695
- const value = optimistic.get();
17696
- return isModelSelection(value) ? value : null;
17697
- },
17698
- format: "legacy",
17699
- reasoningEffort: reasoningEffort.value
17700
- };
17701
- }
17702
- if (!isRecord5(current) || !("modelSettings" in current)) return null;
17703
- const picker = findModelPickerControl(composer);
17704
- if (!picker.found) return null;
17705
- return {
17706
- apply(selection) {
17707
- if (selection) picker.selectModel(selection.model, selection.reasoningEffort);
17708
- else optimistic.set({ ...current, isManuallyChanged: true, modelSettings: null });
17709
- },
17710
- codexSelection: picker.codexSelection,
17711
- current: picker.selection,
17712
- format: "compact",
17713
- reasoningEffort: picker.selection.reasoningEffort
17714
- };
17711
+ if (draftIds.size !== 1) return null;
17712
+ return ["default", draftIds.values().next().value];
17715
17713
  }
17716
17714
  function isMainProcessTitlePolicyReady(value) {
17717
17715
  return isRecord5(value) && value.state === "ready";
17718
17716
  }
17719
17717
  function isDraftPrewarmPolicyReady(value) {
17720
- return isRecord5(value) && value.state === "ready" && typeof value.clear === "function";
17718
+ return isRecord5(value) && value.state === "ready" && typeof value.select === "function" && typeof value.clear === "function";
17721
17719
  }
17722
17720
  async function waitForRendererDraftPrewarmPolicy(target) {
17723
17721
  const deadline = Date.now() + DRAFT_PREWARM_POLICY_WAIT_TIMEOUT_MS;
@@ -17732,15 +17730,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17732
17730
  }
17733
17731
  }
17734
17732
  function modelSelectionForAgent(officialSelection, reasoningEffort, agent, model, thinkingOptionId, permissionModeId) {
17735
- const transportModelId = agent === "pi" ? piTransportModelId(model, thinkingOptionId) : agent === "claude-code" ? claudeTransportModelId(model, permissionModeId, thinkingOptionId) : transportModelIdForAgent(agent);
17733
+ 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);
17736
17734
  return transportModelId ? { model: transportModelId, reasoningEffort } : officialSelection;
17737
17735
  }
17738
17736
  function installCurrentRendererAdapter() {
17739
17737
  let disposed = false;
17740
- let modelController = null;
17741
- let officialSelection = null;
17742
- let hasOfficialSelection = false;
17743
- let selectedAgent = "codex";
17744
17738
  let modelUpdates = 0;
17745
17739
  const liveStatus = {
17746
17740
  state: "installing",
@@ -17795,54 +17789,41 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17795
17789
  );
17796
17790
  }
17797
17791
  });
17798
- const captureController = () => {
17799
- const discovered = findModelStateController();
17800
- if (!discovered) return false;
17801
- modelController = discovered;
17802
- if (selectedAgent === "codex" && discovered.codexSelection !== null) {
17803
- officialSelection = discovered.codexSelection;
17804
- hasOfficialSelection = true;
17805
- } else if (selectedAgent === "codex" && discovered.current === null) {
17806
- officialSelection = null;
17807
- hasOfficialSelection = true;
17808
- }
17809
- if (!hasOfficialSelection) return false;
17810
- updateStatus("ready", "ready", "model-state");
17792
+ let routingPolicy = null;
17793
+ let policyTimer = null;
17794
+ const captureRoutingPolicy = () => {
17795
+ const discovered = window.__codexhostDraftPrewarmPolicyV1;
17796
+ if (!isDraftPrewarmPolicyReady(discovered)) return false;
17797
+ routingPolicy = discovered;
17798
+ if (policyTimer !== null) {
17799
+ window.clearInterval(policyTimer);
17800
+ policyTimer = null;
17801
+ }
17802
+ updateStatus("ready", "ready", "request-bridge");
17811
17803
  return true;
17812
17804
  };
17813
- const applyAgent = (agent, model, thinkingOptionId, permissionModeId, composer) => {
17814
- if (disposed) return false;
17815
- if (agent === "codex" && !hasOfficialSelection) {
17816
- selectedAgent = "codex";
17817
- return true;
17818
- }
17819
- const scopedController = composer ? findModelStateController(composer) : null;
17820
- const controller = scopedController ?? (modelController?.format === "legacy" ? modelController : composer ? null : modelController ?? findModelStateController());
17821
- if (!controller || !hasOfficialSelection) return false;
17822
- modelController = controller;
17805
+ if (!captureRoutingPolicy()) {
17806
+ updateStatus("installing", "draft-routing-policy-unavailable", null);
17807
+ policyTimer = window.setInterval(captureRoutingPolicy, DRAFT_PREWARM_POLICY_POLL_INTERVAL_MS);
17808
+ }
17809
+ const applyAgent = (agent, model, thinkingOptionId, permissionModeId) => {
17810
+ if (disposed || routingPolicy === null) return false;
17823
17811
  const selection = modelSelectionForAgent(
17824
- officialSelection,
17825
- controller.reasoningEffort,
17812
+ null,
17813
+ null,
17826
17814
  agent,
17827
17815
  model,
17828
17816
  thinkingOptionId,
17829
17817
  permissionModeId
17830
17818
  );
17831
- if (!sameModelPowerSelection(controller.current, selection)) {
17832
- controller.apply(selection);
17819
+ const carrier = selection?.model;
17820
+ if (carrier !== null && carrier !== void 0 && typeof carrier !== "string") return false;
17821
+ if (routingPolicy.select(carrier ?? null)) {
17833
17822
  modelUpdates += 1;
17834
17823
  liveStatus.modelUpdates = modelUpdates;
17835
17824
  }
17836
- selectedAgent = agent;
17837
17825
  return true;
17838
17826
  };
17839
- if (!captureController()) {
17840
- updateStatus("installing", "model-controller-unavailable", null);
17841
- }
17842
- const observer = new MutationObserver(() => {
17843
- captureController();
17844
- });
17845
- observer.observe(document.documentElement, { childList: true, subtree: true });
17846
17827
  return {
17847
17828
  status: liveStatus,
17848
17829
  modelControl,
@@ -17850,12 +17831,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17850
17831
  dispose() {
17851
17832
  if (disposed) return;
17852
17833
  disposed = true;
17853
- observer.disconnect();
17834
+ if (policyTimer !== null) window.clearInterval(policyTimer);
17835
+ routingPolicy?.select(null);
17836
+ routingPolicy = null;
17854
17837
  forkControl.dispose();
17855
17838
  usageSubscription.dispose();
17856
- modelController = null;
17857
- officialSelection = null;
17858
- hasOfficialSelection = false;
17859
17839
  }
17860
17840
  };
17861
17841
  }
@@ -17919,15 +17899,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17919
17899
  if (!isRecord6(parsed) || parsed.version !== 1) return void 0;
17920
17900
  if (!KNOWN_RENDERER_AGENTS.some((agent) => agent === parsed.lastAgent)) return void 0;
17921
17901
  const externalByAgent = isRecord6(parsed.externalByAgent) ? parsed.externalByAgent : {};
17922
- const pi = parseExternalConfiguration(externalByAgent.pi);
17923
- const claudeCode = parseExternalConfiguration(externalByAgent["claude-code"]);
17902
+ const parsedExternal = Object.fromEntries(
17903
+ KNOWN_RENDERER_AGENTS.filter(
17904
+ (agent) => agent !== "codex"
17905
+ ).flatMap((agent) => {
17906
+ const configuration2 = parseExternalConfiguration(externalByAgent[agent]);
17907
+ return configuration2 ? [[agent, configuration2]] : [];
17908
+ })
17909
+ );
17924
17910
  return {
17925
17911
  version: 1,
17926
17912
  lastAgent: parsed.lastAgent,
17927
- externalByAgent: {
17928
- ...pi ? { pi } : {},
17929
- ...claudeCode ? { "claude-code": claudeCode } : {}
17930
- }
17913
+ externalByAgent: parsedExternal
17931
17914
  };
17932
17915
  } catch {
17933
17916
  return void 0;
@@ -19555,9 +19538,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19555
19538
  // src/renderer-binding-probe.ts
19556
19539
  var externalHarnessIds = {
19557
19540
  pi: harnessIdSchema.parse("pi"),
19558
- "claude-code": harnessIdSchema.parse("claude-code")
19541
+ "claude-code": harnessIdSchema.parse("claude-code"),
19542
+ "deepseek-harness": harnessIdSchema.parse("deepseek-harness"),
19543
+ grok: harnessIdSchema.parse("grok")
19559
19544
  };
19560
- var externalAgents = ["pi", "claude-code"];
19545
+ var externalAgents = [
19546
+ "pi",
19547
+ "claude-code",
19548
+ "deepseek-harness",
19549
+ "grok"
19550
+ ];
19561
19551
  var rendererUsageRefreshDelays = [250, 500, 1e3, 2e3, 4e3, 8e3];
19562
19552
  function rendererUsageRefreshDelay(attempt) {
19563
19553
  const index = Math.max(0, Math.min(Math.trunc(attempt), rendererUsageRefreshDelays.length - 1));
@@ -19590,6 +19580,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19590
19580
  ...inspection.effectivePermissionModeId ? { permissionModeId: inspection.effectivePermissionModeId } : {}
19591
19581
  };
19592
19582
  }
19583
+ if (inspection.harnessId === "grok") {
19584
+ const transportSelection = decodeGrokTransportModelId(inspection.transportModelId);
19585
+ if (!transportSelection) {
19586
+ throw new Error("Grok Thread reported an incompatible transport Model");
19587
+ }
19588
+ const model = inspection.effectiveModel ?? transportSelection.model;
19589
+ const thinkingOptionId = selectableThinkingOptionId(inspection) ?? transportSelection.thinkingOptionId;
19590
+ return {
19591
+ agent: "grok",
19592
+ ...model ? { model } : {},
19593
+ ...thinkingOptionId ? { thinkingOptionId } : {}
19594
+ };
19595
+ }
19593
19596
  if (inspection.harnessId === "claude-code") {
19594
19597
  const transportSelection = decodeClaudeTransportModelId(inspection.transportModelId);
19595
19598
  if (!transportSelection) {
@@ -19605,6 +19608,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19605
19608
  ...permissionModeId ? { permissionModeId } : {}
19606
19609
  };
19607
19610
  }
19611
+ if (inspection.harnessId === "deepseek-harness") {
19612
+ const transportSelection = decodeDeepSeekHarnessTransportModelId(inspection.transportModelId);
19613
+ if (!transportSelection) {
19614
+ throw new Error("DeepSeek Harness Thread reported an incompatible transport Model");
19615
+ }
19616
+ const model = inspection.effectiveModel ?? transportSelection.model;
19617
+ return { agent: "deepseek-harness", ...model ? { model } : {} };
19618
+ }
19608
19619
  throw new Error("Thread owner is not a Renderer Agent");
19609
19620
  }
19610
19621
  function isOwnershipSubmissionBlocked(status) {
@@ -19696,7 +19707,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19696
19707
  let availabilityRequest = null;
19697
19708
  const usageRefreshTimers = /* @__PURE__ */ new Map();
19698
19709
  const usageRefreshAttempts = /* @__PURE__ */ new Map();
19699
- const isCurrentModelRequest = (mounted, generation) => mounted.composer.isConnected && mountedByComposer.get(mounted.composer) === mounted && controller.isCurrentModelRequest(mounted.composer, generation);
19710
+ const isMountedComposer = (composer) => composer.isConnected && composer.matches(CODEX_COMPOSER_SELECTOR) && mountedByComposer.has(composer);
19711
+ const isCurrentModelRequest = (mounted, generation) => isMountedComposer(mounted.composer) && mountedByComposer.get(mounted.composer) === mounted && controller.isCurrentModelRequest(mounted.composer, generation);
19700
19712
  const isCurrentOwnershipRequest = (mounted, generation) => mounted.composer.isConnected && mountedByComposer.get(mounted.composer) === mounted && controller.isCurrentOwnershipRequest(mounted.composer, generation);
19701
19713
  const notifySubmission = (composer, trigger) => {
19702
19714
  const state = controller.recordSubmission(composer);
@@ -19909,6 +19921,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19909
19921
  };
19910
19922
  mounted.permissionModeView = { status: "idle" };
19911
19923
  renderMounted(mounted);
19924
+ if (availability === "checking") void refreshHarnessAvailability();
19912
19925
  return;
19913
19926
  }
19914
19927
  mounted.modelView = {
@@ -20423,40 +20436,44 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20423
20436
  window.open(url2, "_blank", "noopener,noreferrer");
20424
20437
  };
20425
20438
  const refreshHarnessAvailability = (refresh = false) => {
20426
- if (adapterStatus.state !== "ready" || !modelControl) return Promise.resolve();
20439
+ if (!modelControl) return Promise.resolve();
20427
20440
  const client = modelControl;
20441
+ harnessAvailability = Object.fromEntries(
20442
+ externalAgents.map((agent) => [agent, "checking"])
20443
+ );
20444
+ for (const mounted of mountedByComposer.values()) renderMounted(mounted);
20428
20445
  if (availabilityRequest?.client === client) return availabilityRequest.promise;
20429
20446
  const generation = ++availabilityRequestGeneration;
20430
20447
  const promise2 = (async () => {
20431
- const inspections = await Promise.all(
20448
+ await Promise.all(
20432
20449
  externalAgents.map(async (agent) => {
20450
+ let status = "error";
20433
20451
  try {
20434
20452
  const inspection = await client.inspectHarness({
20435
20453
  harnessId: externalHarnessIds[agent],
20436
20454
  refresh
20437
20455
  });
20438
- return [agent, inspection.status === "ready" ? "ready" : inspection.status];
20456
+ status = inspection.status === "ready" ? "ready" : inspection.status;
20439
20457
  } catch {
20440
- return [agent, "error"];
20458
+ status = "error";
20459
+ }
20460
+ if (generation !== availabilityRequestGeneration || disposed) return;
20461
+ harnessAvailability = { ...harnessAvailability, [agent]: status };
20462
+ for (const mounted of mountedByComposer.values()) {
20463
+ const state = controller.get(mounted.composer);
20464
+ if (adapterStatus.state === "ready" && state.phase === "draft" && state.agent === agent && status !== "ready") {
20465
+ await switchComposerAgent(mounted, "codex");
20466
+ }
20467
+ }
20468
+ for (const mounted of mountedByComposer.values()) {
20469
+ const state = controller.get(mounted.composer);
20470
+ if (state.agent === agent) {
20471
+ void loadExternalCatalog(mounted);
20472
+ }
20473
+ renderMounted(mounted);
20441
20474
  }
20442
20475
  })
20443
20476
  );
20444
- if (generation !== availabilityRequestGeneration || disposed) return;
20445
- harnessAvailability = Object.fromEntries(inspections);
20446
- for (const mounted of mountedByComposer.values()) {
20447
- const state = controller.get(mounted.composer);
20448
- if (state.phase === "draft" && state.agent !== "codex" && harnessAvailability[state.agent] !== "ready") {
20449
- await switchComposerAgent(mounted, "codex");
20450
- }
20451
- }
20452
- for (const mounted of mountedByComposer.values()) {
20453
- const state = controller.get(mounted.composer);
20454
- if (state.agent !== "codex") {
20455
- void loadExternalCatalog(mounted);
20456
- } else {
20457
- renderMounted(mounted);
20458
- }
20459
- }
20460
20477
  })();
20461
20478
  const request = { client, promise: promise2 };
20462
20479
  availabilityRequest = request;
@@ -20471,7 +20488,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20471
20488
  return promise2;
20472
20489
  };
20473
20490
  const mount = (composer) => {
20474
- if (mountedByComposer.has(composer) || !composer.isConnected) return;
20491
+ if (mountedByComposer.has(composer) || !composer.isConnected || !composer.matches(CODEX_COMPOSER_SELECTOR)) {
20492
+ return;
20493
+ }
20475
20494
  const allButtons = [...composer.querySelectorAll("button")];
20476
20495
  const sendButton = sendButtonWithin(composer) ?? allButtons.at(-1) ?? null;
20477
20496
  if (!sendButton) return;
@@ -20558,7 +20577,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20558
20577
  }
20559
20578
  }
20560
20579
  for (const [composer, mounted] of mountedByComposer) {
20561
- if (!composer.isConnected || !mounted.control.root.isConnected) {
20580
+ if (!composer.isConnected || !composer.matches(CODEX_COMPOSER_SELECTOR) || !mounted.control.root.isConnected) {
20581
+ mounted.usageRequestGeneration += 1;
20582
+ usageRefreshAttempts.delete(composer);
20583
+ const timer = usageRefreshTimers.get(composer);
20584
+ if (timer !== void 0) {
20585
+ window.clearTimeout(timer);
20586
+ usageRefreshTimers.delete(composer);
20587
+ }
20562
20588
  disposeComposerAgentControl(mounted.control);
20563
20589
  mountedByComposer.delete(composer);
20564
20590
  continue;
@@ -20660,7 +20686,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20660
20686
  const composerForTarget = (target) => {
20661
20687
  const element = eventElement(target);
20662
20688
  const editor = element ? editorForElement(element) : null;
20663
- return editor ? composerForEditor(editor) : null;
20689
+ const composer = editor ? composerForEditor(editor) : null;
20690
+ return composer && isMountedComposer(composer) ? composer : null;
20664
20691
  };
20665
20692
  const onBeforeInput = (event) => {
20666
20693
  const composer = composerForTarget(event.target);
@@ -20671,7 +20698,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20671
20698
  };
20672
20699
  const onSubmit = (event) => {
20673
20700
  const element = eventElement(event.target);
20674
- const composer = element ? composerForElement(element) : null;
20701
+ const candidate = element ? composerForElement(element) : null;
20702
+ const composer = candidate && isMountedComposer(candidate) ? candidate : null;
20675
20703
  if (!composer) return;
20676
20704
  const prepared = prepareComposer(composer);
20677
20705
  if (prepared === null) return;
@@ -20707,7 +20735,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20707
20735
  const element = eventElement(event.target);
20708
20736
  const button = element?.closest("button");
20709
20737
  if (!button) return;
20710
- const composer = composerForElement(button);
20738
+ const candidate = composerForElement(button);
20739
+ const composer = candidate && isMountedComposer(candidate) ? candidate : null;
20711
20740
  const mounted = composer ? mountedByComposer.get(composer) : void 0;
20712
20741
  if (!composer || mounted?.control.sendButton !== button) return;
20713
20742
  if (!prepareComposer(composer)) {
@@ -20722,6 +20751,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20722
20751
  });
20723
20752
  const onAdapterStatus = () => {
20724
20753
  if (adapterStatus.state === "ready") {
20754
+ sidebarAgentIcons.refresh();
20725
20755
  void refreshHarnessAvailability();
20726
20756
  for (const mounted of mountedByComposer.values()) {
20727
20757
  if (mounted.modelView.status === "waitingForAdapter" && mounted.composer.isConnected && applyComposerAgent(mounted.composer)) {
@@ -20733,7 +20763,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20733
20763
  };
20734
20764
  mutationObserver.observe(document.documentElement, {
20735
20765
  attributes: true,
20736
- attributeFilter: ["hidden", "aria-hidden"],
20766
+ attributeFilter: ["hidden", "aria-hidden", "data-codex-composer-root"],
20737
20767
  characterData: true,
20738
20768
  childList: true,
20739
20769
  subtree: true