codex-chatgpt-control 0.5.1-alpha.1 → 0.5.1-alpha.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.
Files changed (204) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/contracts/v1/fixtures/backend-capabilities.json +1 -0
  3. package/contracts/v1/fixtures/command-descriptors.json +21 -0
  4. package/contracts/v1/fixtures/doctor-bridge-upload.json +2 -2
  5. package/contracts/v1/fixtures/doctor-scenario-preflight.json +26 -4
  6. package/contracts/v1/fixtures/files-attach-indeterminate.json +30 -0
  7. package/contracts/v1/fixtures/help-root.json +1 -1
  8. package/contracts/v1/fixtures/messages-stop-indeterminate.json +31 -0
  9. package/contracts/v1/fixtures/messages-stop-needs-confirmation.json +20 -0
  10. package/contracts/v1/fixtures/messages-stop-noop.json +19 -0
  11. package/contracts/v1/fixtures/messages-stop-success.json +21 -0
  12. package/contracts/v1/fixtures/primitive-bootstrap-blocker.json +3 -3
  13. package/contracts/v1/fixtures/reports-create-redacted.json +3 -3
  14. package/contracts/v1/fixtures/reports-summarize-redacted.json +1 -1
  15. package/contracts/v1/fixtures/run-browser-bridge-blocker.json +12 -12
  16. package/contracts/v1/fixtures/stream-blocked.ndjson +2 -2
  17. package/contracts/v1/manifest.json +25 -0
  18. package/contracts/v1/parity-suite.json +8 -1
  19. package/dist/codex-chatgpt-control-backend.mjs +2259 -498
  20. package/dist/codex-chatgpt-control.bundle.mjs +2263 -472
  21. package/dist/src/backend/client.d.ts +2 -1
  22. package/dist/src/backend/client.js +1 -0
  23. package/dist/src/backend/protocol.d.ts +1 -1
  24. package/dist/src/backend/protocol.js +1 -0
  25. package/dist/src/backend/session.js +2 -0
  26. package/dist/src/browser/attach.d.ts +1 -0
  27. package/dist/src/browser/attach.js +69 -35
  28. package/dist/src/browser/chatgpt-url.d.ts +8 -0
  29. package/dist/src/browser/chatgpt-url.js +28 -0
  30. package/dist/src/browser/page-state.js +211 -4
  31. package/dist/src/client.d.ts +2 -1
  32. package/dist/src/client.js +2 -1
  33. package/dist/src/commands/configuration.js +46 -12
  34. package/dist/src/commands/context.d.ts +5 -1
  35. package/dist/src/commands/context.js +2 -2
  36. package/dist/src/commands/conversation.js +13 -1
  37. package/dist/src/commands/doctor.js +24 -2
  38. package/dist/src/commands/files.d.ts +1 -0
  39. package/dist/src/commands/files.js +742 -191
  40. package/dist/src/commands/messages.d.ts +2 -1
  41. package/dist/src/commands/messages.js +310 -2
  42. package/dist/src/commands/modes.js +197 -52
  43. package/dist/src/commands/registry.js +3 -0
  44. package/dist/src/commands/sequence.js +3 -1
  45. package/dist/src/commands/session.d.ts +4 -1
  46. package/dist/src/commands/session.js +34 -3
  47. package/dist/src/dom/generation-state.d.ts +6 -1
  48. package/dist/src/dom/generation-state.js +206 -45
  49. package/dist/src/dom/locale/am.d.ts +10 -1
  50. package/dist/src/dom/locale/am.js +10 -1
  51. package/dist/src/dom/locale/ar.d.ts +8 -1
  52. package/dist/src/dom/locale/ar.js +9 -2
  53. package/dist/src/dom/locale/bg.d.ts +6 -1
  54. package/dist/src/dom/locale/bg.js +6 -1
  55. package/dist/src/dom/locale/bn.d.ts +10 -1
  56. package/dist/src/dom/locale/bn.js +10 -1
  57. package/dist/src/dom/locale/bs.d.ts +5 -1
  58. package/dist/src/dom/locale/bs.js +5 -1
  59. package/dist/src/dom/locale/ca.d.ts +8 -1
  60. package/dist/src/dom/locale/ca.js +8 -1
  61. package/dist/src/dom/locale/cs.d.ts +5 -1
  62. package/dist/src/dom/locale/cs.js +6 -2
  63. package/dist/src/dom/locale/da.d.ts +5 -1
  64. package/dist/src/dom/locale/da.js +6 -2
  65. package/dist/src/dom/locale/de.d.ts +4 -1
  66. package/dist/src/dom/locale/de.js +5 -2
  67. package/dist/src/dom/locale/el.d.ts +5 -1
  68. package/dist/src/dom/locale/el.js +6 -2
  69. package/dist/src/dom/locale/en.d.ts +2 -1
  70. package/dist/src/dom/locale/en.js +2 -1
  71. package/dist/src/dom/locale/es-419.d.ts +5 -1
  72. package/dist/src/dom/locale/es-419.js +5 -1
  73. package/dist/src/dom/locale/es-ES.d.ts +5 -1
  74. package/dist/src/dom/locale/es-ES.js +5 -1
  75. package/dist/src/dom/locale/et.d.ts +4 -1
  76. package/dist/src/dom/locale/et.js +5 -2
  77. package/dist/src/dom/locale/fa.d.ts +9 -1
  78. package/dist/src/dom/locale/fa.js +10 -2
  79. package/dist/src/dom/locale/fi.d.ts +5 -1
  80. package/dist/src/dom/locale/fi.js +6 -2
  81. package/dist/src/dom/locale/fr-CA.d.ts +4 -1
  82. package/dist/src/dom/locale/fr-CA.js +4 -1
  83. package/dist/src/dom/locale/fr-FR.d.ts +5 -1
  84. package/dist/src/dom/locale/fr-FR.js +7 -3
  85. package/dist/src/dom/locale/gu.d.ts +10 -1
  86. package/dist/src/dom/locale/gu.js +10 -1
  87. package/dist/src/dom/locale/hi.d.ts +10 -1
  88. package/dist/src/dom/locale/hi.js +11 -2
  89. package/dist/src/dom/locale/hr.d.ts +4 -1
  90. package/dist/src/dom/locale/hr.js +4 -1
  91. package/dist/src/dom/locale/hu.d.ts +4 -1
  92. package/dist/src/dom/locale/hu.js +5 -2
  93. package/dist/src/dom/locale/hy.d.ts +10 -1
  94. package/dist/src/dom/locale/hy.js +11 -2
  95. package/dist/src/dom/locale/id.d.ts +5 -1
  96. package/dist/src/dom/locale/id.js +5 -1
  97. package/dist/src/dom/locale/index.js +1 -0
  98. package/dist/src/dom/locale/is.d.ts +9 -1
  99. package/dist/src/dom/locale/is.js +10 -2
  100. package/dist/src/dom/locale/it.d.ts +4 -1
  101. package/dist/src/dom/locale/it.js +6 -3
  102. package/dist/src/dom/locale/ja.d.ts +6 -1
  103. package/dist/src/dom/locale/ja.js +7 -2
  104. package/dist/src/dom/locale/ka.d.ts +10 -1
  105. package/dist/src/dom/locale/ka.js +11 -2
  106. package/dist/src/dom/locale/kk.d.ts +10 -1
  107. package/dist/src/dom/locale/kk.js +11 -2
  108. package/dist/src/dom/locale/kn.d.ts +9 -1
  109. package/dist/src/dom/locale/kn.js +10 -2
  110. package/dist/src/dom/locale/ko.d.ts +6 -1
  111. package/dist/src/dom/locale/ko.js +7 -2
  112. package/dist/src/dom/locale/lt.d.ts +5 -1
  113. package/dist/src/dom/locale/lt.js +6 -2
  114. package/dist/src/dom/locale/lv.d.ts +5 -1
  115. package/dist/src/dom/locale/lv.js +5 -1
  116. package/dist/src/dom/locale/mk.d.ts +9 -1
  117. package/dist/src/dom/locale/mk.js +10 -2
  118. package/dist/src/dom/locale/ml.d.ts +10 -1
  119. package/dist/src/dom/locale/ml.js +10 -1
  120. package/dist/src/dom/locale/mn.d.ts +10 -1
  121. package/dist/src/dom/locale/mn.js +13 -4
  122. package/dist/src/dom/locale/mr.d.ts +10 -1
  123. package/dist/src/dom/locale/mr.js +10 -1
  124. package/dist/src/dom/locale/ms.d.ts +9 -1
  125. package/dist/src/dom/locale/ms.js +9 -1
  126. package/dist/src/dom/locale/my.d.ts +9 -1
  127. package/dist/src/dom/locale/my.js +9 -1
  128. package/dist/src/dom/locale/nb.d.ts +5 -1
  129. package/dist/src/dom/locale/nb.js +6 -2
  130. package/dist/src/dom/locale/nl.d.ts +8 -2
  131. package/dist/src/dom/locale/nl.js +8 -2
  132. package/dist/src/dom/locale/pa.d.ts +10 -1
  133. package/dist/src/dom/locale/pa.js +10 -1
  134. package/dist/src/dom/locale/pl.d.ts +5 -1
  135. package/dist/src/dom/locale/pl.js +6 -2
  136. package/dist/src/dom/locale/pt-BR.d.ts +5 -1
  137. package/dist/src/dom/locale/pt-BR.js +6 -2
  138. package/dist/src/dom/locale/pt-PT.d.ts +5 -1
  139. package/dist/src/dom/locale/pt-PT.js +5 -1
  140. package/dist/src/dom/locale/ro.d.ts +4 -1
  141. package/dist/src/dom/locale/ro.js +4 -1
  142. package/dist/src/dom/locale/ru.d.ts +8 -1
  143. package/dist/src/dom/locale/ru.js +9 -2
  144. package/dist/src/dom/locale/sk.d.ts +5 -1
  145. package/dist/src/dom/locale/sk.js +5 -1
  146. package/dist/src/dom/locale/sl.d.ts +9 -1
  147. package/dist/src/dom/locale/sl.js +9 -1
  148. package/dist/src/dom/locale/so.d.ts +9 -1
  149. package/dist/src/dom/locale/so.js +9 -1
  150. package/dist/src/dom/locale/sq.d.ts +10 -1
  151. package/dist/src/dom/locale/sq.js +12 -3
  152. package/dist/src/dom/locale/sr.d.ts +9 -1
  153. package/dist/src/dom/locale/sr.js +10 -2
  154. package/dist/src/dom/locale/sv.d.ts +4 -1
  155. package/dist/src/dom/locale/sv.js +4 -1
  156. package/dist/src/dom/locale/sw.d.ts +5 -1
  157. package/dist/src/dom/locale/sw.js +7 -3
  158. package/dist/src/dom/locale/ta.d.ts +10 -1
  159. package/dist/src/dom/locale/ta.js +12 -3
  160. package/dist/src/dom/locale/te.d.ts +10 -1
  161. package/dist/src/dom/locale/te.js +11 -2
  162. package/dist/src/dom/locale/th.d.ts +6 -1
  163. package/dist/src/dom/locale/th.js +6 -1
  164. package/dist/src/dom/locale/tl.d.ts +1 -1
  165. package/dist/src/dom/locale/tl.js +2 -2
  166. package/dist/src/dom/locale/tr.d.ts +9 -1
  167. package/dist/src/dom/locale/tr.js +10 -2
  168. package/dist/src/dom/locale/types.d.ts +1 -1
  169. package/dist/src/dom/locale/uk.d.ts +10 -1
  170. package/dist/src/dom/locale/uk.js +11 -2
  171. package/dist/src/dom/locale/ur.d.ts +9 -1
  172. package/dist/src/dom/locale/ur.js +9 -1
  173. package/dist/src/dom/locale/vi.d.ts +9 -1
  174. package/dist/src/dom/locale/vi.js +10 -2
  175. package/dist/src/dom/locale/zh-HK.d.ts +8 -1
  176. package/dist/src/dom/locale/zh-HK.js +9 -2
  177. package/dist/src/dom/locale/zh-Hans.d.ts +10 -1
  178. package/dist/src/dom/locale/zh-Hans.js +11 -2
  179. package/dist/src/dom/locale/zh-TW.d.ts +10 -1
  180. package/dist/src/dom/locale/zh-TW.js +11 -2
  181. package/dist/src/dom/selectors.d.ts +1 -0
  182. package/dist/src/dom/selectors.js +9 -1
  183. package/dist/src/dom/wait-snapshot.d.ts +1 -0
  184. package/dist/src/dom/wait-snapshot.js +45 -22
  185. package/dist/src/errors.d.ts +1 -1
  186. package/dist/src/errors.js +2 -2
  187. package/dist/src/safety/risk.d.ts +1 -0
  188. package/dist/src/safety/risk.js +1 -0
  189. package/dist/src/scripts/apply-intelligence-locale-captures.d.ts +2 -2
  190. package/dist/src/scripts/apply-intelligence-locale-captures.js +54 -14
  191. package/dist/src/scripts/capture-intelligence-locales.d.ts +114 -1
  192. package/dist/src/scripts/capture-intelligence-locales.js +437 -304
  193. package/dist/src/scripts/live-smoke/scenarios.d.ts +2 -1
  194. package/dist/src/scripts/live-smoke/scenarios.js +9 -10
  195. package/dist/src/scripts/locale-capture/surface-graph.d.ts +7 -2
  196. package/dist/src/scripts/locale-capture/surface-graph.js +7 -0
  197. package/dist/src/types.d.ts +27 -6
  198. package/package.json +2 -1
  199. package/references/2026-08-08-model-selection-locale-sweep.md +32 -0
  200. package/references/backend-protocol.md +11 -3
  201. package/references/language-coverage.md +14 -14
  202. package/references/localization.md +17 -13
  203. package/references/python-parity.md +8 -2
  204. package/references/troubleshooting.md +10 -2
@@ -1,5 +1,5 @@
1
1
  // src/errors.ts
2
- var BROWSER_BRIDGE_UNAVAILABLE_MESSAGE = "Codex cannot access the ChatGPT browser bridge from this backend process. In an ordinary shell this is expected; for a live Codex Chrome run, bootstrap the Chrome plugin runtime with setupBrowserRuntime({ globals: globalThis }) before using globalThis.agent.";
2
+ var BROWSER_BRIDGE_UNAVAILABLE_MESSAGE = "Codex cannot access the ChatGPT browser bridge from this backend process. In an ordinary shell this is expected; for a live Codex Chrome run, assign the Chrome plugin runtime returned by setupBrowserRuntime() to globalThis.agent before using it.";
3
3
  var BROWSER_BRIDGE_REMEDIATION = [
4
4
  {
5
5
  label: "Ordinary shell",
@@ -8,7 +8,7 @@ var BROWSER_BRIDGE_REMEDIATION = [
8
8
  },
9
9
  {
10
10
  label: "Codex Chrome bootstrap",
11
- instruction: 'For a live run, initialize the Chrome plugin runtime in node_repl with setupBrowserRuntime({ globals: globalThis }), then set globalThis.browser = await agent.browsers.get("extension") before calling createChatGPT({ agent: globalThis.agent }).',
11
+ instruction: 'For a live run, initialize the Chrome plugin runtime in node_repl with globalThis.agent = await setupBrowserRuntime(), then set globalThis.browser = await agent.browsers.get("extension") before calling createChatGPT({ agent: globalThis.agent }).',
12
12
  userActionRequired: false
13
13
  },
14
14
  {
@@ -167,6 +167,25 @@ function redactLogEvent(event) {
167
167
  return redacted;
168
168
  }
169
169
 
170
+ // src/browser/chatgpt-url.ts
171
+ var CHATGPT_HOME = "https://chatgpt.com/";
172
+ var CHATGPT_HOSTS = /* @__PURE__ */ new Set(["chatgpt.com", "www.chatgpt.com", "chat.openai.com"]);
173
+ function isChatGPTUrl(value) {
174
+ if (value === void 0) return false;
175
+ try {
176
+ const url = new URL(value);
177
+ return url.protocol === "https:" && url.port === "" && url.username === "" && url.password === "" && CHATGPT_HOSTS.has(url.hostname);
178
+ } catch {
179
+ return false;
180
+ }
181
+ }
182
+ function requireChatGPTUrl(value, label) {
183
+ if (!isChatGPTUrl(value)) {
184
+ throw new Error(`${label} must use HTTPS on an allowlisted ChatGPT origin with the default port.`);
185
+ }
186
+ return value;
187
+ }
188
+
170
189
  // src/safety/blockers.ts
171
190
  var RULES = [
172
191
  {
@@ -271,6 +290,7 @@ var en = {
271
290
  work: ["Work"]
272
291
  },
273
292
  configurationAxes: {
293
+ power: ["Power"],
274
294
  model: ["Model"],
275
295
  intelligence: ["Intelligence"],
276
296
  effort: ["Effort"],
@@ -306,7 +326,7 @@ var en = {
306
326
  /** Exact-match transient assistant placeholders filtered out of captured responses. */
307
327
  transientAssistant: ["thinking", "reasoning", "searching", "searching the web"],
308
328
  /** Streaming "stop" control text, matched while a response generates. */
309
- stopControl: ["stop generating", "stop streaming", "stop answering", "cancel"],
329
+ stopControl: ["stop generating", "stop streaming", "stop answering"],
310
330
  /** Interrupted generation markers shown after the assistant stops before completion. */
311
331
  stoppedAssistant: ["stopped thinking", "stopped answering", "generation stopped"],
312
332
  /** Response-action affordance text (fallback to the structural copy-button locator). */
@@ -323,11 +343,14 @@ var en = {
323
343
  // src/dom/locale/de.ts
324
344
  var de = {
325
345
  configurationAxes: {
346
+ power: ["Leistung"],
326
347
  model: ["Modell"],
327
- effort: ["Aufwand"],
328
- speed: ["Tempo"]
348
+ effort: ["Aufwand", "Denkaufwand"],
349
+ speed: ["Tempo"],
350
+ advanced: ["Erweitert"]
329
351
  },
330
352
  configurationOptions: {
353
+ instant: ["Sofort"],
331
354
  light: ["Leicht"],
332
355
  medium: ["Mittel"],
333
356
  high: ["Hoch"],
@@ -363,15 +386,19 @@ var de = {
363
386
  // src/dom/locale/es-ES.ts
364
387
  var esES = {
365
388
  configurationAxes: {
389
+ power: ["Potencia"],
366
390
  model: ["Modelo"],
367
391
  effort: ["Esfuerzo"],
368
- speed: ["Velocidad"]
392
+ speed: ["Velocidad"],
393
+ advanced: ["Avanzadas"]
369
394
  },
370
395
  configurationOptions: {
396
+ instant: ["Instant\xE1nea"],
371
397
  light: ["Ligero"],
372
398
  medium: ["Media"],
373
399
  high: ["Alta"],
374
400
  extraHigh: ["Muy alta"],
401
+ max: ["M\xE1ximo"],
375
402
  standard: ["Est\xE1ndar"],
376
403
  fast: ["R\xE1pido"]
377
404
  },
@@ -405,15 +432,19 @@ var esES = {
405
432
  // src/dom/locale/fr-FR.ts
406
433
  var frFR = {
407
434
  configurationAxes: {
435
+ power: ["Puissance"],
408
436
  model: ["Mod\xE8le"],
409
437
  effort: ["Niveau"],
410
- speed: ["Vitesse"]
438
+ speed: ["Vitesse"],
439
+ advanced: ["Avanc\xE9"]
411
440
  },
412
441
  configurationOptions: {
442
+ instant: ["Instantan\xE9"],
413
443
  light: ["Minimal"],
414
444
  medium: ["Moyenne"],
415
445
  high: ["\xC9lev\xE9e"],
416
446
  extraHigh: ["Tr\xE8s \xE9lev\xE9e"],
447
+ max: ["Maximum"],
417
448
  fast: ["Rapide"]
418
449
  },
419
450
  composerTextbox: ["Discuter avec ChatGPT"],
@@ -425,9 +456,9 @@ var frFR = {
425
456
  addFilesOpenerCandidates: ["Ajouter des fichiers et plus encore"],
426
457
  addPhotosFilesMenuItem: ["Ajouter des photos et fichiers"],
427
458
  copyResponse: ["Copier la r\xE9ponse"],
428
- modeLabels: ["Moyen", "Avanc\xE9", "Tr\xE8s \xE9lev\xE9", "Instantan\xE9e", "Moyenne", "\xC9lev\xE9e", "Tr\xE8s \xE9lev\xE9e"],
459
+ modeLabels: ["Moyen", "Avanc\xE9", "Tr\xE8s \xE9lev\xE9", "Instantan\xE9e", "Moyenne", "\xC9lev\xE9e", "Tr\xE8s \xE9lev\xE9e", "Instantan\xE9"],
429
460
  modeOptions: {
430
- instant: ["Instantan\xE9e"],
461
+ instant: ["Instantan\xE9e", "Instantan\xE9"],
431
462
  medium: ["Moyen", "Moyenne"],
432
463
  high: ["Avanc\xE9", "\xC9lev\xE9e"],
433
464
  extraHigh: ["Tr\xE8s \xE9lev\xE9", "Tr\xE8s \xE9lev\xE9e"]
@@ -446,12 +477,15 @@ var frFR = {
446
477
  // src/dom/locale/zh-HK.ts
447
478
  var zhHK = {
448
479
  configurationAxes: {
480
+ power: ["\u667A\u80FD\u5F37\u5EA6"],
449
481
  model: ["\u6A21\u578B"],
450
482
  effort: ["\u63A8\u7406\u5F37\u5EA6"],
451
- speed: ["\u56DE\u61C9\u901F\u5EA6"]
483
+ speed: ["\u56DE\u61C9\u901F\u5EA6"],
484
+ advanced: ["\u9032\u968E"]
452
485
  },
453
486
  configurationOptions: {
454
- light: ["\u5FEB\u601D"],
487
+ instant: ["\u5373\u6642"],
488
+ light: ["\u5FEB\u601D", "\u8F15\u5EA6"],
455
489
  medium: ["\u4E2D"],
456
490
  high: ["\u9AD8"],
457
491
  extraHigh: ["\u6975\u9AD8"],
@@ -476,6 +510,10 @@ var zhHK = {
476
510
  pro: ["\u5C08\u696D"]
477
511
  },
478
512
  modeOpenerExtra: ["\u8A2D\u5B9A"],
513
+ experienceOptions: {
514
+ chat: ["\u5C0D\u8A71"],
515
+ work: ["\u5DE5\u4F5C"]
516
+ },
479
517
  tools: {
480
518
  web_search: ["\u7DB2\u7D61\u641C\u5C0B"],
481
519
  deep_research: ["\u6DF1\u5EA6\u7814\u7A76"],
@@ -489,15 +527,20 @@ var zhHK = {
489
527
  // src/dom/locale/zh-TW.ts
490
528
  var zhTW = {
491
529
  configurationAxes: {
530
+ power: ["\u80FD\u529B"],
492
531
  model: ["\u6A21\u578B"],
493
532
  effort: ["\u63A8\u7406\u5F37\u5EA6"],
494
- speed: ["\u901F\u5EA6"]
533
+ speed: ["\u901F\u5EA6"],
534
+ advanced: ["\u9032\u968E"]
495
535
  },
496
536
  configurationOptions: {
537
+ instant: ["\u5373\u6642"],
497
538
  light: ["\u5FEB\u601D"],
498
539
  medium: ["\u4E2D"],
499
540
  high: ["\u9AD8"],
500
- extraHigh: ["\u6975\u9AD8"],
541
+ extraHigh: ["\u6975\u9AD8", "\u8D85\u9AD8"],
542
+ max: ["\u6700\u9AD8"],
543
+ ultra: ["\u6975\u81F4"],
501
544
  standard: ["\u6A19\u6E96"],
502
545
  fast: ["\u5FEB\u901F"]
503
546
  },
@@ -519,6 +562,10 @@ var zhTW = {
519
562
  pro: ["\u5C08\u696D"]
520
563
  },
521
564
  modeOpenerExtra: ["\u8A2D\u5B9A"],
565
+ experienceOptions: {
566
+ chat: ["\u5C0D\u8A71"],
567
+ work: ["\u5DE5\u4F5C"]
568
+ },
522
569
  tools: {
523
570
  web_search: ["\u7DB2\u9801\u641C\u5C0B"],
524
571
  deep_research: ["\u6DF1\u5165\u7814\u7A76"],
@@ -532,15 +579,20 @@ var zhTW = {
532
579
  // src/dom/locale/ja.ts
533
580
  var ja = {
534
581
  configurationAxes: {
582
+ power: ["\u30D1\u30EF\u30FC"],
535
583
  model: ["\u30E2\u30C7\u30EB"],
536
- effort: ["\u601D\u8003\u30EC\u30D9\u30EB"],
537
- speed: ["\u901F\u5EA6"]
584
+ effort: ["\u601D\u8003\u30EC\u30D9\u30EB", "\u63A8\u8AD6\u30EC\u30D9\u30EB"],
585
+ speed: ["\u901F\u5EA6"],
586
+ advanced: ["\u8A73\u7D30\u8A2D\u5B9A"]
538
587
  },
539
588
  configurationOptions: {
589
+ instant: ["\u6700\u901F"],
540
590
  light: ["\u8EFD"],
541
591
  medium: ["\u4E2D\u7A0B\u5EA6"],
542
592
  high: ["\u9AD8\u3044"],
543
593
  extraHigh: ["\u975E\u5E38\u306B\u9AD8\u3044"],
594
+ max: ["\u6700\u5927"],
595
+ ultra: ["\u30A6\u30EB\u30C8\u30E9"],
544
596
  standard: ["\u6A19\u6E96"],
545
597
  fast: ["\u9AD8\u901F"]
546
598
  },
@@ -573,11 +625,14 @@ var ja = {
573
625
  // src/dom/locale/it.ts
574
626
  var it = {
575
627
  configurationAxes: {
628
+ power: ["Potenza"],
576
629
  model: ["Modello"],
577
630
  effort: ["Sforzo"],
578
- speed: ["Velocit\xE0"]
631
+ speed: ["Velocit\xE0"],
632
+ advanced: ["Avanzate"]
579
633
  },
580
634
  configurationOptions: {
635
+ instant: ["Istantaneo"],
581
636
  medium: ["Medio"],
582
637
  high: ["Alto"],
583
638
  extraHigh: ["Molto alto"],
@@ -592,9 +647,9 @@ var it = {
592
647
  addFilesOpenerCandidates: ["Aggiungi file e altro"],
593
648
  addPhotosFilesMenuItem: ["Aggiungi foto e file"],
594
649
  copyResponse: ["Copia risposta"],
595
- modeLabels: ["Istantanea", "Media", "Alta", "Extra elevata", "Medio", "Alto", "Molto alto"],
650
+ modeLabels: ["Istantanea", "Media", "Alta", "Extra elevata", "Medio", "Alto", "Molto alto", "Istantaneo"],
596
651
  modeOptions: {
597
- instant: ["Istantanea"],
652
+ instant: ["Istantanea", "Istantaneo"],
598
653
  medium: ["Media", "Medio"],
599
654
  high: ["Alta", "Alto"],
600
655
  extraHigh: ["Extra elevata", "Molto alto"]
@@ -612,15 +667,19 @@ var it = {
612
667
  // src/dom/locale/vi.ts
613
668
  var vi = {
614
669
  configurationAxes: {
670
+ power: ["S\u1EE9c m\u1EA1nh"],
615
671
  model: ["M\xF4 h\xECnh"],
616
- effort: ["M\u1EE9c \u0111\u1ED9"],
617
- speed: ["T\u1ED1c \u0111\u1ED9"]
672
+ effort: ["M\u1EE9c \u0111\u1ED9", "M\u1EE9c suy lu\u1EADn"],
673
+ speed: ["T\u1ED1c \u0111\u1ED9"],
674
+ advanced: ["N\xE2ng cao"]
618
675
  },
619
676
  configurationOptions: {
677
+ instant: ["T\u1EE9c th\xEC"],
620
678
  light: ["Nh\u1EB9"],
621
679
  medium: ["V\u1EEBa"],
622
680
  high: ["Cao"],
623
681
  extraHigh: ["Chuy\xEAn s\xE2u"],
682
+ max: ["T\u1ED1i \u0111a"],
624
683
  standard: ["Ti\xEAu chu\u1EA9n"],
625
684
  fast: ["Nhanh"]
626
685
  },
@@ -641,6 +700,10 @@ var vi = {
641
700
  extraHigh: ["R\u1EA5t cao", "Chuy\xEAn s\xE2u"]
642
701
  },
643
702
  modeOpenerExtra: ["\u0110\u1ECBnh c\u1EA5u h\xECnh"],
703
+ experienceOptions: {
704
+ chat: ["Tr\xF2 chuy\u1EC7n"],
705
+ work: ["C\xF4ng vi\u1EC7c"]
706
+ },
644
707
  tools: {
645
708
  web_search: ["T\xECm ki\u1EBFm tr\xEAn m\u1EA1ng"],
646
709
  deep_research: ["Nghi\xEAn c\u1EE9u chuy\xEAn s\xE2u"],
@@ -654,15 +717,20 @@ var vi = {
654
717
  // src/dom/locale/am.ts
655
718
  var am = {
656
719
  configurationAxes: {
720
+ power: ["\u12A0\u1245\u121D"],
657
721
  model: ["\u121E\u12F4\u120D"],
658
722
  effort: ["\u1325\u1228\u1275"],
659
- speed: ["\u134D\u1325\u1290\u1275"]
723
+ speed: ["\u134D\u1325\u1290\u1275"],
724
+ advanced: ["\u12E8\u120B\u1240"]
660
725
  },
661
726
  configurationOptions: {
727
+ instant: ["\u1348\u1323\u1295"],
662
728
  light: ["\u1240\u120B\u120D"],
663
729
  medium: ["\u1218\u12AB\u12A8\u1208\u129B"],
664
730
  high: ["\u12A8\u134D\u1270\u129B"],
665
731
  extraHigh: ["\u12A5\u1305\u130D \u12A8\u134D\u1270\u129B"],
732
+ max: ["\u12A8\u134D\u1270\u129B\u12CD"],
733
+ ultra: ["\u12A0\u120D\u1275\u122B"],
666
734
  standard: ["\u1218\u12F0\u1260\u129B"],
667
735
  fast: ["\u1348\u1323\u1295"]
668
736
  },
@@ -683,6 +751,10 @@ var am = {
683
751
  extraHigh: ["\u12A5\u1305\u130D \u12A8\u134D\u1270\u129B"]
684
752
  },
685
753
  modeOpenerExtra: ["\u12EB\u12CB\u1245\u1229"],
754
+ experienceOptions: {
755
+ chat: ["\u12CD\u12ED\u12ED\u1275"],
756
+ work: ["\u1225\u122B"]
757
+ },
686
758
  tools: {
687
759
  web_search: ["\u12E8\u12F5\u122D \u134D\u1208\u130B"],
688
760
  deep_research: ["\u1325\u120D\u1245 \u121D\u122D\u121D\u122D"],
@@ -696,16 +768,19 @@ var am = {
696
768
  // src/dom/locale/ar.ts
697
769
  var ar = {
698
770
  configurationAxes: {
771
+ power: ["\u0627\u0644\u0642\u062F\u0631\u0629"],
699
772
  model: ["\u0627\u0644\u0646\u0645\u0648\u0630\u062C"],
700
773
  effort: ["\u0627\u0644\u062C\u0647\u062F"],
701
- speed: ["\u0627\u0644\u0633\u0631\u0639\u0629"]
774
+ speed: ["\u0627\u0644\u0633\u0631\u0639\u0629"],
775
+ advanced: ["\u0645\u062A\u0642\u062F\u0645"]
702
776
  },
703
777
  configurationOptions: {
778
+ instant: ["\u0641\u0648\u0631\u064A"],
704
779
  light: ["\u062E\u0641\u064A\u0641"],
705
780
  medium: ["\u0645\u062A\u0648\u0633\u0637"],
706
781
  high: ["\u0639\u0627\u0644\u064D"],
707
782
  extraHigh: ["\u0639\u0627\u0644\u064D \u062C\u062F\u064B\u0627"],
708
- standard: ["\u0642\u064A\u0627\u0633\u064A"],
783
+ standard: ["\u0642\u064A\u0627\u0633\u064A", "\u0642\u064A\u0627\u0633\u064A\u0629"],
709
784
  fast: ["\u0633\u0631\u064A\u0639"]
710
785
  },
711
786
  composerTextbox: ["\u0627\u0644\u062F\u0631\u062F\u0634\u0629 \u0645\u0639 ChatGPT"],
@@ -726,6 +801,10 @@ var ar = {
726
801
  pro: ["\u0627\u062D\u062A\u0631\u0627\u0641\u064A"]
727
802
  },
728
803
  modeOpenerExtra: ["\u062A\u0643\u0648\u064A\u0646"],
804
+ experienceOptions: {
805
+ chat: ["\u0627\u0644\u062F\u0631\u062F\u0634\u0629"],
806
+ work: ["\u0627\u0644\u0639\u0645\u0644"]
807
+ },
729
808
  tools: {
730
809
  web_search: ["\u0627\u0644\u0628\u062D\u062B \u0641\u064A \u0627\u0644\u0648\u064A\u0628"],
731
810
  deep_research: ["\u0627\u0644\u0628\u062D\u062B \u0627\u0644\u062A\u0641\u0635\u064A\u0644\u064A"],
@@ -739,15 +818,20 @@ var ar = {
739
818
  // src/dom/locale/bg.ts
740
819
  var bg = {
741
820
  configurationAxes: {
821
+ power: ["\u041C\u043E\u0449\u043D\u043E\u0441\u0442"],
742
822
  model: ["\u041C\u043E\u0434\u0435\u043B"],
743
823
  effort: ["\u0423\u0441\u0438\u043B\u0438\u0435"],
744
- speed: ["\u0421\u043A\u043E\u0440\u043E\u0441\u0442"]
824
+ speed: ["\u0421\u043A\u043E\u0440\u043E\u0441\u0442"],
825
+ advanced: ["\u0420\u0430\u0437\u0448\u0438\u0440\u0435\u043D\u0438"]
745
826
  },
746
827
  configurationOptions: {
828
+ instant: ["\u041C\u0438\u0433\u043D\u043E\u0432\u0435\u043D"],
747
829
  light: ["\u041A\u0440\u0430\u0442\u043A\u043E"],
748
830
  medium: ["\u0421\u0440\u0435\u0434\u043D\u043E"],
749
831
  high: ["\u0412\u0438\u0441\u043E\u043A\u043E"],
750
832
  extraHigh: ["\u041C\u043D\u043E\u0433\u043E \u0432\u0438\u0441\u043E\u043A\u043E"],
833
+ max: ["\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u043D\u043E"],
834
+ ultra: ["\u0423\u043B\u0442\u0440\u0430"],
751
835
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u043E"],
752
836
  fast: ["\u0411\u044A\u0440\u0437\u0430"]
753
837
  },
@@ -782,14 +866,18 @@ var bg = {
782
866
  // src/dom/locale/bs.ts
783
867
  var bs = {
784
868
  configurationAxes: {
869
+ power: ["Snaga"],
785
870
  effort: ["Napor"],
786
- speed: ["Brzina"]
871
+ speed: ["Brzina"],
872
+ advanced: ["Napredno"]
787
873
  },
788
874
  configurationOptions: {
875
+ instant: ["Brzo"],
789
876
  light: ["Lagano"],
790
877
  medium: ["Srednja"],
791
878
  high: ["Visoka"],
792
879
  extraHigh: ["Veoma visoka"],
880
+ max: ["Maks."],
793
881
  standard: ["Standardno"],
794
882
  fast: ["Brzo"]
795
883
  },
@@ -823,14 +911,18 @@ var bs = {
823
911
  // src/dom/locale/ca.ts
824
912
  var ca = {
825
913
  configurationAxes: {
914
+ power: ["Pot\xE8ncia"],
826
915
  effort: ["Esfor\xE7"],
827
- speed: ["Velocitat"]
916
+ speed: ["Velocitat"],
917
+ advanced: ["Avan\xE7ades"]
828
918
  },
829
919
  configurationOptions: {
920
+ instant: ["Instant\xE0nia"],
830
921
  light: ["Lleuger"],
831
922
  medium: ["Mitjana"],
832
923
  high: ["Alta"],
833
924
  extraHigh: ["Molt alta"],
925
+ max: ["M\xE0xim"],
834
926
  standard: ["Est\xE0ndard"],
835
927
  fast: ["R\xE0pid"]
836
928
  },
@@ -851,6 +943,9 @@ var ca = {
851
943
  extraHigh: ["Molt alt", "Molt alta"]
852
944
  },
853
945
  modeOpenerExtra: ["Configura\u2026"],
946
+ experienceOptions: {
947
+ chat: ["Conversa"]
948
+ },
854
949
  tools: {
855
950
  web_search: ["Cerca a la xarxa"],
856
951
  deep_research: ["Recerca profunda"],
@@ -864,14 +959,18 @@ var ca = {
864
959
  // src/dom/locale/cs.ts
865
960
  var cs = {
866
961
  configurationAxes: {
867
- effort: ["\xDAsil\xED"],
868
- speed: ["Rychlost"]
962
+ power: ["V\xFDkon"],
963
+ effort: ["\xDAsil\xED", "M\xEDra \xFAsil\xED"],
964
+ speed: ["Rychlost"],
965
+ advanced: ["Pokro\u010Dil\xE9"]
869
966
  },
870
967
  configurationOptions: {
968
+ instant: ["Okam\u017Eit\xE1"],
871
969
  light: ["N\xEDzk\xE1"],
872
970
  medium: ["St\u0159edn\xED"],
873
971
  high: ["Vysok\xE1"],
874
972
  extraHigh: ["Velmi vysok\xE1"],
973
+ max: ["Maxim\xE1ln\xED"],
875
974
  standard: ["Standardn\xED"],
876
975
  fast: ["Rychl\xE9"]
877
976
  },
@@ -905,14 +1004,18 @@ var cs = {
905
1004
  // src/dom/locale/da.ts
906
1005
  var da = {
907
1006
  configurationAxes: {
908
- effort: ["Indsats"],
909
- speed: ["Hastighed"]
1007
+ power: ["Styrke"],
1008
+ effort: ["Indsats", "T\xE6nkeindsats"],
1009
+ speed: ["Hastighed"],
1010
+ advanced: ["Avanceret"]
910
1011
  },
911
1012
  configurationOptions: {
1013
+ instant: ["\xD8jeblikkeligt"],
912
1014
  light: ["Let"],
913
1015
  medium: ["Mellem"],
914
1016
  high: ["H\xF8j"],
915
1017
  extraHigh: ["Ekstra h\xF8j"],
1018
+ max: ["Maks."],
916
1019
  fast: ["Hurtig"]
917
1020
  },
918
1021
  composerTextbox: ["Chat med ChatGPT"],
@@ -945,15 +1048,19 @@ var da = {
945
1048
  // src/dom/locale/el.ts
946
1049
  var el = {
947
1050
  configurationAxes: {
1051
+ power: ["\u0399\u03C3\u03C7\u03CD\u03C2"],
948
1052
  model: ["\u039C\u03BF\u03BD\u03C4\u03AD\u03BB\u03BF"],
949
- effort: ["\u03A0\u03C1\u03BF\u03C3\u03C0\u03AC\u03B8\u03B5\u03B9\u03B1"],
950
- speed: ["\u03A4\u03B1\u03C7\u03CD\u03C4\u03B7\u03C4\u03B1"]
1053
+ effort: ["\u03A0\u03C1\u03BF\u03C3\u03C0\u03AC\u03B8\u03B5\u03B9\u03B1", "\u0395\u03C0\u03AF\u03C0\u03B5\u03B4\u03BF \u03C3\u03C5\u03BB\u03BB\u03BF\u03B3\u03B9\u03C3\u03BC\u03BF\u03CD"],
1054
+ speed: ["\u03A4\u03B1\u03C7\u03CD\u03C4\u03B7\u03C4\u03B1"],
1055
+ advanced: ["\u0393\u03B9\u03B1 \u03C0\u03C1\u03BF\u03C7\u03C9\u03C1\u03B7\u03BC\u03AD\u03BD\u03BF\u03C5\u03C2"]
951
1056
  },
952
1057
  configurationOptions: {
1058
+ instant: ["\u0386\u03BC\u03B5\u03C3\u03B7"],
953
1059
  light: ["\u0395\u03BB\u03B1\u03C6\u03C1\u03B9\u03AC"],
954
1060
  medium: ["\u039C\u03B5\u03C3\u03B1\u03AF\u03BF"],
955
1061
  high: ["\u03A5\u03C8\u03B7\u03BB\u03CC"],
956
1062
  extraHigh: ["\u03A0\u03BF\u03BB\u03CD \u03C5\u03C8\u03B7\u03BB\u03CC"],
1063
+ max: ["\u039C\u03AD\u03B3\u03B9\u03C3\u03C4\u03B7"],
957
1064
  standard: ["\u03A4\u03C5\u03C0\u03B9\u03BA\u03CC"],
958
1065
  fast: ["\u0393\u03C1\u03AE\u03B3\u03BF\u03C1\u03BF"]
959
1066
  },
@@ -987,15 +1094,19 @@ var el = {
987
1094
  // src/dom/locale/es-419.ts
988
1095
  var es419 = {
989
1096
  configurationAxes: {
1097
+ power: ["Potencia"],
990
1098
  model: ["Modelo"],
991
1099
  effort: ["Esfuerzo"],
992
- speed: ["Velocidad"]
1100
+ speed: ["Velocidad"],
1101
+ advanced: ["Avanzado"]
993
1102
  },
994
1103
  configurationOptions: {
1104
+ instant: ["Instant\xE1nea"],
995
1105
  light: ["M\xEDnimo"],
996
1106
  medium: ["Media"],
997
1107
  high: ["Alta"],
998
1108
  extraHigh: ["Muy alta"],
1109
+ max: ["M\xE1x."],
999
1110
  standard: ["Est\xE1ndar"],
1000
1111
  fast: ["R\xE1pido"]
1001
1112
  },
@@ -1029,11 +1140,14 @@ var es419 = {
1029
1140
  // src/dom/locale/et.ts
1030
1141
  var et = {
1031
1142
  configurationAxes: {
1143
+ power: ["V\xF5imsus"],
1032
1144
  model: ["Mudel"],
1033
- effort: ["Pingutus"],
1034
- speed: ["Kiirus"]
1145
+ effort: ["Pingutus", "P\xF5hjalikkus"],
1146
+ speed: ["Kiirus"],
1147
+ advanced: ["T\xE4psemad seaded"]
1035
1148
  },
1036
1149
  configurationOptions: {
1150
+ instant: ["Kohene"],
1037
1151
  light: ["Kerge"],
1038
1152
  medium: ["Keskmine"],
1039
1153
  high: ["K\xF5rge"],
@@ -1070,15 +1184,19 @@ var et = {
1070
1184
  // src/dom/locale/fa.ts
1071
1185
  var fa = {
1072
1186
  configurationAxes: {
1187
+ power: ["\u062A\u0648\u0627\u0646"],
1073
1188
  model: ["\u0645\u062F\u0644"],
1074
- effort: ["\u0633\u0637\u062D \u062A\u0644\u0627\u0634"],
1075
- speed: ["\u0633\u0631\u0639\u062A"]
1189
+ effort: ["\u0633\u0637\u062D \u062A\u0644\u0627\u0634", "\u0645\u06CC\u0632\u0627\u0646 \u0627\u0633\u062A\u062F\u0644\u0627\u0644"],
1190
+ speed: ["\u0633\u0631\u0639\u062A"],
1191
+ advanced: ["\u067E\u06CC\u0634\u0631\u0641\u062A\u0647"]
1076
1192
  },
1077
1193
  configurationOptions: {
1194
+ instant: ["\u0641\u0648\u0631\u06CC"],
1078
1195
  light: ["\u0633\u0628\u06A9"],
1079
1196
  medium: ["\u0645\u062A\u0648\u0633\u0637"],
1080
1197
  high: ["\u0628\u0627\u0644\u0627"],
1081
1198
  extraHigh: ["\u0628\u0633\u06CC\u0627\u0631 \u0628\u0627\u0644\u0627"],
1199
+ max: ["\u062D\u062F\u0627\u06A9\u062B\u0631"],
1082
1200
  fast: ["\u0633\u0631\u06CC\u0639"]
1083
1201
  },
1084
1202
  composerTextbox: ["\u06AF\u0641\u062A\u06AF\u0648 \u0628\u0627 ChatGPT"],
@@ -1099,6 +1217,10 @@ var fa = {
1099
1217
  pro: ["\u062D\u0631\u0641\u0647\u200C\u0627\u06CC"]
1100
1218
  },
1101
1219
  modeOpenerExtra: ["\u067E\u06CC\u06A9\u0631\u0628\u0646\u062F\u06CC..."],
1220
+ experienceOptions: {
1221
+ chat: ["\u0686\u062A"],
1222
+ work: ["\u06A9\u0627\u0631"]
1223
+ },
1102
1224
  tools: {
1103
1225
  web_search: ["\u062C\u0633\u062A\u062C\u0648\u06CC \u0648\u0628"],
1104
1226
  deep_research: ["\u067E\u0698\u0648\u0647\u0634 \u0639\u0645\u06CC\u0642"],
@@ -1112,15 +1234,19 @@ var fa = {
1112
1234
  // src/dom/locale/fi.ts
1113
1235
  var fi = {
1114
1236
  configurationAxes: {
1237
+ power: ["Teho"],
1115
1238
  model: ["Malli"],
1116
- effort: ["M\xE4\xE4r\xE4"],
1117
- speed: ["Nopeus"]
1239
+ effort: ["M\xE4\xE4r\xE4", "P\xE4\xE4ttelytaso"],
1240
+ speed: ["Nopeus"],
1241
+ advanced: ["Lis\xE4asetukset"]
1118
1242
  },
1119
1243
  configurationOptions: {
1244
+ instant: ["V\xE4lit\xF6n"],
1120
1245
  light: ["Kevyt"],
1121
1246
  medium: ["Keskitaso"],
1122
1247
  high: ["Korkea"],
1123
1248
  extraHigh: ["Eritt\xE4in korkea"],
1249
+ max: ["Maksimi"],
1124
1250
  standard: ["Perustaso"],
1125
1251
  fast: ["Nopea"]
1126
1252
  },
@@ -1154,10 +1280,13 @@ var fi = {
1154
1280
  // src/dom/locale/fr-CA.ts
1155
1281
  var frCA = {
1156
1282
  configurationAxes: {
1283
+ power: ["Puissance"],
1157
1284
  model: ["Mod\xE8le"],
1158
- speed: ["Vitesse"]
1285
+ speed: ["Vitesse"],
1286
+ advanced: ["Avanc\xE9"]
1159
1287
  },
1160
1288
  configurationOptions: {
1289
+ instant: ["Instantan\xE9"],
1161
1290
  light: ["L\xE9ger"],
1162
1291
  medium: ["Moyen"],
1163
1292
  high: ["\xC9lev\xE9"],
@@ -1194,15 +1323,20 @@ var frCA = {
1194
1323
  // src/dom/locale/gu.ts
1195
1324
  var gu = {
1196
1325
  configurationAxes: {
1326
+ power: ["\u0A95\u0ACD\u0AB7\u0AAE\u0AA4\u0ABE"],
1197
1327
  model: ["\u0AAE\u0ACB\u0AA1\u0AC7\u0AB2"],
1198
1328
  effort: ["\u0AAA\u0ACD\u0AB0\u0AAF\u0ABE\u0AB8"],
1199
- speed: ["\u0A9D\u0AA1\u0AAA"]
1329
+ speed: ["\u0A9D\u0AA1\u0AAA"],
1330
+ advanced: ["\u0A8F\u0AA1\u0AB5\u0ABE\u0AA8\u0ACD\u0AB8\u0ACD\u0AA1"]
1200
1331
  },
1201
1332
  configurationOptions: {
1333
+ instant: ["\u0AA4\u0AB0\u0AA4"],
1202
1334
  light: ["\u0AB2\u0ABE\u0A87\u0A9F"],
1203
1335
  medium: ["\u0AAE\u0AC0\u0AA1\u0ABF\u0AAF\u0AAE"],
1204
1336
  high: ["\u0AB9\u0ABE\u0A87"],
1205
1337
  extraHigh: ["\u0A8F\u0A95\u0ACD\u0AB8\u0ACD\u0A9F\u0ACD\u0AB0\u0ABE \u0AB9\u0ABE\u0A87"],
1338
+ max: ["\u0AAE\u0AB9\u0AA4\u0ACD\u0AA4\u0AAE"],
1339
+ ultra: ["\u0A85\u0AB2\u0ACD\u0A9F\u0ACD\u0AB0\u0ABE"],
1206
1340
  standard: ["\u0AB8\u0ACD\u0A9F\u0ABE\u0AA8\u0ACD\u0AA1\u0AB0\u0ACD\u0AA1"],
1207
1341
  fast: ["\u0A9D\u0AA1\u0AAA\u0AC0"]
1208
1342
  },
@@ -1223,6 +1357,10 @@ var gu = {
1223
1357
  extraHigh: ["\u0A85\u0AA4\u0ABF \u0A89\u0A9A\u0ACD\u0A9A", "\u0A8F\u0A95\u0ACD\u0AB8\u0ACD\u0A9F\u0ACD\u0AB0\u0ABE \u0AB9\u0ABE\u0A87"]
1224
1358
  },
1225
1359
  modeOpenerExtra: ["\u0A95\u0AA8\u0ACD\u0AAB\u0ABF\u0A97\u0AB0 \u0A95\u0AB0\u0ACB..."],
1360
+ experienceOptions: {
1361
+ chat: ["\u0A9A\u0AC5\u0A9F"],
1362
+ work: ["\u0A95\u0ABE\u0AAE"]
1363
+ },
1226
1364
  tools: {
1227
1365
  web_search: ["\u0AB5\u0AC7\u0AAC \u0AB6\u0ACB\u0AA7"],
1228
1366
  deep_research: ["\u0AA1\u0AC0\u0AAA \u0AB0\u0ABF\u0AB8\u0AB0\u0ACD\u0A9A"],
@@ -1236,15 +1374,20 @@ var gu = {
1236
1374
  // src/dom/locale/hi.ts
1237
1375
  var hi = {
1238
1376
  configurationAxes: {
1377
+ power: ["\u092A\u093E\u0935\u0930"],
1239
1378
  model: ["\u092E\u0949\u0921\u0932"],
1240
- effort: ["\u092A\u094D\u0930\u092F\u093E\u0938"],
1241
- speed: ["\u0917\u0924\u093F"]
1379
+ effort: ["\u092A\u094D\u0930\u092F\u093E\u0938", "\u0938\u094B\u091A\u0928\u0947 \u0915\u093E \u0938\u094D\u0924\u0930"],
1380
+ speed: ["\u0917\u0924\u093F"],
1381
+ advanced: ["\u090F\u0921\u0935\u093E\u0902\u0938\u094D\u0921"]
1242
1382
  },
1243
1383
  configurationOptions: {
1384
+ instant: ["\u0924\u0941\u0930\u0902\u0924"],
1244
1385
  light: ["\u0932\u093E\u0907\u091F"],
1245
1386
  medium: ["\u092E\u0927\u094D\u092F\u092E"],
1246
1387
  high: ["\u0909\u091A\u094D\u091A"],
1247
1388
  extraHigh: ["\u090F\u0915\u094D\u0938\u094D\u091F\u094D\u0930\u093E \u0939\u093E\u0908"],
1389
+ max: ["\u0905\u0927\u093F\u0915\u0924\u092E"],
1390
+ ultra: ["\u0905\u0932\u094D\u091F\u094D\u0930\u093E"],
1248
1391
  standard: ["\u0938\u094D\u091F\u0948\u0902\u0921\u0930\u094D\u0921"],
1249
1392
  fast: ["\u0924\u0947\u091C\u093C"]
1250
1393
  },
@@ -1265,6 +1408,10 @@ var hi = {
1265
1408
  extraHigh: ["\u092C\u0939\u0941\u0924 \u0909\u091A\u094D\u091A", "\u090F\u0915\u094D\u0938\u094D\u091F\u094D\u0930\u093E \u0939\u093E\u0908"]
1266
1409
  },
1267
1410
  modeOpenerExtra: ["\u0915\u0949\u0928\u094D\u092B\u093C\u093F\u0917\u0930 \u0915\u0930\u0947\u0902..."],
1411
+ experienceOptions: {
1412
+ chat: ["\u091A\u0948\u091F"],
1413
+ work: ["\u0935\u0930\u094D\u0915"]
1414
+ },
1268
1415
  tools: {
1269
1416
  web_search: ["\u0935\u0947\u092C \u0938\u0930\u094D\u091A"],
1270
1417
  deep_research: ["\u0921\u0940\u092A \u0930\u093F\u0938\u0930\u094D\u091A"],
@@ -1278,14 +1425,17 @@ var hi = {
1278
1425
  // src/dom/locale/hr.ts
1279
1426
  var hr = {
1280
1427
  configurationAxes: {
1428
+ power: ["Snaga"],
1281
1429
  effort: ["Razina napora"],
1282
- speed: ["Brzina"]
1430
+ speed: ["Brzina"],
1431
+ advanced: ["Napredno"]
1283
1432
  },
1284
1433
  configurationOptions: {
1285
1434
  light: ["Lagano"],
1286
1435
  medium: ["Srednja"],
1287
1436
  high: ["Visoka"],
1288
1437
  extraHigh: ["Vrlo visoka"],
1438
+ max: ["Maks."],
1289
1439
  standard: ["Standardno"],
1290
1440
  fast: ["Brzo"]
1291
1441
  },
@@ -1318,11 +1468,14 @@ var hr = {
1318
1468
  // src/dom/locale/hu.ts
1319
1469
  var hu = {
1320
1470
  configurationAxes: {
1471
+ power: ["Teljes\xEDtm\xE9ny"],
1321
1472
  model: ["Modell"],
1322
- effort: ["R\xE1ford\xEDt\xE1s"],
1323
- speed: ["Sebess\xE9g"]
1473
+ effort: ["R\xE1ford\xEDt\xE1s", "Er\u0151fesz\xEDt\xE9s"],
1474
+ speed: ["Sebess\xE9g"],
1475
+ advanced: ["Speci\xE1lis"]
1324
1476
  },
1325
1477
  configurationOptions: {
1478
+ instant: ["Azonnali"],
1326
1479
  light: ["Egyszer\u0171"],
1327
1480
  medium: ["K\xF6zepes"],
1328
1481
  high: ["Er\u0151s"],
@@ -1360,15 +1513,20 @@ var hu = {
1360
1513
  // src/dom/locale/hy.ts
1361
1514
  var hy = {
1362
1515
  configurationAxes: {
1516
+ power: ["\u0540\u0566\u0578\u0580\u0578\u0582\u0569\u0575\u0578\u0582\u0576"],
1363
1517
  model: ["\u0544\u0578\u0564\u0565\u056C"],
1364
- effort: ["\u054B\u0561\u0576\u0584"],
1365
- speed: ["\u0531\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576"]
1518
+ effort: ["\u054B\u0561\u0576\u0584", "\u0544\u057F\u0561\u056E\u0578\u0572\u0578\u0582\u0569\u0575\u0561\u0576 \u0574\u0561\u056F\u0561\u0580\u0564\u0561\u056F"],
1519
+ speed: ["\u0531\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576"],
1520
+ advanced: ["\u0538\u0576\u0564\u056C\u0561\u0575\u0576\u057E\u0561\u056E"]
1366
1521
  },
1367
1522
  configurationOptions: {
1523
+ instant: ["\u0531\u056F\u0576\u0569\u0561\u0580\u0569\u0561\u0575\u056B\u0576"],
1368
1524
  light: ["\u0539\u0565\u0569\u0587"],
1369
1525
  medium: ["\u0544\u056B\u057B\u056B\u0576"],
1370
1526
  high: ["\u0540\u0566\u0578\u0580"],
1371
1527
  extraHigh: ["\u0531\u057E\u0565\u056C\u056B \u0570\u0566\u0578\u0580"],
1528
+ max: ["\u0531\u057C\u0561\u057E\u0565\u056C\u0561\u0563\u0578\u0582\u0575\u0576"],
1529
+ ultra: ["\u0548\u0582\u056C\u057F\u0580\u0561"],
1372
1530
  standard: ["\u054D\u057F\u0561\u0576\u0564\u0561\u0580\u057F"],
1373
1531
  fast: ["\u0531\u0580\u0561\u0563"]
1374
1532
  },
@@ -1390,6 +1548,10 @@ var hy = {
1390
1548
  pro: ["\u054A\u0580\u0578"]
1391
1549
  },
1392
1550
  modeOpenerExtra: ["\u053F\u0561\u0566\u0574\u0561\u0571\u0587\u0565\u056C\u2024\u2024\u2024"],
1551
+ experienceOptions: {
1552
+ chat: ["\u0536\u0580\u0578\u0582\u0575\u0581"],
1553
+ work: ["\u0531\u0577\u056D\u0561\u057F\u0561\u0576\u0584"]
1554
+ },
1393
1555
  tools: {
1394
1556
  web_search: ["\u054E\u0565\u0562 \u0578\u0580\u0578\u0576\u0578\u0582\u0574"],
1395
1557
  deep_research: ["\u053D\u0578\u0580\u0568 \u0578\u0582\u057D\u0578\u0582\u0574\u0576\u0561\u057D\u056B\u0580\u0578\u0582\u0569\u0575\u0578\u0582\u0576"],
@@ -1403,14 +1565,18 @@ var hy = {
1403
1565
  // src/dom/locale/id.ts
1404
1566
  var id = {
1405
1567
  configurationAxes: {
1568
+ power: ["Daya"],
1406
1569
  effort: ["Upaya"],
1407
- speed: ["Kecepatan"]
1570
+ speed: ["Kecepatan"],
1571
+ advanced: ["Tingkat lanjut"]
1408
1572
  },
1409
1573
  configurationOptions: {
1574
+ instant: ["Instan"],
1410
1575
  light: ["Ringan"],
1411
1576
  medium: ["Sedang"],
1412
1577
  high: ["Tinggi"],
1413
1578
  extraHigh: ["Ekstra Tinggi"],
1579
+ max: ["Maks"],
1414
1580
  standard: ["Standar"],
1415
1581
  fast: ["Cepat"]
1416
1582
  },
@@ -1444,15 +1610,19 @@ var id = {
1444
1610
  // src/dom/locale/is.ts
1445
1611
  var is = {
1446
1612
  configurationAxes: {
1613
+ power: ["Afl"],
1447
1614
  model: ["L\xEDkan"],
1448
- effort: ["\xC1reynsla"],
1449
- speed: ["Hra\xF0i"]
1615
+ effort: ["\xC1reynsla", "Vinnsla"],
1616
+ speed: ["Hra\xF0i"],
1617
+ advanced: ["\xCDtarlegt"]
1450
1618
  },
1451
1619
  configurationOptions: {
1620
+ instant: ["Strax"],
1452
1621
  light: ["L\xE9tt"],
1453
1622
  medium: ["Mi\xF0lungs"],
1454
1623
  high: ["H\xE1tt"],
1455
1624
  extraHigh: ["Mj\xF6g h\xE1tt"],
1625
+ max: ["H\xE1mark"],
1456
1626
  fast: ["Hratt"]
1457
1627
  },
1458
1628
  composerTextbox: ["Spjalla\xF0u vi\xF0 ChatGPT"],
@@ -1472,6 +1642,10 @@ var is = {
1472
1642
  extraHigh: ["Mj\xF6g h\xE1tt"]
1473
1643
  },
1474
1644
  modeOpenerExtra: ["Stillir\u2026"],
1645
+ experienceOptions: {
1646
+ chat: ["Spjall"],
1647
+ work: ["Vinna"]
1648
+ },
1475
1649
  tools: {
1476
1650
  web_search: ["Vefleit"],
1477
1651
  deep_research: ["\xCDtarleg ranns\xF3kn"],
@@ -1485,15 +1659,20 @@ var is = {
1485
1659
  // src/dom/locale/ka.ts
1486
1660
  var ka = {
1487
1661
  configurationAxes: {
1662
+ power: ["\u10E1\u10D8\u10DB\u10EB\u10DA\u10D0\u10D5\u10E0\u10D4"],
1488
1663
  model: ["\u10DB\u10DD\u10D3\u10D4\u10DA\u10D8"],
1489
- effort: ["\u10EB\u10D0\u10DA\u10D8\u10E1\u10EE\u10DB\u10D4\u10D5\u10D0"],
1490
- speed: ["\u10E1\u10D8\u10E9\u10E5\u10D0\u10E0\u10D4"]
1664
+ effort: ["\u10EB\u10D0\u10DA\u10D8\u10E1\u10EE\u10DB\u10D4\u10D5\u10D0", "\u10DB\u10E1\u10EF\u10D4\u10DA\u10DD\u10D1\u10D8\u10E1 \u10D3\u10DD\u10DC\u10D4"],
1665
+ speed: ["\u10E1\u10D8\u10E9\u10E5\u10D0\u10E0\u10D4"],
1666
+ advanced: ["\u10D2\u10D0\u10E4\u10D0\u10E0\u10D7\u10DD\u10D4\u10D1\u10E3\u10DA\u10D8"]
1491
1667
  },
1492
1668
  configurationOptions: {
1669
+ instant: ["\u10DB\u10E7\u10D8\u10E1\u10D8\u10D4\u10E0\u10D8"],
1493
1670
  light: ["\u10DB\u10E1\u10E3\u10D1\u10E3\u10E5\u10D8"],
1494
1671
  medium: ["\u10E1\u10D0\u10E8\u10E3\u10D0\u10DA\u10DD"],
1495
1672
  high: ["\u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"],
1496
1673
  extraHigh: ["\u10EB\u10D0\u10DA\u10D8\u10D0\u10DC \u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"],
1674
+ max: ["\u10DB\u10D0\u10E5\u10E1."],
1675
+ ultra: ["\u10E3\u10DA\u10E2\u10E0\u10D0"],
1497
1676
  standard: ["\u10E1\u10E2\u10D0\u10DC\u10D3\u10D0\u10E0\u10E2\u10E3\u10DA\u10D8"],
1498
1677
  fast: ["\u10E1\u10EC\u10E0\u10D0\u10E4\u10D8"]
1499
1678
  },
@@ -1514,6 +1693,10 @@ var ka = {
1514
1693
  extraHigh: ["\u10EB\u10D0\u10DA\u10D8\u10D0\u10DC \u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"]
1515
1694
  },
1516
1695
  modeOpenerExtra: ["\u10D9\u10DD\u10DC\u10E4\u10D8\u10D2\u10E3\u10E0\u10D8\u10E0\u10D4\u10D1\u10D0\u2026"],
1696
+ experienceOptions: {
1697
+ chat: ["\u10E9\u10D0\u10E2\u10D8"],
1698
+ work: ["\u10DB\u10E3\u10E8\u10D0\u10DD\u10D1\u10D0"]
1699
+ },
1517
1700
  tools: {
1518
1701
  web_search: ["\u10D5\u10D4\u10D1\u10E8\u10D8 \u10EB\u10D8\u10D4\u10D1\u10D0"],
1519
1702
  deep_research: ["\u10E1\u10D8\u10E6\u10E0\u10DB\u10D8\u10E1\u10D4\u10E3\u10DA\u10D8 \u10D9\u10D5\u10DA\u10D4\u10D5\u10D0"],
@@ -1527,15 +1710,20 @@ var ka = {
1527
1710
  // src/dom/locale/kk.ts
1528
1711
  var kk = {
1529
1712
  configurationAxes: {
1713
+ power: ["\u049A\u0443\u0430\u0442"],
1530
1714
  model: ["\u041C\u043E\u0434\u0435\u043B\u044C"],
1531
- effort: ["\u041A\u04AF\u0448-\u0436\u0456\u0433\u0435\u0440"],
1532
- speed: ["\u0416\u044B\u043B\u0434\u0430\u043C\u0434\u044B\u049B"]
1715
+ effort: ["\u041A\u04AF\u0448-\u0436\u0456\u0433\u0435\u0440", "\u041E\u0439\u043B\u0430\u043D\u0443 \u0434\u0435\u04A3\u0433\u0435\u0439\u0456"],
1716
+ speed: ["\u0416\u044B\u043B\u0434\u0430\u043C\u0434\u044B\u049B"],
1717
+ advanced: ["\u041A\u0435\u04A3\u0435\u0439\u0442\u0456\u043B\u0433\u0435\u043D"]
1533
1718
  },
1534
1719
  configurationOptions: {
1720
+ instant: ["\u0416\u0435\u0434\u0435\u043B"],
1535
1721
  light: ["\u0416\u0435\u04A3\u0456\u043B"],
1536
1722
  medium: ["\u041E\u0440\u0442\u0430\u0448\u0430"],
1537
1723
  high: ["\u0416\u043E\u0493\u0430\u0440\u044B"],
1538
1724
  extraHigh: ["\u04E8\u0442\u0435 \u0436\u043E\u0493\u0430\u0440\u044B"],
1725
+ max: ["\u041C\u0430\u043A\u0441"],
1726
+ ultra: ["\u0423\u043B\u044C\u0442\u0440\u0430"],
1539
1727
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u0442\u044B"],
1540
1728
  fast: ["\u0416\u044B\u043B\u0434\u0430\u043C"]
1541
1729
  },
@@ -1556,6 +1744,10 @@ var kk = {
1556
1744
  extraHigh: ["\u0410\u0441\u0430 \u0436\u043E\u0493\u0430\u0440\u044B", "\u04E8\u0442\u0435 \u0436\u043E\u0493\u0430\u0440\u044B"]
1557
1745
  },
1558
1746
  modeOpenerExtra: ["\u041A\u043E\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F\u043B\u0430\u0443..."],
1747
+ experienceOptions: {
1748
+ chat: ["\u0427\u0430\u0442"],
1749
+ work: ["\u0416\u04B1\u043C\u044B\u0441"]
1750
+ },
1559
1751
  tools: {
1560
1752
  web_search: ["\u0406\u0437\u0434\u0435\u0443"],
1561
1753
  deep_research: ["\u0422\u0435\u0440\u0435\u04A3 \u0437\u0435\u0440\u0442\u0442\u0435\u0443"],
@@ -1569,15 +1761,20 @@ var kk = {
1569
1761
  // src/dom/locale/kn.ts
1570
1762
  var kn = {
1571
1763
  configurationAxes: {
1764
+ power: ["\u0CAA\u0CB5\u0CB0\u0CCD"],
1572
1765
  model: ["\u0CAE\u0CBE\u0CA1\u0CC6\u0CB2\u0CCD"],
1573
- effort: ["\u0C8E\u0CAB\u0CB0\u0CCD\u0C9F\u0CCD"],
1574
- speed: ["\u0CB5\u0CC7\u0C97"]
1766
+ effort: ["\u0C8E\u0CAB\u0CB0\u0CCD\u0C9F\u0CCD", "\u0CAA\u0CCD\u0CB0\u0CAF\u0CA4\u0CCD\u0CA8"],
1767
+ speed: ["\u0CB5\u0CC7\u0C97"],
1768
+ advanced: ["\u0CB8\u0CC1\u0CA7\u0CBE\u0CB0\u0CBF\u0CA4"]
1575
1769
  },
1576
1770
  configurationOptions: {
1771
+ instant: ["\u0CA4\u0C95\u0CCD\u0CB7\u0CA3"],
1577
1772
  light: ["\u0CB2\u0CC8\u0C9F\u0CCD"],
1578
1773
  medium: ["\u0CAE\u0CC0\u0CA1\u0CBF\u0CAF\u0C82"],
1579
1774
  high: ["\u0CB9\u0CC8"],
1580
1775
  extraHigh: ["\u0C8E\u0C95\u0CCD\u0CB8\u0CCD\u200C\u0C9F\u0CCD\u0CB0\u0CBE \u0CB9\u0CC8"],
1776
+ max: ["\u0C97\u0CB0\u0CBF\u0CB7\u0CCD\u0CA0"],
1777
+ ultra: ["\u0C85\u0CB2\u0CCD\u0C9F\u0CCD\u0CB0\u0CBE"],
1581
1778
  standard: ["\u0CB8\u0CCD\u0C9F\u0CCD\u0CAF\u0CBE\u0C82\u0CA1\u0CB0\u0CCD\u0CA1\u0CCD"],
1582
1779
  fast: ["\u0CA4\u0CCD\u0CB5\u0CB0\u0CBF\u0CA4"]
1583
1780
  },
@@ -1599,6 +1796,9 @@ var kn = {
1599
1796
  pro: ["\u0CAA\u0CCD\u0CB0\u0CCA"]
1600
1797
  },
1601
1798
  modeOpenerExtra: ["\u0C95\u0CBE\u0CA8\u0CCD\u0CAB\u0CBF\u0C97\u0CB0\u0CCD \u0CAE\u0CBE\u0CA1\u0CBF..."],
1799
+ experienceOptions: {
1800
+ chat: ["\u0C9A\u0CBE\u0C9F\u0CCD"]
1801
+ },
1602
1802
  tools: {
1603
1803
  web_search: ["\u0CB5\u0CC6\u0CAC\u0CCD \u0CB8\u0CB0\u0CCD\u0C9A\u0CCD"],
1604
1804
  deep_research: ["\u0CA1\u0CC0\u0CAA\u0CCD \u0CB0\u0CBF\u0CB8\u0CB0\u0CCD\u0C9A\u0CCD"],
@@ -1612,14 +1812,19 @@ var kn = {
1612
1812
  // src/dom/locale/ko.ts
1613
1813
  var ko = {
1614
1814
  configurationAxes: {
1815
+ power: ["\uC131\uB2A5"],
1615
1816
  model: ["\uBAA8\uB378"],
1616
- effort: ["\uCD94\uB860 \uC218\uC900"],
1617
- speed: ["\uC18D\uB3C4"]
1817
+ effort: ["\uCD94\uB860 \uC218\uC900", "\uCD94\uB860 \uAC15\uB3C4"],
1818
+ speed: ["\uC18D\uB3C4"],
1819
+ advanced: ["\uACE0\uAE09"]
1618
1820
  },
1619
1821
  configurationOptions: {
1822
+ instant: ["\uC989\uC2DC"],
1620
1823
  medium: ["\uC911\uAC04"],
1621
1824
  high: ["\uB192\uC74C"],
1622
1825
  extraHigh: ["\uB9E4\uC6B0 \uB192\uC74C"],
1826
+ max: ["\uCD5C\uB300"],
1827
+ ultra: ["\uC6B8\uD2B8\uB77C"],
1623
1828
  fast: ["\uBE60\uB984"]
1624
1829
  },
1625
1830
  composerTextbox: ["ChatGPT\uC640 \uCC44\uD305"],
@@ -1652,15 +1857,19 @@ var ko = {
1652
1857
  // src/dom/locale/lt.ts
1653
1858
  var lt = {
1654
1859
  configurationAxes: {
1860
+ power: ["Paj\u0117gumas"],
1655
1861
  model: ["Modelis"],
1656
- effort: ["Pastangos"],
1657
- speed: ["Greitis"]
1862
+ effort: ["Pastangos", "M\u0105stymo lygis"],
1863
+ speed: ["Greitis"],
1864
+ advanced: ["I\u0161pl\u0117stiniai"]
1658
1865
  },
1659
1866
  configurationOptions: {
1867
+ instant: ["Momentinis"],
1660
1868
  light: ["Lengvas"],
1661
1869
  medium: ["Vidutinis"],
1662
1870
  high: ["Auk\u0161tas"],
1663
1871
  extraHigh: ["Labai auk\u0161tas"],
1872
+ max: ["Maks."],
1664
1873
  standard: ["Standartinis"],
1665
1874
  fast: ["Greitas"]
1666
1875
  },
@@ -1695,15 +1904,20 @@ var lt = {
1695
1904
  // src/dom/locale/zh-Hans.ts
1696
1905
  var zhHans = {
1697
1906
  configurationAxes: {
1907
+ power: ["\u80FD\u529B"],
1698
1908
  model: ["\u6A21\u578B"],
1699
- effort: ["\u63A8\u7406\u5F3A\u5EA6"],
1700
- speed: ["\u901F\u5EA6"]
1909
+ effort: ["\u63A8\u7406\u5F3A\u5EA6", "\u601D\u8003\u5F3A\u5EA6"],
1910
+ speed: ["\u901F\u5EA6"],
1911
+ advanced: ["\u9AD8\u7EA7"]
1701
1912
  },
1702
1913
  configurationOptions: {
1914
+ instant: ["\u6781\u901F"],
1703
1915
  light: ["\u8F7B\u5EA6"],
1704
1916
  medium: ["\u4E2D"],
1705
1917
  high: ["\u9AD8"],
1706
1918
  extraHigh: ["\u6781\u9AD8"],
1919
+ max: ["\u6700\u9AD8"],
1920
+ ultra: ["\u8D85\u9AD8"],
1707
1921
  standard: ["\u6807\u51C6"],
1708
1922
  fast: ["\u5FEB\u901F"]
1709
1923
  },
@@ -1725,6 +1939,10 @@ var zhHans = {
1725
1939
  pro: ["\u4E13\u4E1A"]
1726
1940
  },
1727
1941
  modeOpenerExtra: ["\u914D\u7F6E\u2026"],
1942
+ experienceOptions: {
1943
+ chat: ["\u804A\u5929"],
1944
+ work: ["\u5DE5\u4F5C"]
1945
+ },
1728
1946
  tools: {
1729
1947
  web_search: ["\u7F51\u9875\u641C\u7D22"],
1730
1948
  deep_research: ["\u6DF1\u5EA6\u7814\u7A76"],
@@ -1740,13 +1958,17 @@ var ur = {
1740
1958
  configurationAxes: {
1741
1959
  model: ["\u0645\u0627\u0688\u0644"],
1742
1960
  effort: ["\u06A9\u0648\u0634\u0634"],
1743
- speed: ["\u0631\u0641\u062A\u0627\u0631"]
1961
+ speed: ["\u0631\u0641\u062A\u0627\u0631"],
1962
+ advanced: ["\u0627\u06CC\u0688\u0648\u0627\u0646\u0633\u0688"]
1744
1963
  },
1745
1964
  configurationOptions: {
1965
+ instant: ["\u0641\u0648\u0631\u06CC"],
1746
1966
  light: ["\u0644\u0627\u0626\u0679"],
1747
1967
  medium: ["\u0627\u0648\u0633\u0637"],
1748
1968
  high: ["\u06C1\u0627\u0626\u06CC"],
1749
1969
  extraHigh: ["\u0627\u06CC\u06A9\u0633\u0679\u0631\u0627 \u06C1\u0627\u0626\u06CC"],
1970
+ max: ["\u0632\u06CC\u0627\u062F\u06C1 \u0633\u06D2 \u0632\u06CC\u0627\u062F\u06C1"],
1971
+ ultra: ["\u0627\u0644\u0679\u0631\u0627"],
1750
1972
  standard: ["\u0627\u0633\u0679\u06CC\u0646\u0688\u0631\u0688"],
1751
1973
  fast: ["\u062A\u06CC\u0632"]
1752
1974
  },
@@ -1767,6 +1989,10 @@ var ur = {
1767
1989
  extraHigh: ["\u0627\u0646\u062A\u06C1\u0627\u0626\u06CC \u0627\u0639\u0644\u06CC\u0670", "\u0627\u06CC\u06A9\u0633\u0679\u0631\u0627 \u06C1\u0627\u0626\u06CC"]
1768
1990
  },
1769
1991
  modeOpenerExtra: ["\u06A9\u0646\u0641\u06CC\u06AF\u0631 \u06A9\u0631\u06CC\u06BA..."],
1992
+ experienceOptions: {
1993
+ chat: ["\u0686\u064E\u06CC\u0679"],
1994
+ work: ["\u06A9\u0627\u0645"]
1995
+ },
1770
1996
  tools: {
1771
1997
  web_search: ["\u0648\u06CC\u0628 \u067E\u0631 \u062A\u0644\u0627\u0634"],
1772
1998
  deep_research: ["\u0688\u06CC\u067E \u0631\u06CC\u0633\u0631\u0686"],
@@ -1780,15 +2006,20 @@ var ur = {
1780
2006
  // src/dom/locale/uk.ts
1781
2007
  var uk = {
1782
2008
  configurationAxes: {
2009
+ power: ["\u041F\u043E\u0442\u0443\u0436\u043D\u0456\u0441\u0442\u044C"],
1783
2010
  model: ["\u041C\u043E\u0434\u0435\u043B\u044C"],
1784
- effort: ["\u0417\u0443\u0441\u0438\u043B\u043B\u044F"],
1785
- speed: ["\u0428\u0432\u0438\u0434\u043A\u0456\u0441\u0442\u044C"]
2011
+ effort: ["\u0417\u0443\u0441\u0438\u043B\u043B\u044F", "\u041C\u0456\u0440\u043A\u0443\u0432\u0430\u043D\u043D\u044F"],
2012
+ speed: ["\u0428\u0432\u0438\u0434\u043A\u0456\u0441\u0442\u044C"],
2013
+ advanced: ["\u0414\u043E\u0434\u0430\u0442\u043A\u043E\u0432\u043E"]
1786
2014
  },
1787
2015
  configurationOptions: {
2016
+ instant: ["\u041C\u0438\u0442\u0442\u0454\u0432\u0438\u0439"],
1788
2017
  light: ["\u041D\u0438\u0437\u044C\u043A\u0438\u0439"],
1789
2018
  medium: ["\u0421\u0435\u0440\u0435\u0434\u043D\u0456\u0439"],
1790
2019
  high: ["\u0412\u0438\u0441\u043E\u043A\u0438\u0439"],
1791
2020
  extraHigh: ["\u041D\u0430\u0439\u0432\u0438\u0449\u0438\u0439"],
2021
+ max: ["\u041C\u0430\u043A\u0441."],
2022
+ ultra: ["\u0423\u043B\u044C\u0442\u0440\u0430"],
1792
2023
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u0438\u0439"],
1793
2024
  fast: ["\u0428\u0432\u0438\u0434\u043A\u0430"]
1794
2025
  },
@@ -1809,6 +2040,10 @@ var uk = {
1809
2040
  extraHigh: ["\u0414\u0443\u0436\u0435 \u0432\u0438\u0441\u043E\u043A\u0438\u0439", "\u041D\u0430\u0439\u0432\u0438\u0449\u0438\u0439"]
1810
2041
  },
1811
2042
  modeOpenerExtra: ["\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438\u2026"],
2043
+ experienceOptions: {
2044
+ chat: ["\u0427\u0430\u0442"],
2045
+ work: ["\u0420\u043E\u0431\u043E\u0442\u0430"]
2046
+ },
1812
2047
  tools: {
1813
2048
  web_search: ["\u041F\u043E\u0448\u0443\u043A \u0432 \u0406\u043D\u0442\u0435\u0440\u043D\u0435\u0442\u0456"],
1814
2049
  deep_research: ["\u0413\u043B\u0438\u0431\u043E\u043A\u043E \u0434\u043E\u0441\u043B\u0456\u0434\u0438\u0442\u0438"],
@@ -1822,15 +2057,19 @@ var uk = {
1822
2057
  // src/dom/locale/pt-BR.ts
1823
2058
  var ptBR = {
1824
2059
  configurationAxes: {
2060
+ power: ["Pot\xEAncia"],
1825
2061
  model: ["Modelo"],
1826
- effort: ["Esfor\xE7o"],
1827
- speed: ["Velocidade"]
2062
+ effort: ["Esfor\xE7o", "N\xEDvel de racioc\xEDnio"],
2063
+ speed: ["Velocidade"],
2064
+ advanced: ["Avan\xE7ado"]
1828
2065
  },
1829
2066
  configurationOptions: {
2067
+ instant: ["Instant\xE2neo"],
1830
2068
  light: ["Leve"],
1831
2069
  medium: ["M\xE9dio"],
1832
2070
  high: ["Alto"],
1833
2071
  extraHigh: ["Extra alto"],
2072
+ max: ["M\xE1ximo"],
1834
2073
  standard: ["Padr\xE3o"],
1835
2074
  fast: ["R\xE1pido"]
1836
2075
  },
@@ -1864,15 +2103,19 @@ var ptBR = {
1864
2103
  // src/dom/locale/pt-PT.ts
1865
2104
  var ptPT = {
1866
2105
  configurationAxes: {
2106
+ power: ["Capacidade"],
1867
2107
  model: ["Modelo"],
1868
2108
  effort: ["Esfor\xE7o"],
1869
- speed: ["Velocidade"]
2109
+ speed: ["Velocidade"],
2110
+ advanced: ["Avan\xE7ado"]
1870
2111
  },
1871
2112
  configurationOptions: {
2113
+ instant: ["Instant\xE2neo"],
1872
2114
  light: ["Leve"],
1873
2115
  medium: ["M\xE9dio"],
1874
2116
  high: ["Elevado"],
1875
2117
  extraHigh: ["Muito elevado"],
2118
+ max: ["M\xE1x."],
1876
2119
  standard: ["Padr\xE3o"],
1877
2120
  fast: ["R\xE1pido"]
1878
2121
  },
@@ -1906,14 +2149,18 @@ var ptPT = {
1906
2149
  // src/dom/locale/pl.ts
1907
2150
  var pl = {
1908
2151
  configurationAxes: {
1909
- effort: ["Nak\u0142ad pracy"],
1910
- speed: ["Szybko\u015B\u0107"]
2152
+ power: ["Moc"],
2153
+ effort: ["Nak\u0142ad pracy", "Wysi\u0142ek"],
2154
+ speed: ["Szybko\u015B\u0107"],
2155
+ advanced: ["Zaawansowane"]
1911
2156
  },
1912
2157
  configurationOptions: {
2158
+ instant: ["B\u0142yskawiczny"],
1913
2159
  light: ["Lekki"],
1914
2160
  medium: ["\u015Aredni"],
1915
2161
  high: ["Wysoki"],
1916
2162
  extraHigh: ["Bardzo wysoki"],
2163
+ max: ["Maks."],
1917
2164
  standard: ["Standardowy"],
1918
2165
  fast: ["Szybki"]
1919
2166
  },
@@ -1947,14 +2194,18 @@ var pl = {
1947
2194
  // src/dom/locale/sk.ts
1948
2195
  var sk = {
1949
2196
  configurationAxes: {
2197
+ power: ["V\xFDkon"],
1950
2198
  effort: ["\xDAsilie"],
1951
- speed: ["R\xFDchlos\u0165"]
2199
+ speed: ["R\xFDchlos\u0165"],
2200
+ advanced: ["Roz\u0161\xEDren\xE9"]
1952
2201
  },
1953
2202
  configurationOptions: {
2203
+ instant: ["Okam\u017Eit\xE1"],
1954
2204
  light: ["\u013Dahk\xE9"],
1955
2205
  medium: ["Stredn\xE1"],
1956
2206
  high: ["Vysok\xE1"],
1957
2207
  extraHigh: ["Ve\u013Emi vysok\xE1"],
2208
+ max: ["Maxim\xE1lne"],
1958
2209
  standard: ["\u0160tandardn\xE1"],
1959
2210
  fast: ["R\xFDchla"]
1960
2211
  },
@@ -1988,14 +2239,17 @@ var sk = {
1988
2239
  // src/dom/locale/ro.ts
1989
2240
  var ro = {
1990
2241
  configurationAxes: {
2242
+ power: ["Capacitate"],
1991
2243
  effort: ["Efort"],
1992
- speed: ["Vitez\u0103"]
2244
+ speed: ["Vitez\u0103"],
2245
+ advanced: ["Avansat"]
1993
2246
  },
1994
2247
  configurationOptions: {
1995
2248
  light: ["U\u0219or"],
1996
2249
  medium: ["Medie"],
1997
2250
  high: ["Ridicat\u0103"],
1998
2251
  extraHigh: ["Foarte ridicat\u0103"],
2252
+ max: ["Maxim"],
1999
2253
  fast: ["Rapid"]
2000
2254
  },
2001
2255
  composerTextbox: ["\xCEntreab\u0103 orice"],
@@ -2027,15 +2281,19 @@ var ro = {
2027
2281
  // src/dom/locale/nb.ts
2028
2282
  var nb = {
2029
2283
  configurationAxes: {
2284
+ power: ["Styrke"],
2030
2285
  model: ["Modell"],
2031
- effort: ["Innsats"],
2032
- speed: ["Hastighet"]
2286
+ effort: ["Innsats", "Resonneringsniv\xE5"],
2287
+ speed: ["Hastighet"],
2288
+ advanced: ["Avansert"]
2033
2289
  },
2034
2290
  configurationOptions: {
2291
+ instant: ["\xD8yeblikkelig"],
2035
2292
  light: ["Lett"],
2036
2293
  medium: ["Middels"],
2037
2294
  high: ["H\xF8y"],
2038
2295
  extraHigh: ["Ekstra h\xF8y"],
2296
+ max: ["Maks"],
2039
2297
  fast: ["Rask"]
2040
2298
  },
2041
2299
  composerTextbox: ["Sp\xF8r om hva som helst"],
@@ -2068,15 +2326,20 @@ var nb = {
2068
2326
  // src/dom/locale/ml.ts
2069
2327
  var ml = {
2070
2328
  configurationAxes: {
2329
+ power: ["\u0D2A\u0D35\u0D7C"],
2071
2330
  model: ["\u0D2E\u0D4B\u0D21\u0D7D"],
2072
2331
  effort: ["\u0D36\u0D4D\u0D30\u0D2E\u0D02"],
2073
- speed: ["\u0D35\u0D47\u0D17\u0D24"]
2332
+ speed: ["\u0D35\u0D47\u0D17\u0D24"],
2333
+ advanced: ["\u0D35\u0D3F\u0D2A\u0D41\u0D32\u0D2E\u0D3E\u0D2F\u0D24\u0D4D"]
2074
2334
  },
2075
2335
  configurationOptions: {
2336
+ instant: ["\u0D24\u0D7D\u0D15\u0D4D\u0D37\u0D23\u0D02"],
2076
2337
  light: ["\u0D32\u0D33\u0D3F\u0D24\u0D02"],
2077
2338
  medium: ["\u0D07\u0D1F\u0D24\u0D4D\u0D24\u0D30\u0D02"],
2078
2339
  high: ["\u0D09\u0D2F\u0D7C\u0D28\u0D4D\u0D28\u0D24\u0D4D"],
2079
2340
  extraHigh: ["\u0D05\u0D24\u0D4D\u0D2F\u0D27\u0D3F\u0D15\u0D02 \u0D09\u0D2F\u0D7C\u0D28\u0D4D\u0D28\u0D24\u0D4D"],
2341
+ max: ["\u0D2A\u0D30\u0D2E\u0D3E\u0D35\u0D27\u0D3F"],
2342
+ ultra: ["\u0D05\u0D7E\u0D1F\u0D4D\u0D30\u0D3E"],
2080
2343
  standard: ["\u0D05\u0D1F\u0D3F\u0D38\u0D4D\u0D25\u0D3E\u0D28\u0D02"],
2081
2344
  fast: ["\u0D35\u0D47\u0D17\u0D02"]
2082
2345
  },
@@ -2098,6 +2361,10 @@ var ml = {
2098
2361
  pro: ["\u0D2A\u0D4D\u0D30\u0D4B"]
2099
2362
  },
2100
2363
  modeOpenerExtra: ["\u0D15\u0D4B\u0D7A\u0D2B\u0D3F\u0D17\u0D7C \u0D1A\u0D46\u0D2F\u0D4D\u0D2F\u0D41\u0D15\u2026"],
2364
+ experienceOptions: {
2365
+ chat: ["\u0D1A\u0D3E\u0D31\u0D4D\u0D31\u0D4D"],
2366
+ work: ["\u0D1C\u0D4B\u0D32\u0D3F"]
2367
+ },
2101
2368
  tools: {
2102
2369
  web_search: ["\u0D35\u0D46\u0D2C\u0D4D \u0D24\u0D3F\u0D30\u0D2F\u0D7D"],
2103
2370
  deep_research: ["\u0D21\u0D40\u0D2A\u0D4D\u0D2A\u0D4D \u0D31\u0D3F\u0D38\u0D47\u0D7C\u0D1A\u0D4D\u0D1A\u0D4D"],
@@ -2112,14 +2379,17 @@ var ml = {
2112
2379
  var ru = {
2113
2380
  configurationAxes: {
2114
2381
  model: ["\u041C\u043E\u0434\u0435\u043B\u044C"],
2115
- effort: ["\u0423\u0440\u043E\u0432\u0435\u043D\u044C"],
2116
- speed: ["\u0421\u043A\u043E\u0440\u043E\u0441\u0442\u044C"]
2382
+ effort: ["\u0423\u0440\u043E\u0432\u0435\u043D\u044C", "\u0423\u0440\u043E\u0432\u0435\u043D\u044C \u043F\u0440\u043E\u0440\u0430\u0431\u043E\u0442\u043A\u0438"],
2383
+ speed: ["\u0421\u043A\u043E\u0440\u043E\u0441\u0442\u044C"],
2384
+ advanced: ["\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u043D\u044B\u0435"]
2117
2385
  },
2118
2386
  configurationOptions: {
2119
2387
  light: ["\u041D\u0438\u0437\u043A\u0438\u0439"],
2120
2388
  medium: ["\u0421\u0440\u0435\u0434\u043D\u0438\u0439"],
2121
2389
  high: ["\u0412\u044B\u0441\u043E\u043A\u0438\u0439"],
2122
2390
  extraHigh: ["\u041E\u0447\u0435\u043D\u044C \u0432\u044B\u0441\u043E\u043A\u0438\u0439"],
2391
+ max: ["\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u044B\u0439"],
2392
+ ultra: ["\u0423\u043B\u044C\u0442\u0440\u0430"],
2123
2393
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u044B\u0439"],
2124
2394
  fast: ["\u0411\u044B\u0441\u0442\u0440\u043E"]
2125
2395
  },
@@ -2139,6 +2409,10 @@ var ru = {
2139
2409
  extraHigh: ["\u041E\u0447\u0435\u043D\u044C \u0432\u044B\u0441\u043E\u043A\u0438\u0439"]
2140
2410
  },
2141
2411
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F..."],
2412
+ experienceOptions: {
2413
+ chat: ["\u0427\u0430\u0442"],
2414
+ work: ["\u0420\u0430\u0431\u043E\u0442\u0430"]
2415
+ },
2142
2416
  tools: {
2143
2417
  web_search: ["\u041F\u043E\u0438\u0441\u043A \u0432 \u0441\u0435\u0442\u0438"],
2144
2418
  deep_research: ["\u0413\u043B\u0443\u0431\u043E\u043A\u043E\u0435 \u0438\u0441\u0441\u043B\u0435\u0434\u043E\u0432\u0430\u043D\u0438\u0435"],
@@ -2152,15 +2426,20 @@ var ru = {
2152
2426
  // src/dom/locale/pa.ts
2153
2427
  var pa = {
2154
2428
  configurationAxes: {
2429
+ power: ["\u0A2A\u0A3E\u0A35\u0A30"],
2155
2430
  model: ["\u0A2E\u0A3E\u0A21\u0A32"],
2156
2431
  effort: ["\u0A15\u0A4B\u0A38\u0A3C\u0A3F\u0A38\u0A3C"],
2157
- speed: ["\u0A17\u0A24\u0A40"]
2432
+ speed: ["\u0A17\u0A24\u0A40"],
2433
+ advanced: ["\u0A09\u0A71\u0A28\u0A24"]
2158
2434
  },
2159
2435
  configurationOptions: {
2436
+ instant: ["\u0A24\u0A41\u0A30\u0A70\u0A24"],
2160
2437
  light: ["\u0A39\u0A32\u0A15\u0A3E"],
2161
2438
  medium: ["\u0A2E\u0A40\u0A21\u0A40\u0A05\u0A2E"],
2162
2439
  high: ["\u0A39\u0A3E\u0A08"],
2163
2440
  extraHigh: ["\u0A10\u0A15\u0A38\u0A1F\u0A4D\u0A30\u0A3E \u0A39\u0A3E\u0A08"],
2441
+ max: ["\u0A05\u0A27\u0A3F\u0A15\u0A24\u0A2E"],
2442
+ ultra: ["\u0A05\u0A32\u0A1F\u0A30\u0A3E"],
2164
2443
  standard: ["\u0A2E\u0A3F\u0A06\u0A30\u0A40"],
2165
2444
  fast: ["\u0A24\u0A47\u0A1C\u0A3C"]
2166
2445
  },
@@ -2182,6 +2461,10 @@ var pa = {
2182
2461
  pro: ["\u0A2A\u0A4D\u0A30\u0A4B"]
2183
2462
  },
2184
2463
  modeOpenerExtra: ["\u0A15\u0A4C\u0A28\u0A2B\u0A3F\u0A17\u0A30..."],
2464
+ experienceOptions: {
2465
+ chat: ["\u0A1A\u0A48\u0A1F"],
2466
+ work: ["\u0A35\u0A30\u0A15"]
2467
+ },
2185
2468
  tools: {
2186
2469
  web_search: ["\u0A35\u0A48\u0A71\u0A2C \u0A16\u0A4B\u0A1C"],
2187
2470
  deep_research: ["\u0A21\u0A42\u0A70\u0A18\u0A40 \u0A16\u0A4B\u0A1C"],
@@ -2195,15 +2478,20 @@ var pa = {
2195
2478
  // src/dom/locale/mr.ts
2196
2479
  var mr = {
2197
2480
  configurationAxes: {
2481
+ power: ["\u092A\u0949\u0935\u0930"],
2198
2482
  model: ["\u092E\u0949\u0921\u0947\u0932"],
2199
2483
  effort: ["\u092A\u094D\u0930\u092F\u0924\u094D\u0928"],
2200
- speed: ["\u0935\u0947\u0917"]
2484
+ speed: ["\u0935\u0947\u0917"],
2485
+ advanced: ["\u092A\u094D\u0930\u0917\u0924"]
2201
2486
  },
2202
2487
  configurationOptions: {
2488
+ instant: ["\u091D\u091F\u092A\u091F"],
2203
2489
  light: ["\u0939\u0932\u0915\u093E"],
2204
2490
  medium: ["\u092E\u0927\u094D\u092F\u092E"],
2205
2491
  high: ["\u0909\u091A\u094D\u091A"],
2206
2492
  extraHigh: ["\u0905\u0924\u094D\u092F\u0941\u091A\u094D\u091A"],
2493
+ max: ["\u0915\u092E\u093E\u0932"],
2494
+ ultra: ["\u0905\u0932\u094D\u091F\u094D\u0930\u093E"],
2207
2495
  standard: ["\u0938\u094D\u091F\u0901\u0921\u0930\u094D\u0921"],
2208
2496
  fast: ["\u091C\u0932\u0926"]
2209
2497
  },
@@ -2225,6 +2513,10 @@ var mr = {
2225
2513
  pro: ["\u092A\u094D\u0930\u094B"]
2226
2514
  },
2227
2515
  modeOpenerExtra: ["\u0915\u0949\u0928\u094D\u092B\u093F\u0917\u0930 \u0915\u0930\u093E..."],
2516
+ experienceOptions: {
2517
+ chat: ["\u091A\u0945\u091F"],
2518
+ work: ["\u0915\u093E\u092E"]
2519
+ },
2228
2520
  tools: {
2229
2521
  web_search: ["\u0935\u0947\u092C\u0935\u0930 \u0936\u094B\u0927"],
2230
2522
  deep_research: ["\u0938\u0916\u094B\u0932 \u0938\u0902\u0936\u094B\u0927\u0928"],
@@ -2238,14 +2530,18 @@ var mr = {
2238
2530
  // src/dom/locale/tr.ts
2239
2531
  var tr = {
2240
2532
  configurationAxes: {
2241
- effort: ["D\xFCzey"],
2242
- speed: ["H\u0131z"]
2533
+ power: ["G\xFC\xE7"],
2534
+ effort: ["D\xFCzey", "\xC7aba"],
2535
+ speed: ["H\u0131z"],
2536
+ advanced: ["Geli\u015Fmi\u015F"]
2243
2537
  },
2244
2538
  configurationOptions: {
2539
+ instant: ["H\u0131zl\u0131"],
2245
2540
  light: ["S\u0131n\u0131rl\u0131"],
2246
2541
  medium: ["Orta"],
2247
2542
  high: ["Y\xFCksek"],
2248
2543
  extraHigh: ["\xC7ok Y\xFCksek"],
2544
+ max: ["Maks"],
2249
2545
  standard: ["Standart"],
2250
2546
  fast: ["H\u0131zl\u0131"]
2251
2547
  },
@@ -2266,6 +2562,10 @@ var tr = {
2266
2562
  extraHigh: ["\xC7ok Y\xFCksek"]
2267
2563
  },
2268
2564
  modeOpenerExtra: ["Yap\u0131land\u0131r..."],
2565
+ experienceOptions: {
2566
+ chat: ["Sohbet"],
2567
+ work: ["\xC7al\u0131\u015Fma"]
2568
+ },
2269
2569
  tools: {
2270
2570
  web_search: ["Web aramas\u0131"],
2271
2571
  deep_research: ["Derin ara\u015Ft\u0131rma"],
@@ -2279,15 +2579,19 @@ var tr = {
2279
2579
  // src/dom/locale/sw.ts
2280
2580
  var sw = {
2281
2581
  configurationAxes: {
2282
- model: ["Modeli"],
2283
- effort: ["Juhudi"],
2284
- speed: ["Kasi"]
2582
+ power: ["Umahiri"],
2583
+ model: ["Modeli", "Mfumo"],
2584
+ effort: ["Juhudi", "Kiwango cha uchambuzi"],
2585
+ speed: ["Kasi"],
2586
+ advanced: ["Za kina"]
2285
2587
  },
2286
2588
  configurationOptions: {
2589
+ instant: ["Papo hapo"],
2287
2590
  light: ["Nyepesi"],
2288
2591
  medium: ["Wastani"],
2289
2592
  high: ["Juu"],
2290
2593
  extraHigh: ["Juu Zaidi"],
2594
+ max: ["Juu kabisa"],
2291
2595
  standard: ["Kawaida"],
2292
2596
  fast: ["Haraka"]
2293
2597
  },
@@ -2321,15 +2625,20 @@ var sw = {
2321
2625
  // src/dom/locale/te.ts
2322
2626
  var te = {
2323
2627
  configurationAxes: {
2628
+ power: ["\u0C2A\u0C35\u0C30\u0C4D"],
2324
2629
  model: ["\u0C2E\u0C4B\u0C21\u0C32\u0C4D"],
2325
- effort: ["\u0C2A\u0C4D\u0C30\u0C2F\u0C24\u0C4D\u0C28\u0C02"],
2326
- speed: ["\u0C35\u0C47\u0C17\u0C02"]
2630
+ effort: ["\u0C2A\u0C4D\u0C30\u0C2F\u0C24\u0C4D\u0C28\u0C02", "\u0C06\u0C32\u0C4B\u0C1A\u0C28"],
2631
+ speed: ["\u0C35\u0C47\u0C17\u0C02"],
2632
+ advanced: ["\u0C05\u0C27\u0C41\u0C28\u0C3E\u0C24\u0C28\u0C02"]
2327
2633
  },
2328
2634
  configurationOptions: {
2635
+ instant: ["\u0C24\u0C15\u0C4D\u0C37\u0C23\u0C02"],
2329
2636
  light: ["\u0C32\u0C48\u0C1F\u0C4D"],
2330
2637
  medium: ["\u0C2E\u0C40\u0C21\u0C3F\u0C2F\u0C02"],
2331
2638
  high: ["\u0C39\u0C48"],
2332
2639
  extraHigh: ["\u0C0E\u0C15\u0C4D\u0C38\u0C4D\u200C\u0C1F\u0C4D\u0C30\u0C3E \u0C39\u0C48"],
2640
+ max: ["\u0C17\u0C30\u0C3F\u0C37\u0C4D\u0C20\u0C02"],
2641
+ ultra: ["\u0C05\u0C32\u0C4D\u0C1F\u0C4D\u0C30\u0C3E"],
2333
2642
  standard: ["\u0C38\u0C4D\u0C1F\u0C3E\u0C02\u0C21\u0C30\u0C4D\u0C21\u0C4D"],
2334
2643
  fast: ["\u0C35\u0C47\u0C17\u0C35\u0C02\u0C24\u0C02"]
2335
2644
  },
@@ -2351,6 +2660,10 @@ var te = {
2351
2660
  pro: ["\u0C2A\u0C4D\u0C30\u0C4B"]
2352
2661
  },
2353
2662
  modeOpenerExtra: ["\u0C15\u0C3E\u0C28\u0C4D\u0C2B\u0C3F\u0C17\u0C30\u0C4D \u0C1A\u0C47\u0C2F\u0C02\u0C21\u0C3F"],
2663
+ experienceOptions: {
2664
+ chat: ["\u0C1A\u0C3E\u0C1F\u0C4D"],
2665
+ work: ["\u0C35\u0C30\u0C4D\u0C15\u0C4D"]
2666
+ },
2354
2667
  tools: {
2355
2668
  web_search: ["\u0C35\u0C46\u0C2C\u0C4D\u200C\u0C32\u0C4B \u0C35\u0C46\u0C24\u0C15\u0C21\u0C02"],
2356
2669
  deep_research: ["\u0C38\u0C02\u0C2A\u0C42\u0C30\u0C4D\u0C23 \u0C2A\u0C30\u0C3F\u0C36\u0C4B\u0C27\u0C28"],
@@ -2364,7 +2677,7 @@ var te = {
2364
2677
  // src/dom/locale/tl.ts
2365
2678
  var tl = {
2366
2679
  configurationAxes: {
2367
- effort: ["Pagsisikap"],
2680
+ effort: ["Pagsisikap", "Pag-iisip"],
2368
2681
  speed: ["Bilis"]
2369
2682
  },
2370
2683
  configurationOptions: {
@@ -2392,9 +2705,14 @@ var tl = {
2392
2705
  // src/dom/locale/th.ts
2393
2706
  var th = {
2394
2707
  configurationAxes: {
2708
+ power: ["\u0E23\u0E30\u0E14\u0E31\u0E1A\u0E04\u0E27\u0E32\u0E21\u0E2A\u0E32\u0E21\u0E32\u0E23\u0E16"],
2395
2709
  model: ["\u0E42\u0E21\u0E40\u0E14\u0E25"],
2396
2710
  effort: ["\u0E23\u0E30\u0E14\u0E31\u0E1A\u0E01\u0E32\u0E23\u0E04\u0E34\u0E14"],
2397
- speed: ["\u0E04\u0E27\u0E32\u0E21\u0E40\u0E23\u0E47\u0E27"]
2711
+ speed: ["\u0E04\u0E27\u0E32\u0E21\u0E40\u0E23\u0E47\u0E27"],
2712
+ advanced: ["\u0E02\u0E31\u0E49\u0E19\u0E2A\u0E39\u0E07"]
2713
+ },
2714
+ configurationOptions: {
2715
+ instant: ["\u0E17\u0E31\u0E19\u0E17\u0E35"]
2398
2716
  },
2399
2717
  composerTextbox: ["\u0E16\u0E32\u0E21\u0E2D\u0E30\u0E44\u0E23\u0E01\u0E47\u0E44\u0E14\u0E49"],
2400
2718
  sendButton: ["\u0E2A\u0E48\u0E07\u0E04\u0E33\u0E2A\u0E31\u0E48\u0E07"],
@@ -2426,15 +2744,20 @@ var th = {
2426
2744
  // src/dom/locale/bn.ts
2427
2745
  var bn = {
2428
2746
  configurationAxes: {
2747
+ power: ["\u0995\u09CD\u09B7\u09AE\u09A4\u09BE"],
2429
2748
  model: ["\u09AE\u09A1\u09C7\u09B2"],
2430
2749
  effort: ["\u09AA\u09CD\u09B0\u099A\u09C7\u09B7\u09CD\u099F\u09BE"],
2431
- speed: ["\u0997\u09A4\u09BF"]
2750
+ speed: ["\u0997\u09A4\u09BF"],
2751
+ advanced: ["\u0989\u09A8\u09CD\u09A8\u09A4"]
2432
2752
  },
2433
2753
  configurationOptions: {
2754
+ instant: ["\u09A4\u09BE\u09CE\u0995\u09CD\u09B7\u09A3\u09BF\u0995"],
2434
2755
  light: ["\u09B2\u09BE\u0987\u099F"],
2435
2756
  medium: ["\u09AE\u09BE\u099D\u09BE\u09B0\u09BF"],
2436
2757
  high: ["\u0989\u099A\u09CD\u099A"],
2437
2758
  extraHigh: ["\u0985\u09A4\u09BF \u0989\u099A\u09CD\u099A"],
2759
+ max: ["\u09B8\u09B0\u09CD\u09AC\u09CB\u099A\u09CD\u099A"],
2760
+ ultra: ["\u0986\u09B2\u09CD\u099F\u09CD\u09B0\u09BE"],
2438
2761
  standard: ["\u09B8\u09CD\u099F\u09CD\u09AF\u09BE\u09A8\u09CD\u09A1\u09BE\u09B0\u09CD\u09A1"],
2439
2762
  fast: ["\u09A6\u09CD\u09B0\u09C1\u09A4"]
2440
2763
  },
@@ -2456,6 +2779,10 @@ var bn = {
2456
2779
  pro: ["\u09AA\u09CD\u09B0\u09CB"]
2457
2780
  },
2458
2781
  modeOpenerExtra: ["\u0995\u09A8\u09AB\u09BF\u0997\u09BE\u09B0 \u0995\u09B0\u09C1\u09A8..."],
2782
+ experienceOptions: {
2783
+ chat: ["\u099A\u09CD\u09AF\u09BE\u099F"],
2784
+ work: ["\u0993\u09AF\u09BC\u09BE\u09B0\u09CD\u0995"]
2785
+ },
2459
2786
  tools: {
2460
2787
  web_search: ["\u0993\u09AF\u09BC\u09C7\u09AC \u09B8\u09A8\u09CD\u09A7\u09BE\u09A8"],
2461
2788
  deep_research: ["\u0997\u09AD\u09C0\u09B0 \u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8"],
@@ -2469,14 +2796,18 @@ var bn = {
2469
2796
  // src/dom/locale/ms.ts
2470
2797
  var ms = {
2471
2798
  configurationAxes: {
2799
+ power: ["Kuasa"],
2472
2800
  effort: ["Usaha"],
2473
- speed: ["Kelajuan"]
2801
+ speed: ["Kelajuan"],
2802
+ advanced: ["Lanjutan"]
2474
2803
  },
2475
2804
  configurationOptions: {
2805
+ instant: ["Segera"],
2476
2806
  light: ["Ringan"],
2477
2807
  medium: ["Sederhana"],
2478
2808
  high: ["Tinggi"],
2479
2809
  extraHigh: ["Sangat Tinggi"],
2810
+ max: ["Sangat Tinggi"],
2480
2811
  fast: ["Pantas"]
2481
2812
  },
2482
2813
  composerTextbox: ["Tanya apa-apa sahaja..."],
@@ -2496,6 +2827,10 @@ var ms = {
2496
2827
  extraHigh: ["Sangat Tinggi"]
2497
2828
  },
2498
2829
  modeOpenerExtra: ["Konfigurasikan\u2026"],
2830
+ experienceOptions: {
2831
+ chat: ["Sembang"],
2832
+ work: ["Kerja"]
2833
+ },
2499
2834
  tools: {
2500
2835
  web_search: ["Carian web"],
2501
2836
  deep_research: ["Kajian mendalam"],
@@ -2509,15 +2844,19 @@ var ms = {
2509
2844
  // src/dom/locale/so.ts
2510
2845
  var so = {
2511
2846
  configurationAxes: {
2847
+ power: ["Awood"],
2512
2848
  model: ["Moodel"],
2513
2849
  effort: ["Dadaal"],
2514
- speed: ["Xawaare"]
2850
+ speed: ["Xawaare"],
2851
+ advanced: ["Horumarsan"]
2515
2852
  },
2516
2853
  configurationOptions: {
2854
+ instant: ["Degdeg"],
2517
2855
  light: ["Fudud"],
2518
2856
  medium: ["Dhexdhexaad"],
2519
2857
  high: ["Sare"],
2520
2858
  extraHigh: ["Aad U Sarreeya"],
2859
+ max: ["Ugu badan"],
2521
2860
  standard: ["Caadi"],
2522
2861
  fast: ["Degdeg"]
2523
2862
  },
@@ -2538,6 +2877,10 @@ var so = {
2538
2877
  extraHigh: ["Aad u sarreeya", "Aad U Sarreeya"]
2539
2878
  },
2540
2879
  modeOpenerExtra: ["Ku xidh..."],
2880
+ experienceOptions: {
2881
+ chat: ["Sheekaysi"],
2882
+ work: ["Shaqo"]
2883
+ },
2541
2884
  tools: {
2542
2885
  web_search: ["Raadi shakabada"],
2543
2886
  deep_research: ["Cilmi baadhid qoto dheer"],
@@ -2551,10 +2894,13 @@ var so = {
2551
2894
  // src/dom/locale/nl.ts
2552
2895
  var nl = {
2553
2896
  configurationAxes: {
2897
+ power: ["Rekenkracht"],
2554
2898
  effort: ["Inspanning"],
2555
- speed: ["Snelheid"]
2899
+ speed: ["Snelheid"],
2900
+ advanced: ["Geavanceerd"]
2556
2901
  },
2557
2902
  configurationOptions: {
2903
+ instant: ["Direct"],
2558
2904
  light: ["Licht"],
2559
2905
  medium: ["Gemiddeld"],
2560
2906
  high: ["Hoog"],
@@ -2585,18 +2931,20 @@ var nl = {
2585
2931
  create_image: ["Maak een afbeelding"]
2586
2932
  },
2587
2933
  signedInMarkers: ["Nieuwe chat", "Chats doorzoeken", "Recente items", "Chatgeschiedenis", "Projecten", "Stel een vraag"],
2588
- responseActions: ["Reactie kopi\xEBren"],
2589
- stopControl: ["Prompt versturen"]
2934
+ responseActions: ["Reactie kopi\xEBren"]
2590
2935
  };
2591
2936
 
2592
2937
  // src/dom/locale/sv.ts
2593
2938
  var sv = {
2594
2939
  configurationAxes: {
2940
+ power: ["Prestanda"],
2595
2941
  model: ["Modell"],
2596
2942
  effort: ["Resonemangsniv\xE5"],
2597
- speed: ["Hastighet"]
2943
+ speed: ["Hastighet"],
2944
+ advanced: ["Avancerat"]
2598
2945
  },
2599
2946
  configurationOptions: {
2947
+ instant: ["Direkt"],
2600
2948
  light: ["L\xE5g"],
2601
2949
  medium: ["Balanserad"],
2602
2950
  high: ["H\xF6g"],
@@ -2633,15 +2981,19 @@ var sv = {
2633
2981
  // src/dom/locale/lv.ts
2634
2982
  var lv = {
2635
2983
  configurationAxes: {
2984
+ power: ["Jauda"],
2636
2985
  model: ["Modelis"],
2637
2986
  effort: ["P\u016Bles"],
2638
- speed: ["\u0100trums"]
2987
+ speed: ["\u0100trums"],
2988
+ advanced: ["Papildu"]
2639
2989
  },
2640
2990
  configurationOptions: {
2991
+ instant: ["T\u016Bl\u012Bt\u0113js"],
2641
2992
  light: ["Viegls"],
2642
2993
  medium: ["Vid\u0113js"],
2643
2994
  high: ["Augsts"],
2644
2995
  extraHigh: ["\u013Boti augsts"],
2996
+ max: ["Maks."],
2645
2997
  standard: ["Standarta"],
2646
2998
  fast: ["\u0100trs"]
2647
2999
  },
@@ -2675,15 +3027,19 @@ var lv = {
2675
3027
  // src/dom/locale/mk.ts
2676
3028
  var mk = {
2677
3029
  configurationAxes: {
3030
+ power: ["\u041C\u043E\u045C\u043D\u043E\u0441\u0442"],
2678
3031
  model: ["\u041C\u043E\u0434\u0435\u043B"],
2679
3032
  effort: ["\u041D\u0430\u043F\u043E\u0440"],
2680
- speed: ["\u0411\u0440\u0437\u0438\u043D\u0430"]
3033
+ speed: ["\u0411\u0440\u0437\u0438\u043D\u0430"],
3034
+ advanced: ["\u041D\u0430\u043F\u0440\u0435\u0434\u043D\u043E"]
2681
3035
  },
2682
3036
  configurationOptions: {
2683
3037
  light: ["\u041B\u0435\u0441\u043D\u043E"],
2684
3038
  medium: ["\u0421\u0440\u0435\u0434\u043D\u0430"],
2685
3039
  high: ["\u0412\u0438\u0441\u043E\u043A\u0430"],
2686
- extraHigh: ["\u0415\u043A\u0441\u0442\u0440\u0430 \u0432\u0438\u0441\u043E\u043A\u0430"],
3040
+ extraHigh: ["\u0415\u043A\u0441\u0442\u0440\u0430 \u0432\u0438\u0441\u043E\u043A\u0430", "\u041C\u043D\u043E\u0433\u0443 \u0432\u0438\u0441\u043E\u043A\u0430"],
3041
+ max: ["\u041C\u0430\u043A\u0441"],
3042
+ ultra: ["\u0423\u043B\u0442\u0440\u0430"],
2687
3043
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0434\u0435\u043D"],
2688
3044
  fast: ["\u0411\u0440\u0437\u043E"]
2689
3045
  },
@@ -2703,6 +3059,10 @@ var mk = {
2703
3059
  extraHigh: ["\u041C\u043D\u043E\u0433\u0443 \u0432\u0438\u0441\u043E\u043A\u043E", "\u041C\u043D\u043E\u0433\u0443 \u0432\u0438\u0441\u043E\u043A\u0430"]
2704
3060
  },
2705
3061
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0458..."],
3062
+ experienceOptions: {
3063
+ chat: ["\u0420\u0430\u0437\u0433\u043E\u0432\u043E\u0440"],
3064
+ work: ["\u0420\u0430\u0431\u043E\u0442\u0430"]
3065
+ },
2706
3066
  tools: {
2707
3067
  web_search: ["\u041F\u0440\u0435\u0431\u0430\u0440\u0443\u0432\u0430\u045A\u0435 \u043D\u0430 \u0438\u043D\u0442\u0435\u0440\u043D\u0435\u0442"],
2708
3068
  deep_research: ["\u0414\u043B\u0430\u0431\u043E\u043A\u043E \u0438\u0441\u0442\u0440\u0430\u0436\u0443\u0432\u0430\u045A\u0435"],
@@ -2716,14 +3076,19 @@ var mk = {
2716
3076
  // src/dom/locale/sq.ts
2717
3077
  var sq = {
2718
3078
  configurationAxes: {
2719
- effort: ["P\xEBrpjekje"],
2720
- speed: ["Shpejt\xEBsi"]
3079
+ power: ["Fuqia"],
3080
+ model: ["Modeli"],
3081
+ effort: ["P\xEBrpjekje", "Arsyetim"],
3082
+ speed: ["Shpejt\xEBsi"],
3083
+ advanced: ["T\xEB avancuara"]
2721
3084
  },
2722
3085
  configurationOptions: {
2723
- light: ["I leht\xEB"],
3086
+ instant: ["I menj\xEBhersh\xEBm"],
3087
+ light: ["I leht\xEB", "E leht\xEB"],
2724
3088
  medium: ["Mesatare"],
2725
3089
  high: ["E lart\xEB"],
2726
3090
  extraHigh: ["Tep\xEBr e lart\xEB"],
3091
+ max: ["Maks."],
2727
3092
  fast: ["I shpejt\xEB"]
2728
3093
  },
2729
3094
  composerTextbox: ["Pyet p\xEBr \xE7do gj\xEB"],
@@ -2743,6 +3108,10 @@ var sq = {
2743
3108
  extraHigh: ["Shum\xEB i lart\xEB", "Tep\xEBr e lart\xEB"]
2744
3109
  },
2745
3110
  modeOpenerExtra: ["Konfiguro..."],
3111
+ experienceOptions: {
3112
+ chat: ["Bised\xEB"],
3113
+ work: ["Pun\xEB"]
3114
+ },
2746
3115
  tools: {
2747
3116
  web_search: ["K\xEBrkim n\xEB ueb"],
2748
3117
  deep_research: ["K\xEBrkim i thell\xEB"],
@@ -2756,14 +3125,18 @@ var sq = {
2756
3125
  // src/dom/locale/sl.ts
2757
3126
  var sl = {
2758
3127
  configurationAxes: {
3128
+ power: ["Mo\u010D"],
2759
3129
  effort: ["Napor"],
2760
- speed: ["Hitrost"]
3130
+ speed: ["Hitrost"],
3131
+ advanced: ["Napredno"]
2761
3132
  },
2762
3133
  configurationOptions: {
3134
+ instant: ["Takoj"],
2763
3135
  light: ["Osnovno"],
2764
3136
  medium: ["Srednje"],
2765
3137
  high: ["Visoko"],
2766
3138
  extraHigh: ["Zelo visoko"],
3139
+ max: ["Najve\u010D"],
2767
3140
  standard: ["Standardno"],
2768
3141
  fast: ["Hitro"]
2769
3142
  },
@@ -2784,6 +3157,10 @@ var sl = {
2784
3157
  extraHigh: ["Zelo visoko"]
2785
3158
  },
2786
3159
  modeOpenerExtra: ["Konfiguracija \u2026"],
3160
+ experienceOptions: {
3161
+ chat: ["Klepet"],
3162
+ work: ["Delo"]
3163
+ },
2787
3164
  tools: {
2788
3165
  web_search: ["Iskanje po spletu"],
2789
3166
  deep_research: ["Poglobljeno raziskovanje"],
@@ -2797,15 +3174,19 @@ var sl = {
2797
3174
  // src/dom/locale/sr.ts
2798
3175
  var sr = {
2799
3176
  configurationAxes: {
3177
+ power: ["\u0421\u043D\u0430\u0433\u0430"],
2800
3178
  model: ["\u041C\u043E\u0434\u0435\u043B"],
2801
- effort: ["\u041D\u0438\u0432\u043E"],
2802
- speed: ["\u0411\u0440\u0437\u0438\u043D\u0430"]
3179
+ effort: ["\u041D\u0438\u0432\u043E", "\u041D\u0430\u043F\u043E\u0440"],
3180
+ speed: ["\u0411\u0440\u0437\u0438\u043D\u0430"],
3181
+ advanced: ["\u041D\u0430\u043F\u0440\u0435\u0434\u043D\u043E"]
2803
3182
  },
2804
3183
  configurationOptions: {
2805
3184
  light: ["\u041B\u0430\u0433\u0430\u043D\u043E"],
2806
3185
  medium: ["\u0421\u0440\u0435\u0434\u045A\u0435"],
2807
3186
  high: ["\u0412\u0438\u0441\u043E\u043A\u043E"],
2808
3187
  extraHigh: ["\u0412\u0435\u043E\u043C\u0430 \u0432\u0438\u0441\u043E\u043A\u043E"],
3188
+ max: ["\u041C\u0430\u043A\u0441"],
3189
+ ultra: ["\u0423\u043B\u0442\u0440\u0430"],
2809
3190
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0434\u043D\u043E"],
2810
3191
  fast: ["\u0411\u0440\u0437\u043E"]
2811
3192
  },
@@ -2825,6 +3206,10 @@ var sr = {
2825
3206
  extraHigh: ["\u0412\u0435\u043E\u043C\u0430 \u0432\u0438\u0441\u043E\u043A\u043E"]
2826
3207
  },
2827
3208
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0448\u0438..."],
3209
+ experienceOptions: {
3210
+ chat: ["\u040B\u0430\u0441\u043A\u0430\u045A\u0435"],
3211
+ work: ["\u041F\u043E\u0441\u0430\u043E"]
3212
+ },
2828
3213
  tools: {
2829
3214
  web_search: ["\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u0432\u0435\u0431\u0430"],
2830
3215
  deep_research: ["\u0414\u0443\u0431\u0438\u043D\u0441\u043A\u043E \u0438\u0441\u0442\u0440\u0430\u0436\u0438\u0432\u0430\u045A\u0435"],
@@ -2838,15 +3223,20 @@ var sr = {
2838
3223
  // src/dom/locale/mn.ts
2839
3224
  var mn = {
2840
3225
  configurationAxes: {
3226
+ power: ["\u0427\u0430\u0434\u0430\u043B"],
2841
3227
  model: ["\u0417\u0430\u0433\u0432\u0430\u0440"],
2842
- effort: ["\u0425\u04AF\u0447\u0438\u043D \u0447\u0430\u0440\u043C\u0430\u0439\u043B\u0442"],
2843
- speed: ["\u0425\u0443\u0440\u0434"]
3228
+ effort: ["\u0425\u04AF\u0447\u0438\u043D \u0447\u0430\u0440\u043C\u0430\u0439\u043B\u0442", "\u0422\u043E\u043E\u0446\u043E\u043E\u043B\u043E\u043B"],
3229
+ speed: ["\u0425\u0443\u0440\u0434"],
3230
+ advanced: ["\u0414\u044D\u0432\u0448\u0438\u043B\u0442\u044D\u0442"]
2844
3231
  },
2845
3232
  configurationOptions: {
3233
+ instant: ["\u0428\u0443\u0443\u0440\u0445\u0430\u0439"],
2846
3234
  light: ["\u0425\u04E9\u043D\u0433\u04E9\u043D"],
2847
3235
  medium: ["\u0414\u0443\u043D\u0434"],
2848
- high: ["\u0418\u0445"],
2849
- extraHigh: ["\u041C\u0430\u0448 \u0438\u0445"],
3236
+ high: ["\u0418\u0445", "\u04E8\u043D\u0434\u04E9\u0440"],
3237
+ extraHigh: ["\u041C\u0430\u0448 \u0438\u0445", "\u041C\u0430\u0448 \u04E9\u043D\u0434\u04E9\u0440"],
3238
+ max: ["\u0425\u0430\u043C\u0433\u0438\u0439\u043D \u0438\u0445"],
3239
+ ultra: ["\u0423\u043B\u044C\u0442\u0440\u0430"],
2850
3240
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442"],
2851
3241
  fast: ["\u0425\u0443\u0440\u0434\u0430\u043D"]
2852
3242
  },
@@ -2868,6 +3258,10 @@ var mn = {
2868
3258
  pro: ["\u041F\u0440\u043E"]
2869
3259
  },
2870
3260
  modeOpenerExtra: ["\u0422\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0445..."],
3261
+ experienceOptions: {
3262
+ chat: ["\u0427\u0430\u0442"],
3263
+ work: ["\u0410\u0436\u0438\u043B"]
3264
+ },
2871
3265
  tools: {
2872
3266
  web_search: ["\u0412\u0435\u0431 \u0445\u0430\u0439\u043B\u0442"],
2873
3267
  deep_research: ["\u0413\u04AF\u043D \u0441\u0443\u0434\u0430\u043B\u0433\u0430\u0430"],
@@ -2881,15 +3275,20 @@ var mn = {
2881
3275
  // src/dom/locale/my.ts
2882
3276
  var my = {
2883
3277
  configurationAxes: {
3278
+ power: ["\u1005\u103D\u1019\u103A\u1038\u1021\u102C\u1038"],
2884
3279
  model: ["\u1019\u1031\u102C\u103A\u1012\u101A\u103A"],
2885
3280
  effort: ["\u1021\u102C\u1038\u1011\u102F\u1010\u103A\u1019\u103E\u102F"],
2886
- speed: ["\u1021\u1019\u103C\u1014\u103A\u1014\u103E\u102F\u1014\u103A\u1038"]
3281
+ speed: ["\u1021\u1019\u103C\u1014\u103A\u1014\u103E\u102F\u1014\u103A\u1038"],
3282
+ advanced: ["\u1021\u1006\u1004\u1037\u103A\u1019\u103C\u1004\u1037\u103A"]
2887
3283
  },
2888
3284
  configurationOptions: {
3285
+ instant: ["\u1001\u103B\u1000\u103A\u1001\u103B\u1004\u103A\u1038"],
2889
3286
  light: ["\u1015\u1031\u102B\u1037\u1015\u102B\u1038"],
2890
3287
  medium: ["\u1021\u101C\u101A\u103A\u1021\u101C\u1010\u103A"],
2891
3288
  high: ["\u1021\u1019\u103C\u1004\u1037\u103A"],
2892
3289
  extraHigh: ["\u1021\u101C\u103D\u1014\u103A\u1019\u103C\u1004\u1037\u103A"],
3290
+ max: ["\u1021\u1019\u103C\u1004\u1037\u103A\u1006\u102F\u1036\u1038"],
3291
+ ultra: ["\u1021\u101A\u103A\u101C\u103A\u1011\u101B\u102C"],
2893
3292
  standard: ["\u1015\u102F\u1036\u1019\u103E\u1014\u103A"],
2894
3293
  fast: ["\u1021\u1019\u103C\u1014\u103A"]
2895
3294
  },
@@ -2910,6 +3309,9 @@ var my = {
2910
3309
  extraHigh: ["\u1021\u101C\u103D\u1014\u103A\u1019\u103C\u1004\u1037\u103A"]
2911
3310
  },
2912
3311
  modeOpenerExtra: ["\u1015\u103C\u102F\u1015\u103C\u1004\u103A\u1019\u103D\u1019\u103A\u1038\u1019\u1036\u101B\u1014\u103A"],
3312
+ experienceOptions: {
3313
+ work: ["\u1021\u101C\u102F\u1015\u103A"]
3314
+ },
2913
3315
  tools: {
2914
3316
  web_search: ["\u101D\u1018\u103A\u101B\u103E\u102C\u1016\u103D\u1031\u101B\u1014\u103A"],
2915
3317
  deep_research: ["\u1014\u1000\u103A\u1014\u1032\u101E\u1031\u102C \u101E\u102F\u1010\u1031\u101E\u1014"],
@@ -2923,15 +3325,20 @@ var my = {
2923
3325
  // src/dom/locale/ta.ts
2924
3326
  var ta = {
2925
3327
  configurationAxes: {
2926
- model: ["\u0BAE\u0BBE\u0BA4\u0BBF\u0BB0\u0BBF"],
2927
- effort: ["\u0BAE\u0BC1\u0BAF\u0BB1\u0BCD\u0B9A\u0BBF"],
2928
- speed: ["\u0BB5\u0BC7\u0B95\u0BAE\u0BCD"]
3328
+ power: ["\u0BA4\u0BBF\u0BB1\u0BA9\u0BCD"],
3329
+ model: ["\u0BAE\u0BBE\u0BA4\u0BBF\u0BB0\u0BBF", "\u0BAE\u0BBE\u0B9F\u0BB2\u0BCD"],
3330
+ effort: ["\u0BAE\u0BC1\u0BAF\u0BB1\u0BCD\u0B9A\u0BBF", "\u0B9A\u0BBF\u0BA8\u0BCD\u0BA4\u0BA9\u0BC8 \u0B85\u0BB3\u0BB5\u0BC1"],
3331
+ speed: ["\u0BB5\u0BC7\u0B95\u0BAE\u0BCD"],
3332
+ advanced: ["\u0BAE\u0BC7\u0BAE\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F"]
2929
3333
  },
2930
3334
  configurationOptions: {
3335
+ instant: ["\u0B89\u0B9F\u0BA9\u0B9F\u0BBF"],
2931
3336
  light: ["\u0B95\u0BC1\u0BB1\u0BC8\u0BB5\u0BC1"],
2932
3337
  medium: ["\u0BAE\u0BBF\u0BA4\u0BAE\u0BBE\u0BA9"],
2933
3338
  high: ["\u0B85\u0BA4\u0BBF\u0B95\u0BAE\u0BBE\u0BA9"],
2934
3339
  extraHigh: ["\u0BAE\u0BBF\u0B95 \u0B85\u0BA4\u0BBF\u0B95\u0BAE\u0BBE\u0BA9"],
3340
+ max: ["\u0B85\u0BA4\u0BBF\u0B95\u0BAA\u0B9F\u0BCD\u0B9A\u0BAE\u0BCD"],
3341
+ ultra: ["\u0B85\u0BB2\u0BCD\u0B9F\u0BCD\u0BB0\u0BBE"],
2935
3342
  standard: ["\u0BB5\u0BB4\u0B95\u0BCD\u0B95\u0BAE\u0BBE\u0BA9"],
2936
3343
  fast: ["\u0BB5\u0BBF\u0BB0\u0BC8\u0BB5\u0BC1"]
2937
3344
  },
@@ -2953,6 +3360,10 @@ var ta = {
2953
3360
  pro: ["\u0BAA\u0BCD\u0BB0\u0BCB"]
2954
3361
  },
2955
3362
  modeOpenerExtra: ["\u0B95\u0B9F\u0BCD\u0B9F\u0BAE\u0BC8\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD..."],
3363
+ experienceOptions: {
3364
+ chat: ["\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8"],
3365
+ work: ["\u0BB5\u0BC7\u0BB2\u0BC8"]
3366
+ },
2956
3367
  tools: {
2957
3368
  web_search: ["\u0B87\u0BA3\u0BC8\u0BAF \u0BA4\u0BC7\u0B9F\u0BB2\u0BCD"],
2958
3369
  deep_research: ["\u0B86\u0BB4\u0BCD\u0BA8\u0BCD\u0BA4 \u0B86\u0BAF\u0BCD\u0BB5\u0BC1"],
@@ -2996,6 +3407,7 @@ var MODE_OPTION_IDS = [
2996
3407
  ];
2997
3408
  var EXPERIENCE_OPTION_IDS = ["chat", "work"];
2998
3409
  var CONFIGURATION_AXIS_IDS = [
3410
+ "power",
2999
3411
  "model",
3000
3412
  "intelligence",
3001
3413
  "effort",
@@ -3184,9 +3596,13 @@ async function readPageState(page) {
3184
3596
  const url = typeof rawUrl === "string" ? rawUrl : "";
3185
3597
  const rawTitle = typeof page.title === "function" ? await page.title().catch(() => void 0) : void 0;
3186
3598
  const title = typeof rawTitle === "string" ? rawTitle : void 0;
3187
- const visibleText = await readVisibleText(page);
3188
- const signedIn = isLikelySignedIn(visibleText);
3189
- const classifiedBlocker = classifyVisibleText(visibleText);
3599
+ const surface = await readPageSurfaceSnapshot(page);
3600
+ const visibleText = surface.visibleText;
3601
+ const blockerSurface = surface.blockerSurface;
3602
+ const fullPageBlocker = classifyVisibleText(visibleText);
3603
+ const classifiedBlocker = blockerSurface.hasConversationMessages ? classifyVisibleText(blockerSurface.text) : classifyVisibleText(blockerSurface.text) ?? fullPageBlocker;
3604
+ const loginWall = classifiedBlocker?.kind === "login_required" && isLikelyLoginWall(visibleText);
3605
+ const signedIn = isLikelySignedIn(visibleText) && !loginWall;
3190
3606
  const blocker = classifiedBlocker?.kind === "login_required" && signedIn ? void 0 : classifiedBlocker;
3191
3607
  const conversationId = parseConversationId(url);
3192
3608
  const state = {
@@ -3230,23 +3646,203 @@ async function readVisibleText(page) {
3230
3646
  }
3231
3647
  return "";
3232
3648
  }
3649
+ async function readPageSurfaceSnapshot(page) {
3650
+ if (typeof page.evaluate === "function") {
3651
+ try {
3652
+ const snapshot = await withTimeout(page.evaluate(() => {
3653
+ const messageSelector = "[data-message-author-role], [data-testid^='conversation-turn']";
3654
+ const systemSelector = [
3655
+ "[role='alert']",
3656
+ "[role='status']",
3657
+ "[role='dialog']",
3658
+ "[aria-live='assertive']",
3659
+ "[data-testid*='toast' i]",
3660
+ "[data-testid*='banner' i]",
3661
+ "[class*='toast' i]",
3662
+ "[class*='banner' i]"
3663
+ ].join(", ");
3664
+ const visible = (element) => {
3665
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
3666
+ const style = window.getComputedStyle(element);
3667
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none") return false;
3668
+ const rect = element.getBoundingClientRect();
3669
+ return rect.width > 0 || rect.height > 0;
3670
+ };
3671
+ const blockerText = Array.from(document.querySelectorAll(systemSelector)).filter((element) => visible(element)).filter((element) => element.closest(messageSelector) === null).map((element) => `${element.textContent ?? ""} ${element.getAttribute("aria-label") ?? ""}`).join(" ");
3672
+ return {
3673
+ visibleText: document.body?.innerText ?? "",
3674
+ blockerText,
3675
+ hasConversationMessages: Array.from(document.querySelectorAll(messageSelector)).some(visible)
3676
+ };
3677
+ }), 1e3, "Timed out while reading the visible ChatGPT page surface.");
3678
+ if (typeof snapshot === "string") {
3679
+ return {
3680
+ visibleText: snapshot,
3681
+ blockerSurface: { text: snapshot, hasConversationMessages: false }
3682
+ };
3683
+ }
3684
+ if (typeof snapshot === "object" && snapshot !== null && typeof snapshot.visibleText === "string" && typeof snapshot.blockerText === "string" && typeof snapshot.hasConversationMessages === "boolean") {
3685
+ const typed = snapshot;
3686
+ return {
3687
+ visibleText: typed.visibleText,
3688
+ blockerSurface: {
3689
+ text: typed.blockerText,
3690
+ hasConversationMessages: typed.hasConversationMessages
3691
+ }
3692
+ };
3693
+ }
3694
+ } catch {
3695
+ }
3696
+ }
3697
+ if (typeof page.content === "function") {
3698
+ try {
3699
+ const html = await withTimeout(page.content(), 1e3, "Timed out while reading the serialized ChatGPT page surface.");
3700
+ return serializedPageSurface(html);
3701
+ } catch {
3702
+ }
3703
+ }
3704
+ return {
3705
+ visibleText: "",
3706
+ blockerSurface: { text: "", hasConversationMessages: false }
3707
+ };
3708
+ }
3709
+ function serializedPageSurface(html) {
3710
+ const stack = [];
3711
+ const blockerNodes = [];
3712
+ const voidElements = /* @__PURE__ */ new Set([
3713
+ "area",
3714
+ "base",
3715
+ "br",
3716
+ "col",
3717
+ "embed",
3718
+ "hr",
3719
+ "img",
3720
+ "input",
3721
+ "link",
3722
+ "meta",
3723
+ "param",
3724
+ "source",
3725
+ "track",
3726
+ "wbr"
3727
+ ]);
3728
+ let hasConversationMessages = false;
3729
+ let visibleText = "";
3730
+ const hidden = (attributes) => /(?:^|\s)(?:hidden|inert)(?:\s|=|$)/i.test(attributes) || /\baria-hidden\s*=\s*["']?true/i.test(attributes) || /\bstyle\s*=\s*["'][^"']*(?:display\s*:\s*none|visibility\s*:\s*hidden|opacity\s*:\s*0|pointer-events\s*:\s*none)/i.test(attributes);
3731
+ const hiddenInChain = (node) => {
3732
+ for (let current = node; current !== void 0; current = current.parent) {
3733
+ if (hidden(current.attributes)) return true;
3734
+ }
3735
+ return false;
3736
+ };
3737
+ const messageNode = (node) => {
3738
+ const authorRole = serializedAttribute(node.attributes, "data-message-author-role");
3739
+ const testId = serializedAttribute(node.attributes, "data-testid");
3740
+ return authorRole !== void 0 && authorRole.length > 0 || testId?.toLowerCase().startsWith("conversation-turn") === true;
3741
+ };
3742
+ const insideMessage = (node) => {
3743
+ for (let current = node; current !== void 0; current = current.parent) {
3744
+ if (messageNode(current)) return true;
3745
+ }
3746
+ return false;
3747
+ };
3748
+ const systemSurface = (node) => {
3749
+ const role = serializedAttribute(node.attributes, "role")?.toLowerCase();
3750
+ const ariaLive = serializedAttribute(node.attributes, "aria-live")?.toLowerCase();
3751
+ const testId = serializedAttribute(node.attributes, "data-testid")?.toLowerCase() ?? "";
3752
+ const className = serializedAttribute(node.attributes, "class")?.toLowerCase() ?? "";
3753
+ return role === "alert" || role === "status" || role === "dialog" || ariaLive === "assertive" || testId.includes("toast") || testId.includes("banner") || className.includes("toast") || className.includes("banner");
3754
+ };
3755
+ const ignoredInChain = (node) => {
3756
+ for (let current = node; current !== void 0; current = current.parent) {
3757
+ if (current.tag === "script" || current.tag === "style" || current.tag === "template") return true;
3758
+ }
3759
+ return false;
3760
+ };
3761
+ for (const match of html.matchAll(/<!--[\s\S]*?-->|<![^>]*>|<\/?[a-z0-9-]+\b[^>]*>|[^<]+/gi)) {
3762
+ const token = match[0];
3763
+ const closing = /^<\/([a-z0-9-]+)/i.exec(token);
3764
+ if (closing?.[1] !== void 0) {
3765
+ const tag = closing[1].toLowerCase();
3766
+ const index = stack.map((node) => node.tag).lastIndexOf(tag);
3767
+ if (index >= 0) stack.splice(index);
3768
+ continue;
3769
+ }
3770
+ const opening = /^<([a-z0-9-]+)\b([^>]*)>/i.exec(token);
3771
+ if (opening?.[1] !== void 0) {
3772
+ const node = {
3773
+ tag: opening[1].toLowerCase(),
3774
+ attributes: opening[2] ?? "",
3775
+ parent: stack.at(-1),
3776
+ blockerText: ""
3777
+ };
3778
+ const ignored = ignoredInChain(node);
3779
+ if (messageNode(node) && !hiddenInChain(node) && !ignored) hasConversationMessages = true;
3780
+ if (systemSurface(node) && !hiddenInChain(node) && !insideMessage(node) && !ignored) {
3781
+ const ariaLabel = serializedAttribute(node.attributes, "aria-label");
3782
+ if (ariaLabel !== void 0) node.blockerText = ` ${ariaLabel}`;
3783
+ blockerNodes.push(node);
3784
+ }
3785
+ if (!voidElements.has(node.tag) && !/\/\s*>$/.test(token)) stack.push(node);
3786
+ continue;
3787
+ }
3788
+ const currentNode = stack.at(-1);
3789
+ if (!hiddenInChain(currentNode) && !ignoredInChain(currentNode)) {
3790
+ visibleText += ` ${token}`;
3791
+ for (const node of blockerNodes) {
3792
+ for (let current = currentNode; current !== void 0; current = current.parent) {
3793
+ if (current === node) {
3794
+ node.blockerText += ` ${token}`;
3795
+ break;
3796
+ }
3797
+ }
3798
+ }
3799
+ }
3800
+ }
3801
+ return {
3802
+ visibleText: htmlToText(visibleText),
3803
+ blockerSurface: {
3804
+ text: blockerNodes.map((node) => htmlToText(node.blockerText)).filter(Boolean).join(" "),
3805
+ hasConversationMessages
3806
+ }
3807
+ };
3808
+ }
3809
+ function serializedAttribute(attributes, name) {
3810
+ const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3811
+ const match = new RegExp(`\\b${escapedName}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s"'=<>\`]+))`, "i").exec(attributes);
3812
+ return match?.[1] ?? match?.[2] ?? match?.[3];
3813
+ }
3233
3814
  function htmlToText(html) {
3234
- return html.replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<[^>]+>/g, " ").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/\s+/g, " ").trim();
3815
+ return stripHiddenMarkup(html).replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<[^>]+>/g, " ").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/\s+/g, " ").trim();
3816
+ }
3817
+ function stripHiddenMarkup(html) {
3818
+ let visible = html;
3819
+ const hiddenElement = /<([a-z0-9-]+)\b[^>]*(?:\bhidden\b|\binert\b|\baria-hidden\s*=\s*["']?true|\bstyle\s*=\s*["'][^"']*(?:display\s*:\s*none|visibility\s*:\s*hidden|opacity\s*:\s*0))[^>]*>[\s\S]*?<\/\1>/gi;
3820
+ for (let pass = 0; pass < 4; pass += 1) {
3821
+ const next = visible.replace(hiddenElement, " ");
3822
+ if (next === visible) break;
3823
+ visible = next;
3824
+ }
3825
+ return visible;
3235
3826
  }
3236
3827
  function isLikelySignedIn(visibleText) {
3237
3828
  const markers = localeLabels.signedInMarkers.map(escapeRegExp).join("|");
3238
3829
  return new RegExp(`\\b(${markers})\\b`, "i").test(visibleText);
3239
3830
  }
3831
+ function isLikelyLoginWall(visibleText) {
3832
+ const labels = localeLabels.loginBlocker.map(escapeRegExp).join("|");
3833
+ const matches = visibleText.match(new RegExp(`(?:${labels})`, "gi")) ?? [];
3834
+ return matches.length >= 2 || /\bsign\s?up\b|\bcreate (?:an )?account\b/i.test(visibleText);
3835
+ }
3240
3836
 
3241
3837
  // src/browser/attach.ts
3242
- var CHATGPT_HOME = "https://chatgpt.com/";
3243
- var CHATGPT_HOSTS = /* @__PURE__ */ new Set(["chatgpt.com", "www.chatgpt.com", "chat.openai.com"]);
3244
3838
  var MAX_EXISTING_TAB_DIAGNOSTIC_CANDIDATES = 10;
3245
3839
  var MAX_EXISTING_TAB_DIAGNOSTIC_FIELD_LENGTH = 240;
3246
3840
  async function attachChatGPTBrowser(env, args = {}) {
3247
3841
  const browser = await getBrowser(env);
3248
3842
  const page = await getOrCreateChatGPTPage(browser, env, args);
3843
+ await assertPageOnChatGPTOrigin(page);
3249
3844
  const state = await readPageState(page);
3845
+ if (!isChatGPTUrl(state.url)) throw unsafeChatGPTOriginError();
3250
3846
  if (state.blocker?.kind === "login_required") {
3251
3847
  throw new LoginRequiredError(state.blocker.visibleText);
3252
3848
  }
@@ -3309,6 +3905,7 @@ async function tryBrowserGetPreferredListed(browsers) {
3309
3905
  }
3310
3906
  async function getOrCreateChatGPTPage(browser, env, args) {
3311
3907
  const targetUrl = args.url ?? CHATGPT_HOME;
3908
+ assertSafeChatGPTNavigation(targetUrl);
3312
3909
  const explicitExistingPolicy = normalizeExplicitExistingTabPolicy(args);
3313
3910
  if (env.page !== void 0) {
3314
3911
  const cached = normalizePage(env.page);
@@ -3366,7 +3963,7 @@ function normalizeExplicitExistingTabPolicy(args) {
3366
3963
  if (args.existingTab === true) {
3367
3964
  return {
3368
3965
  target: { type: "selected", host: "chatgpt" },
3369
- ifMissing: "create",
3966
+ ifMissing: "block",
3370
3967
  ifMultiple: "first",
3371
3968
  requireChatGPT: true
3372
3969
  };
@@ -3404,6 +4001,23 @@ async function selectExistingTab(browser, policy) {
3404
4001
  }
3405
4002
  }
3406
4003
  }
4004
+ if (typeof browser.tabs?.list === "function") {
4005
+ const controlled = await Promise.resolve(browser.tabs.list.call(browser.tabs)).catch(() => []);
4006
+ const matches = [];
4007
+ for (const candidate of controlled) {
4008
+ const page = await hydrateTab(browser, candidate);
4009
+ if (await pageMatchesExistingTarget(page, policy)) matches.push(page);
4010
+ }
4011
+ if (matches.length === 1 || matches.length > 1 && (policy.ifMultiple ?? "block") === "first") {
4012
+ return { page: matches[0] };
4013
+ }
4014
+ if (matches.length > 1) {
4015
+ throw new ExistingTabSelectionError(
4016
+ "Multiple already-controlled ChatGPT tabs matched the requested existing-tab target.",
4017
+ "existing_tab_ambiguous"
4018
+ );
4019
+ }
4020
+ }
3407
4021
  return userMatch.diagnostics === void 0 ? { diagnostics: diagnosticsForUnavailableUserTabs(policy) } : userMatch;
3408
4022
  }
3409
4023
  async function selectExistingUserTab(browser, policy, collectDiagnostics) {
@@ -3431,6 +4045,7 @@ async function selectExistingUserTab(browser, policy, collectDiagnostics) {
3431
4045
  }
3432
4046
  const selected = matches[0];
3433
4047
  const page = normalizePage(await claimTab.call(browser.user, selected));
4048
+ await assertPageOnChatGPTOrigin(page);
3434
4049
  return diagnostics === void 0 ? { page } : { page, diagnostics };
3435
4050
  }
3436
4051
  function userTabMatchesTarget(tab, policy) {
@@ -3546,23 +4161,15 @@ async function pageMatchesExistingTarget(page, policy) {
3546
4161
  return userTabMatchesTarget(tab, policy);
3547
4162
  }
3548
4163
  async function findExistingChatGPTTab(browser) {
3549
- const userTab = await selectExistingUserTab(browser, {
3550
- target: { type: "selected", host: "chatgpt" },
3551
- ifMultiple: "first",
3552
- requireChatGPT: true
3553
- }, false).catch(() => ({ page: void 0 }));
3554
- if (userTab.page !== void 0) {
3555
- return userTab.page;
3556
- }
3557
4164
  const selected = browser.tabs?.selected;
3558
4165
  if (typeof selected === "function") {
3559
4166
  try {
3560
4167
  const current = await selected.call(browser.tabs);
3561
4168
  if (current !== void 0) {
3562
- const normalized2 = normalizePage(current);
4169
+ const normalized = normalizePage(current);
3563
4170
  try {
3564
- if ((await normalized2.url?.())?.includes("chatgpt.com") === true) {
3565
- return normalized2;
4171
+ if (isChatGPTUrl(await normalized.url?.())) {
4172
+ return normalized;
3566
4173
  }
3567
4174
  } catch {
3568
4175
  }
@@ -3571,19 +4178,31 @@ async function findExistingChatGPTTab(browser) {
3571
4178
  }
3572
4179
  }
3573
4180
  const list = browser.tabs?.list;
3574
- if (typeof list !== "function") {
3575
- return void 0;
3576
- }
3577
- const tabs = await list.call(browser.tabs);
3578
- const normalized = await Promise.all(tabs.map((tab) => hydrateTab(browser, tab)));
3579
- for (const tab of normalized) {
3580
- try {
3581
- if ((await tab.url?.())?.includes("chatgpt.com") === true) {
3582
- return tab;
4181
+ if (typeof list === "function") {
4182
+ const tabs = await list.call(browser.tabs);
4183
+ const normalized = await Promise.all(tabs.map((tab) => hydrateTab(browser, tab)));
4184
+ for (const tab of normalized) {
4185
+ try {
4186
+ if (isChatGPTUrl(await tab.url?.())) {
4187
+ return tab;
4188
+ }
4189
+ } catch {
3583
4190
  }
3584
- } catch {
3585
4191
  }
3586
4192
  }
4193
+ const userTab = await selectExistingUserTab(browser, {
4194
+ target: { type: "selected", host: "chatgpt" },
4195
+ ifMultiple: "first",
4196
+ requireChatGPT: true
4197
+ }, false).catch((error) => {
4198
+ if (error instanceof ChatGPTControlError && error.blockerDetails.code === "unsafe_chatgpt_origin") {
4199
+ throw error;
4200
+ }
4201
+ return { page: void 0 };
4202
+ });
4203
+ if (userTab.page !== void 0) {
4204
+ return userTab.page;
4205
+ }
3587
4206
  return void 0;
3588
4207
  }
3589
4208
  var ExistingTabSelectionError = class extends ChatGPTControlError {
@@ -3621,16 +4240,6 @@ function targetRequiresChatGPT(target) {
3621
4240
  return true;
3622
4241
  }
3623
4242
  }
3624
- function isChatGPTUrl(url) {
3625
- if (url === void 0) {
3626
- return false;
3627
- }
3628
- try {
3629
- return CHATGPT_HOSTS.has(new URL(url).hostname);
3630
- } catch {
3631
- return false;
3632
- }
3633
- }
3634
4243
  function urlMatches(actual, expected) {
3635
4244
  if (actual === void 0) {
3636
4245
  return false;
@@ -3682,6 +4291,7 @@ function userTabCandidateLabel(tab) {
3682
4291
  return `tab ${tab.id} - ${tab.title ?? "Untitled"} - ${tab.url ?? "unknown URL"}`;
3683
4292
  }
3684
4293
  async function createTab(browser, url) {
4294
+ assertSafeChatGPTNavigation(url);
3685
4295
  if (typeof browser.tabs?.create === "function") {
3686
4296
  const tab = await browser.tabs.create(url);
3687
4297
  const page = await hydrateTab(browser, tab);
@@ -3699,18 +4309,39 @@ async function createTab(browser, url) {
3699
4309
  if (typeof page.goto === "function") {
3700
4310
  await page.goto(url);
3701
4311
  }
4312
+ await assertPageOnChatGPTOrigin(page);
3702
4313
  return page;
3703
4314
  }
3704
4315
  return void 0;
3705
4316
  }
4317
+ function assertSafeChatGPTNavigation(url) {
4318
+ if (isChatGPTUrl(url)) return;
4319
+ throw unsafeChatGPTOriginError(
4320
+ "ChatGPT navigation requires HTTPS on an allowlisted ChatGPT origin with the default port."
4321
+ );
4322
+ }
3706
4323
  async function ensurePageAt(page, url) {
3707
4324
  const currentUrl = await Promise.resolve(page.url?.()).catch(() => "");
3708
- if (currentUrl?.includes("chatgpt.com") === true) {
4325
+ if (isChatGPTUrl(currentUrl)) {
3709
4326
  return;
3710
4327
  }
3711
4328
  if (typeof page.goto === "function") {
3712
4329
  await page.goto(url);
3713
4330
  }
4331
+ await assertPageOnChatGPTOrigin(page);
4332
+ }
4333
+ async function assertPageOnChatGPTOrigin(page) {
4334
+ const actualUrl = await Promise.resolve(page.url?.()).catch(() => void 0);
4335
+ if (!isChatGPTUrl(actualUrl)) throw unsafeChatGPTOriginError();
4336
+ }
4337
+ function unsafeChatGPTOriginError(message = "The browser did not remain on a supported ChatGPT origin after navigation or attachment.") {
4338
+ return new ChatGPTControlError(
4339
+ message,
4340
+ "selector_drift",
4341
+ false,
4342
+ void 0,
4343
+ { code: "unsafe_chatgpt_origin" }
4344
+ );
3714
4345
  }
3715
4346
  function normalizeBrowser(browser) {
3716
4347
  if (browser === void 0 || browser === null || typeof browser !== "object") {
@@ -4721,6 +5352,14 @@ function sendButton(page) {
4721
5352
  }
4722
5353
  return page.getByRole("button", { name: anyLabelPattern(localeLabels.sendButton) });
4723
5354
  }
5355
+ function stopGenerationButton(page) {
5356
+ if (typeof page.getByRole !== "function") {
5357
+ return requiredLocator(page, "button[aria-label*='Stop'], button[title*='Stop']");
5358
+ }
5359
+ return page.getByRole("button", {
5360
+ name: new RegExp(`^(?:${localeLabels.stopControl.map(escapeRegExp).join("|")})$`, "i")
5361
+ });
5362
+ }
4724
5363
  function searchChatsButton(page) {
4725
5364
  if (typeof page.getByRole !== "function") {
4726
5365
  return requiredLocator(page, "button");
@@ -5342,8 +5981,8 @@ function isNodeError(error) {
5342
5981
  }
5343
5982
 
5344
5983
  // src/commands/context.ts
5345
- async function contextFromPage(page, partial = {}) {
5346
- if (page === void 0) {
5984
+ async function contextFromPage(page, partial = {}, options = {}) {
5985
+ if (page === void 0 || options.minimal === true) {
5347
5986
  return { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...partial };
5348
5987
  }
5349
5988
  const url = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => partial.url) : partial.url;
@@ -5397,7 +6036,7 @@ async function bootstrap(env, args = {}) {
5397
6036
  return resultError(error instanceof Error ? error : new Error(String(error)));
5398
6037
  }
5399
6038
  }
5400
- async function ensurePage(env) {
6039
+ async function ensurePage(env, options = {}) {
5401
6040
  if (env.page === void 0) {
5402
6041
  return bootstrap(env, { preferExistingTab: true });
5403
6042
  }
@@ -5405,26 +6044,59 @@ async function ensurePage(env) {
5405
6044
  if (affinity !== void 0) {
5406
6045
  return affinity;
5407
6046
  }
5408
- return resultOk({}, await contextFromPage(env.page, tabContext(env)));
5409
- }
5410
- async function verifyTabAffinity(env) {
5411
- if (env.expectedTabId === void 0 || env.page === void 0) {
5412
- return void 0;
5413
- }
5414
- const actualTabId = tabIdFromPage(env.page);
5415
- if (actualTabId === env.expectedTabId) {
5416
- return void 0;
6047
+ const origin = await verifyChatGPTOrigin(env);
6048
+ if (origin !== void 0) {
6049
+ return origin;
5417
6050
  }
5418
- const code = actualTabId === void 0 ? "tab_affinity_unverifiable" : "tab_affinity_lost";
5419
- const message = actualTabId === void 0 ? `ChatGPT command cannot verify it is still attached to expected tab ${env.expectedTabId}.` : `ChatGPT command would run on tab ${actualTabId}, but the workflow expected tab ${env.expectedTabId}.`;
6051
+ return resultOk({}, await contextFromPage(
6052
+ env.page,
6053
+ tabContext(env),
6054
+ { minimal: options.minimalContext === true }
6055
+ ));
6056
+ }
6057
+ async function verifyChatGPTOrigin(env) {
6058
+ if (env.page === void 0) return void 0;
6059
+ const actualUrl = await Promise.resolve(env.page.url?.()).catch(() => void 0);
6060
+ if (isChatGPTUrl(actualUrl)) return void 0;
5420
6061
  return {
5421
6062
  ok: false,
5422
6063
  status: "blocked",
5423
6064
  warnings: [],
5424
6065
  blocker: {
5425
6066
  kind: "selector_drift",
5426
- code,
5427
- message,
6067
+ code: "unsafe_chatgpt_origin",
6068
+ message: "ChatGPT command refused to operate because the controlled tab is not on an allowlisted ChatGPT origin.",
6069
+ visibleText: actualUrl ?? "The current tab URL could not be verified.",
6070
+ remediation: [
6071
+ {
6072
+ label: "Reopen ChatGPT",
6073
+ instruction: "Run session.bootstrap against https://chatgpt.com or claim an exact supported ChatGPT tab before retrying.",
6074
+ userActionRequired: false
6075
+ }
6076
+ ],
6077
+ resumable: false
6078
+ },
6079
+ context: await contextFromPage(env.page, tabContext(env))
6080
+ };
6081
+ }
6082
+ async function verifyTabAffinity(env) {
6083
+ if (env.expectedTabId === void 0 || env.page === void 0) {
6084
+ return void 0;
6085
+ }
6086
+ const actualTabId = tabIdFromPage(env.page);
6087
+ if (actualTabId === env.expectedTabId) {
6088
+ return void 0;
6089
+ }
6090
+ const code = actualTabId === void 0 ? "tab_affinity_unverifiable" : "tab_affinity_lost";
6091
+ const message = actualTabId === void 0 ? `ChatGPT command cannot verify it is still attached to expected tab ${env.expectedTabId}.` : `ChatGPT command would run on tab ${actualTabId}, but the workflow expected tab ${env.expectedTabId}.`;
6092
+ return {
6093
+ ok: false,
6094
+ status: "blocked",
6095
+ warnings: [],
6096
+ blocker: {
6097
+ kind: "selector_drift",
6098
+ code,
6099
+ message,
5428
6100
  remediation: [
5429
6101
  {
5430
6102
  label: "Reclaim the intended tab",
@@ -5446,14 +6118,22 @@ function tabContext(env, actualTabId = tabIdFromPage(env.page)) {
5446
6118
  var CHATGPT_HOME2 = "https://chatgpt.com/";
5447
6119
  async function ensureConversationTarget(page, target, options) {
5448
6120
  const targetUrl = absoluteConversationUrl(target);
6121
+ requireChatGPTUrl(targetUrl, "Conversation target URL");
5449
6122
  const expectedConversationId = parseConversationId(targetUrl);
5450
6123
  const currentUrl = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
5451
- if (expectedConversationId !== void 0 && parseConversationId(typeof currentUrl === "string" ? currentUrl : "") === expectedConversationId) {
6124
+ if (isChatGPTUrl(typeof currentUrl === "string" ? currentUrl : "") && expectedConversationId !== void 0 && parseConversationId(typeof currentUrl === "string" ? currentUrl : "") === expectedConversationId) {
5452
6125
  await waitForConversationHydrated(page, options.timeoutMs, expectedConversationId);
5453
6126
  return ensureResult(false, targetUrl, expectedConversationId);
5454
6127
  }
5455
6128
  await page.goto?.(targetUrl, { waitUntil: "domcontentloaded", timeout: options.timeoutMs });
6129
+ const navigatedUrl = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
6130
+ requireChatGPTUrl(typeof navigatedUrl === "string" ? navigatedUrl : "", "Conversation navigation result");
5456
6131
  await waitForConversationHydrated(page, options.timeoutMs, expectedConversationId);
6132
+ const finalUrl = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
6133
+ requireChatGPTUrl(typeof finalUrl === "string" ? finalUrl : "", "Hydrated conversation URL");
6134
+ if (expectedConversationId !== void 0 && parseConversationId(typeof finalUrl === "string" ? finalUrl : "") !== expectedConversationId) {
6135
+ throw new Error(`Visible Chat navigation did not reach conversation ${expectedConversationId}.`);
6136
+ }
5457
6137
  return ensureResult(true, targetUrl, expectedConversationId);
5458
6138
  }
5459
6139
  async function waitForConversationHydrated(page, timeoutMs, expectedConversationId) {
@@ -5744,48 +6424,83 @@ import { createHash as createHash2 } from "node:crypto";
5744
6424
 
5745
6425
  // src/dom/generation-state.ts
5746
6426
  var EMPTY_GENERATION_STATE = {
6427
+ observed: false,
5747
6428
  active: false,
5748
6429
  stopped: false,
5749
6430
  signals: []
5750
6431
  };
5751
- async function readAssistantGenerationState(page) {
6432
+ async function readAssistantGenerationState(page, options = {}) {
6433
+ const expiresAtMs = options.timeoutMs === void 0 ? void 0 : Date.now() + Math.max(1, options.timeoutMs);
5752
6434
  if (typeof page.evaluate === "function") {
5753
- return page.evaluate((args) => {
5754
- const normalize = (value) => (value ?? "").trim().toLowerCase();
5755
- const isVisible = (element) => {
5756
- const style = window.getComputedStyle(element);
5757
- return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && element.getAttribute("aria-hidden") !== "true";
5758
- };
5759
- const visibleButtons = Array.from(document.querySelectorAll("button")).filter((button) => isVisible(button) && button.disabled !== true && button.getAttribute("aria-disabled") !== "true");
5760
- const buttonTexts = visibleButtons.map((button) => [
5761
- button.innerText,
5762
- button.textContent,
5763
- button.getAttribute("aria-label"),
5764
- button.getAttribute("title")
5765
- ].map(normalize).filter(Boolean).join(" ")).filter(Boolean);
5766
- const bodyText = normalize(document.body?.innerText);
5767
- const haystacks = [bodyText, ...buttonTexts];
5768
- const matchingSignals = (phrases) => haystacks.flatMap(
5769
- (text) => phrases.map((phrase) => phrase.toLowerCase()).filter((phrase) => text.includes(phrase))
5770
- );
5771
- const activeSignals = matchingSignals(args.stop);
5772
- const stoppedSignals = matchingSignals(args.stopped);
5773
- return {
5774
- active: activeSignals.length > 0,
5775
- stopped: stoppedSignals.length > 0,
5776
- signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals, ...buttonTexts.filter((text) => /stop|cancel|stopped|answering|thinking/i.test(text))])].slice(0, 5)
5777
- };
5778
- }, {
5779
- stop: [...localeLabels.stopControl],
5780
- stopped: [...localeLabels.stoppedAssistant]
5781
- }).catch(() => EMPTY_GENERATION_STATE);
6435
+ const evaluateOptions = remainingGenerationStateOptions(expiresAtMs);
6436
+ if (expiresAtMs !== void 0 && evaluateOptions === void 0) return EMPTY_GENERATION_STATE;
6437
+ try {
6438
+ return await page.evaluate((args) => {
6439
+ const normalize = (value) => (value ?? "").replace(/\s+/g, " ").trim().toLowerCase();
6440
+ const isVisible = (element) => {
6441
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) {
6442
+ return false;
6443
+ }
6444
+ const style = window.getComputedStyle(element);
6445
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none") {
6446
+ return false;
6447
+ }
6448
+ const rect = element.getBoundingClientRect();
6449
+ return (rect.width > 0 || rect.height > 0) && style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0";
6450
+ };
6451
+ const values = (element) => [
6452
+ element.getAttribute("aria-label"),
6453
+ element.getAttribute("title"),
6454
+ element.innerText,
6455
+ element.textContent
6456
+ ].map(normalize).filter(Boolean);
6457
+ const matchingLabels2 = (element, phrases) => {
6458
+ const elementValues = values(element);
6459
+ return phrases.filter((phrase) => elementValues.includes(normalize(phrase)));
6460
+ };
6461
+ const textboxes = Array.from(document.querySelectorAll(
6462
+ "textarea, [contenteditable='true'], [role='textbox']"
6463
+ )).filter(isVisible);
6464
+ const activeComposers = [...new Set(textboxes.map((textbox) => textbox.closest("form") ?? textbox.closest("[data-testid*='composer' i]") ?? textbox.closest("[aria-label*='composer' i]") ?? textbox.closest("[class*='composer' i]")).filter((value) => value !== null))];
6465
+ const isScopedStopControl = (button) => activeComposers.length === 1 && activeComposers[0].contains(button);
6466
+ const visibleStopButtons = Array.from(document.querySelectorAll("button")).filter((button) => isVisible(button) && button.disabled !== true && button.getAttribute("aria-disabled") !== "true" && isScopedStopControl(button) && matchingLabels2(button, args.send).length === 0 && matchingLabels2(button, args.stop).length > 0);
6467
+ const activeSignals = [...new Set(visibleStopButtons.flatMap((button) => matchingLabels2(button, args.stop)))];
6468
+ const turns = Array.from(document.querySelectorAll("[data-testid^='conversation-turn']"));
6469
+ const latestAssistant = Array.from(document.querySelectorAll("[data-message-author-role='assistant']")).at(-1);
6470
+ const latestTurn = latestAssistant?.closest("[data-testid^='conversation-turn']") ?? turns.at(-1);
6471
+ const stoppedSignals = latestTurn === void 0 ? [] : [...new Set(Array.from(latestTurn.querySelectorAll(
6472
+ "button, [role='status'], [aria-label], [title], p, span, div"
6473
+ )).filter((element) => isVisible(element)).flatMap((element) => matchingLabels2(element, args.stopped)))];
6474
+ return {
6475
+ observed: true,
6476
+ active: activeSignals.length > 0,
6477
+ stopped: stoppedSignals.length > 0,
6478
+ signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals])].slice(0, 5)
6479
+ };
6480
+ }, {
6481
+ stop: [...localeLabels.stopControl],
6482
+ stopped: [...localeLabels.stoppedAssistant],
6483
+ send: [...localeLabels.sendButton]
6484
+ }, evaluateOptions);
6485
+ } catch {
6486
+ }
5782
6487
  }
5783
6488
  if (typeof page.content === "function") {
5784
- const html = await page.content().catch(() => "");
5785
- return generationStateFromText(html);
6489
+ const contentOptions = remainingGenerationStateOptions(expiresAtMs);
6490
+ if (expiresAtMs !== void 0 && contentOptions === void 0) return EMPTY_GENERATION_STATE;
6491
+ try {
6492
+ return generationStateFromHtml(await page.content(contentOptions));
6493
+ } catch {
6494
+ return EMPTY_GENERATION_STATE;
6495
+ }
5786
6496
  }
5787
6497
  return EMPTY_GENERATION_STATE;
5788
6498
  }
6499
+ function remainingGenerationStateOptions(expiresAtMs) {
6500
+ if (expiresAtMs === void 0) return void 0;
6501
+ const timeoutMs = expiresAtMs - Date.now();
6502
+ return timeoutMs > 0 ? { timeoutMs } : void 0;
6503
+ }
5789
6504
  async function latestAssistantTurnHasResponseActions(page) {
5790
6505
  if (typeof page.evaluate === "function") {
5791
6506
  const scoped = await page.evaluate((phrases) => {
@@ -5822,16 +6537,117 @@ async function latestAssistantTurnHasResponseActions(page) {
5822
6537
  return true;
5823
6538
  }
5824
6539
  }
5825
- function generationStateFromText(text) {
5826
- const normalized = text.toLowerCase();
5827
- const activeSignals = localeLabels.stopControl.filter((phrase) => normalized.includes(phrase.toLowerCase()));
5828
- const stoppedSignals = localeLabels.stoppedAssistant.filter((phrase) => normalized.includes(phrase.toLowerCase()));
6540
+ function generationStateFromHtml(html) {
6541
+ const normalize = (value) => value.replace(/<[^>]*>/g, " ").replace(/&nbsp;/gi, " ").replace(/\s+/g, " ").trim().toLowerCase();
6542
+ const isHiddenTag = (tag) => /\b(?:hidden|inert)\b/i.test(tag) || /\baria-hidden\s*=\s*["']?true/i.test(tag) || /\bstyle\s*=\s*["'][^"']*(?:display\s*:\s*none|visibility\s*:\s*hidden|opacity\s*:\s*0)/i.test(tag);
6543
+ const candidateValues = (tag, text) => {
6544
+ const values = [text];
6545
+ for (const attribute of ["aria-label", "title"]) {
6546
+ const match = new RegExp(`\\b${attribute}\\s*=\\s*["']([^"']*)["']`, "i").exec(tag);
6547
+ if (match?.[1] !== void 0) values.push(match[1]);
6548
+ }
6549
+ return values.map(normalize).filter(Boolean);
6550
+ };
6551
+ const exactMatches = (values, phrases) => phrases.filter((phrase) => values.includes(normalize(phrase)));
6552
+ const activeSignals = serializedStopButtonCandidates(html).filter((candidate) => candidate.scoped && !candidate.hidden && !candidate.disabled).flatMap((candidate) => {
6553
+ const values = candidateValues(candidate.attributes, candidate.text);
6554
+ return exactMatches(values, localeLabels.sendButton).length > 0 ? [] : exactMatches(values, localeLabels.stopControl);
6555
+ });
6556
+ const latestTurnStart = Math.max(
6557
+ html.toLowerCase().lastIndexOf('data-message-author-role="assistant"'),
6558
+ html.toLowerCase().lastIndexOf("data-message-author-role='assistant'")
6559
+ );
6560
+ const latestAssistantHtml = latestTurnStart >= 0 ? html.slice(latestTurnStart) : "";
6561
+ const stoppedSignals = [...latestAssistantHtml.matchAll(
6562
+ /<(?:button|p|span|div)\b([^>]*)>([\s\S]*?)<\/(?:button|p|span|div)>/gi
6563
+ )].filter((match) => !isHiddenTag(match[1] ?? "")).flatMap((match) => exactMatches(candidateValues(match[1] ?? "", match[2] ?? ""), localeLabels.stoppedAssistant));
5829
6564
  return {
6565
+ observed: true,
5830
6566
  active: activeSignals.length > 0,
5831
6567
  stopped: stoppedSignals.length > 0,
5832
- signals: [...activeSignals, ...stoppedSignals].slice(0, 5)
6568
+ signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals])].slice(0, 5)
5833
6569
  };
5834
6570
  }
6571
+ function serializedStopButtonCandidates(html) {
6572
+ const stack = [];
6573
+ const buttons = [];
6574
+ const activeComposers = /* @__PURE__ */ new Set();
6575
+ const voidElements = /* @__PURE__ */ new Set([
6576
+ "area",
6577
+ "base",
6578
+ "br",
6579
+ "col",
6580
+ "embed",
6581
+ "hr",
6582
+ "img",
6583
+ "input",
6584
+ "link",
6585
+ "meta",
6586
+ "param",
6587
+ "source",
6588
+ "track",
6589
+ "wbr"
6590
+ ]);
6591
+ const hidden = (attributes) => /\b(?:hidden|inert)\b/i.test(attributes) || /\baria-hidden\s*=\s*["']?true/i.test(attributes) || /\bstyle\s*=\s*["'][^"']*(?:display\s*:\s*none|visibility\s*:\s*hidden|opacity\s*:\s*0)/i.test(attributes);
6592
+ const hiddenInChain = (node) => {
6593
+ for (let current = node; current !== void 0; current = current.parent) {
6594
+ if (hidden(current.attributes)) return true;
6595
+ }
6596
+ return false;
6597
+ };
6598
+ const isComposerMetadata = (node) => /\b(?:data-testid|aria-label|class)\s*=\s*["'][^"']*composer/i.test(node.attributes);
6599
+ const isTextbox = (node) => node.tag === "textarea" || /\bcontenteditable\s*=\s*["']?true/i.test(node.attributes) || /\brole\s*=\s*["']textbox["']/i.test(node.attributes);
6600
+ for (const match of html.matchAll(/<!--[\s\S]*?-->|<![^>]*>|<\/?[a-z0-9-]+\b[^>]*>|[^<]+/gi)) {
6601
+ const token = match[0];
6602
+ const closing = /^<\/([a-z0-9-]+)/i.exec(token);
6603
+ if (closing?.[1] !== void 0) {
6604
+ const tag = closing[1].toLowerCase();
6605
+ const index = stack.map((node) => node.tag).lastIndexOf(tag);
6606
+ if (index >= 0) stack.splice(index);
6607
+ continue;
6608
+ }
6609
+ const opening = /^<([a-z0-9-]+)\b([^>]*)>/i.exec(token);
6610
+ if (opening?.[1] !== void 0) {
6611
+ const node = {
6612
+ tag: opening[1].toLowerCase(),
6613
+ attributes: opening[2] ?? "",
6614
+ parent: stack.at(-1),
6615
+ text: ""
6616
+ };
6617
+ if (node.tag === "button") buttons.push(node);
6618
+ if (isTextbox(node) && !hiddenInChain(node)) {
6619
+ const ancestors = [...stack].reverse();
6620
+ const composer = ancestors.find((ancestor) => ancestor.tag === "form") ?? ancestors.find(isComposerMetadata);
6621
+ if (composer !== void 0 && !hiddenInChain(composer)) activeComposers.add(composer);
6622
+ }
6623
+ if (!voidElements.has(node.tag) && !/\/\s*>$/.test(token)) stack.push(node);
6624
+ continue;
6625
+ }
6626
+ for (let index = stack.length - 1; index >= 0; index -= 1) {
6627
+ if (stack[index].tag === "button") {
6628
+ stack[index].text += ` ${token}`;
6629
+ break;
6630
+ }
6631
+ }
6632
+ }
6633
+ const activeComposer = activeComposers.size === 1 ? [...activeComposers][0] : void 0;
6634
+ return buttons.map((button) => {
6635
+ let scoped = false;
6636
+ for (let current = button.parent; current !== void 0; current = current.parent) {
6637
+ if (current === activeComposer) {
6638
+ scoped = true;
6639
+ break;
6640
+ }
6641
+ }
6642
+ return {
6643
+ attributes: button.attributes,
6644
+ text: button.text,
6645
+ scoped,
6646
+ hidden: hiddenInChain(button),
6647
+ disabled: /\bdisabled(?:\s|=|$)/i.test(button.attributes) || /\baria-disabled\s*=\s*["']?true/i.test(button.attributes)
6648
+ };
6649
+ });
6650
+ }
5835
6651
 
5836
6652
  // src/dom/wait-snapshot.ts
5837
6653
  function waitTextMetadata(rawText) {
@@ -5873,27 +6689,43 @@ async function readWaitDomSnapshot(page) {
5873
6689
  const trimmedForTransient = normalizedText.replace(/[.。…]+$/g, "").trim().toLowerCase();
5874
6690
  const transient = args.transient.some((phrase) => trimmedForTransient === phrase.toLowerCase()) || /^analyzing (?:the )?images?$/.test(trimmedForTransient) || /^processing (?:the )?images?$/.test(trimmedForTransient) || /^reading (?:the )?images?$/.test(trimmedForTransient);
5875
6691
  const isVisible = (element) => {
6692
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) {
6693
+ return false;
6694
+ }
5876
6695
  const style = window.getComputedStyle(element);
5877
- return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && element.getAttribute("aria-hidden") !== "true";
6696
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none") {
6697
+ return false;
6698
+ }
6699
+ const rect = element.getBoundingClientRect();
6700
+ return rect.width > 0 || rect.height > 0;
5878
6701
  };
5879
- const visibleButtons = Array.from(document.querySelectorAll("button")).filter((button) => isVisible(button) && button.disabled !== true && button.getAttribute("aria-disabled") !== "true");
5880
- const buttonTexts = visibleButtons.map((button) => [
5881
- button.innerText,
5882
- button.textContent,
5883
- button.getAttribute("aria-label"),
5884
- button.getAttribute("title")
5885
- ].map(normalizeLower).filter(Boolean).join(" ")).filter(Boolean);
5886
- const bodyText = normalizeLower(document.body?.innerText);
5887
- const haystacks = [bodyText, ...buttonTexts];
5888
- const matchingSignals = (phrases) => haystacks.flatMap(
5889
- (text) => phrases.map((phrase) => phrase.toLowerCase()).filter((phrase) => text.includes(phrase))
5890
- );
5891
- const activeSignals = matchingSignals(args.stop);
5892
- const stoppedSignals = matchingSignals(args.stopped);
6702
+ const elementValues = (element) => [
6703
+ element.getAttribute("aria-label"),
6704
+ element.getAttribute("title"),
6705
+ element.innerText,
6706
+ element.textContent
6707
+ ].map(normalizeLower).filter(Boolean);
6708
+ const matchingLabels2 = (element, phrases) => {
6709
+ const values = elementValues(element);
6710
+ return phrases.filter((phrase) => values.includes(normalizeLower(phrase)));
6711
+ };
6712
+ const isScopedStopControl = (button) => {
6713
+ if (button.matches("[data-testid='stop-button'], [data-testid*='stop' i]")) return true;
6714
+ if (button.closest("[data-testid*='composer' i], [aria-label*='composer' i]") !== null) return true;
6715
+ const form = button.closest("form");
6716
+ return form?.querySelector("textarea, [contenteditable='true'], [role='textbox']") !== null;
6717
+ };
6718
+ const visibleStopButtons = Array.from(document.querySelectorAll("button")).filter((button) => isVisible(button) && button.disabled !== true && button.getAttribute("aria-disabled") !== "true" && isScopedStopControl(button) && matchingLabels2(button, args.send).length === 0 && matchingLabels2(button, args.stop).length > 0);
6719
+ const activeSignals = [...new Set(visibleStopButtons.flatMap((button) => matchingLabels2(button, args.stop)))];
6720
+ const latestAssistantTurn = latestAssistant?.closest("[data-testid^='conversation-turn']") ?? Array.from(document.querySelectorAll("[data-testid^='conversation-turn']")).at(-1);
6721
+ const stoppedSignals = latestAssistantTurn === void 0 ? [] : [...new Set(Array.from(latestAssistantTurn.querySelectorAll(
6722
+ "button, [role='status'], [aria-label], [title], p, span, div"
6723
+ )).filter((element) => isVisible(element)).flatMap((element) => matchingLabels2(element, args.stopped)))];
5893
6724
  const generation = {
6725
+ observed: true,
5894
6726
  active: activeSignals.length > 0,
5895
6727
  stopped: stoppedSignals.length > 0,
5896
- signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals, ...buttonTexts.filter((text) => /stop|cancel|stopped|answering|thinking/i.test(text))])].slice(0, 5)
6728
+ signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals])].slice(0, 5)
5897
6729
  };
5898
6730
  const turns = Array.from(document.querySelectorAll("[data-testid^='conversation-turn']"));
5899
6731
  let hasResponseActions;
@@ -5928,6 +6760,7 @@ async function readWaitDomSnapshot(page) {
5928
6760
  transient: [...localeLabels.transientAssistant],
5929
6761
  stop: [...localeLabels.stopControl],
5930
6762
  stopped: [...localeLabels.stoppedAssistant],
6763
+ send: [...localeLabels.sendButton],
5931
6764
  actions: [...localeLabels.responseActions]
5932
6765
  });
5933
6766
  }
@@ -6039,7 +6872,7 @@ var ProbeTimeoutError = class extends Error {
6039
6872
 
6040
6873
  // src/commands/messages.ts
6041
6874
  function isResponseComplete(snapshot) {
6042
- return snapshot.latestText.trim().length > 0 && !isTransientAssistantText(snapshot.latestText) && snapshot.textStableForMs >= snapshot.stableMs && !snapshot.generation.active && !snapshot.generation.stopped && snapshot.hasResponseActions;
6875
+ return snapshot.latestText.trim().length > 0 && !isTransientAssistantText(snapshot.latestText) && snapshot.textStableForMs >= snapshot.stableMs && snapshot.generation.observed && !snapshot.generation.active && !snapshot.generation.stopped && snapshot.hasResponseActions;
6043
6876
  }
6044
6877
  async function composeMessage(env, args) {
6045
6878
  const boot = await ensurePage(env);
@@ -6168,6 +7001,282 @@ async function submitMessage(env, args = {}) {
6168
7001
  return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
6169
7002
  }
6170
7003
  }
7004
+ async function stopGeneration(env, args = {}) {
7005
+ const timeoutMs = Math.max(1, args.timeoutMs ?? 5e3);
7006
+ const deadline = createDeadline(timeoutMs);
7007
+ if (args.confirmStop !== true) {
7008
+ return {
7009
+ ok: false,
7010
+ status: "needs_confirmation",
7011
+ warnings: [],
7012
+ blocker: {
7013
+ kind: "confirmation",
7014
+ code: "stop_generation_confirmation_required",
7015
+ fieldPath: "confirmStop",
7016
+ message: "Stopping the visible ChatGPT response requires an explicit caller decision.",
7017
+ resumable: true
7018
+ },
7019
+ context: env.page === void 0 ? { timestamp: (/* @__PURE__ */ new Date()).toISOString() } : await stopContext(env.page, deadline)
7020
+ };
7021
+ }
7022
+ let boot;
7023
+ try {
7024
+ boot = await withinStopDeadline(
7025
+ deadline,
7026
+ () => ensurePage(env, { minimalContext: true }),
7027
+ "ChatGPT page verification"
7028
+ );
7029
+ } catch (error) {
7030
+ return stopDeadlineResult(error);
7031
+ }
7032
+ if (!boot.ok) return boot;
7033
+ const page = env.page;
7034
+ const warnings = /* @__PURE__ */ new Set();
7035
+ let stopActivationStarted = false;
7036
+ let beforeActivation;
7037
+ try {
7038
+ const beforeProbeTimeoutMs = Math.min(1e3, Math.max(1, remainingMs(deadline)));
7039
+ const beforeResult = await readStopGenerationState(page, deadline, beforeProbeTimeoutMs);
7040
+ addWarnings(warnings, beforeResult.warnings);
7041
+ if (!beforeResult.ok || !beforeResult.value.observed) {
7042
+ if (remainingMs(deadline) <= 0) {
7043
+ return stopDeadlineResult(void 0, void 0, [...warnings]);
7044
+ }
7045
+ return {
7046
+ ok: false,
7047
+ status: "blocked",
7048
+ warnings: [...warnings],
7049
+ blocker: {
7050
+ kind: "selector_drift",
7051
+ code: "stop_generation_state_unavailable",
7052
+ message: "ChatGPT generation state could not be inspected safely, so no control was clicked.",
7053
+ resumable: true
7054
+ },
7055
+ context: await stopContext(page, deadline)
7056
+ };
7057
+ }
7058
+ const before = beforeResult.value;
7059
+ beforeActivation = before;
7060
+ if (!before.active) {
7061
+ return resultOk({
7062
+ wasGenerating: false,
7063
+ stopped: false,
7064
+ signalsBefore: before.signals,
7065
+ signalsAfter: before.signals
7066
+ }, await stopContext(page, deadline), [...warnings]);
7067
+ }
7068
+ const resolution = await resolveStopControl(page, deadline);
7069
+ if (!resolution.ok) {
7070
+ return {
7071
+ ok: false,
7072
+ status: "blocked",
7073
+ data: { wasGenerating: true, stopped: false, signalsBefore: before.signals, signalsAfter: before.signals },
7074
+ warnings: [...warnings],
7075
+ blocker: {
7076
+ kind: "selector_drift",
7077
+ code: resolution.code,
7078
+ message: resolution.message,
7079
+ resumable: true
7080
+ },
7081
+ context: await stopContext(page, deadline)
7082
+ };
7083
+ }
7084
+ stopActivationStarted = true;
7085
+ await withinNativeStopDeadline(
7086
+ deadline,
7087
+ (timeoutMs2) => resolution.control.click?.({ timeoutMs: timeoutMs2 }) ?? Promise.reject(new Error("The resolved Stop control does not support click().")),
7088
+ "Stop control click"
7089
+ );
7090
+ let after = EMPTY_GENERATION_STATE;
7091
+ while (remainingMs(deadline) > 0) {
7092
+ const afterProbeTimeoutMs = Math.min(1e3, Math.max(1, remainingMs(deadline)));
7093
+ const afterResult = await readStopGenerationState(page, deadline, afterProbeTimeoutMs);
7094
+ addWarnings(warnings, afterResult.warnings);
7095
+ if (afterResult.ok) {
7096
+ after = afterResult.value;
7097
+ if (after.observed && !after.active) {
7098
+ return resultOk({
7099
+ wasGenerating: true,
7100
+ stopped: true,
7101
+ signalsBefore: before.signals,
7102
+ signalsAfter: after.signals
7103
+ }, await stopContext(page, deadline), [...warnings]);
7104
+ }
7105
+ }
7106
+ await sleepWithinDeadline(page, deadline, 100);
7107
+ }
7108
+ const data = {
7109
+ wasGenerating: true,
7110
+ stopped: false,
7111
+ signalsBefore: before.signals,
7112
+ signalsAfter: after.signals
7113
+ };
7114
+ return stopDeadlineResult(void 0, data, [...warnings]);
7115
+ } catch (error) {
7116
+ if (remainingMs(deadline) <= 0 || error instanceof StopDeadlineError) {
7117
+ const data = stopActivationStarted && beforeActivation !== void 0 ? {
7118
+ wasGenerating: true,
7119
+ stopped: false,
7120
+ signalsBefore: beforeActivation.signals,
7121
+ signalsAfter: beforeActivation.signals
7122
+ } : void 0;
7123
+ return stopDeadlineResult(error, data, [...warnings]);
7124
+ }
7125
+ return resultError(error instanceof Error ? error : new Error(String(error)), await stopContext(page, deadline));
7126
+ }
7127
+ }
7128
+ async function readStopGenerationState(page, deadline, capMs) {
7129
+ const timeoutMs = Math.min(capMs, remainingMs(deadline));
7130
+ if (timeoutMs <= 0) {
7131
+ return {
7132
+ ok: false,
7133
+ timedOut: true,
7134
+ warnings: ["Skipped generation state DOM probe because no deadline budget remained."]
7135
+ };
7136
+ }
7137
+ try {
7138
+ const value = await readAssistantGenerationState(page, { timeoutMs });
7139
+ return { ok: true, value, warnings: [] };
7140
+ } catch (error) {
7141
+ return {
7142
+ ok: false,
7143
+ warnings: [`generation state DOM probe failed: ${error instanceof Error ? error.message : String(error)}`]
7144
+ };
7145
+ }
7146
+ }
7147
+ async function resolveStopControl(page, deadline) {
7148
+ const candidates = stopGenerationButton(page);
7149
+ if (typeof candidates.count !== "function") {
7150
+ return {
7151
+ ok: false,
7152
+ code: "stop_generation_control_unavailable",
7153
+ message: "ChatGPT is generating, but the Stop-control candidate set could not be enumerated safely."
7154
+ };
7155
+ }
7156
+ const count = await stopControlCount(candidates, deadline);
7157
+ if (count === 0) {
7158
+ return {
7159
+ ok: false,
7160
+ code: "stop_generation_control_unavailable",
7161
+ message: "ChatGPT is generating, but no visible Stop control was found."
7162
+ };
7163
+ }
7164
+ if (count > 8) {
7165
+ return {
7166
+ ok: false,
7167
+ code: "stop_generation_control_ambiguous",
7168
+ message: `ChatGPT exposed ${count} Stop-control candidates; refusing to choose among an unexpectedly broad set.`
7169
+ };
7170
+ }
7171
+ const eligible = [];
7172
+ for (let index = 0; index < count; index += 1) {
7173
+ const control = count === 1 ? candidates : typeof candidates.nth === "function" ? candidates.nth(index) : void 0;
7174
+ if (control === void 0 || typeof control.evaluate !== "function") {
7175
+ continue;
7176
+ }
7177
+ const evaluationTimeoutMs = Math.min(1e3, Math.max(1, remainingMs(deadline)));
7178
+ const scoped = await withinNativeStopDeadline(deadline, (timeoutMs) => control.evaluate((element) => {
7179
+ const button = element;
7180
+ if (button.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
7181
+ if (button.disabled || button.getAttribute("aria-disabled") === "true") return false;
7182
+ const visible = (node) => {
7183
+ if (node.hidden || node.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
7184
+ const style = window.getComputedStyle(node);
7185
+ const rect = node.getBoundingClientRect();
7186
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && style.pointerEvents !== "none" && (rect.width > 0 || rect.height > 0);
7187
+ };
7188
+ const textboxes = Array.from(document.querySelectorAll(
7189
+ "textarea, [contenteditable='true'], [role='textbox']"
7190
+ )).filter(visible);
7191
+ const activeComposers = [...new Set(textboxes.map((textbox) => textbox.closest("form") ?? textbox.closest("[data-testid*='composer' i]") ?? textbox.closest("[aria-label*='composer' i]") ?? textbox.closest("[class*='composer' i]")).filter((value) => value !== null))];
7192
+ return activeComposers.length === 1 && activeComposers[0].contains(button);
7193
+ }, void 0, { timeoutMs }), `Stop control ${index + 1} visibility and scope check`, evaluationTimeoutMs);
7194
+ if (scoped) eligible.push(control);
7195
+ }
7196
+ if (eligible.length === 1) {
7197
+ return { ok: true, control: eligible[0] };
7198
+ }
7199
+ if (eligible.length > 1) {
7200
+ return {
7201
+ ok: false,
7202
+ code: "stop_generation_control_ambiguous",
7203
+ message: `ChatGPT exposed ${eligible.length} visible Stop controls in active composer regions; no control was clicked.`
7204
+ };
7205
+ }
7206
+ return {
7207
+ ok: false,
7208
+ code: "stop_generation_control_unavailable",
7209
+ message: "ChatGPT is generating, but no uniquely scoped visible Stop control could be activated."
7210
+ };
7211
+ }
7212
+ async function stopControlCount(candidates, deadline) {
7213
+ if (typeof candidates.allTextContents === "function") {
7214
+ const values = await withinNativeStopDeadline(
7215
+ deadline,
7216
+ (timeoutMs) => candidates.allTextContents({ timeoutMs }),
7217
+ "Stop control enumeration",
7218
+ 1e3
7219
+ );
7220
+ return values.length;
7221
+ }
7222
+ return withinStopDeadline(deadline, () => candidates.count(), "Stop control enumeration");
7223
+ }
7224
+ async function withinStopDeadline(deadline, operation, label) {
7225
+ const budget = remainingMs(deadline);
7226
+ if (budget <= 0) throw new StopDeadlineError(label);
7227
+ try {
7228
+ return await withTimeout(operation(), budget, `${label} exceeded the messages.stop deadline.`);
7229
+ } catch (error) {
7230
+ if (remainingMs(deadline) <= 0) throw new StopDeadlineError(label);
7231
+ throw error;
7232
+ }
7233
+ }
7234
+ async function withinNativeStopDeadline(deadline, operation, label, capMs = 2e3) {
7235
+ const timeoutMs = Math.min(capMs, remainingMs(deadline));
7236
+ if (timeoutMs <= 0) throw new StopDeadlineError(label);
7237
+ try {
7238
+ return await operation(timeoutMs);
7239
+ } catch (error) {
7240
+ if (remainingMs(deadline) <= 0 || isNativeBrowserTimeout(error)) {
7241
+ throw new StopDeadlineError(label);
7242
+ }
7243
+ throw error;
7244
+ }
7245
+ }
7246
+ function isNativeBrowserTimeout(error) {
7247
+ return error instanceof Error && /timed?\s*out|timeout/i.test(error.message);
7248
+ }
7249
+ async function sleepWithinDeadline(_page, deadline, requestedMs) {
7250
+ const waitMs = Math.min(requestedMs, Math.max(0, remainingMs(deadline) - 1));
7251
+ if (waitMs <= 0) return;
7252
+ await new Promise((resolve4) => setTimeout(resolve4, waitMs));
7253
+ }
7254
+ async function stopContext(page, _deadline) {
7255
+ return contextFromPage(page, {}, { minimal: true });
7256
+ }
7257
+ function stopDeadlineResult(error, data, warnings = []) {
7258
+ const message = data?.wasGenerating === true ? "Stop activation reached its browser-native deadline and was terminated, but the click may already have taken effect. Inspect the visible generation state and do not retry automatically." : "ChatGPT generation could not be inspected and stopped before the single operation deadline.";
7259
+ const result = {
7260
+ ok: false,
7261
+ status: "timeout",
7262
+ warnings: error === void 0 ? warnings : [...warnings, error instanceof Error ? error.message : String(error)],
7263
+ blocker: {
7264
+ kind: "selector_drift",
7265
+ code: data?.wasGenerating === true ? "stop_generation_unverified" : "stop_generation_deadline_exhausted",
7266
+ message,
7267
+ resumable: data?.wasGenerating !== true
7268
+ },
7269
+ context: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
7270
+ };
7271
+ if (data !== void 0) result.data = data;
7272
+ return result;
7273
+ }
7274
+ var StopDeadlineError = class extends Error {
7275
+ constructor(label) {
7276
+ super(`${label} could not complete before the messages.stop deadline.`);
7277
+ this.name = "StopDeadlineError";
7278
+ }
7279
+ };
6171
7280
  async function clickSendControl(page) {
6172
7281
  try {
6173
7282
  await sendButton(page).click?.();
@@ -6359,7 +7468,7 @@ async function waitForMessage(env, args = {}) {
6359
7468
  context: await contextFromPage(page)
6360
7469
  });
6361
7470
  }
6362
- const metadataComplete = targetReached && snapshot.text.length > 0 && !snapshot.text.transient && Date.now() - lastChangedAt >= stableMs && !snapshot.generation.active && !snapshot.generation.stopped && hasResponseActions;
7471
+ const metadataComplete = targetReached && snapshot.text.length > 0 && !snapshot.text.transient && Date.now() - lastChangedAt >= stableMs && snapshot.generation.observed && !snapshot.generation.active && !snapshot.generation.stopped && hasResponseActions;
6363
7472
  if (metadataComplete) {
6364
7473
  const latestText = normalizeWhitespace(await fetchLatestAssistantText(page) ?? "");
6365
7474
  const fetchedMetadata = waitTextMetadata(latestText);
@@ -7906,7 +9015,8 @@ async function setMode(env, args) {
7906
9015
  return selectorDrift(page, "No unique ChatGPT mode menu opener was found.");
7907
9016
  }
7908
9017
  await page.waitForTimeout?.(250);
7909
- const candidates = await enumerateVisibleMenuItems(page);
9018
+ let candidates = await enumerateVisibleMenuItems(page);
9019
+ const observedCandidates = [...candidates];
7910
9020
  const selected = [];
7911
9021
  if (requested.length > 0 && shouldRejectAsWrongModeMenu(candidates)) {
7912
9022
  const candidateLabels2 = candidates.map((candidate) => candidate.label);
@@ -7919,9 +9029,20 @@ async function setMode(env, args) {
7919
9029
  };
7920
9030
  }
7921
9031
  for (const request of requested) {
7922
- const match = findModeMenuItem(candidates, request);
9032
+ let match = findModeMenuItem(candidates, request);
9033
+ if (match === void 0) {
9034
+ const sliderSelection = await selectModeWithPowerSlider(page, request);
9035
+ if (sliderSelection !== void 0) {
9036
+ selected.push(sliderSelection);
9037
+ continue;
9038
+ }
9039
+ const nested = await openEffortSubmenu(page, candidates, request);
9040
+ observedCandidates.push(...nested);
9041
+ candidates = nested;
9042
+ match = findModeMenuItem(candidates, request);
9043
+ }
7923
9044
  if (match === void 0) {
7924
- const candidateLabels2 = candidates.map((candidate) => candidate.label);
9045
+ const candidateLabels2 = dedupeLabels(observedCandidates.map((candidate) => candidate.label));
7925
9046
  return {
7926
9047
  ok: false,
7927
9048
  status: "unsupported",
@@ -7930,12 +9051,12 @@ async function setMode(env, args) {
7930
9051
  context: await contextFromPage(page)
7931
9052
  };
7932
9053
  }
7933
- if (!await clickMenuItem(page, match.label)) {
9054
+ if (!await clickResolvedMenuItem(page, match)) {
7934
9055
  return selectorDrift(page, `Mode option "${match.label}" was visible but could not be clicked.`, candidates.map((candidate) => candidate.label));
7935
9056
  }
7936
9057
  selected.push(match.label);
7937
9058
  }
7938
- let candidateLabels = candidates.map((candidate) => candidate.label);
9059
+ let candidateLabels = dedupeLabels(observedCandidates.map((candidate) => candidate.label));
7939
9060
  if (requestedVersion !== void 0) {
7940
9061
  const versionResult = await selectModelVersion(page, requestedVersion, candidates, args.timeoutMs ?? 3e4);
7941
9062
  candidateLabels = dedupeLabels([...candidateLabels, ...versionResult.candidates]);
@@ -7956,6 +9077,59 @@ async function setMode(env, args) {
7956
9077
  return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
7957
9078
  }
7958
9079
  }
9080
+ async function selectModeWithPowerSlider(page, request) {
9081
+ const wanted = request.modeId === void 0 ? void 0 : CANONICAL_INTELLIGENCE_ORDER.get(request.modeId);
9082
+ const slider = page.locator?.("[role='slider'][aria-valuemin='0'][aria-valuemax='4']");
9083
+ if (wanted === void 0 || slider?.count === void 0 || slider.evaluate === void 0 || slider.press === void 0 || slider.isVisible === void 0 || !await slider.isVisible().catch(() => false) || await slider.count().catch(() => 0) !== 1) {
9084
+ return void 0;
9085
+ }
9086
+ const state = await slider.evaluate((element) => ({
9087
+ min: Number(element.getAttribute("aria-valuemin")),
9088
+ max: Number(element.getAttribute("aria-valuemax")),
9089
+ now: Number(element.getAttribute("aria-valuenow"))
9090
+ })).catch(() => void 0);
9091
+ if (state === void 0 || state.min !== 0 || state.max !== CANONICAL_INTELLIGENCE_ORDER.size - 1 || !Number.isInteger(state.now) || state.now < state.min || state.now > state.max) {
9092
+ return void 0;
9093
+ }
9094
+ const key = wanted > state.now ? "ArrowRight" : "ArrowLeft";
9095
+ for (let step = 0; step < Math.abs(wanted - state.now); step += 1) {
9096
+ await slider.press(key);
9097
+ }
9098
+ await page.waitForTimeout?.(150);
9099
+ return findUniqueVisibleLabelForRequest(await visibleModeButtonLabelList(page), request);
9100
+ }
9101
+ async function openEffortSubmenu(page, rootItems, request) {
9102
+ const axisLabels = [
9103
+ ...localeLabels.configurationAxes.effort,
9104
+ ...localeLabels.configurationAxes.intelligence
9105
+ ].map(normalizeForLabelMatch);
9106
+ const effortRows = (items) => items.filter((item) => {
9107
+ if (item.role === "menuitemradio") return false;
9108
+ const normalized = normalizeForLabelMatch(item.label);
9109
+ return axisLabels.some((axis) => normalized === axis || normalized.startsWith(`${axis} `));
9110
+ });
9111
+ let visibleRootItems = rootItems;
9112
+ let rows = effortRows(visibleRootItems);
9113
+ if (rows.length === 0) {
9114
+ const advancedLabels = localeLabels.configurationAxes.advanced.map(normalizeForLabelMatch);
9115
+ const advancedRows = visibleRootItems.filter((item) => {
9116
+ const normalized = normalizeForLabelMatch(item.label);
9117
+ return advancedLabels.some((label) => normalized === label || visibleLabelMatches(item.label, label));
9118
+ });
9119
+ if (advancedRows.length !== 1 || !await clickResolvedMenuItem(page, advancedRows[0])) {
9120
+ return [];
9121
+ }
9122
+ await page.waitForTimeout?.(250);
9123
+ visibleRootItems = await enumerateVisibleMenuItems(page);
9124
+ rows = effortRows(visibleRootItems);
9125
+ }
9126
+ if (rows.length !== 1 || !await clickResolvedMenuItem(page, rows[0])) {
9127
+ return [];
9128
+ }
9129
+ await page.waitForTimeout?.(250);
9130
+ const nested = await enumerateVisibleMenuItems(page);
9131
+ return findModeMenuItem(nested, request) === void 0 ? [] : nested;
9132
+ }
7959
9133
  async function modeVerificationWarnings(page, requested, selected) {
7960
9134
  if (requested.length === 0) {
7961
9135
  return [];
@@ -8047,7 +9221,7 @@ async function selectTool(env, args) {
8047
9221
  context: await contextFromPage(page)
8048
9222
  };
8049
9223
  }
8050
- if (!await clickMenuItem(page, match.label)) {
9224
+ if (!await clickMenuItem(page, match)) {
8051
9225
  return selectorDrift(page, `Tool "${match.label}" was visible but could not be clicked.`, candidates.map((candidate) => candidate.label));
8052
9226
  }
8053
9227
  return resultOk({ selected: match.label, candidates: candidates.map((candidate) => candidate.label) }, await contextFromPage(page));
@@ -8115,25 +9289,25 @@ function shouldRejectAsWrongModeMenu(items) {
8115
9289
  }
8116
9290
  return items.some((item) => isThreadActionLabel(item.label));
8117
9291
  }
8118
- async function clickMenuItem(page, label) {
8119
- if (await clickModelSwitcherMenuItem(page, label)) {
8120
- return true;
8121
- }
8122
- if (await clickMenuItemByPointer(page, label)) {
9292
+ async function clickMenuItem(page, item) {
9293
+ if (await clickModelSwitcherMenuItem(page, item)) {
8123
9294
  return true;
8124
9295
  }
8125
- if (await clickMenuItemByDom(page, label)) {
9296
+ if (await clickMenuItemByPointer(page, item)) {
8126
9297
  return true;
8127
9298
  }
8128
- const roleLocator = page.locator?.("[role='menuitem'], [role='menuitemradio'], [role='option']")?.filter?.({ hasText: label });
8129
- if (await clickIfUnique2(roleLocator)) {
8130
- return true;
9299
+ if (item.role !== void 0) {
9300
+ const accessibleName = item.ariaLabel ?? item.label;
9301
+ if (await clickIfUniqueMenuControl(
9302
+ page.getByRole?.(item.role, { name: accessibleName, exact: true }),
9303
+ item
9304
+ )) return true;
8131
9305
  }
8132
- const textLocator = page.getByText?.(label, { exact: true });
8133
- return clickIfUnique2(textLocator);
9306
+ const roleLocator = page.locator?.("[role='menuitem'], [role='menuitemradio'], [role='option']")?.filter?.({ hasText: new RegExp(`^\\s*${escapeRegExp3(item.label)}\\s*$`, "i") });
9307
+ return clickIfUniqueMenuControl(roleLocator, item);
8134
9308
  }
8135
- async function clickMenuItemByPointer(page, label) {
8136
- const point = await menuItemCenter(page, { label });
9309
+ async function clickMenuItemByPointer(page, item) {
9310
+ const point = await menuItemCenter(page, item);
8137
9311
  if (point === void 0) {
8138
9312
  return false;
8139
9313
  }
@@ -8148,43 +9322,27 @@ async function clickMenuItemByPointer(page, label) {
8148
9322
  }
8149
9323
  return false;
8150
9324
  }
8151
- async function clickModelSwitcherMenuItem(page, label) {
9325
+ async function clickModelSwitcherMenuItem(page, item) {
8152
9326
  if (typeof page.evaluate !== "function" || typeof page.locator !== "function") {
8153
9327
  return false;
8154
9328
  }
8155
9329
  const testId = await page.evaluate((wanted) => {
8156
- const normalizedWanted = wanted.replace(/\s+/g, " ").trim().toLowerCase();
9330
+ const normalizedWanted = wanted.label.replace(/\s+/g, " ").trim().toLowerCase();
8157
9331
  const candidates = Array.from(document.querySelectorAll("[data-testid^='model-switcher-']"));
8158
9332
  const matches = candidates.filter((node) => {
8159
9333
  const element = node;
8160
9334
  const candidateTestId = element.getAttribute("data-testid") ?? "";
8161
9335
  if (candidateTestId.endsWith("-effort")) return false;
9336
+ if (wanted.testId !== void 0 && candidateTestId !== wanted.testId) return false;
8162
9337
  const text = (element.innerText ?? element.textContent ?? "").replace(/\s+/g, " ").trim().toLowerCase();
8163
9338
  return text === normalizedWanted;
8164
9339
  }).map((node) => node.getAttribute("data-testid")).filter((value) => value !== null);
8165
9340
  return matches.length === 1 ? matches[0] : void 0;
8166
- }, label).catch(() => void 0);
9341
+ }, item.testId === void 0 ? { label: item.label } : { label: item.label, testId: item.testId }).catch(() => void 0);
8167
9342
  if (testId === void 0) {
8168
9343
  return false;
8169
9344
  }
8170
- return clickIfUnique2(page.locator(`[data-testid="${escapeAttributeValue(testId)}"]`));
8171
- }
8172
- async function clickMenuItemByDom(page, label) {
8173
- if (typeof page.evaluate !== "function") {
8174
- return false;
8175
- }
8176
- return page.evaluate((wanted) => {
8177
- const normalizedWanted = wanted.replace(/\s+/g, " ").trim().toLowerCase();
8178
- const candidates = Array.from(document.querySelectorAll("[role='menuitem'], [role='menuitemradio'], [role='option']"));
8179
- const matches = candidates.filter((node) => {
8180
- const element = node;
8181
- const text = (element.innerText ?? element.textContent ?? "").replace(/\s+/g, " ").trim().toLowerCase();
8182
- return text === normalizedWanted;
8183
- });
8184
- if (matches.length !== 1) return false;
8185
- matches[0].click();
8186
- return true;
8187
- }, label).catch(() => false);
9345
+ return clickIfUniqueMenuControl(page.locator(`[data-testid="${escapeAttributeValue(testId)}"]`), item);
8188
9346
  }
8189
9347
  async function clickIfUnique2(locator) {
8190
9348
  if (locator === void 0 || typeof locator.count !== "function" || typeof locator.click !== "function") {
@@ -8197,6 +9355,32 @@ async function clickIfUnique2(locator) {
8197
9355
  await locator.click();
8198
9356
  return true;
8199
9357
  }
9358
+ async function clickIfUniqueMenuControl(locator, item) {
9359
+ if (locator === void 0 || typeof locator.count !== "function" || typeof locator.evaluate !== "function" || typeof locator.click !== "function") {
9360
+ return false;
9361
+ }
9362
+ if (await locator.count().catch(() => 0) !== 1) return false;
9363
+ const safe = await locator.evaluate((element) => {
9364
+ const control = element;
9365
+ if (control.disabled || control.getAttribute("aria-disabled") === "true") return false;
9366
+ if (control.hidden || control.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
9367
+ const style = window.getComputedStyle(control);
9368
+ const rect = control.getBoundingClientRect();
9369
+ if (rect.width <= 0 || rect.height <= 0 || style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none") return false;
9370
+ const containers = Array.from(document.querySelectorAll(
9371
+ "[role='menu'], [role='listbox'], [data-radix-popper-content-wrapper]"
9372
+ )).filter((container) => {
9373
+ if (container.hidden || container.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
9374
+ const containerStyle = window.getComputedStyle(container);
9375
+ const containerRect = container.getBoundingClientRect();
9376
+ return containerRect.width > 0 && containerRect.height > 0 && containerStyle.display !== "none" && containerStyle.visibility !== "hidden" && containerStyle.opacity !== "0";
9377
+ });
9378
+ return containers.length > 0 && containers.some((container) => container.contains(control));
9379
+ }).catch(() => false);
9380
+ if (!safe) return false;
9381
+ await locator.click();
9382
+ return true;
9383
+ }
8200
9384
  function toolLabels(tool) {
8201
9385
  const known = localeLabels.tools[tool];
8202
9386
  return known !== void 0 ? [...known] : [tool];
@@ -8280,6 +9464,9 @@ function findUniqueVisibleLabel(labels, wanted) {
8280
9464
  const fuzzy = labels.filter((label) => visibleLabelMatches(normalizeLabel(label), normalized));
8281
9465
  return fuzzy.length === 1 ? fuzzy[0] : void 0;
8282
9466
  }
9467
+ function escapeRegExp3(value) {
9468
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9469
+ }
8283
9470
  function escapeAttributeValue(value) {
8284
9471
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
8285
9472
  }
@@ -8320,17 +9507,19 @@ function isModelVersionSubmenuOpener(item) {
8320
9507
  return item.hasPopup === true || item.role !== "menuitemradio" && MODEL_VERSION_FAMILY_PATTERN.test(item.label);
8321
9508
  }
8322
9509
  async function clickResolvedMenuItem(page, item) {
8323
- if (item.testId !== void 0 && await clickIfUnique2(
8324
- page.locator?.(`[data-testid="${escapeAttributeValue(item.testId)}"]`)
9510
+ if (item.testId !== void 0 && await clickIfUniqueMenuControl(
9511
+ page.locator?.(`[data-testid="${escapeAttributeValue(item.testId)}"]`),
9512
+ item
8325
9513
  )) {
8326
9514
  return true;
8327
9515
  }
8328
- if (item.role !== void 0 && await clickIfUnique2(
8329
- page.getByRole?.(item.role, { name: item.label, exact: true })
9516
+ if (item.role !== void 0 && await clickIfUniqueMenuControl(
9517
+ page.getByRole?.(item.role, { name: item.ariaLabel ?? item.label, exact: true }),
9518
+ item
8330
9519
  )) {
8331
9520
  return true;
8332
9521
  }
8333
- return clickMenuItem(page, item.label);
9522
+ return clickMenuItem(page, item);
8334
9523
  }
8335
9524
  async function openModelVersionSubmenu(page, candidates) {
8336
9525
  const submenuOpeners = candidates.filter((item) => item.hasPopup === true || MODEL_VERSION_FAMILY_PATTERN.test(item.label));
@@ -8344,7 +9533,7 @@ async function openModelVersionSubmenu(page, candidates) {
8344
9533
  return true;
8345
9534
  }
8346
9535
  }
8347
- if (await clickMenuItem(page, candidate.label)) {
9536
+ if (await clickMenuItem(page, candidate)) {
8348
9537
  await page.waitForTimeout?.(250);
8349
9538
  if (await modelVersionMenuItemsAreVisible(page)) {
8350
9539
  return true;
@@ -8381,18 +9570,26 @@ async function menuItemCenter(page, item, roles = ["menuitem", "menuitemradio",
8381
9570
  const normalize = (value) => value.replace(/\s+/g, " ").trim().toLowerCase();
8382
9571
  const normalizedLabel = normalize(target2.label);
8383
9572
  const roleSelector = target2.roles.map((role) => `[role='${role}']`).join(",");
9573
+ const visible = (element) => {
9574
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
9575
+ const rect2 = element.getBoundingClientRect();
9576
+ const style = window.getComputedStyle(element);
9577
+ return rect2.width > 0 && rect2.height > 0 && style.visibility !== "hidden" && style.display !== "none" && style.opacity !== "0" && style.pointerEvents !== "none";
9578
+ };
9579
+ const containers = Array.from(document.querySelectorAll(
9580
+ "[role='menu'], [role='listbox'], [data-radix-popper-content-wrapper]"
9581
+ )).filter(visible);
8384
9582
  const matches = Array.from(document.querySelectorAll(roleSelector)).filter((node) => {
8385
9583
  const element = node;
8386
9584
  if (target2.testId !== void 0 && element.getAttribute("data-testid") !== target2.testId) {
8387
9585
  return false;
8388
9586
  }
9587
+ if (element.disabled || element.getAttribute("aria-disabled") === "true") return false;
8389
9588
  const label = normalize(element.innerText ?? element.textContent ?? "");
8390
9589
  if (label !== normalizedLabel) {
8391
9590
  return false;
8392
9591
  }
8393
- const rect2 = element.getBoundingClientRect();
8394
- const style = window.getComputedStyle(element);
8395
- return rect2.width > 0 && rect2.height > 0 && style.visibility !== "hidden" && style.display !== "none" && style.opacity !== "0";
9592
+ return visible(element) && containers.length > 0 && containers.some((container) => container.contains(element));
8396
9593
  });
8397
9594
  if (matches.length !== 1) return void 0;
8398
9595
  const rect = matches[0].getBoundingClientRect();
@@ -8470,6 +9667,11 @@ async function visibleModeButtonLabelList(page) {
8470
9667
  ));
8471
9668
  return Array.from(document.querySelectorAll("button, [role='button']")).map((node) => {
8472
9669
  const element = node;
9670
+ if (element.hidden || element.getAttribute("aria-hidden") === "true" || typeof element.closest === "function" && element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return "";
9671
+ const style = typeof window?.getComputedStyle === "function" ? window.getComputedStyle(element) : void 0;
9672
+ if (style?.display === "none" || style?.visibility === "hidden" || style?.opacity === "0" || style?.pointerEvents === "none") return "";
9673
+ const rect = typeof element.getBoundingClientRect === "function" ? element.getBoundingClientRect() : { width: 1, height: 1 };
9674
+ if (rect.width <= 0 && rect.height <= 0) return "";
8473
9675
  if (scopedRoots.length > 0 && !scopedRoots.some((root) => root.contains(node))) return "";
8474
9676
  const visibleText = (element.innerText ?? element.textContent ?? "").replace(/\s+/g, " ").trim();
8475
9677
  const ariaLabel = (element.getAttribute("aria-label") ?? "").replace(/\s+/g, " ").trim();
@@ -8530,6 +9732,7 @@ async function inspectConfiguration(env, args = {}) {
8530
9732
  };
8531
9733
  }
8532
9734
  const experience = detected.data.experience;
9735
+ const initialPanel = await readConfigurationPanel(page);
8533
9736
  const rootOpened = experience !== "unknown" && await waitForConfigurationRoot(
8534
9737
  page,
8535
9738
  experience,
@@ -8543,6 +9746,9 @@ async function inspectConfiguration(env, args = {}) {
8543
9746
  await page.waitForTimeout?.(150);
8544
9747
  }
8545
9748
  const panel = await readConfigurationPanel(page);
9749
+ if (panel.openerLabel === void 0 && initialPanel.openerLabel !== void 0) {
9750
+ panel.openerLabel = initialPanel.openerLabel;
9751
+ }
8546
9752
  const rootItems = rootOpened ? await enumerateVisibleMenuItems(page) : [];
8547
9753
  const data = configurationInspectionFromSurface(
8548
9754
  experience,
@@ -8909,14 +10115,12 @@ async function openConfigurationRoot(page, experience) {
8909
10115
  }
8910
10116
  return true;
8911
10117
  };
8912
- const composerRoots = Array.from(document.querySelectorAll(
8913
- "main form, main [data-testid*='composer' i], main [class*='composer' i]"
8914
- ));
10118
+ const formRoots = Array.from(document.querySelectorAll("main form"));
10119
+ const testIdRoots = Array.from(document.querySelectorAll("main [data-testid*='composer' i]"));
10120
+ const classRoots = Array.from(document.querySelectorAll("main [class*='composer' i]"));
10121
+ const composerRoots = formRoots.length > 0 ? formRoots : testIdRoots.length > 0 ? testIdRoots : classRoots;
8915
10122
  const main = document.querySelector("main");
8916
- const roots = Array.from(/* @__PURE__ */ new Set([
8917
- ...composerRoots,
8918
- ...main === null ? [] : [main]
8919
- ]));
10123
+ const roots = Array.from(new Set(composerRoots.length > 0 ? composerRoots : main === null ? [] : [main]));
8920
10124
  const controls = Array.from(new Set(roots.flatMap(
8921
10125
  (root) => Array.from(root.querySelectorAll("button, [role='button']"))
8922
10126
  ))).filter(visible);
@@ -9052,14 +10256,12 @@ async function readConfigurationPanel(page) {
9052
10256
  break;
9053
10257
  }
9054
10258
  }
9055
- const composerRoots = Array.from(document.querySelectorAll(
9056
- "main form, main [data-testid*='composer' i], main [class*='composer' i]"
9057
- ));
10259
+ const formRoots = Array.from(document.querySelectorAll("main form"));
10260
+ const testIdRoots = Array.from(document.querySelectorAll("main [data-testid*='composer' i]"));
10261
+ const classRoots = Array.from(document.querySelectorAll("main [class*='composer' i]"));
10262
+ const composerRoots = formRoots.length > 0 ? formRoots : testIdRoots.length > 0 ? testIdRoots : classRoots;
9058
10263
  const main = document.querySelector("main");
9059
- const openerRoots = Array.from(/* @__PURE__ */ new Set([
9060
- ...composerRoots,
9061
- ...main === null ? [] : [main]
9062
- ]));
10264
+ const openerRoots = Array.from(new Set(composerRoots.length > 0 ? composerRoots : main === null ? [] : [main]));
9063
10265
  const openerCandidates = Array.from(new Set(openerRoots.flatMap(
9064
10266
  (root) => Array.from(root.querySelectorAll("button, [role='button']"))
9065
10267
  ))).filter(visible).map((control) => {
@@ -9082,7 +10284,7 @@ async function readConfigurationPanel(page) {
9082
10284
  async function findWorkAxisRow(page, axis) {
9083
10285
  const labels = axis === "modelVersion" ? [] : localeLabels.configurationAxes[axis] ?? [];
9084
10286
  for (const label of labels) {
9085
- const pattern = new RegExp(`^${escapeRegExp3(label)}(?:\\s|$)`, "i");
10287
+ const pattern = new RegExp(`^${escapeRegExp4(label)}(?:\\s|$)`, "i");
9086
10288
  for (const role of ["button", "menuitem"]) {
9087
10289
  const locator = page.getByRole?.(role, { name: pattern });
9088
10290
  if (locator?.count !== void 0 && await locator.count().catch(() => 0) === 1) {
@@ -9096,12 +10298,28 @@ async function clickVisibleMenuItem(page, item) {
9096
10298
  if (item.testId !== void 0 && await clickIfUnique3(page.locator?.(`[data-testid="${escapeAttributeValue2(item.testId)}"]`))) {
9097
10299
  return true;
9098
10300
  }
9099
- for (const role of ["menuitemradio", "menuitem", "option"]) {
9100
- if (await clickIfUnique3(page.getByRole?.(role, { name: item.label, exact: true }))) {
10301
+ const roles = [...new Set([
10302
+ item.role,
10303
+ "menuitemradio",
10304
+ "menuitem",
10305
+ "option"
10306
+ ].filter((role) => role !== void 0))];
10307
+ if (item.ariaLabel !== void 0) {
10308
+ for (const role of roles) {
10309
+ if (await clickIfUnique3(page.getByRole?.(role, { name: item.ariaLabel, exact: true }))) {
10310
+ return true;
10311
+ }
10312
+ }
10313
+ }
10314
+ for (const role of roles) {
10315
+ if (await clickIfUnique3(page.getByRole?.(role, { name: item.label, exact: true }))) {
9101
10316
  return true;
9102
10317
  }
9103
10318
  }
9104
- return clickIfUnique3(page.getByText?.(item.label, { exact: true }));
10319
+ const exactText = new RegExp(`^\\s*${escapeRegExp4(item.label)}\\s*$`, "i");
10320
+ return clickIfUnique3(page.locator?.(
10321
+ "button, [role='button'], [role='menuitem'], [role='menuitemradio'], [role='option']"
10322
+ )?.filter?.({ hasText: exactText }));
9105
10323
  }
9106
10324
  function findConfigurationOption(items, requested) {
9107
10325
  const normalizedRequested = normalizeConfigurationId(requested);
@@ -9280,7 +10498,7 @@ async function configurationFailure(page, before, desired, selected, message, co
9280
10498
  })
9281
10499
  };
9282
10500
  }
9283
- function escapeRegExp3(value) {
10501
+ function escapeRegExp4(value) {
9284
10502
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9285
10503
  }
9286
10504
  function escapeAttributeValue2(value) {
@@ -9451,6 +10669,7 @@ async function preflightFiles(env, args) {
9451
10669
  return resultOk({ files, totalBytes }, filePreflightContext(env), warnings);
9452
10670
  }
9453
10671
  async function attachFiles(env, args) {
10672
+ const deadline = createDeadline(Math.max(1, args.timeoutMs ?? 3e4));
9454
10673
  const preflightArgs = { paths: args.paths };
9455
10674
  if (args.includeDiagnostics === true && args.includeHashes !== void 0) {
9456
10675
  preflightArgs.includeHashes = args.includeHashes;
@@ -9459,50 +10678,57 @@ async function attachFiles(env, args) {
9459
10678
  if (!preflight.ok || preflight.data === void 0) {
9460
10679
  return preflight;
9461
10680
  }
9462
- const boot = await ensurePage(env);
10681
+ let boot;
10682
+ try {
10683
+ boot = await withinAttachmentDeadline(
10684
+ deadline,
10685
+ () => ensurePage(env, { minimalContext: true }),
10686
+ "ChatGPT page verification"
10687
+ );
10688
+ } catch (error) {
10689
+ if (error instanceof AttachmentDeadlineError || remainingMs(deadline) <= 0) {
10690
+ return attachmentDeadlineResult(error);
10691
+ }
10692
+ return resultError(error instanceof Error ? error : new Error(String(error)));
10693
+ }
9463
10694
  if (!boot.ok) {
9464
10695
  return boot;
9465
10696
  }
9466
10697
  const page = env.page;
10698
+ const mutationState = { handoffStarted: false };
9467
10699
  try {
9468
10700
  const files = preflight.data.files.map((file) => ({
9469
10701
  path: file.path,
9470
10702
  name: file.name,
9471
10703
  bytes: file.bytes
9472
10704
  }));
9473
- await uploadFiles(page, files, args.timeoutMs ?? 3e4);
9474
- const browserInput = args.includeDiagnostics === true ? await readBrowserInputDiagnostic(page).catch(() => void 0) : void 0;
9475
- await page.waitForTimeout?.(args.timeoutMs === void 0 ? 1e3 : Math.min(args.timeoutMs, 3e3));
9476
- const readiness = await waitForAttachedFilesReady(page, files, args.timeoutMs ?? 3e4);
10705
+ const rawBaseline = await withinNativeAttachmentDeadline(
10706
+ deadline,
10707
+ (timeoutMs) => readAttachmentEvidenceBaseline(page, timeoutMs),
10708
+ "Pre-upload attachment baseline",
10709
+ 2e3
10710
+ ).catch(() => ({ supported: false, inputFiles: [], attachmentLabels: [] }));
10711
+ const baseline = rawBaseline !== null && typeof rawBaseline === "object" && Array.isArray(rawBaseline.inputFiles) && Array.isArray(rawBaseline.attachmentLabels) ? rawBaseline : { supported: false, inputFiles: [], attachmentLabels: [] };
10712
+ await uploadFiles(page, files, deadline, mutationState);
10713
+ const browserInput = args.includeDiagnostics === true ? await withinNativeAttachmentDeadline(
10714
+ deadline,
10715
+ (timeoutMs) => readBrowserInputDiagnostic(page, timeoutMs),
10716
+ "Browser input diagnostic",
10717
+ 2e3
10718
+ ).catch(() => void 0) : void 0;
10719
+ await attachmentDelay(
10720
+ page,
10721
+ deadline,
10722
+ Math.min(250, Math.max(1, Math.floor(remainingMs(deadline) / 4)))
10723
+ );
10724
+ const readiness = await waitForAttachedFilesReady(page, files, baseline, deadline);
9477
10725
  if (!readiness.ready) {
9478
- const blocker = {
9479
- kind: "upload_failed",
9480
- code: "attachment_processing",
9481
- message: "ChatGPT still appears to be processing the attached file, so the prompt was not submitted.",
9482
- remediation: [
9483
- {
9484
- label: "Wait for upload",
9485
- instruction: "Wait until the visible attachment finishes uploading or processing, then retry the askWithFiles call.",
9486
- userActionRequired: false
9487
- },
9488
- {
9489
- label: "Retry smaller file",
9490
- instruction: "If processing never finishes, retry with a smaller file or a different supported file type.",
9491
- userActionRequired: true
9492
- }
9493
- ],
9494
- resumable: true
9495
- };
9496
- if (readiness.processingText !== void 0) {
9497
- blocker.visibleText = readiness.processingText;
9498
- }
9499
- return {
9500
- ok: false,
9501
- status: "blocked",
9502
- warnings: [],
9503
- blocker,
9504
- context: await contextFromPage(page)
9505
- };
10726
+ return attachmentOutcomeIndeterminate(
10727
+ files,
10728
+ [],
10729
+ await attachmentContext(page, deadline),
10730
+ readiness.processingText
10731
+ );
9506
10732
  }
9507
10733
  const data = { files };
9508
10734
  if (args.includeDiagnostics === true) {
@@ -9511,9 +10737,49 @@ async function attachFiles(env, args) {
9511
10737
  data.diagnostics.browserInput = browserInput;
9512
10738
  }
9513
10739
  }
9514
- return resultOk(data, await contextFromPage(page), preflight.warnings);
10740
+ return resultOk(data, await attachmentContext(page, deadline), preflight.warnings);
9515
10741
  } catch (error) {
9516
- if (isUploadBridgeBlocker(error)) {
10742
+ if (mutationState.handoffStarted) {
10743
+ const permissionFailure = isUploadPermissionBlocker(error);
10744
+ return attachmentOutcomeIndeterminate(
10745
+ preflight.data.files,
10746
+ [error instanceof Error ? error.message : String(error)],
10747
+ await attachmentContext(page, deadline),
10748
+ permissionFailure ? uploadPermissionDetails(error) : void 0,
10749
+ permissionFailure ? uploadPermissionRemediation() : void 0
10750
+ );
10751
+ }
10752
+ if (error instanceof AttachmentDeadlineError || remainingMs(deadline) <= 0) {
10753
+ return attachmentDeadlineResult(error);
10754
+ }
10755
+ if (isUploadTransportFailure(error)) {
10756
+ return {
10757
+ ok: false,
10758
+ status: "blocked",
10759
+ warnings: [],
10760
+ blocker: {
10761
+ kind: "browser_bridge_unavailable",
10762
+ code: "upload_transport_failed",
10763
+ message: "The Codex Chrome bridge disconnected while handing files to ChatGPT's visible composer. File attachment did not complete, so callers must not submit the prompt.",
10764
+ visibleText: error instanceof Error ? error.message : String(error),
10765
+ remediation: [
10766
+ {
10767
+ label: "Retry live attachment",
10768
+ instruction: "Retry the attachment from the live Codex Chrome runtime; the operation is safe to resume because file attachment did not complete.",
10769
+ userActionRequired: false
10770
+ },
10771
+ {
10772
+ label: "Restart bridge if repeated",
10773
+ instruction: "If the bridge disconnects again, restart Chrome or Codex before retrying. Do not change upload permissions unless Chrome explicitly reports a permission denial.",
10774
+ userActionRequired: true
10775
+ }
10776
+ ],
10777
+ resumable: true
10778
+ },
10779
+ context: await attachmentContext(page, deadline)
10780
+ };
10781
+ }
10782
+ if (isUploadPermissionBlocker(error)) {
9517
10783
  return {
9518
10784
  ok: false,
9519
10785
  status: "blocked",
@@ -9526,12 +10792,68 @@ async function attachFiles(env, args) {
9526
10792
  remediation: uploadPermissionRemediation(),
9527
10793
  resumable: true
9528
10794
  },
9529
- context: await contextFromPage(page)
10795
+ context: await attachmentContext(page, deadline)
9530
10796
  };
9531
10797
  }
9532
- return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
10798
+ if (isUploadPathFailure(error)) {
10799
+ return {
10800
+ ok: false,
10801
+ status: "blocked",
10802
+ warnings: [],
10803
+ blocker: {
10804
+ kind: "upload_failed",
10805
+ code: "upload_path_unavailable",
10806
+ message: "None of the browser's supported ChatGPT file-attachment paths completed. Callers must not submit the prompt.",
10807
+ visibleText: error instanceof Error ? error.message : String(error),
10808
+ remediation: [
10809
+ {
10810
+ label: "Retry live attachment",
10811
+ instruction: "Retry from the live Codex Chrome runtime after confirming the ChatGPT composer is visible. Do not change upload permissions unless Chrome explicitly reports a permission denial.",
10812
+ userActionRequired: false
10813
+ }
10814
+ ],
10815
+ resumable: true
10816
+ },
10817
+ context: await attachmentContext(page, deadline)
10818
+ };
10819
+ }
10820
+ return resultError(error instanceof Error ? error : new Error(String(error)), await attachmentContext(page, deadline));
9533
10821
  }
9534
10822
  }
10823
+ function attachmentDeadlineResult(error) {
10824
+ return {
10825
+ ok: false,
10826
+ status: "timeout",
10827
+ warnings: error === void 0 ? [] : [error instanceof Error ? error.message : String(error)],
10828
+ blocker: {
10829
+ kind: "upload_failed",
10830
+ code: "attachment_deadline_exhausted",
10831
+ message: "ChatGPT file attachment did not complete before the caller's single operation deadline. The prompt was not submitted.",
10832
+ resumable: true
10833
+ },
10834
+ context: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
10835
+ };
10836
+ }
10837
+ function attachmentOutcomeIndeterminate(files, warnings, context, visibleText, remediation) {
10838
+ const blocker = {
10839
+ kind: "upload_failed",
10840
+ code: "attachment_outcome_indeterminate",
10841
+ message: "The native file handoff started, but its outcome could not be verified. The browser request is no longer in flight, though the file may already be present. Inspect the current composer; do not submit or retry automatically.",
10842
+ resumable: false
10843
+ };
10844
+ if (visibleText !== void 0) blocker.visibleText = visibleText;
10845
+ if (remediation !== void 0) blocker.remediation = remediation;
10846
+ return {
10847
+ ok: false,
10848
+ status: "partial",
10849
+ data: {
10850
+ files: files.map((file) => ({ path: file.path, name: file.name, bytes: file.bytes }))
10851
+ },
10852
+ warnings,
10853
+ blocker,
10854
+ context
10855
+ };
10856
+ }
9535
10857
  function filePreflightBlocker(args) {
9536
10858
  return {
9537
10859
  ok: false,
@@ -9642,44 +10964,120 @@ function guessFileType(extension) {
9642
10964
  function isNodeError2(error) {
9643
10965
  return error instanceof Error && "code" in error;
9644
10966
  }
9645
- async function waitForAttachedFilesReady(page, files, timeoutMs) {
9646
- const started = Date.now();
10967
+ async function readAttachmentEvidenceBaseline(page, timeoutMs) {
10968
+ if (typeof page.evaluate !== "function") {
10969
+ return { supported: false, inputFiles: [], attachmentLabels: [] };
10970
+ }
10971
+ return page.evaluate(() => {
10972
+ const visible = (element) => {
10973
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
10974
+ const style = window.getComputedStyle(element);
10975
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
10976
+ const rect = element.getBoundingClientRect();
10977
+ return rect.width > 0 || rect.height > 0;
10978
+ };
10979
+ const textboxes = Array.from(document.querySelectorAll(
10980
+ "textarea, [contenteditable='true'], [role='textbox']"
10981
+ )).filter(visible);
10982
+ const composers = [...new Set(textboxes.map((textbox) => textbox.closest("form") ?? textbox.closest("[data-testid*='composer' i]") ?? textbox.closest("[aria-label*='composer' i]") ?? textbox.closest("[class*='composer' i]")).filter((value) => value !== null))];
10983
+ if (composers.length !== 1) {
10984
+ return { supported: false, inputFiles: [], attachmentLabels: [] };
10985
+ }
10986
+ const composer = composers[0];
10987
+ const allInputs = Array.from(composer.querySelectorAll("input[type='file']")).filter((input) => !input.disabled && input.getAttribute("aria-disabled") !== "true");
10988
+ const preferred = allInputs.filter((input) => input.id === "upload-files");
10989
+ const nonImage = allInputs.filter((input) => input.getAttribute("accept") !== "image/*");
10990
+ const inputs = preferred.length > 0 ? preferred : nonImage.length > 0 ? nonImage : allInputs;
10991
+ if (inputs.length !== 1) {
10992
+ return { supported: false, inputFiles: [], attachmentLabels: [] };
10993
+ }
10994
+ const attachmentSelector = [
10995
+ "[data-testid*='attachment' i]",
10996
+ "[data-testid*='file' i]",
10997
+ "[aria-label*='attachment' i]",
10998
+ "[aria-label*='upload' i]",
10999
+ "[aria-label*='file' i]",
11000
+ "[class*='attachment' i]",
11001
+ "[class*='upload' i]",
11002
+ "[class*='file' i]",
11003
+ "[role='progressbar']"
11004
+ ].join(", ");
11005
+ const labels = Array.from(composer.querySelectorAll(attachmentSelector)).filter(visible).map((element) => [
11006
+ element.textContent ?? "",
11007
+ element.getAttribute("aria-label") ?? "",
11008
+ element.getAttribute("title") ?? ""
11009
+ ].join(" ").replace(/\s+/g, " ").trim().toLocaleLowerCase()).filter(Boolean);
11010
+ return {
11011
+ supported: true,
11012
+ inputFiles: Array.from(inputs[0].files ?? []).map((file) => `${file.name.toLocaleLowerCase()}\0${file.size}`),
11013
+ attachmentLabels: labels
11014
+ };
11015
+ }, void 0, { timeoutMs });
11016
+ }
11017
+ async function waitForAttachedFilesReady(page, files, baseline, deadline) {
9647
11018
  let lastProcessingText;
9648
- while (Date.now() - started < timeoutMs) {
9649
- const snapshot = await readAttachmentReadiness(page, files).catch(() => void 0);
9650
- if (snapshot === void 0) {
9651
- return { ready: true };
11019
+ let sawProcessing = false;
11020
+ while (remainingMs(deadline) > 0) {
11021
+ const snapshot = await withinNativeAttachmentDeadline(
11022
+ deadline,
11023
+ (timeoutMs) => readAttachmentReadiness(page, files, baseline, timeoutMs),
11024
+ "Attachment readiness inspection",
11025
+ 2e3
11026
+ ).catch(() => void 0);
11027
+ if (snapshot === void 0 || snapshot.supported === false) {
11028
+ return { ready: false, reason: "unverified" };
9652
11029
  }
9653
- const allNamesVisible = snapshot.files.length > 0 && snapshot.files.every((file) => file.visible);
11030
+ const allNamesVisible = snapshot.files.length === files.length && snapshot.files.every((file) => file.visible);
9654
11031
  if (!snapshot.processing && allNamesVisible) {
9655
11032
  return { ready: true };
9656
11033
  }
9657
- if (!snapshot.processing && Date.now() - started >= Math.min(timeoutMs, 1e3)) {
9658
- return { ready: true };
9659
- }
11034
+ sawProcessing ||= snapshot.processing;
9660
11035
  if (snapshot.processingText !== void 0) {
9661
11036
  lastProcessingText = snapshot.processingText;
9662
11037
  }
9663
- await page.waitForTimeout?.(250);
11038
+ const pollBudget = remainingMs(deadline);
11039
+ if (pollBudget <= 10) break;
11040
+ await attachmentDelay(page, deadline, Math.min(250, pollBudget - 10));
9664
11041
  }
9665
- const blocked2 = { ready: false };
11042
+ const blocked2 = {
11043
+ ready: false,
11044
+ reason: sawProcessing ? "processing" : "unverified"
11045
+ };
9666
11046
  if (lastProcessingText !== void 0) {
9667
11047
  blocked2.processingText = lastProcessingText;
9668
11048
  }
9669
11049
  return blocked2;
9670
11050
  }
9671
- async function readAttachmentReadiness(page, files) {
11051
+ async function readAttachmentReadiness(page, files, baseline, timeoutMs) {
9672
11052
  if (typeof page.evaluate !== "function") {
9673
11053
  return void 0;
9674
11054
  }
9675
- return page.evaluate((fileNames) => {
9676
- const visibleText = document.body?.innerText ?? "";
11055
+ return page.evaluate((args) => {
11056
+ const expectedFiles = args.expectedFiles;
9677
11057
  const normalize = (value) => value.toLocaleLowerCase();
9678
- const normalizedVisibleText = normalize(visibleText);
9679
- const files2 = fileNames.map((name) => ({
9680
- name,
9681
- visible: normalizedVisibleText.includes(normalize(name))
9682
- }));
11058
+ const visible = (element) => {
11059
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
11060
+ const style = window.getComputedStyle(element);
11061
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
11062
+ const rect = element.getBoundingClientRect();
11063
+ return rect.width > 0 || rect.height > 0;
11064
+ };
11065
+ const textboxes = Array.from(document.querySelectorAll(
11066
+ "textarea, [contenteditable='true'], [role='textbox']"
11067
+ )).filter(visible);
11068
+ const composers = [...new Set(textboxes.map((textbox) => textbox.closest("form") ?? textbox.closest("[data-testid*='composer' i]") ?? textbox.closest("[aria-label*='composer' i]") ?? textbox.closest("[class*='composer' i]")).filter((value) => value !== null))];
11069
+ if (composers.length !== 1) {
11070
+ return { supported: false, files: expectedFiles.map((file) => ({ name: file.name, visible: false })), processing: false };
11071
+ }
11072
+ const composer = composers[0];
11073
+ const allInputs = Array.from(composer.querySelectorAll("input[type='file']")).filter((input2) => !input2.disabled && input2.getAttribute("aria-disabled") !== "true");
11074
+ const preferred = allInputs.filter((input2) => input2.id === "upload-files");
11075
+ const nonImage = allInputs.filter((input2) => input2.getAttribute("accept") !== "image/*");
11076
+ const inputs = preferred.length > 0 ? preferred : nonImage.length > 0 ? nonImage : allInputs;
11077
+ if (inputs.length !== 1) {
11078
+ return { supported: false, files: expectedFiles.map((file) => ({ name: file.name, visible: false })), processing: false };
11079
+ }
11080
+ const input = inputs[0];
9683
11081
  const attachmentSelectors = [
9684
11082
  "[data-testid*='attachment' i]",
9685
11083
  "[data-testid*='file' i]",
@@ -9691,88 +11089,163 @@ async function readAttachmentReadiness(page, files) {
9691
11089
  "[class*='file' i]",
9692
11090
  "[role='progressbar']"
9693
11091
  ].join(", ");
9694
- const attachmentText = Array.from(document.querySelectorAll(attachmentSelectors)).map((element) => [
11092
+ const attachmentElements = Array.from(composer.querySelectorAll(attachmentSelectors)).filter(visible);
11093
+ const attachmentText = attachmentElements.map((element) => [
9695
11094
  element.textContent ?? "",
9696
11095
  element.getAttribute("aria-label") ?? "",
9697
11096
  element.getAttribute("title") ?? ""
9698
11097
  ].join(" ")).join(" ");
9699
- const relevantText = attachmentText.length > 0 ? attachmentText : visibleText;
9700
- const processingMatch = /\b(uploading|processing|attaching|preparing|reading|scanning|analyzing)\b/i.exec(relevantText);
11098
+ const inputFiles = Array.from(input.files ?? []).map((file) => ({
11099
+ name: normalize(file.name),
11100
+ size: file.size,
11101
+ signature: `${normalize(file.name)}\0${file.size}`
11102
+ }));
11103
+ const attachmentLabels = attachmentElements.map((element) => normalize([
11104
+ element.textContent ?? "",
11105
+ element.getAttribute("aria-label") ?? "",
11106
+ element.getAttribute("title") ?? ""
11107
+ ].join(" ")));
11108
+ const occurrence = (values, index) => values.slice(0, index + 1).filter((value) => value === values[index]).length;
11109
+ const inputSignatures = inputFiles.map((file) => file.signature);
11110
+ const newInputIndices = new Set(inputSignatures.map((signature, index) => occurrence(inputSignatures, index) > args.baseline.inputFiles.filter((value) => value === signature).length ? index : -1).filter((index) => index >= 0));
11111
+ const newLabelIndices = new Set(attachmentLabels.map((label, index) => args.baseline.supported && occurrence(attachmentLabels, index) > args.baseline.attachmentLabels.filter((value) => value === label).length ? index : -1).filter((index) => index >= 0));
11112
+ const usedInputs = /* @__PURE__ */ new Set();
11113
+ const usedLabels = /* @__PURE__ */ new Set();
11114
+ const visibleFiles = expectedFiles.map((expected) => {
11115
+ const expectedName = normalize(expected.name);
11116
+ const inputIndex = inputFiles.findIndex(
11117
+ (candidate, index) => !usedInputs.has(index) && newInputIndices.has(index) && candidate.name === expectedName && candidate.size === expected.bytes
11118
+ );
11119
+ if (inputIndex >= 0) {
11120
+ usedInputs.add(inputIndex);
11121
+ return { name: expected.name, visible: true };
11122
+ }
11123
+ const labelIndex = attachmentLabels.findIndex(
11124
+ (label, index) => !usedLabels.has(index) && newLabelIndices.has(index) && label.includes(expectedName)
11125
+ );
11126
+ if (labelIndex >= 0) usedLabels.add(labelIndex);
11127
+ return { name: expected.name, visible: labelIndex >= 0 };
11128
+ });
11129
+ const processingMatch = /\b(uploading|processing|attaching|preparing|reading|scanning|analyzing)\b/i.exec(attachmentText);
9701
11130
  const snapshot = {
9702
- files: files2,
11131
+ supported: true,
11132
+ files: visibleFiles,
9703
11133
  processing: processingMatch !== null
9704
11134
  };
9705
11135
  if (processingMatch !== null) {
9706
- snapshot.processingText = relevantText.slice(0, 500);
11136
+ snapshot.processingText = attachmentText.slice(0, 500);
9707
11137
  }
9708
11138
  return snapshot;
9709
- }, files.map((file) => file.name));
11139
+ }, {
11140
+ expectedFiles: files.map((file) => ({ name: file.name, bytes: file.bytes })),
11141
+ baseline
11142
+ }, { timeoutMs });
9710
11143
  }
9711
- async function uploadFiles(page, files, timeoutMs) {
11144
+ async function uploadFiles(page, files, deadline, mutationState) {
9712
11145
  const paths = files.map((file) => file.path);
9713
11146
  const errors = [];
9714
- const attempts = [
9715
- {
11147
+ let activeComposerInput;
11148
+ try {
11149
+ activeComposerInput = await resolveUniqueActiveComposerFileInput(page, deadline);
11150
+ } catch (error) {
11151
+ errors.push(`active-composer-input: ${error instanceof Error ? error.message : String(error)}`);
11152
+ }
11153
+ const attempts = [];
11154
+ if (activeComposerInput !== void 0) {
11155
+ const resolvedInput = activeComposerInput;
11156
+ attempts.push({
9716
11157
  name: "visible-chatgpt-file-input",
9717
11158
  run: async () => {
9718
- await clickFileChooserTarget(page, "#upload-files", paths, timeoutMs, { requireVisible: true });
11159
+ if (!await locatorIsRendered(resolvedInput, deadline)) {
11160
+ throw new Error("The active-composer upload target is hidden.");
11161
+ }
11162
+ await clickFileChooserLocator(page, resolvedInput, paths, deadline, mutationState);
9719
11163
  }
9720
- },
11164
+ });
11165
+ }
11166
+ attempts.push(
9721
11167
  {
9722
11168
  name: "add-photos-files-menu-item",
9723
11169
  run: async () => {
9724
- await clickChatGPTAddPhotosMenuItem(page, paths, timeoutMs);
11170
+ await clickChatGPTAddPhotosMenuItem(page, paths, deadline, mutationState);
9725
11171
  }
9726
11172
  },
9727
11173
  {
9728
11174
  name: "generic-add-files-button",
9729
11175
  run: async () => {
9730
- await clickFileChooserLocator(page, addFilesButton(page), paths, timeoutMs);
11176
+ const control = addFilesButton(page);
11177
+ await assertControlInUniqueActiveComposer(control, deadline, "Generic Add files control");
11178
+ await clickFileChooserLocator(page, control, paths, deadline, mutationState);
9731
11179
  }
9732
11180
  },
9733
11181
  {
9734
- name: "direct-file-input-set",
11182
+ name: "cdp-file-input-chooser",
9735
11183
  run: async () => {
9736
- await setHiddenFileInput(page, files);
11184
+ await clickHiddenFileInputWithCdp(page, paths, deadline, mutationState);
9737
11185
  }
9738
11186
  }
9739
- ];
11187
+ );
11188
+ if (activeComposerInput !== void 0) {
11189
+ const resolvedInput = activeComposerInput;
11190
+ attempts.push({
11191
+ name: "direct-file-input-set",
11192
+ run: async () => {
11193
+ await setResolvedFileInput(resolvedInput, files, deadline, mutationState);
11194
+ }
11195
+ });
11196
+ }
9740
11197
  for (const attempt of attempts) {
11198
+ if (remainingMs(deadline) <= 0) {
11199
+ errors.push(`${attempt.name}: skipped because the single attachment deadline was exhausted`);
11200
+ break;
11201
+ }
9741
11202
  try {
9742
11203
  await attempt.run();
9743
11204
  return;
9744
11205
  } catch (error) {
11206
+ if (mutationState.handoffStarted) {
11207
+ throw error;
11208
+ }
11209
+ if (isUploadPermissionBlocker(error) || isUploadTransportFailure(error)) {
11210
+ throw error;
11211
+ }
9745
11212
  errors.push(`${attempt.name}: ${error instanceof Error ? error.message : String(error)}`);
9746
11213
  }
9747
11214
  }
9748
11215
  throw new Error(`No ChatGPT upload path completed.
9749
11216
  ${errors.join("\n")}`);
9750
11217
  }
9751
- async function clickChatGPTAddPhotosMenuItem(page, paths, timeoutMs) {
9752
- const addPhotosFilesText = localeLabels.addPhotosFilesMenuItem[0];
9753
- const menuItem = requiredLocator(page, "div[role='menuitem']").filter?.({ hasText: addPhotosFilesText });
9754
- if (await locatorCount(menuItem) !== 1) {
11218
+ async function clickChatGPTAddPhotosMenuItem(page, paths, deadline, mutationState) {
11219
+ const addPhotosFilesLabels = localeLabels.addPhotosFilesMenuItem;
11220
+ let menuItem = await findChatGPTUploadMenuItem(page, addPhotosFilesLabels, deadline);
11221
+ if (menuItem === void 0) {
9755
11222
  const plusButton = requiredLocator(page, "#composer-plus-btn, button[aria-label='Add files and more']");
9756
- if (await locatorCount(plusButton) !== 1) {
11223
+ if (await locatorCount(plusButton, deadline) !== 1) {
9757
11224
  throw new Error("ChatGPT Add files button was not uniquely available.");
9758
11225
  }
9759
- await plusButton.click?.({ timeoutMs: Math.min(timeoutMs, 1e4) });
9760
- await page.waitForTimeout?.(250);
9761
- }
9762
- const refreshedMenuItem = requiredLocator(page, "div[role='menuitem']").filter?.({ hasText: addPhotosFilesText });
9763
- await clickFileChooserLocator(page, refreshedMenuItem, paths, timeoutMs);
9764
- }
9765
- async function clickFileChooserTarget(page, selector, paths, timeoutMs, options = {}) {
9766
- const locator = requiredLocator(page, selector);
9767
- if (await locatorCount(locator) !== 1) {
9768
- throw new Error(`Upload target was not uniquely available: ${selector}`);
11226
+ await assertControlInUniqueActiveComposer(plusButton, deadline, "ChatGPT Add files control");
11227
+ if (plusButton.click === void 0) throw new Error("ChatGPT Add files button does not expose click().");
11228
+ await withinNativeAttachmentDeadline(
11229
+ deadline,
11230
+ (timeoutMs) => plusButton.click({ timeoutMs }),
11231
+ "ChatGPT Add files control click",
11232
+ 1e4
11233
+ );
11234
+ await attachmentDelay(page, deadline, 250);
9769
11235
  }
9770
- if (options.requireVisible === true && locator.isVisible !== void 0 && !await locator.isVisible({ timeoutMs: 1e3 })) {
9771
- throw new Error(`Upload target is hidden: ${selector}`);
11236
+ menuItem = await findChatGPTUploadMenuItem(page, addPhotosFilesLabels, deadline);
11237
+ if (menuItem === void 0) {
11238
+ throw new Error("ChatGPT's visible Add photos & files upload row was not uniquely available.");
9772
11239
  }
9773
- await clickFileChooserLocator(page, locator, paths, timeoutMs);
11240
+ const refreshedMenuItem = menuItem;
11241
+ await clickFileChooserLocator(page, refreshedMenuItem, paths, deadline, mutationState);
9774
11242
  }
9775
- async function clickFileChooserLocator(page, locator, paths, timeoutMs) {
11243
+ async function findChatGPTUploadMenuItem(page, addPhotosFilesLabels, deadline) {
11244
+ const pattern = new RegExp(addPhotosFilesLabels.map(escapeRegExp).join("|"), "i");
11245
+ const candidate = requiredLocator(page, "div[tabindex='0']").filter?.({ hasText: pattern });
11246
+ return await locatorCount(candidate, deadline) === 1 ? candidate : void 0;
11247
+ }
11248
+ async function clickFileChooserLocator(page, locator, paths, deadline, mutationState) {
9776
11249
  if (locator === void 0) {
9777
11250
  throw new Error("Upload locator was not available.");
9778
11251
  }
@@ -9782,26 +11255,131 @@ async function clickFileChooserLocator(page, locator, paths, timeoutMs) {
9782
11255
  if (typeof locator.click !== "function") {
9783
11256
  throw new Error("Upload locator does not expose click().");
9784
11257
  }
9785
- const chooserPromise = waitForFileChooser(page, timeoutMs);
11258
+ const chooserPromise = waitForFileChooser(page, deadline).then(
11259
+ (chooser2) => ({ ok: true, chooser: chooser2 }),
11260
+ (error) => ({ ok: false, error })
11261
+ );
11262
+ try {
11263
+ await withinNativeAttachmentDeadline(
11264
+ deadline,
11265
+ (timeoutMs) => locator.click({ timeoutMs }),
11266
+ "ChatGPT upload-control click",
11267
+ 1e4
11268
+ );
11269
+ } catch (error) {
11270
+ await chooserPromise;
11271
+ throw error;
11272
+ }
11273
+ const chooserResult = await chooserPromise;
11274
+ if (!chooserResult.ok) {
11275
+ throw chooserResult.error;
11276
+ }
11277
+ const chooser = chooserResult.chooser;
11278
+ await validateChooserTarget(chooser, deadline, "scoped-composer-trigger");
11279
+ await withinAttachmentDeadline(
11280
+ deadline,
11281
+ () => validateChooserMultiplicity(chooser, paths),
11282
+ "File-chooser multiplicity validation"
11283
+ );
9786
11284
  try {
9787
- await locator.click({ timeoutMs: Math.min(timeoutMs, 1e4) });
11285
+ mutationState.handoffStarted = true;
11286
+ await withinNativeAttachmentDeadline(
11287
+ deadline,
11288
+ (timeoutMs) => chooser.setFiles(paths, { timeoutMs }),
11289
+ "File-chooser handoff",
11290
+ 15e3
11291
+ );
9788
11292
  } catch (error) {
9789
- await chooserPromise.catch(() => void 0);
11293
+ throw new Error(`fileChooser.setFiles failed. ${error instanceof Error ? error.message : String(error)}`);
11294
+ }
11295
+ }
11296
+ async function clickHiddenFileInputWithCdp(page, paths, deadline, mutationState) {
11297
+ if (typeof page.waitForEvent !== "function") {
11298
+ throw new Error("The active browser page does not expose file chooser events.");
11299
+ }
11300
+ const rawCapability = await withinAttachmentDeadline(
11301
+ deadline,
11302
+ () => Promise.resolve(page.capabilities?.get?.("cdp")),
11303
+ "Scoped CDP upload capability resolution"
11304
+ );
11305
+ const cdp = rawCapability;
11306
+ if (typeof cdp?.send !== "function") {
11307
+ throw new Error("The active browser page does not expose the scoped CDP capability needed to click a hidden file input.");
11308
+ }
11309
+ const chooserPromise = waitForFileChooser(page, deadline).then(
11310
+ (chooser) => ({ ok: true, chooser }),
11311
+ (error) => ({ ok: false, error })
11312
+ );
11313
+ try {
11314
+ const evaluation = await withinNativeAttachmentDeadline(deadline, (timeoutMs) => Promise.resolve(cdp.send("Runtime.evaluate", {
11315
+ expression: `(() => {
11316
+ const visible = element => {
11317
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']")) return false;
11318
+ const style = getComputedStyle(element);
11319
+ const rect = element.getBoundingClientRect();
11320
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0"
11321
+ && (rect.width > 0 || rect.height > 0);
11322
+ };
11323
+ const textboxes = [...document.querySelectorAll("textarea, [contenteditable='true'], [role='textbox']")].filter(visible);
11324
+ const composers = [...new Set(textboxes.map(textbox =>
11325
+ textbox.closest("form")
11326
+ ?? textbox.closest("[data-testid*='composer' i]")
11327
+ ?? textbox.closest("[aria-label*='composer' i]")
11328
+ ?? textbox.closest("[class*='composer' i]")
11329
+ ).filter(Boolean))];
11330
+ if (composers.length !== 1) return { ok: false, reason: "active composer was not unique" };
11331
+ const all = [...composers[0].querySelectorAll("input[type='file']")]
11332
+ .filter(input => !input.disabled && input.getAttribute("aria-disabled") !== "true");
11333
+ const preferred = all.filter(input => input.id === "upload-files");
11334
+ const nonImage = all.filter(input => input.getAttribute("accept") !== "image/*");
11335
+ const candidates = preferred.length ? preferred : nonImage.length ? nonImage : all;
11336
+ if (candidates.length !== 1) return { ok: false, reason: "active composer file input was not unique" };
11337
+ candidates[0].click();
11338
+ return { ok: true };
11339
+ })()`,
11340
+ userGesture: true,
11341
+ awaitPromise: true,
11342
+ returnByValue: true
11343
+ }, {
11344
+ timeoutMs
11345
+ })), "Scoped CDP file-input click", 1e4);
11346
+ const wrappedValue = evaluation?.result?.value;
11347
+ const value = wrappedValue ?? evaluation;
11348
+ if (value?.ok !== true) {
11349
+ throw new Error(`Scoped CDP file-input click was refused: ${value?.reason ?? "no success result"}.`);
11350
+ }
11351
+ } catch (error) {
11352
+ await chooserPromise;
9790
11353
  throw error;
9791
11354
  }
9792
- const chooser = await chooserPromise;
9793
- await validateChooserMultiplicity(chooser, paths);
11355
+ const chooserResult = await chooserPromise;
11356
+ if (!chooserResult.ok) {
11357
+ throw chooserResult.error;
11358
+ }
11359
+ await validateChooserTarget(chooserResult.chooser, deadline, "scoped-cdp-input");
11360
+ await withinAttachmentDeadline(
11361
+ deadline,
11362
+ () => validateChooserMultiplicity(chooserResult.chooser, paths),
11363
+ "File-chooser multiplicity validation"
11364
+ );
9794
11365
  try {
9795
- await chooser.setFiles(paths);
11366
+ mutationState.handoffStarted = true;
11367
+ await withinNativeAttachmentDeadline(
11368
+ deadline,
11369
+ (timeoutMs) => chooserResult.chooser.setFiles(paths, { timeoutMs }),
11370
+ "File-chooser handoff",
11371
+ 15e3
11372
+ );
9796
11373
  } catch (error) {
9797
11374
  throw new Error(`fileChooser.setFiles failed. ${error instanceof Error ? error.message : String(error)}`);
9798
11375
  }
9799
11376
  }
9800
- async function waitForFileChooser(page, timeoutMs) {
9801
- const rawChooser = await page.waitForEvent?.("filechooser", {
9802
- timeout: timeoutMs,
9803
- timeoutMs
9804
- });
11377
+ async function waitForFileChooser(page, deadline) {
11378
+ const rawChooser = await withinNativeAttachmentDeadline(
11379
+ deadline,
11380
+ (timeoutMs) => Promise.resolve(page.waitForEvent?.("filechooser", { timeoutMs })),
11381
+ "File-chooser event wait"
11382
+ );
9805
11383
  if (!isFileChooserLike(rawChooser)) {
9806
11384
  throw new Error("File chooser event did not return a setFiles-capable chooser.");
9807
11385
  }
@@ -9819,12 +11397,116 @@ async function validateChooserMultiplicity(chooser, paths) {
9819
11397
  function isFileChooserLike(value) {
9820
11398
  return value !== null && typeof value === "object" && typeof value.setFiles === "function";
9821
11399
  }
9822
- async function locatorCount(locator) {
9823
- if (locator === void 0 || typeof locator.count !== "function") {
11400
+ async function validateChooserTarget(chooser, deadline, _triggerProof) {
11401
+ if (typeof chooser.element !== "function") {
11402
+ return;
11403
+ }
11404
+ const element = await withinAttachmentDeadline(
11405
+ deadline,
11406
+ () => Promise.resolve(chooser.element()),
11407
+ "File-chooser backing-input resolution"
11408
+ );
11409
+ if (typeof element?.evaluate !== "function") {
11410
+ throw new Error("The file chooser backing input could not be inspected safely.");
11411
+ }
11412
+ const scoped = await withinNativeAttachmentDeadline(deadline, (timeoutMs) => element.evaluate((candidate) => {
11413
+ const visible = (node) => {
11414
+ if (node.hidden || node.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
11415
+ const style = window.getComputedStyle(node);
11416
+ const rect = node.getBoundingClientRect();
11417
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && style.pointerEvents !== "none" && (rect.width > 0 || rect.height > 0);
11418
+ };
11419
+ const textboxes = Array.from(document.querySelectorAll(
11420
+ "textarea, [contenteditable='true'], [role='textbox']"
11421
+ )).filter(visible);
11422
+ const composers = [...new Set(textboxes.map((textbox) => textbox.closest("form") ?? textbox.closest("[data-testid*='composer' i]") ?? textbox.closest("[aria-label*='composer' i]") ?? textbox.closest("[class*='composer' i]")).filter((value) => value !== null))];
11423
+ if (composers.length !== 1 || !composers[0].contains(candidate)) return false;
11424
+ const all = Array.from(composers[0].querySelectorAll("input[type='file']")).filter((input) => !input.disabled && input.getAttribute("aria-disabled") !== "true");
11425
+ const preferred = all.filter((input) => input.id === "upload-files");
11426
+ const nonImage = all.filter((input) => input.getAttribute("accept") !== "image/*");
11427
+ const resolved = preferred.length > 0 ? preferred : nonImage.length > 0 ? nonImage : all;
11428
+ return resolved.length === 1 && resolved[0] === candidate;
11429
+ }, void 0, { timeoutMs }), "File-chooser active-composer identity check", 2e3);
11430
+ if (!scoped) {
11431
+ throw new Error("The file chooser backing input was not the unique active-composer upload target.");
11432
+ }
11433
+ }
11434
+ async function locatorCount(locator, deadline) {
11435
+ if (locator === void 0) {
9824
11436
  return 0;
9825
11437
  }
11438
+ if (deadline !== void 0 && typeof locator.allTextContents === "function") {
11439
+ const values = await withinNativeAttachmentDeadline(
11440
+ deadline,
11441
+ (timeoutMs) => locator.allTextContents({ timeoutMs }),
11442
+ "Locator enumeration",
11443
+ 2e3
11444
+ );
11445
+ return values.length;
11446
+ }
11447
+ if (typeof locator.count !== "function") return 0;
11448
+ if (deadline !== void 0) {
11449
+ return withinAttachmentDeadline(deadline, () => locator.count(), "Locator enumeration");
11450
+ }
9826
11451
  return locator.count();
9827
11452
  }
11453
+ async function locatorIsRendered(locator, deadline) {
11454
+ if (typeof locator.evaluate !== "function") return false;
11455
+ return withinNativeAttachmentDeadline(deadline, (timeoutMs) => locator.evaluate((element) => {
11456
+ const node = element;
11457
+ if (node.hidden || node.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
11458
+ const style = window.getComputedStyle(node);
11459
+ const rect = node.getBoundingClientRect();
11460
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && style.pointerEvents !== "none" && (rect.width > 0 || rect.height > 0);
11461
+ }, void 0, { timeoutMs }), "Active-composer file-input visibility check", 1e3);
11462
+ }
11463
+ function attachmentBudget(deadline) {
11464
+ const budget = remainingMs(deadline);
11465
+ if (budget <= 0) {
11466
+ throw new AttachmentDeadlineError("Attachment operation");
11467
+ }
11468
+ return budget;
11469
+ }
11470
+ var AttachmentDeadlineError = class extends Error {
11471
+ constructor(label) {
11472
+ super(`${label} exceeded the single attachment deadline.`);
11473
+ this.name = "AttachmentDeadlineError";
11474
+ }
11475
+ };
11476
+ async function withinAttachmentDeadline(deadline, operation, label) {
11477
+ const budget = attachmentBudget(deadline);
11478
+ try {
11479
+ return await withTimeout(operation(), budget, `${label} exceeded the single attachment deadline.`);
11480
+ } catch (error) {
11481
+ if (remainingMs(deadline) <= 0 || error instanceof Error && error.message.includes("exceeded the single attachment deadline")) {
11482
+ throw new AttachmentDeadlineError(label);
11483
+ }
11484
+ throw error;
11485
+ }
11486
+ }
11487
+ async function withinNativeAttachmentDeadline(deadline, operation, label, capMs = Number.POSITIVE_INFINITY) {
11488
+ const timeoutMs = Math.min(capMs, attachmentBudget(deadline));
11489
+ try {
11490
+ return await operation(timeoutMs);
11491
+ } catch (error) {
11492
+ if (remainingMs(deadline) <= 0) {
11493
+ throw new AttachmentDeadlineError(label);
11494
+ }
11495
+ throw error;
11496
+ }
11497
+ }
11498
+ async function attachmentDelay(_page, deadline, requestedMs) {
11499
+ const budget = attachmentBudget(deadline);
11500
+ const delayMs = Math.min(Math.max(0, requestedMs), Math.max(0, budget - 1));
11501
+ if (delayMs <= 0) {
11502
+ if (requestedMs > 0) throw new AttachmentDeadlineError("Attachment settling delay");
11503
+ return;
11504
+ }
11505
+ await new Promise((resolve4) => setTimeout(resolve4, delayMs));
11506
+ }
11507
+ async function attachmentContext(page, _deadline) {
11508
+ return contextFromPage(page, {}, { minimal: true });
11509
+ }
9828
11510
  async function downloadLatestFile(env, args) {
9829
11511
  const boot = await ensurePage(env);
9830
11512
  if (!boot.ok) {
@@ -9915,7 +11597,8 @@ async function tryGeneratedFilePreviewDownload(page, args) {
9915
11597
  }
9916
11598
  const assistant = assistantMessages.nth?.(selected.assistantIndex) ?? assistantMessages;
9917
11599
  const role = selected.tag === "button" ? "button" : "link";
9918
- const affordance = assistant.getByRole?.(role, { name: selected.filename, exact: true }) ?? assistant.locator?.(`${selected.tag}[aria-label="${escapeCssAttribute(selected.filename)}"]`);
11600
+ const controlLabel = selected.controlLabel ?? selected.filename;
11601
+ const affordance = assistant.getByRole?.(role, { name: controlLabel, exact: true }) ?? assistant.locator?.(`${selected.tag}[aria-label="${escapeCssAttribute(controlLabel)}"]`);
9919
11602
  const affordanceCount = await locatorCountWithTimeout(
9920
11603
  affordance,
9921
11604
  localGuardTimeout(timeoutMs, 5e3),
@@ -9935,8 +11618,14 @@ async function tryGeneratedFilePreviewDownload(page, args) {
9935
11618
  return resultOk(downloaded2, await contextFromPage(page));
9936
11619
  }
9937
11620
  await affordance.click({ timeoutMs: localGuardTimeout(timeoutMs, 1e4) });
9938
- const preview = requiredLocator(page, `section[aria-label="${escapeCssAttribute(selected.filename)}"]`);
9939
- const download = await waitForPreviewDownloadControl(page, preview, timeoutMs);
11621
+ const labelledPreview = requiredLocator(page, `section[aria-label="${escapeCssAttribute(selected.filename)}"]`);
11622
+ const workbookPreviews = requiredLocator(page, "section[data-testid^='popcorn-']");
11623
+ const workbookPreview = workbookPreviews.filter?.({ hasText: selected.filename }) ?? workbookPreviews;
11624
+ const download = await waitForPreviewDownloadControl(
11625
+ page,
11626
+ [labelledPreview, workbookPreview],
11627
+ timeoutMs
11628
+ );
9940
11629
  if (download === void 0) {
9941
11630
  throw new Error(`The artifact preview for ${selected.filename} did not expose a visible Download control.`);
9942
11631
  }
@@ -9955,7 +11644,7 @@ async function tryGeneratedFilePreviewDownload(page, args) {
9955
11644
  async function inspectGeneratedFileAffordances(page, timeoutMs) {
9956
11645
  if (typeof page.evaluate === "function") {
9957
11646
  const fromDom = await withTimeout(
9958
- page.evaluate(() => {
11647
+ page.evaluate((downloadLabels) => {
9959
11648
  const visible = (element) => {
9960
11649
  let current = element;
9961
11650
  while (current !== null) {
@@ -9969,14 +11658,32 @@ async function inspectGeneratedFileAffordances(page, timeoutMs) {
9969
11658
  return true;
9970
11659
  };
9971
11660
  const fileLike = (value) => /^[^\\/\r\n]{1,255}\.[a-z0-9][a-z0-9._-]{0,15}$/i.test(value);
11661
+ const normalizedFilename = (value) => {
11662
+ const trimmed = value.trim();
11663
+ const lowered = trimmed.toLocaleLowerCase();
11664
+ const prefix = downloadLabels.map((label) => label.trim()).filter(Boolean).sort((left, right) => right.length - left.length).find((label) => lowered.startsWith(`${label.toLocaleLowerCase()} `));
11665
+ return prefix === void 0 ? trimmed : trimmed.slice(prefix.length).trim();
11666
+ };
9972
11667
  const assistants = Array.from(document.querySelectorAll("[data-message-author-role='assistant']"));
9973
- return assistants.flatMap((assistant, assistantIndex) => Array.from(assistant.querySelectorAll("button[aria-label], a[download], a[href*='/backend-api/files/']")).filter(visible).map((element) => ({
9974
- assistantIndex,
9975
- filename: (element.getAttribute("aria-label") ?? element.textContent ?? "").trim(),
9976
- tag: element.tagName.toLocaleLowerCase(),
9977
- text: (element.textContent ?? "").trim()
9978
- })).filter((item) => (item.tag === "button" || item.tag === "a") && fileLike(item.filename) && item.filename === item.text).map(({ assistantIndex: assistantIndex2, filename, tag }) => ({ assistantIndex: assistantIndex2, filename, tag })));
9979
- }),
11668
+ return assistants.flatMap(
11669
+ (assistant, assistantIndex) => Array.from(assistant.querySelectorAll("button[aria-label], a[download], a[href*='/backend-api/files/']")).filter(visible).map((element) => {
11670
+ const controlLabel = (element.getAttribute("aria-label") ?? element.textContent ?? "").trim();
11671
+ const text = (element.textContent ?? "").trim();
11672
+ return {
11673
+ assistantIndex,
11674
+ filename: normalizedFilename(controlLabel),
11675
+ controlLabel,
11676
+ tag: element.tagName.toLocaleLowerCase(),
11677
+ textFilename: normalizedFilename(text)
11678
+ };
11679
+ }).filter((item) => (item.tag === "button" || item.tag === "a") && fileLike(item.filename) && item.filename === item.textFilename).map(({ assistantIndex: index, filename, controlLabel, tag }) => ({
11680
+ assistantIndex: index,
11681
+ filename,
11682
+ ...controlLabel === filename ? {} : { controlLabel },
11683
+ tag
11684
+ }))
11685
+ );
11686
+ }, [...localeLabels.download]),
9980
11687
  timeoutMs,
9981
11688
  "Timed out while inspecting generated-file buttons."
9982
11689
  ).catch(() => void 0);
@@ -9992,14 +11699,30 @@ async function inspectGeneratedFileAffordances(page, timeoutMs) {
9992
11699
  const buttonPattern = /<(button|a)\b[^>]*\baria-label=(['"])(.*?)\2[^>]*>([\s\S]*?)<\/\1>/gi;
9993
11700
  let match;
9994
11701
  while ((match = buttonPattern.exec(html)) !== null) {
9995
- const filename = decodeBasicHtml(match[3] ?? "").trim();
11702
+ const controlLabel = decodeBasicHtml(match[3] ?? "").trim();
9996
11703
  const text = decodeBasicHtml((match[4] ?? "").replace(/<[^>]+>/g, " ")).replace(/\s+/g, " ").trim();
9997
- if (/^[^\\/\r\n]{1,255}\.[a-z0-9][a-z0-9._-]{0,15}$/i.test(filename) && filename === text) {
9998
- candidates.push({ assistantIndex: 0, filename, tag: (match[1] ?? "button").toLocaleLowerCase() });
11704
+ const filename = normalizeGeneratedFileControlLabel(controlLabel);
11705
+ const textFilename = normalizeGeneratedFileControlLabel(text);
11706
+ if (/^[^\\/\r\n]{1,255}\.[a-z0-9][a-z0-9._-]{0,15}$/i.test(filename) && filename === textFilename) {
11707
+ candidates.push({
11708
+ assistantIndex: 0,
11709
+ filename,
11710
+ ...controlLabel === filename ? {} : { controlLabel },
11711
+ tag: (match[1] ?? "button").toLocaleLowerCase()
11712
+ });
9999
11713
  }
10000
11714
  }
10001
11715
  return candidates;
10002
11716
  }
11717
+ function normalizeGeneratedFileControlLabel(value) {
11718
+ return stripLocalizedDownloadPrefix(value, localeLabels.download);
11719
+ }
11720
+ function stripLocalizedDownloadPrefix(value, labels) {
11721
+ const trimmed = value.trim();
11722
+ const lowered = trimmed.toLocaleLowerCase();
11723
+ const prefix = labels.map((label) => label.trim()).filter(Boolean).sort((left, right) => right.length - left.length).find((label) => lowered.startsWith(`${label.toLocaleLowerCase()} `));
11724
+ return prefix === void 0 ? trimmed : trimmed.slice(prefix.length).trim();
11725
+ }
10003
11726
  function selectGeneratedFileAffordance(candidates, args) {
10004
11727
  let scoped = candidates;
10005
11728
  const from = args.from;
@@ -10021,13 +11744,15 @@ function filenameMatches(filename, pattern) {
10021
11744
  return filename.toLocaleLowerCase().includes(pattern.toLocaleLowerCase());
10022
11745
  }
10023
11746
  }
10024
- async function waitForPreviewDownloadControl(page, preview, timeoutMs) {
10025
- const deadline = Date.now() + Math.min(timeoutMs, 15e3);
11747
+ async function waitForPreviewDownloadControl(page, previews, timeoutMs) {
11748
+ const deadline = Date.now() + Math.min(timeoutMs, 6e4);
10026
11749
  while (Date.now() < deadline) {
10027
- for (const label of localeLabels.download) {
10028
- const control = preview.getByRole?.("button", { name: label, exact: true }) ?? preview.locator?.(`button[aria-label="${escapeCssAttribute(label)}"]`);
10029
- if (await locatorCountWithTimeout(control, localGuardTimeout(timeoutMs, 2e3), "artifact_preview_download_count_timeout") === 1) {
10030
- return control;
11750
+ for (const preview of previews) {
11751
+ for (const label of localeLabels.download) {
11752
+ const control = preview.getByRole?.("button", { name: label, exact: true }) ?? preview.locator?.(`button[aria-label="${escapeCssAttribute(label)}"]`);
11753
+ if (await locatorCountWithTimeout(control, localGuardTimeout(timeoutMs, 2e3), "artifact_preview_download_count_timeout") === 1) {
11754
+ return control;
11755
+ }
10031
11756
  }
10032
11757
  }
10033
11758
  if (typeof page.waitForTimeout === "function") {
@@ -10044,26 +11769,96 @@ function escapeCssAttribute(value) {
10044
11769
  function decodeBasicHtml(value) {
10045
11770
  return value.replace(/&quot;/gi, '"').replace(/&#39;|&apos;/gi, "'").replace(/&lt;/gi, "<").replace(/&gt;/gi, ">").replace(/&amp;/gi, "&");
10046
11771
  }
10047
- async function setHiddenFileInput(page, files) {
10048
- if (page === void 0) {
10049
- throw new Error("No active page is available for file upload.");
11772
+ async function resolveUniqueActiveComposerFileInput(page, deadline) {
11773
+ const candidates = requiredLocator(page, cssSelectors.hiddenFileInputs);
11774
+ if (typeof candidates.count !== "function") {
11775
+ throw new Error("ChatGPT file inputs could not be enumerated safely.");
10050
11776
  }
10051
- const input = requiredLocator(page, cssSelectors.hiddenFileInputs).last?.() ?? requiredLocator(page, cssSelectors.hiddenFileInputs);
11777
+ const count = await locatorCount(candidates, deadline);
11778
+ const eligible = [];
11779
+ for (let index = 0; index < count; index += 1) {
11780
+ const input = count === 1 ? candidates : candidates.nth?.(index);
11781
+ if (input === void 0 || typeof input.evaluate !== "function") continue;
11782
+ const scoped = await withinNativeAttachmentDeadline(deadline, (timeoutMs) => input.evaluate((element) => {
11783
+ const candidate = element;
11784
+ const visible = (node) => {
11785
+ if (node.hidden || node.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
11786
+ const style = window.getComputedStyle(node);
11787
+ const rect = node.getBoundingClientRect();
11788
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && (rect.width > 0 || rect.height > 0);
11789
+ };
11790
+ const textboxes = Array.from(document.querySelectorAll(
11791
+ "textarea, [contenteditable='true'], [role='textbox']"
11792
+ )).filter(visible);
11793
+ const composers = [...new Set(textboxes.map((textbox) => textbox.closest("form") ?? textbox.closest("[data-testid*='composer' i]") ?? textbox.closest("[aria-label*='composer' i]") ?? textbox.closest("[class*='composer' i]")).filter((value) => value !== null))];
11794
+ if (composers.length !== 1 || !composers[0].contains(candidate)) return false;
11795
+ const all = Array.from(composers[0].querySelectorAll("input[type='file']")).filter((input2) => !input2.disabled && input2.getAttribute("aria-disabled") !== "true");
11796
+ const preferred = all.filter((input2) => input2.id === "upload-files");
11797
+ const nonImage = all.filter((input2) => input2.getAttribute("accept") !== "image/*");
11798
+ const resolved = preferred.length > 0 ? preferred : nonImage.length > 0 ? nonImage : all;
11799
+ return resolved.length === 1 && resolved[0] === candidate;
11800
+ }, void 0, { timeoutMs }), `File-input ${index + 1} scope check`, 2e3);
11801
+ if (scoped) eligible.push(input);
11802
+ }
11803
+ if (eligible.length !== 1) {
11804
+ throw new Error("The active browser exposes no sanctioned native file handoff because the active composer file input was not uniquely available.");
11805
+ }
11806
+ return eligible[0];
11807
+ }
11808
+ async function assertControlInUniqueActiveComposer(control, deadline, label) {
11809
+ if (control === void 0 || typeof control.evaluate !== "function") {
11810
+ throw new Error(`${label} could not be scoped to the active composer.`);
11811
+ }
11812
+ const scoped = await withinNativeAttachmentDeadline(deadline, (timeoutMs) => control.evaluate((element) => {
11813
+ const visible = (node) => {
11814
+ if (node.hidden || node.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
11815
+ const style = window.getComputedStyle(node);
11816
+ const rect = node.getBoundingClientRect();
11817
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && (rect.width > 0 || rect.height > 0);
11818
+ };
11819
+ const textboxes = Array.from(document.querySelectorAll(
11820
+ "textarea, [contenteditable='true'], [role='textbox']"
11821
+ )).filter(visible);
11822
+ const composers = [...new Set(textboxes.map((textbox) => textbox.closest("form") ?? textbox.closest("[data-testid*='composer' i]") ?? textbox.closest("[aria-label*='composer' i]") ?? textbox.closest("[class*='composer' i]")).filter((value) => value !== null))];
11823
+ return composers.length === 1 && composers[0].contains(element);
11824
+ }, void 0, { timeoutMs }), `${label} scope check`, 2e3);
11825
+ if (!scoped) throw new Error(`${label} was outside the unique active composer.`);
11826
+ }
11827
+ async function setResolvedFileInput(input, files, deadline, mutationState) {
10052
11828
  if (typeof input.setInputFiles !== "function") {
10053
- await setFilesViaDomDataTransfer(page, files);
10054
- return;
10055
- }
10056
- await input.setInputFiles(files.map((file) => file.path));
11829
+ throw new Error("The active browser exposes no sanctioned native file handoff for ChatGPT's file input.");
11830
+ }
11831
+ mutationState.handoffStarted = true;
11832
+ await withinNativeAttachmentDeadline(
11833
+ deadline,
11834
+ (timeoutMs) => input.setInputFiles(files.map((file) => file.path), { timeoutMs }),
11835
+ "Direct file-input handoff",
11836
+ 15e3
11837
+ );
10057
11838
  }
10058
- async function readBrowserInputDiagnostic(page) {
11839
+ async function readBrowserInputDiagnostic(page, timeoutMs) {
10059
11840
  if (typeof page.evaluate !== "function") {
10060
11841
  return void 0;
10061
11842
  }
10062
11843
  return page.evaluate(() => {
10063
- const input = document.querySelector("#upload-files") || document.querySelector("input[type='file']:not([accept='image/*'])") || document.querySelector("input[type='file']");
10064
- if (!input) {
10065
- return { files: [] };
10066
- }
11844
+ const visible = (element) => {
11845
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
11846
+ const style = window.getComputedStyle(element);
11847
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
11848
+ const rect = element.getBoundingClientRect();
11849
+ return rect.width > 0 || rect.height > 0;
11850
+ };
11851
+ const textboxes = Array.from(document.querySelectorAll(
11852
+ "textarea, [contenteditable='true'], [role='textbox']"
11853
+ )).filter(visible);
11854
+ const composers = [...new Set(textboxes.map((textbox) => textbox.closest("form") ?? textbox.closest("[data-testid*='composer' i]") ?? textbox.closest("[aria-label*='composer' i]") ?? textbox.closest("[class*='composer' i]")).filter((value) => value !== null))];
11855
+ if (composers.length !== 1) return void 0;
11856
+ const allInputs = Array.from(composers[0].querySelectorAll("input[type='file']")).filter((input2) => !input2.disabled && input2.getAttribute("aria-disabled") !== "true");
11857
+ const preferred = allInputs.filter((input2) => input2.id === "upload-files");
11858
+ const nonImage = allInputs.filter((input2) => input2.getAttribute("accept") !== "image/*");
11859
+ const inputs = preferred.length > 0 ? preferred : nonImage.length > 0 ? nonImage : allInputs;
11860
+ if (inputs.length !== 1) return void 0;
11861
+ const input = inputs[0];
10067
11862
  return {
10068
11863
  files: Array.from(input.files ?? []).map((file) => {
10069
11864
  const diagnostic2 = {
@@ -10079,43 +11874,7 @@ async function readBrowserInputDiagnostic(page) {
10079
11874
  return diagnostic2;
10080
11875
  })
10081
11876
  };
10082
- });
10083
- }
10084
- async function setFilesViaDomDataTransfer(page, files) {
10085
- const totalBytes = files.reduce((sum, file) => sum + file.bytes, 0);
10086
- const maxInlineBytes = 25 * 1024 * 1024;
10087
- if (totalBytes > maxInlineBytes) {
10088
- throw new Error(`No file chooser or setInputFiles support is available for large uploads. ${CODEX_UPLOAD_PERMISSION_FIX} ${CHROME_FILE_URL_PERMISSION_FIX}`);
10089
- }
10090
- if (typeof page.evaluate !== "function") {
10091
- throw new Error(`No file chooser, setInputFiles, or page.evaluate support is available for file upload. ${CODEX_UPLOAD_PERMISSION_FIX} ${CHROME_FILE_URL_PERMISSION_FIX}`);
10092
- }
10093
- const payload = await Promise.all(files.map(async (file) => ({
10094
- name: file.name,
10095
- bytesBase64: (await readFile3(file.path)).toString("base64"),
10096
- type: guessMimeType(file.name)
10097
- })));
10098
- await page.evaluate(
10099
- async (payload2) => {
10100
- const input = document.querySelector("#upload-files") || document.querySelector("input[type='file']:not([accept='image/*'])") || document.querySelector("input[type='file']");
10101
- if (!input) {
10102
- throw new Error("No ChatGPT file input found in the DOM.");
10103
- }
10104
- const dataTransfer = new DataTransfer();
10105
- for (const item of payload2) {
10106
- const binary = atob(item.bytesBase64);
10107
- const bytes = new Uint8Array(binary.length);
10108
- for (let index = 0; index < binary.length; index += 1) {
10109
- bytes[index] = binary.charCodeAt(index);
10110
- }
10111
- dataTransfer.items.add(new File([bytes], item.name, { type: item.type }));
10112
- }
10113
- input.files = dataTransfer.files;
10114
- input.dispatchEvent(new Event("input", { bubbles: true }));
10115
- input.dispatchEvent(new Event("change", { bubbles: true }));
10116
- },
10117
- payload
10118
- );
11877
+ }, void 0, { timeoutMs });
10119
11878
  }
10120
11879
  function guessMimeType(name) {
10121
11880
  if (/\.txt$/i.test(name)) return "text/plain";
@@ -10125,9 +11884,17 @@ function guessMimeType(name) {
10125
11884
  if (/\.md$/i.test(name)) return "text/markdown";
10126
11885
  return "application/octet-stream";
10127
11886
  }
10128
- function isUploadBridgeBlocker(error) {
11887
+ function isUploadPermissionBlocker(error) {
11888
+ const message = error instanceof Error ? error.message : String(error);
11889
+ return /Allow access to file URLs|Codex Settings > Computer Use|Browser Use rejected|requested that files not be uploaded|permission denied|browser blocked|fileChooser\.setFiles failed[^\n]*(?:Not allowed|permission|denied|rejected)/i.test(message);
11890
+ }
11891
+ function isUploadTransportFailure(error) {
11892
+ const message = error instanceof Error ? error.message : String(error);
11893
+ return /native pipe closed before response|browser bridge.*(?:closed|disconnect)|connection (?:was )?closed|target page, context or browser has been closed/i.test(message);
11894
+ }
11895
+ function isUploadPathFailure(error) {
10129
11896
  const message = error instanceof Error ? error.message : String(error);
10130
- return /DataTransfer is not a constructor|No file chooser|setInputFiles|Allow access to file URLs|file upload|fileChooser\.setFiles failed|Not allowed|No ChatGPT upload path completed/i.test(message);
11897
+ return /No ChatGPT upload path completed/i.test(message);
10131
11898
  }
10132
11899
  function uploadPermissionMessage(error) {
10133
11900
  const message = error instanceof Error ? error.message : String(error);
@@ -11265,6 +13032,8 @@ async function executeStep(step, env, previousResults) {
11265
13032
  return readLatest(env, step.args);
11266
13033
  case "messages.status":
11267
13034
  return messageStatus(env, step.args);
13035
+ case "messages.stop":
13036
+ return stopGeneration(env, step.args);
11268
13037
  case "messages.waitAndRead":
11269
13038
  return waitAndRead(env, step.args);
11270
13039
  case "artifacts.listLatest":
@@ -11639,6 +13408,8 @@ var REQUIRED_LOCALE_KEYS = [
11639
13408
  ];
11640
13409
  var REQUIRED_TOOL_IDS = ["web_search", "deep_research", "create_image"];
11641
13410
  var REQUIRED_MODE_OPTION_IDS = ["latest", "instant", "thinking", "extended", "medium", "high", "extraHigh", "pro"];
13411
+ var REQUIRED_CONFIGURATION_AXIS_IDS = ["power", "model", "intelligence", "effort", "speed", "advanced"];
13412
+ var REQUIRED_CONFIGURATION_OPTION_IDS = ["instant", "light", "medium", "high", "extraHigh", "max", "ultra", "pro", "standard", "fast"];
11642
13413
  async function doctor(env, args = {}) {
11643
13414
  const wanted = args.check ?? DEFAULT_CHECKS;
11644
13415
  const checks = {};
@@ -11839,8 +13610,12 @@ function localizationCheck(env) {
11839
13610
  const requiredKeysMissing = REQUIRED_LOCALE_KEYS.filter((key) => localeLabels[key].length === 0);
11840
13611
  const missingToolIds = REQUIRED_TOOL_IDS.filter((id2) => (localeLabels.tools[id2]?.length ?? 0) === 0);
11841
13612
  const missingModeOptionIds = REQUIRED_MODE_OPTION_IDS.filter((id2) => (localeLabels.modeOptions[id2]?.length ?? 0) === 0);
13613
+ const missingConfigurationAxisIds = REQUIRED_CONFIGURATION_AXIS_IDS.filter((id2) => (localeLabels.configurationAxes[id2]?.length ?? 0) === 0);
13614
+ const missingConfigurationOptionIds = REQUIRED_CONFIGURATION_OPTION_IDS.filter((id2) => (localeLabels.configurationOptions[id2]?.length ?? 0) === 0);
11842
13615
  const toolIds = Object.keys(localeLabels.tools);
11843
13616
  const modeOptionIds = Object.keys(localeLabels.modeOptions);
13617
+ const configurationAxisIds = Object.keys(localeLabels.configurationAxes);
13618
+ const configurationOptionIds = Object.keys(localeLabels.configurationOptions);
11844
13619
  const proAliases = [...localeLabels.modeOptions.pro];
11845
13620
  const supportsProExtendedAlias = proAliases.some((alias) => /pro\s*(?:•\s*)?extended/i.test(alias)) && proAliases.some((alias) => /extended\s+pro/i.test(alias));
11846
13621
  const runningStateLocalizationSupport = runningStateSupport();
@@ -11852,15 +13627,19 @@ function localizationCheck(env) {
11852
13627
  registeredLocaleCount: localeCoverageSummary.registeredLocaleCount,
11853
13628
  nonEnglishLocaleCount: localeCoverageSummary.nonEnglishLocaleCount
11854
13629
  };
11855
- const englishCanonicalPresent = localeLabels.composerTextbox[0] === "Chat with ChatGPT" && localeLabels.sendButton[0] === "Send prompt" && localeLabels.modeLabels.includes("Thinking") && localeLabels.modeOptions.pro?.[0] === "Pro" && localeLabels.tools.web_search?.[0] === "Web search";
11856
- const labelCandidateCount = REQUIRED_LOCALE_KEYS.reduce((total, key) => total + localeLabels[key].length, 0) + Object.values(localeLabels.tools).reduce((total, values) => total + values.length, 0) + Object.values(localeLabels.modeOptions).reduce((total, values) => total + values.length, 0);
13630
+ const englishCanonicalPresent = localeLabels.composerTextbox[0] === "Chat with ChatGPT" && localeLabels.sendButton[0] === "Send prompt" && localeLabels.modeLabels.includes("Thinking") && localeLabels.modeOptions.pro?.[0] === "Pro" && localeLabels.configurationAxes.power?.[0] === "Power" && localeLabels.configurationAxes.advanced?.[0] === "Advanced" && localeLabels.configurationOptions.ultra?.[0] === "Ultra" && localeLabels.tools.web_search?.[0] === "Web search";
13631
+ const labelCandidateCount = REQUIRED_LOCALE_KEYS.reduce((total, key) => total + localeLabels[key].length, 0) + Object.values(localeLabels.tools).reduce((total, values) => total + values.length, 0) + Object.values(localeLabels.modeOptions).reduce((total, values) => total + values.length, 0) + Object.values(localeLabels.configurationAxes).reduce((total, values) => total + values.length, 0) + Object.values(localeLabels.configurationOptions).reduce((total, values) => total + values.length, 0);
11857
13632
  const details = {
11858
13633
  englishCanonicalPresent,
11859
13634
  requiredKeysMissing,
11860
13635
  missingToolIds,
11861
13636
  missingModeOptionIds,
13637
+ missingConfigurationAxisIds,
13638
+ missingConfigurationOptionIds,
11862
13639
  toolIds,
11863
13640
  modeOptionIds,
13641
+ configurationAxisIds,
13642
+ configurationOptionIds,
11864
13643
  proAliases,
11865
13644
  supportsProExtendedAlias,
11866
13645
  runningStateLabelCoverage,
@@ -11868,7 +13647,7 @@ function localizationCheck(env) {
11868
13647
  pageAvailable: env.page !== void 0,
11869
13648
  runtimeSelectorCoverage: "registry_only_stage_2"
11870
13649
  };
11871
- if (englishCanonicalPresent && requiredKeysMissing.length === 0 && missingToolIds.length === 0 && missingModeOptionIds.length === 0) {
13650
+ if (englishCanonicalPresent && requiredKeysMissing.length === 0 && missingToolIds.length === 0 && missingModeOptionIds.length === 0 && missingConfigurationAxisIds.length === 0 && missingConfigurationOptionIds.length === 0) {
11872
13651
  const runningStateMessage = runningStateLocalizationSupport === "complete" ? "running-state labels are present for every registered non-English locale" : runningStateLocalizationSupport === "partial" ? "running-state labels are partially localized" : runningStateLocalizationSupport === "english_only" ? "running-state labels are English-only" : "running-state labels are missing";
11873
13652
  return unknown(`The locale registry is loaded; localized runtime selector coverage is registry-only in Stage 2 and ${runningStateMessage}.`, void 0, details);
11874
13653
  }
@@ -12106,6 +13885,7 @@ var commandRisk = {
12106
13885
  "messages.wait": "low",
12107
13886
  "messages.readLatest": "medium",
12108
13887
  "messages.status": "medium",
13888
+ "messages.stop": "medium",
12109
13889
  "messages.waitAndRead": "medium",
12110
13890
  "artifacts.listLatest": "medium",
12111
13891
  "artifacts.wait": "low",
@@ -12219,6 +13999,7 @@ var descriptors = [
12219
13999
  primitive("messages.wait", "Wait for the latest assistant response to stabilize.", 12e4),
12220
14000
  primitive("messages.readLatest", "Read the latest message as Markdown, normalized text, blocks, or HTML.", 3e4),
12221
14001
  primitive("messages.status", "Read a compact latest-assistant progress snapshot without treating partial text as complete.", 5e3),
14002
+ primitive("messages.stop", "Stop the current visible ChatGPT response after explicit confirmation and verify generation became inactive.", 5e3),
12222
14003
  primitive("messages.waitAndRead", "Wait for completion and read the latest message.", 12e4),
12223
14004
  primitive("artifacts.listLatest", "Detect the latest visible generated ChatGPT artifact, such as an image-only result.", 3e4),
12224
14005
  primitive("artifacts.wait", "Wait for a visible generated ChatGPT artifact to appear and stabilize.", 12e4),
@@ -12392,6 +14173,7 @@ function primitiveArgs(name) {
12392
14173
  };
12393
14174
  if (name === "messages.readLatest") return { role: "assistant or user", format: "markdown, normalized_text, visible_text, html, blocks, or all" };
12394
14175
  if (name === "messages.status") return { maxPreviewChars: "maximum latest-assistant preview characters to return; defaults to 240" };
14176
+ if (name === "messages.stop") return { confirmStop: "must be true to stop a visible response", timeoutMs: "maximum time to verify generation became inactive" };
12395
14177
  if (name === "experience.detect") return { timeoutMs: "optional timeout for attaching to the ChatGPT page" };
12396
14178
  if (name === "experience.open") return { experience: "chat or work", timeoutMs: "optional verified-switch timeout" };
12397
14179
  if (name === "configuration.inspect") return { experience: "optional expected chat or work surface", includeOptions: "open visible axis menus to enumerate options; defaults to true", timeoutMs: "optional inspection timeout" };
@@ -13171,6 +14953,7 @@ function createChatGPT(options = {}) {
13171
14953
  wait: (args) => waitForMessage(env, args),
13172
14954
  readLatest: (args) => readLatest(env, args),
13173
14955
  status: (args) => messageStatus(env, args),
14956
+ stop: (args) => stopGeneration(env, args),
13174
14957
  waitAndRead: (args) => waitAndRead(env, args)
13175
14958
  },
13176
14959
  files: {
@@ -13901,6 +15684,7 @@ var backendCommands = [
13901
15684
  "messages.wait",
13902
15685
  "messages.readLatest",
13903
15686
  "messages.status",
15687
+ "messages.stop",
13904
15688
  "messages.waitAndRead",
13905
15689
  "artifacts.listLatest",
13906
15690
  "artifacts.wait",
@@ -14094,6 +15878,7 @@ function createChatGPTBackendClient(transport) {
14094
15878
  wait: (args) => request("messages.wait", args ?? {}),
14095
15879
  readLatest: (args) => request("messages.readLatest", args ?? {}),
14096
15880
  status: (args) => request("messages.status", args ?? {}),
15881
+ stop: (args) => request("messages.stop", args),
14097
15882
  waitAndRead: (args) => request("messages.waitAndRead", args)
14098
15883
  },
14099
15884
  artifacts: {
@@ -14634,6 +16419,8 @@ async function dispatchBackendCommand(client, request) {
14634
16419
  return client.messages.readLatest(emptyToUndefined(payload));
14635
16420
  case "messages.status":
14636
16421
  return client.messages.status(emptyToUndefined(payload));
16422
+ case "messages.stop":
16423
+ return client.messages.stop(payload);
14637
16424
  case "messages.waitAndRead":
14638
16425
  return client.messages.waitAndRead(payload);
14639
16426
  case "artifacts.listLatest":
@@ -14816,6 +16603,7 @@ export {
14816
16603
  htmlToText,
14817
16604
  inspectConfiguration,
14818
16605
  interruptionFromCommandResult,
16606
+ isChatGPTUrl,
14819
16607
  isHighRiskCommand,
14820
16608
  isResponseComplete,
14821
16609
  isTransientAssistantText,
@@ -14891,7 +16679,10 @@ export {
14891
16679
  sha256Text,
14892
16680
  startWork,
14893
16681
  steerWork,
16682
+ stopGeneration,
16683
+ stopGenerationButton,
14894
16684
  streamFromRunResult,
16685
+ stripLocalizedDownloadPrefix,
14895
16686
  stripTags,
14896
16687
  submitMessage,
14897
16688
  submittedUserTurnMatches,