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
@@ -186,6 +186,7 @@ var en = {
186
186
  work: ["Work"]
187
187
  },
188
188
  configurationAxes: {
189
+ power: ["Power"],
189
190
  model: ["Model"],
190
191
  intelligence: ["Intelligence"],
191
192
  effort: ["Effort"],
@@ -221,7 +222,7 @@ var en = {
221
222
  /** Exact-match transient assistant placeholders filtered out of captured responses. */
222
223
  transientAssistant: ["thinking", "reasoning", "searching", "searching the web"],
223
224
  /** Streaming "stop" control text, matched while a response generates. */
224
- stopControl: ["stop generating", "stop streaming", "stop answering", "cancel"],
225
+ stopControl: ["stop generating", "stop streaming", "stop answering"],
225
226
  /** Interrupted generation markers shown after the assistant stops before completion. */
226
227
  stoppedAssistant: ["stopped thinking", "stopped answering", "generation stopped"],
227
228
  /** Response-action affordance text (fallback to the structural copy-button locator). */
@@ -238,11 +239,14 @@ var en = {
238
239
  // src/dom/locale/de.ts
239
240
  var de = {
240
241
  configurationAxes: {
242
+ power: ["Leistung"],
241
243
  model: ["Modell"],
242
- effort: ["Aufwand"],
243
- speed: ["Tempo"]
244
+ effort: ["Aufwand", "Denkaufwand"],
245
+ speed: ["Tempo"],
246
+ advanced: ["Erweitert"]
244
247
  },
245
248
  configurationOptions: {
249
+ instant: ["Sofort"],
246
250
  light: ["Leicht"],
247
251
  medium: ["Mittel"],
248
252
  high: ["Hoch"],
@@ -278,15 +282,19 @@ var de = {
278
282
  // src/dom/locale/es-ES.ts
279
283
  var esES = {
280
284
  configurationAxes: {
285
+ power: ["Potencia"],
281
286
  model: ["Modelo"],
282
287
  effort: ["Esfuerzo"],
283
- speed: ["Velocidad"]
288
+ speed: ["Velocidad"],
289
+ advanced: ["Avanzadas"]
284
290
  },
285
291
  configurationOptions: {
292
+ instant: ["Instant\xE1nea"],
286
293
  light: ["Ligero"],
287
294
  medium: ["Media"],
288
295
  high: ["Alta"],
289
296
  extraHigh: ["Muy alta"],
297
+ max: ["M\xE1ximo"],
290
298
  standard: ["Est\xE1ndar"],
291
299
  fast: ["R\xE1pido"]
292
300
  },
@@ -320,15 +328,19 @@ var esES = {
320
328
  // src/dom/locale/fr-FR.ts
321
329
  var frFR = {
322
330
  configurationAxes: {
331
+ power: ["Puissance"],
323
332
  model: ["Mod\xE8le"],
324
333
  effort: ["Niveau"],
325
- speed: ["Vitesse"]
334
+ speed: ["Vitesse"],
335
+ advanced: ["Avanc\xE9"]
326
336
  },
327
337
  configurationOptions: {
338
+ instant: ["Instantan\xE9"],
328
339
  light: ["Minimal"],
329
340
  medium: ["Moyenne"],
330
341
  high: ["\xC9lev\xE9e"],
331
342
  extraHigh: ["Tr\xE8s \xE9lev\xE9e"],
343
+ max: ["Maximum"],
332
344
  fast: ["Rapide"]
333
345
  },
334
346
  composerTextbox: ["Discuter avec ChatGPT"],
@@ -340,9 +352,9 @@ var frFR = {
340
352
  addFilesOpenerCandidates: ["Ajouter des fichiers et plus encore"],
341
353
  addPhotosFilesMenuItem: ["Ajouter des photos et fichiers"],
342
354
  copyResponse: ["Copier la r\xE9ponse"],
343
- modeLabels: ["Moyen", "Avanc\xE9", "Tr\xE8s \xE9lev\xE9", "Instantan\xE9e", "Moyenne", "\xC9lev\xE9e", "Tr\xE8s \xE9lev\xE9e"],
355
+ modeLabels: ["Moyen", "Avanc\xE9", "Tr\xE8s \xE9lev\xE9", "Instantan\xE9e", "Moyenne", "\xC9lev\xE9e", "Tr\xE8s \xE9lev\xE9e", "Instantan\xE9"],
344
356
  modeOptions: {
345
- instant: ["Instantan\xE9e"],
357
+ instant: ["Instantan\xE9e", "Instantan\xE9"],
346
358
  medium: ["Moyen", "Moyenne"],
347
359
  high: ["Avanc\xE9", "\xC9lev\xE9e"],
348
360
  extraHigh: ["Tr\xE8s \xE9lev\xE9", "Tr\xE8s \xE9lev\xE9e"]
@@ -361,12 +373,15 @@ var frFR = {
361
373
  // src/dom/locale/zh-HK.ts
362
374
  var zhHK = {
363
375
  configurationAxes: {
376
+ power: ["\u667A\u80FD\u5F37\u5EA6"],
364
377
  model: ["\u6A21\u578B"],
365
378
  effort: ["\u63A8\u7406\u5F37\u5EA6"],
366
- speed: ["\u56DE\u61C9\u901F\u5EA6"]
379
+ speed: ["\u56DE\u61C9\u901F\u5EA6"],
380
+ advanced: ["\u9032\u968E"]
367
381
  },
368
382
  configurationOptions: {
369
- light: ["\u5FEB\u601D"],
383
+ instant: ["\u5373\u6642"],
384
+ light: ["\u5FEB\u601D", "\u8F15\u5EA6"],
370
385
  medium: ["\u4E2D"],
371
386
  high: ["\u9AD8"],
372
387
  extraHigh: ["\u6975\u9AD8"],
@@ -391,6 +406,10 @@ var zhHK = {
391
406
  pro: ["\u5C08\u696D"]
392
407
  },
393
408
  modeOpenerExtra: ["\u8A2D\u5B9A"],
409
+ experienceOptions: {
410
+ chat: ["\u5C0D\u8A71"],
411
+ work: ["\u5DE5\u4F5C"]
412
+ },
394
413
  tools: {
395
414
  web_search: ["\u7DB2\u7D61\u641C\u5C0B"],
396
415
  deep_research: ["\u6DF1\u5EA6\u7814\u7A76"],
@@ -404,15 +423,20 @@ var zhHK = {
404
423
  // src/dom/locale/zh-TW.ts
405
424
  var zhTW = {
406
425
  configurationAxes: {
426
+ power: ["\u80FD\u529B"],
407
427
  model: ["\u6A21\u578B"],
408
428
  effort: ["\u63A8\u7406\u5F37\u5EA6"],
409
- speed: ["\u901F\u5EA6"]
429
+ speed: ["\u901F\u5EA6"],
430
+ advanced: ["\u9032\u968E"]
410
431
  },
411
432
  configurationOptions: {
433
+ instant: ["\u5373\u6642"],
412
434
  light: ["\u5FEB\u601D"],
413
435
  medium: ["\u4E2D"],
414
436
  high: ["\u9AD8"],
415
- extraHigh: ["\u6975\u9AD8"],
437
+ extraHigh: ["\u6975\u9AD8", "\u8D85\u9AD8"],
438
+ max: ["\u6700\u9AD8"],
439
+ ultra: ["\u6975\u81F4"],
416
440
  standard: ["\u6A19\u6E96"],
417
441
  fast: ["\u5FEB\u901F"]
418
442
  },
@@ -434,6 +458,10 @@ var zhTW = {
434
458
  pro: ["\u5C08\u696D"]
435
459
  },
436
460
  modeOpenerExtra: ["\u8A2D\u5B9A"],
461
+ experienceOptions: {
462
+ chat: ["\u5C0D\u8A71"],
463
+ work: ["\u5DE5\u4F5C"]
464
+ },
437
465
  tools: {
438
466
  web_search: ["\u7DB2\u9801\u641C\u5C0B"],
439
467
  deep_research: ["\u6DF1\u5165\u7814\u7A76"],
@@ -447,15 +475,20 @@ var zhTW = {
447
475
  // src/dom/locale/ja.ts
448
476
  var ja = {
449
477
  configurationAxes: {
478
+ power: ["\u30D1\u30EF\u30FC"],
450
479
  model: ["\u30E2\u30C7\u30EB"],
451
- effort: ["\u601D\u8003\u30EC\u30D9\u30EB"],
452
- speed: ["\u901F\u5EA6"]
480
+ effort: ["\u601D\u8003\u30EC\u30D9\u30EB", "\u63A8\u8AD6\u30EC\u30D9\u30EB"],
481
+ speed: ["\u901F\u5EA6"],
482
+ advanced: ["\u8A73\u7D30\u8A2D\u5B9A"]
453
483
  },
454
484
  configurationOptions: {
485
+ instant: ["\u6700\u901F"],
455
486
  light: ["\u8EFD"],
456
487
  medium: ["\u4E2D\u7A0B\u5EA6"],
457
488
  high: ["\u9AD8\u3044"],
458
489
  extraHigh: ["\u975E\u5E38\u306B\u9AD8\u3044"],
490
+ max: ["\u6700\u5927"],
491
+ ultra: ["\u30A6\u30EB\u30C8\u30E9"],
459
492
  standard: ["\u6A19\u6E96"],
460
493
  fast: ["\u9AD8\u901F"]
461
494
  },
@@ -488,11 +521,14 @@ var ja = {
488
521
  // src/dom/locale/it.ts
489
522
  var it = {
490
523
  configurationAxes: {
524
+ power: ["Potenza"],
491
525
  model: ["Modello"],
492
526
  effort: ["Sforzo"],
493
- speed: ["Velocit\xE0"]
527
+ speed: ["Velocit\xE0"],
528
+ advanced: ["Avanzate"]
494
529
  },
495
530
  configurationOptions: {
531
+ instant: ["Istantaneo"],
496
532
  medium: ["Medio"],
497
533
  high: ["Alto"],
498
534
  extraHigh: ["Molto alto"],
@@ -507,9 +543,9 @@ var it = {
507
543
  addFilesOpenerCandidates: ["Aggiungi file e altro"],
508
544
  addPhotosFilesMenuItem: ["Aggiungi foto e file"],
509
545
  copyResponse: ["Copia risposta"],
510
- modeLabels: ["Istantanea", "Media", "Alta", "Extra elevata", "Medio", "Alto", "Molto alto"],
546
+ modeLabels: ["Istantanea", "Media", "Alta", "Extra elevata", "Medio", "Alto", "Molto alto", "Istantaneo"],
511
547
  modeOptions: {
512
- instant: ["Istantanea"],
548
+ instant: ["Istantanea", "Istantaneo"],
513
549
  medium: ["Media", "Medio"],
514
550
  high: ["Alta", "Alto"],
515
551
  extraHigh: ["Extra elevata", "Molto alto"]
@@ -527,15 +563,19 @@ var it = {
527
563
  // src/dom/locale/vi.ts
528
564
  var vi = {
529
565
  configurationAxes: {
566
+ power: ["S\u1EE9c m\u1EA1nh"],
530
567
  model: ["M\xF4 h\xECnh"],
531
- effort: ["M\u1EE9c \u0111\u1ED9"],
532
- speed: ["T\u1ED1c \u0111\u1ED9"]
568
+ effort: ["M\u1EE9c \u0111\u1ED9", "M\u1EE9c suy lu\u1EADn"],
569
+ speed: ["T\u1ED1c \u0111\u1ED9"],
570
+ advanced: ["N\xE2ng cao"]
533
571
  },
534
572
  configurationOptions: {
573
+ instant: ["T\u1EE9c th\xEC"],
535
574
  light: ["Nh\u1EB9"],
536
575
  medium: ["V\u1EEBa"],
537
576
  high: ["Cao"],
538
577
  extraHigh: ["Chuy\xEAn s\xE2u"],
578
+ max: ["T\u1ED1i \u0111a"],
539
579
  standard: ["Ti\xEAu chu\u1EA9n"],
540
580
  fast: ["Nhanh"]
541
581
  },
@@ -556,6 +596,10 @@ var vi = {
556
596
  extraHigh: ["R\u1EA5t cao", "Chuy\xEAn s\xE2u"]
557
597
  },
558
598
  modeOpenerExtra: ["\u0110\u1ECBnh c\u1EA5u h\xECnh"],
599
+ experienceOptions: {
600
+ chat: ["Tr\xF2 chuy\u1EC7n"],
601
+ work: ["C\xF4ng vi\u1EC7c"]
602
+ },
559
603
  tools: {
560
604
  web_search: ["T\xECm ki\u1EBFm tr\xEAn m\u1EA1ng"],
561
605
  deep_research: ["Nghi\xEAn c\u1EE9u chuy\xEAn s\xE2u"],
@@ -569,15 +613,20 @@ var vi = {
569
613
  // src/dom/locale/am.ts
570
614
  var am = {
571
615
  configurationAxes: {
616
+ power: ["\u12A0\u1245\u121D"],
572
617
  model: ["\u121E\u12F4\u120D"],
573
618
  effort: ["\u1325\u1228\u1275"],
574
- speed: ["\u134D\u1325\u1290\u1275"]
619
+ speed: ["\u134D\u1325\u1290\u1275"],
620
+ advanced: ["\u12E8\u120B\u1240"]
575
621
  },
576
622
  configurationOptions: {
623
+ instant: ["\u1348\u1323\u1295"],
577
624
  light: ["\u1240\u120B\u120D"],
578
625
  medium: ["\u1218\u12AB\u12A8\u1208\u129B"],
579
626
  high: ["\u12A8\u134D\u1270\u129B"],
580
627
  extraHigh: ["\u12A5\u1305\u130D \u12A8\u134D\u1270\u129B"],
628
+ max: ["\u12A8\u134D\u1270\u129B\u12CD"],
629
+ ultra: ["\u12A0\u120D\u1275\u122B"],
581
630
  standard: ["\u1218\u12F0\u1260\u129B"],
582
631
  fast: ["\u1348\u1323\u1295"]
583
632
  },
@@ -598,6 +647,10 @@ var am = {
598
647
  extraHigh: ["\u12A5\u1305\u130D \u12A8\u134D\u1270\u129B"]
599
648
  },
600
649
  modeOpenerExtra: ["\u12EB\u12CB\u1245\u1229"],
650
+ experienceOptions: {
651
+ chat: ["\u12CD\u12ED\u12ED\u1275"],
652
+ work: ["\u1225\u122B"]
653
+ },
601
654
  tools: {
602
655
  web_search: ["\u12E8\u12F5\u122D \u134D\u1208\u130B"],
603
656
  deep_research: ["\u1325\u120D\u1245 \u121D\u122D\u121D\u122D"],
@@ -611,16 +664,19 @@ var am = {
611
664
  // src/dom/locale/ar.ts
612
665
  var ar = {
613
666
  configurationAxes: {
667
+ power: ["\u0627\u0644\u0642\u062F\u0631\u0629"],
614
668
  model: ["\u0627\u0644\u0646\u0645\u0648\u0630\u062C"],
615
669
  effort: ["\u0627\u0644\u062C\u0647\u062F"],
616
- speed: ["\u0627\u0644\u0633\u0631\u0639\u0629"]
670
+ speed: ["\u0627\u0644\u0633\u0631\u0639\u0629"],
671
+ advanced: ["\u0645\u062A\u0642\u062F\u0645"]
617
672
  },
618
673
  configurationOptions: {
674
+ instant: ["\u0641\u0648\u0631\u064A"],
619
675
  light: ["\u062E\u0641\u064A\u0641"],
620
676
  medium: ["\u0645\u062A\u0648\u0633\u0637"],
621
677
  high: ["\u0639\u0627\u0644\u064D"],
622
678
  extraHigh: ["\u0639\u0627\u0644\u064D \u062C\u062F\u064B\u0627"],
623
- standard: ["\u0642\u064A\u0627\u0633\u064A"],
679
+ standard: ["\u0642\u064A\u0627\u0633\u064A", "\u0642\u064A\u0627\u0633\u064A\u0629"],
624
680
  fast: ["\u0633\u0631\u064A\u0639"]
625
681
  },
626
682
  composerTextbox: ["\u0627\u0644\u062F\u0631\u062F\u0634\u0629 \u0645\u0639 ChatGPT"],
@@ -641,6 +697,10 @@ var ar = {
641
697
  pro: ["\u0627\u062D\u062A\u0631\u0627\u0641\u064A"]
642
698
  },
643
699
  modeOpenerExtra: ["\u062A\u0643\u0648\u064A\u0646"],
700
+ experienceOptions: {
701
+ chat: ["\u0627\u0644\u062F\u0631\u062F\u0634\u0629"],
702
+ work: ["\u0627\u0644\u0639\u0645\u0644"]
703
+ },
644
704
  tools: {
645
705
  web_search: ["\u0627\u0644\u0628\u062D\u062B \u0641\u064A \u0627\u0644\u0648\u064A\u0628"],
646
706
  deep_research: ["\u0627\u0644\u0628\u062D\u062B \u0627\u0644\u062A\u0641\u0635\u064A\u0644\u064A"],
@@ -654,15 +714,20 @@ var ar = {
654
714
  // src/dom/locale/bg.ts
655
715
  var bg = {
656
716
  configurationAxes: {
717
+ power: ["\u041C\u043E\u0449\u043D\u043E\u0441\u0442"],
657
718
  model: ["\u041C\u043E\u0434\u0435\u043B"],
658
719
  effort: ["\u0423\u0441\u0438\u043B\u0438\u0435"],
659
- speed: ["\u0421\u043A\u043E\u0440\u043E\u0441\u0442"]
720
+ speed: ["\u0421\u043A\u043E\u0440\u043E\u0441\u0442"],
721
+ advanced: ["\u0420\u0430\u0437\u0448\u0438\u0440\u0435\u043D\u0438"]
660
722
  },
661
723
  configurationOptions: {
724
+ instant: ["\u041C\u0438\u0433\u043D\u043E\u0432\u0435\u043D"],
662
725
  light: ["\u041A\u0440\u0430\u0442\u043A\u043E"],
663
726
  medium: ["\u0421\u0440\u0435\u0434\u043D\u043E"],
664
727
  high: ["\u0412\u0438\u0441\u043E\u043A\u043E"],
665
728
  extraHigh: ["\u041C\u043D\u043E\u0433\u043E \u0432\u0438\u0441\u043E\u043A\u043E"],
729
+ max: ["\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u043D\u043E"],
730
+ ultra: ["\u0423\u043B\u0442\u0440\u0430"],
666
731
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u043E"],
667
732
  fast: ["\u0411\u044A\u0440\u0437\u0430"]
668
733
  },
@@ -697,14 +762,18 @@ var bg = {
697
762
  // src/dom/locale/bs.ts
698
763
  var bs = {
699
764
  configurationAxes: {
765
+ power: ["Snaga"],
700
766
  effort: ["Napor"],
701
- speed: ["Brzina"]
767
+ speed: ["Brzina"],
768
+ advanced: ["Napredno"]
702
769
  },
703
770
  configurationOptions: {
771
+ instant: ["Brzo"],
704
772
  light: ["Lagano"],
705
773
  medium: ["Srednja"],
706
774
  high: ["Visoka"],
707
775
  extraHigh: ["Veoma visoka"],
776
+ max: ["Maks."],
708
777
  standard: ["Standardno"],
709
778
  fast: ["Brzo"]
710
779
  },
@@ -738,14 +807,18 @@ var bs = {
738
807
  // src/dom/locale/ca.ts
739
808
  var ca = {
740
809
  configurationAxes: {
810
+ power: ["Pot\xE8ncia"],
741
811
  effort: ["Esfor\xE7"],
742
- speed: ["Velocitat"]
812
+ speed: ["Velocitat"],
813
+ advanced: ["Avan\xE7ades"]
743
814
  },
744
815
  configurationOptions: {
816
+ instant: ["Instant\xE0nia"],
745
817
  light: ["Lleuger"],
746
818
  medium: ["Mitjana"],
747
819
  high: ["Alta"],
748
820
  extraHigh: ["Molt alta"],
821
+ max: ["M\xE0xim"],
749
822
  standard: ["Est\xE0ndard"],
750
823
  fast: ["R\xE0pid"]
751
824
  },
@@ -766,6 +839,9 @@ var ca = {
766
839
  extraHigh: ["Molt alt", "Molt alta"]
767
840
  },
768
841
  modeOpenerExtra: ["Configura\u2026"],
842
+ experienceOptions: {
843
+ chat: ["Conversa"]
844
+ },
769
845
  tools: {
770
846
  web_search: ["Cerca a la xarxa"],
771
847
  deep_research: ["Recerca profunda"],
@@ -779,14 +855,18 @@ var ca = {
779
855
  // src/dom/locale/cs.ts
780
856
  var cs = {
781
857
  configurationAxes: {
782
- effort: ["\xDAsil\xED"],
783
- speed: ["Rychlost"]
858
+ power: ["V\xFDkon"],
859
+ effort: ["\xDAsil\xED", "M\xEDra \xFAsil\xED"],
860
+ speed: ["Rychlost"],
861
+ advanced: ["Pokro\u010Dil\xE9"]
784
862
  },
785
863
  configurationOptions: {
864
+ instant: ["Okam\u017Eit\xE1"],
786
865
  light: ["N\xEDzk\xE1"],
787
866
  medium: ["St\u0159edn\xED"],
788
867
  high: ["Vysok\xE1"],
789
868
  extraHigh: ["Velmi vysok\xE1"],
869
+ max: ["Maxim\xE1ln\xED"],
790
870
  standard: ["Standardn\xED"],
791
871
  fast: ["Rychl\xE9"]
792
872
  },
@@ -820,14 +900,18 @@ var cs = {
820
900
  // src/dom/locale/da.ts
821
901
  var da = {
822
902
  configurationAxes: {
823
- effort: ["Indsats"],
824
- speed: ["Hastighed"]
903
+ power: ["Styrke"],
904
+ effort: ["Indsats", "T\xE6nkeindsats"],
905
+ speed: ["Hastighed"],
906
+ advanced: ["Avanceret"]
825
907
  },
826
908
  configurationOptions: {
909
+ instant: ["\xD8jeblikkeligt"],
827
910
  light: ["Let"],
828
911
  medium: ["Mellem"],
829
912
  high: ["H\xF8j"],
830
913
  extraHigh: ["Ekstra h\xF8j"],
914
+ max: ["Maks."],
831
915
  fast: ["Hurtig"]
832
916
  },
833
917
  composerTextbox: ["Chat med ChatGPT"],
@@ -860,15 +944,19 @@ var da = {
860
944
  // src/dom/locale/el.ts
861
945
  var el = {
862
946
  configurationAxes: {
947
+ power: ["\u0399\u03C3\u03C7\u03CD\u03C2"],
863
948
  model: ["\u039C\u03BF\u03BD\u03C4\u03AD\u03BB\u03BF"],
864
- effort: ["\u03A0\u03C1\u03BF\u03C3\u03C0\u03AC\u03B8\u03B5\u03B9\u03B1"],
865
- speed: ["\u03A4\u03B1\u03C7\u03CD\u03C4\u03B7\u03C4\u03B1"]
949
+ 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"],
950
+ speed: ["\u03A4\u03B1\u03C7\u03CD\u03C4\u03B7\u03C4\u03B1"],
951
+ advanced: ["\u0393\u03B9\u03B1 \u03C0\u03C1\u03BF\u03C7\u03C9\u03C1\u03B7\u03BC\u03AD\u03BD\u03BF\u03C5\u03C2"]
866
952
  },
867
953
  configurationOptions: {
954
+ instant: ["\u0386\u03BC\u03B5\u03C3\u03B7"],
868
955
  light: ["\u0395\u03BB\u03B1\u03C6\u03C1\u03B9\u03AC"],
869
956
  medium: ["\u039C\u03B5\u03C3\u03B1\u03AF\u03BF"],
870
957
  high: ["\u03A5\u03C8\u03B7\u03BB\u03CC"],
871
958
  extraHigh: ["\u03A0\u03BF\u03BB\u03CD \u03C5\u03C8\u03B7\u03BB\u03CC"],
959
+ max: ["\u039C\u03AD\u03B3\u03B9\u03C3\u03C4\u03B7"],
872
960
  standard: ["\u03A4\u03C5\u03C0\u03B9\u03BA\u03CC"],
873
961
  fast: ["\u0393\u03C1\u03AE\u03B3\u03BF\u03C1\u03BF"]
874
962
  },
@@ -902,15 +990,19 @@ var el = {
902
990
  // src/dom/locale/es-419.ts
903
991
  var es419 = {
904
992
  configurationAxes: {
993
+ power: ["Potencia"],
905
994
  model: ["Modelo"],
906
995
  effort: ["Esfuerzo"],
907
- speed: ["Velocidad"]
996
+ speed: ["Velocidad"],
997
+ advanced: ["Avanzado"]
908
998
  },
909
999
  configurationOptions: {
1000
+ instant: ["Instant\xE1nea"],
910
1001
  light: ["M\xEDnimo"],
911
1002
  medium: ["Media"],
912
1003
  high: ["Alta"],
913
1004
  extraHigh: ["Muy alta"],
1005
+ max: ["M\xE1x."],
914
1006
  standard: ["Est\xE1ndar"],
915
1007
  fast: ["R\xE1pido"]
916
1008
  },
@@ -944,11 +1036,14 @@ var es419 = {
944
1036
  // src/dom/locale/et.ts
945
1037
  var et = {
946
1038
  configurationAxes: {
1039
+ power: ["V\xF5imsus"],
947
1040
  model: ["Mudel"],
948
- effort: ["Pingutus"],
949
- speed: ["Kiirus"]
1041
+ effort: ["Pingutus", "P\xF5hjalikkus"],
1042
+ speed: ["Kiirus"],
1043
+ advanced: ["T\xE4psemad seaded"]
950
1044
  },
951
1045
  configurationOptions: {
1046
+ instant: ["Kohene"],
952
1047
  light: ["Kerge"],
953
1048
  medium: ["Keskmine"],
954
1049
  high: ["K\xF5rge"],
@@ -985,15 +1080,19 @@ var et = {
985
1080
  // src/dom/locale/fa.ts
986
1081
  var fa = {
987
1082
  configurationAxes: {
1083
+ power: ["\u062A\u0648\u0627\u0646"],
988
1084
  model: ["\u0645\u062F\u0644"],
989
- effort: ["\u0633\u0637\u062D \u062A\u0644\u0627\u0634"],
990
- speed: ["\u0633\u0631\u0639\u062A"]
1085
+ effort: ["\u0633\u0637\u062D \u062A\u0644\u0627\u0634", "\u0645\u06CC\u0632\u0627\u0646 \u0627\u0633\u062A\u062F\u0644\u0627\u0644"],
1086
+ speed: ["\u0633\u0631\u0639\u062A"],
1087
+ advanced: ["\u067E\u06CC\u0634\u0631\u0641\u062A\u0647"]
991
1088
  },
992
1089
  configurationOptions: {
1090
+ instant: ["\u0641\u0648\u0631\u06CC"],
993
1091
  light: ["\u0633\u0628\u06A9"],
994
1092
  medium: ["\u0645\u062A\u0648\u0633\u0637"],
995
1093
  high: ["\u0628\u0627\u0644\u0627"],
996
1094
  extraHigh: ["\u0628\u0633\u06CC\u0627\u0631 \u0628\u0627\u0644\u0627"],
1095
+ max: ["\u062D\u062F\u0627\u06A9\u062B\u0631"],
997
1096
  fast: ["\u0633\u0631\u06CC\u0639"]
998
1097
  },
999
1098
  composerTextbox: ["\u06AF\u0641\u062A\u06AF\u0648 \u0628\u0627 ChatGPT"],
@@ -1014,6 +1113,10 @@ var fa = {
1014
1113
  pro: ["\u062D\u0631\u0641\u0647\u200C\u0627\u06CC"]
1015
1114
  },
1016
1115
  modeOpenerExtra: ["\u067E\u06CC\u06A9\u0631\u0628\u0646\u062F\u06CC..."],
1116
+ experienceOptions: {
1117
+ chat: ["\u0686\u062A"],
1118
+ work: ["\u06A9\u0627\u0631"]
1119
+ },
1017
1120
  tools: {
1018
1121
  web_search: ["\u062C\u0633\u062A\u062C\u0648\u06CC \u0648\u0628"],
1019
1122
  deep_research: ["\u067E\u0698\u0648\u0647\u0634 \u0639\u0645\u06CC\u0642"],
@@ -1027,15 +1130,19 @@ var fa = {
1027
1130
  // src/dom/locale/fi.ts
1028
1131
  var fi = {
1029
1132
  configurationAxes: {
1133
+ power: ["Teho"],
1030
1134
  model: ["Malli"],
1031
- effort: ["M\xE4\xE4r\xE4"],
1032
- speed: ["Nopeus"]
1135
+ effort: ["M\xE4\xE4r\xE4", "P\xE4\xE4ttelytaso"],
1136
+ speed: ["Nopeus"],
1137
+ advanced: ["Lis\xE4asetukset"]
1033
1138
  },
1034
1139
  configurationOptions: {
1140
+ instant: ["V\xE4lit\xF6n"],
1035
1141
  light: ["Kevyt"],
1036
1142
  medium: ["Keskitaso"],
1037
1143
  high: ["Korkea"],
1038
1144
  extraHigh: ["Eritt\xE4in korkea"],
1145
+ max: ["Maksimi"],
1039
1146
  standard: ["Perustaso"],
1040
1147
  fast: ["Nopea"]
1041
1148
  },
@@ -1069,10 +1176,13 @@ var fi = {
1069
1176
  // src/dom/locale/fr-CA.ts
1070
1177
  var frCA = {
1071
1178
  configurationAxes: {
1179
+ power: ["Puissance"],
1072
1180
  model: ["Mod\xE8le"],
1073
- speed: ["Vitesse"]
1181
+ speed: ["Vitesse"],
1182
+ advanced: ["Avanc\xE9"]
1074
1183
  },
1075
1184
  configurationOptions: {
1185
+ instant: ["Instantan\xE9"],
1076
1186
  light: ["L\xE9ger"],
1077
1187
  medium: ["Moyen"],
1078
1188
  high: ["\xC9lev\xE9"],
@@ -1109,15 +1219,20 @@ var frCA = {
1109
1219
  // src/dom/locale/gu.ts
1110
1220
  var gu = {
1111
1221
  configurationAxes: {
1222
+ power: ["\u0A95\u0ACD\u0AB7\u0AAE\u0AA4\u0ABE"],
1112
1223
  model: ["\u0AAE\u0ACB\u0AA1\u0AC7\u0AB2"],
1113
1224
  effort: ["\u0AAA\u0ACD\u0AB0\u0AAF\u0ABE\u0AB8"],
1114
- speed: ["\u0A9D\u0AA1\u0AAA"]
1225
+ speed: ["\u0A9D\u0AA1\u0AAA"],
1226
+ advanced: ["\u0A8F\u0AA1\u0AB5\u0ABE\u0AA8\u0ACD\u0AB8\u0ACD\u0AA1"]
1115
1227
  },
1116
1228
  configurationOptions: {
1229
+ instant: ["\u0AA4\u0AB0\u0AA4"],
1117
1230
  light: ["\u0AB2\u0ABE\u0A87\u0A9F"],
1118
1231
  medium: ["\u0AAE\u0AC0\u0AA1\u0ABF\u0AAF\u0AAE"],
1119
1232
  high: ["\u0AB9\u0ABE\u0A87"],
1120
1233
  extraHigh: ["\u0A8F\u0A95\u0ACD\u0AB8\u0ACD\u0A9F\u0ACD\u0AB0\u0ABE \u0AB9\u0ABE\u0A87"],
1234
+ max: ["\u0AAE\u0AB9\u0AA4\u0ACD\u0AA4\u0AAE"],
1235
+ ultra: ["\u0A85\u0AB2\u0ACD\u0A9F\u0ACD\u0AB0\u0ABE"],
1121
1236
  standard: ["\u0AB8\u0ACD\u0A9F\u0ABE\u0AA8\u0ACD\u0AA1\u0AB0\u0ACD\u0AA1"],
1122
1237
  fast: ["\u0A9D\u0AA1\u0AAA\u0AC0"]
1123
1238
  },
@@ -1138,6 +1253,10 @@ var gu = {
1138
1253
  extraHigh: ["\u0A85\u0AA4\u0ABF \u0A89\u0A9A\u0ACD\u0A9A", "\u0A8F\u0A95\u0ACD\u0AB8\u0ACD\u0A9F\u0ACD\u0AB0\u0ABE \u0AB9\u0ABE\u0A87"]
1139
1254
  },
1140
1255
  modeOpenerExtra: ["\u0A95\u0AA8\u0ACD\u0AAB\u0ABF\u0A97\u0AB0 \u0A95\u0AB0\u0ACB..."],
1256
+ experienceOptions: {
1257
+ chat: ["\u0A9A\u0AC5\u0A9F"],
1258
+ work: ["\u0A95\u0ABE\u0AAE"]
1259
+ },
1141
1260
  tools: {
1142
1261
  web_search: ["\u0AB5\u0AC7\u0AAC \u0AB6\u0ACB\u0AA7"],
1143
1262
  deep_research: ["\u0AA1\u0AC0\u0AAA \u0AB0\u0ABF\u0AB8\u0AB0\u0ACD\u0A9A"],
@@ -1151,15 +1270,20 @@ var gu = {
1151
1270
  // src/dom/locale/hi.ts
1152
1271
  var hi = {
1153
1272
  configurationAxes: {
1273
+ power: ["\u092A\u093E\u0935\u0930"],
1154
1274
  model: ["\u092E\u0949\u0921\u0932"],
1155
- effort: ["\u092A\u094D\u0930\u092F\u093E\u0938"],
1156
- speed: ["\u0917\u0924\u093F"]
1275
+ effort: ["\u092A\u094D\u0930\u092F\u093E\u0938", "\u0938\u094B\u091A\u0928\u0947 \u0915\u093E \u0938\u094D\u0924\u0930"],
1276
+ speed: ["\u0917\u0924\u093F"],
1277
+ advanced: ["\u090F\u0921\u0935\u093E\u0902\u0938\u094D\u0921"]
1157
1278
  },
1158
1279
  configurationOptions: {
1280
+ instant: ["\u0924\u0941\u0930\u0902\u0924"],
1159
1281
  light: ["\u0932\u093E\u0907\u091F"],
1160
1282
  medium: ["\u092E\u0927\u094D\u092F\u092E"],
1161
1283
  high: ["\u0909\u091A\u094D\u091A"],
1162
1284
  extraHigh: ["\u090F\u0915\u094D\u0938\u094D\u091F\u094D\u0930\u093E \u0939\u093E\u0908"],
1285
+ max: ["\u0905\u0927\u093F\u0915\u0924\u092E"],
1286
+ ultra: ["\u0905\u0932\u094D\u091F\u094D\u0930\u093E"],
1163
1287
  standard: ["\u0938\u094D\u091F\u0948\u0902\u0921\u0930\u094D\u0921"],
1164
1288
  fast: ["\u0924\u0947\u091C\u093C"]
1165
1289
  },
@@ -1180,6 +1304,10 @@ var hi = {
1180
1304
  extraHigh: ["\u092C\u0939\u0941\u0924 \u0909\u091A\u094D\u091A", "\u090F\u0915\u094D\u0938\u094D\u091F\u094D\u0930\u093E \u0939\u093E\u0908"]
1181
1305
  },
1182
1306
  modeOpenerExtra: ["\u0915\u0949\u0928\u094D\u092B\u093C\u093F\u0917\u0930 \u0915\u0930\u0947\u0902..."],
1307
+ experienceOptions: {
1308
+ chat: ["\u091A\u0948\u091F"],
1309
+ work: ["\u0935\u0930\u094D\u0915"]
1310
+ },
1183
1311
  tools: {
1184
1312
  web_search: ["\u0935\u0947\u092C \u0938\u0930\u094D\u091A"],
1185
1313
  deep_research: ["\u0921\u0940\u092A \u0930\u093F\u0938\u0930\u094D\u091A"],
@@ -1193,14 +1321,17 @@ var hi = {
1193
1321
  // src/dom/locale/hr.ts
1194
1322
  var hr = {
1195
1323
  configurationAxes: {
1324
+ power: ["Snaga"],
1196
1325
  effort: ["Razina napora"],
1197
- speed: ["Brzina"]
1326
+ speed: ["Brzina"],
1327
+ advanced: ["Napredno"]
1198
1328
  },
1199
1329
  configurationOptions: {
1200
1330
  light: ["Lagano"],
1201
1331
  medium: ["Srednja"],
1202
1332
  high: ["Visoka"],
1203
1333
  extraHigh: ["Vrlo visoka"],
1334
+ max: ["Maks."],
1204
1335
  standard: ["Standardno"],
1205
1336
  fast: ["Brzo"]
1206
1337
  },
@@ -1233,11 +1364,14 @@ var hr = {
1233
1364
  // src/dom/locale/hu.ts
1234
1365
  var hu = {
1235
1366
  configurationAxes: {
1367
+ power: ["Teljes\xEDtm\xE9ny"],
1236
1368
  model: ["Modell"],
1237
- effort: ["R\xE1ford\xEDt\xE1s"],
1238
- speed: ["Sebess\xE9g"]
1369
+ effort: ["R\xE1ford\xEDt\xE1s", "Er\u0151fesz\xEDt\xE9s"],
1370
+ speed: ["Sebess\xE9g"],
1371
+ advanced: ["Speci\xE1lis"]
1239
1372
  },
1240
1373
  configurationOptions: {
1374
+ instant: ["Azonnali"],
1241
1375
  light: ["Egyszer\u0171"],
1242
1376
  medium: ["K\xF6zepes"],
1243
1377
  high: ["Er\u0151s"],
@@ -1275,15 +1409,20 @@ var hu = {
1275
1409
  // src/dom/locale/hy.ts
1276
1410
  var hy = {
1277
1411
  configurationAxes: {
1412
+ power: ["\u0540\u0566\u0578\u0580\u0578\u0582\u0569\u0575\u0578\u0582\u0576"],
1278
1413
  model: ["\u0544\u0578\u0564\u0565\u056C"],
1279
- effort: ["\u054B\u0561\u0576\u0584"],
1280
- speed: ["\u0531\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576"]
1414
+ 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"],
1415
+ speed: ["\u0531\u0580\u0561\u0563\u0578\u0582\u0569\u0575\u0578\u0582\u0576"],
1416
+ advanced: ["\u0538\u0576\u0564\u056C\u0561\u0575\u0576\u057E\u0561\u056E"]
1281
1417
  },
1282
1418
  configurationOptions: {
1419
+ instant: ["\u0531\u056F\u0576\u0569\u0561\u0580\u0569\u0561\u0575\u056B\u0576"],
1283
1420
  light: ["\u0539\u0565\u0569\u0587"],
1284
1421
  medium: ["\u0544\u056B\u057B\u056B\u0576"],
1285
1422
  high: ["\u0540\u0566\u0578\u0580"],
1286
1423
  extraHigh: ["\u0531\u057E\u0565\u056C\u056B \u0570\u0566\u0578\u0580"],
1424
+ max: ["\u0531\u057C\u0561\u057E\u0565\u056C\u0561\u0563\u0578\u0582\u0575\u0576"],
1425
+ ultra: ["\u0548\u0582\u056C\u057F\u0580\u0561"],
1287
1426
  standard: ["\u054D\u057F\u0561\u0576\u0564\u0561\u0580\u057F"],
1288
1427
  fast: ["\u0531\u0580\u0561\u0563"]
1289
1428
  },
@@ -1305,6 +1444,10 @@ var hy = {
1305
1444
  pro: ["\u054A\u0580\u0578"]
1306
1445
  },
1307
1446
  modeOpenerExtra: ["\u053F\u0561\u0566\u0574\u0561\u0571\u0587\u0565\u056C\u2024\u2024\u2024"],
1447
+ experienceOptions: {
1448
+ chat: ["\u0536\u0580\u0578\u0582\u0575\u0581"],
1449
+ work: ["\u0531\u0577\u056D\u0561\u057F\u0561\u0576\u0584"]
1450
+ },
1308
1451
  tools: {
1309
1452
  web_search: ["\u054E\u0565\u0562 \u0578\u0580\u0578\u0576\u0578\u0582\u0574"],
1310
1453
  deep_research: ["\u053D\u0578\u0580\u0568 \u0578\u0582\u057D\u0578\u0582\u0574\u0576\u0561\u057D\u056B\u0580\u0578\u0582\u0569\u0575\u0578\u0582\u0576"],
@@ -1318,14 +1461,18 @@ var hy = {
1318
1461
  // src/dom/locale/id.ts
1319
1462
  var id = {
1320
1463
  configurationAxes: {
1464
+ power: ["Daya"],
1321
1465
  effort: ["Upaya"],
1322
- speed: ["Kecepatan"]
1466
+ speed: ["Kecepatan"],
1467
+ advanced: ["Tingkat lanjut"]
1323
1468
  },
1324
1469
  configurationOptions: {
1470
+ instant: ["Instan"],
1325
1471
  light: ["Ringan"],
1326
1472
  medium: ["Sedang"],
1327
1473
  high: ["Tinggi"],
1328
1474
  extraHigh: ["Ekstra Tinggi"],
1475
+ max: ["Maks"],
1329
1476
  standard: ["Standar"],
1330
1477
  fast: ["Cepat"]
1331
1478
  },
@@ -1359,15 +1506,19 @@ var id = {
1359
1506
  // src/dom/locale/is.ts
1360
1507
  var is = {
1361
1508
  configurationAxes: {
1509
+ power: ["Afl"],
1362
1510
  model: ["L\xEDkan"],
1363
- effort: ["\xC1reynsla"],
1364
- speed: ["Hra\xF0i"]
1511
+ effort: ["\xC1reynsla", "Vinnsla"],
1512
+ speed: ["Hra\xF0i"],
1513
+ advanced: ["\xCDtarlegt"]
1365
1514
  },
1366
1515
  configurationOptions: {
1516
+ instant: ["Strax"],
1367
1517
  light: ["L\xE9tt"],
1368
1518
  medium: ["Mi\xF0lungs"],
1369
1519
  high: ["H\xE1tt"],
1370
1520
  extraHigh: ["Mj\xF6g h\xE1tt"],
1521
+ max: ["H\xE1mark"],
1371
1522
  fast: ["Hratt"]
1372
1523
  },
1373
1524
  composerTextbox: ["Spjalla\xF0u vi\xF0 ChatGPT"],
@@ -1387,6 +1538,10 @@ var is = {
1387
1538
  extraHigh: ["Mj\xF6g h\xE1tt"]
1388
1539
  },
1389
1540
  modeOpenerExtra: ["Stillir\u2026"],
1541
+ experienceOptions: {
1542
+ chat: ["Spjall"],
1543
+ work: ["Vinna"]
1544
+ },
1390
1545
  tools: {
1391
1546
  web_search: ["Vefleit"],
1392
1547
  deep_research: ["\xCDtarleg ranns\xF3kn"],
@@ -1400,15 +1555,20 @@ var is = {
1400
1555
  // src/dom/locale/ka.ts
1401
1556
  var ka = {
1402
1557
  configurationAxes: {
1558
+ power: ["\u10E1\u10D8\u10DB\u10EB\u10DA\u10D0\u10D5\u10E0\u10D4"],
1403
1559
  model: ["\u10DB\u10DD\u10D3\u10D4\u10DA\u10D8"],
1404
- effort: ["\u10EB\u10D0\u10DA\u10D8\u10E1\u10EE\u10DB\u10D4\u10D5\u10D0"],
1405
- speed: ["\u10E1\u10D8\u10E9\u10E5\u10D0\u10E0\u10D4"]
1560
+ effort: ["\u10EB\u10D0\u10DA\u10D8\u10E1\u10EE\u10DB\u10D4\u10D5\u10D0", "\u10DB\u10E1\u10EF\u10D4\u10DA\u10DD\u10D1\u10D8\u10E1 \u10D3\u10DD\u10DC\u10D4"],
1561
+ speed: ["\u10E1\u10D8\u10E9\u10E5\u10D0\u10E0\u10D4"],
1562
+ advanced: ["\u10D2\u10D0\u10E4\u10D0\u10E0\u10D7\u10DD\u10D4\u10D1\u10E3\u10DA\u10D8"]
1406
1563
  },
1407
1564
  configurationOptions: {
1565
+ instant: ["\u10DB\u10E7\u10D8\u10E1\u10D8\u10D4\u10E0\u10D8"],
1408
1566
  light: ["\u10DB\u10E1\u10E3\u10D1\u10E3\u10E5\u10D8"],
1409
1567
  medium: ["\u10E1\u10D0\u10E8\u10E3\u10D0\u10DA\u10DD"],
1410
1568
  high: ["\u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"],
1411
1569
  extraHigh: ["\u10EB\u10D0\u10DA\u10D8\u10D0\u10DC \u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"],
1570
+ max: ["\u10DB\u10D0\u10E5\u10E1."],
1571
+ ultra: ["\u10E3\u10DA\u10E2\u10E0\u10D0"],
1412
1572
  standard: ["\u10E1\u10E2\u10D0\u10DC\u10D3\u10D0\u10E0\u10E2\u10E3\u10DA\u10D8"],
1413
1573
  fast: ["\u10E1\u10EC\u10E0\u10D0\u10E4\u10D8"]
1414
1574
  },
@@ -1429,6 +1589,10 @@ var ka = {
1429
1589
  extraHigh: ["\u10EB\u10D0\u10DA\u10D8\u10D0\u10DC \u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"]
1430
1590
  },
1431
1591
  modeOpenerExtra: ["\u10D9\u10DD\u10DC\u10E4\u10D8\u10D2\u10E3\u10E0\u10D8\u10E0\u10D4\u10D1\u10D0\u2026"],
1592
+ experienceOptions: {
1593
+ chat: ["\u10E9\u10D0\u10E2\u10D8"],
1594
+ work: ["\u10DB\u10E3\u10E8\u10D0\u10DD\u10D1\u10D0"]
1595
+ },
1432
1596
  tools: {
1433
1597
  web_search: ["\u10D5\u10D4\u10D1\u10E8\u10D8 \u10EB\u10D8\u10D4\u10D1\u10D0"],
1434
1598
  deep_research: ["\u10E1\u10D8\u10E6\u10E0\u10DB\u10D8\u10E1\u10D4\u10E3\u10DA\u10D8 \u10D9\u10D5\u10DA\u10D4\u10D5\u10D0"],
@@ -1442,15 +1606,20 @@ var ka = {
1442
1606
  // src/dom/locale/kk.ts
1443
1607
  var kk = {
1444
1608
  configurationAxes: {
1609
+ power: ["\u049A\u0443\u0430\u0442"],
1445
1610
  model: ["\u041C\u043E\u0434\u0435\u043B\u044C"],
1446
- effort: ["\u041A\u04AF\u0448-\u0436\u0456\u0433\u0435\u0440"],
1447
- speed: ["\u0416\u044B\u043B\u0434\u0430\u043C\u0434\u044B\u049B"]
1611
+ effort: ["\u041A\u04AF\u0448-\u0436\u0456\u0433\u0435\u0440", "\u041E\u0439\u043B\u0430\u043D\u0443 \u0434\u0435\u04A3\u0433\u0435\u0439\u0456"],
1612
+ speed: ["\u0416\u044B\u043B\u0434\u0430\u043C\u0434\u044B\u049B"],
1613
+ advanced: ["\u041A\u0435\u04A3\u0435\u0439\u0442\u0456\u043B\u0433\u0435\u043D"]
1448
1614
  },
1449
1615
  configurationOptions: {
1616
+ instant: ["\u0416\u0435\u0434\u0435\u043B"],
1450
1617
  light: ["\u0416\u0435\u04A3\u0456\u043B"],
1451
1618
  medium: ["\u041E\u0440\u0442\u0430\u0448\u0430"],
1452
1619
  high: ["\u0416\u043E\u0493\u0430\u0440\u044B"],
1453
1620
  extraHigh: ["\u04E8\u0442\u0435 \u0436\u043E\u0493\u0430\u0440\u044B"],
1621
+ max: ["\u041C\u0430\u043A\u0441"],
1622
+ ultra: ["\u0423\u043B\u044C\u0442\u0440\u0430"],
1454
1623
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u0442\u044B"],
1455
1624
  fast: ["\u0416\u044B\u043B\u0434\u0430\u043C"]
1456
1625
  },
@@ -1471,6 +1640,10 @@ var kk = {
1471
1640
  extraHigh: ["\u0410\u0441\u0430 \u0436\u043E\u0493\u0430\u0440\u044B", "\u04E8\u0442\u0435 \u0436\u043E\u0493\u0430\u0440\u044B"]
1472
1641
  },
1473
1642
  modeOpenerExtra: ["\u041A\u043E\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F\u043B\u0430\u0443..."],
1643
+ experienceOptions: {
1644
+ chat: ["\u0427\u0430\u0442"],
1645
+ work: ["\u0416\u04B1\u043C\u044B\u0441"]
1646
+ },
1474
1647
  tools: {
1475
1648
  web_search: ["\u0406\u0437\u0434\u0435\u0443"],
1476
1649
  deep_research: ["\u0422\u0435\u0440\u0435\u04A3 \u0437\u0435\u0440\u0442\u0442\u0435\u0443"],
@@ -1484,15 +1657,20 @@ var kk = {
1484
1657
  // src/dom/locale/kn.ts
1485
1658
  var kn = {
1486
1659
  configurationAxes: {
1660
+ power: ["\u0CAA\u0CB5\u0CB0\u0CCD"],
1487
1661
  model: ["\u0CAE\u0CBE\u0CA1\u0CC6\u0CB2\u0CCD"],
1488
- effort: ["\u0C8E\u0CAB\u0CB0\u0CCD\u0C9F\u0CCD"],
1489
- speed: ["\u0CB5\u0CC7\u0C97"]
1662
+ effort: ["\u0C8E\u0CAB\u0CB0\u0CCD\u0C9F\u0CCD", "\u0CAA\u0CCD\u0CB0\u0CAF\u0CA4\u0CCD\u0CA8"],
1663
+ speed: ["\u0CB5\u0CC7\u0C97"],
1664
+ advanced: ["\u0CB8\u0CC1\u0CA7\u0CBE\u0CB0\u0CBF\u0CA4"]
1490
1665
  },
1491
1666
  configurationOptions: {
1667
+ instant: ["\u0CA4\u0C95\u0CCD\u0CB7\u0CA3"],
1492
1668
  light: ["\u0CB2\u0CC8\u0C9F\u0CCD"],
1493
1669
  medium: ["\u0CAE\u0CC0\u0CA1\u0CBF\u0CAF\u0C82"],
1494
1670
  high: ["\u0CB9\u0CC8"],
1495
1671
  extraHigh: ["\u0C8E\u0C95\u0CCD\u0CB8\u0CCD\u200C\u0C9F\u0CCD\u0CB0\u0CBE \u0CB9\u0CC8"],
1672
+ max: ["\u0C97\u0CB0\u0CBF\u0CB7\u0CCD\u0CA0"],
1673
+ ultra: ["\u0C85\u0CB2\u0CCD\u0C9F\u0CCD\u0CB0\u0CBE"],
1496
1674
  standard: ["\u0CB8\u0CCD\u0C9F\u0CCD\u0CAF\u0CBE\u0C82\u0CA1\u0CB0\u0CCD\u0CA1\u0CCD"],
1497
1675
  fast: ["\u0CA4\u0CCD\u0CB5\u0CB0\u0CBF\u0CA4"]
1498
1676
  },
@@ -1514,6 +1692,9 @@ var kn = {
1514
1692
  pro: ["\u0CAA\u0CCD\u0CB0\u0CCA"]
1515
1693
  },
1516
1694
  modeOpenerExtra: ["\u0C95\u0CBE\u0CA8\u0CCD\u0CAB\u0CBF\u0C97\u0CB0\u0CCD \u0CAE\u0CBE\u0CA1\u0CBF..."],
1695
+ experienceOptions: {
1696
+ chat: ["\u0C9A\u0CBE\u0C9F\u0CCD"]
1697
+ },
1517
1698
  tools: {
1518
1699
  web_search: ["\u0CB5\u0CC6\u0CAC\u0CCD \u0CB8\u0CB0\u0CCD\u0C9A\u0CCD"],
1519
1700
  deep_research: ["\u0CA1\u0CC0\u0CAA\u0CCD \u0CB0\u0CBF\u0CB8\u0CB0\u0CCD\u0C9A\u0CCD"],
@@ -1527,14 +1708,19 @@ var kn = {
1527
1708
  // src/dom/locale/ko.ts
1528
1709
  var ko = {
1529
1710
  configurationAxes: {
1711
+ power: ["\uC131\uB2A5"],
1530
1712
  model: ["\uBAA8\uB378"],
1531
- effort: ["\uCD94\uB860 \uC218\uC900"],
1532
- speed: ["\uC18D\uB3C4"]
1713
+ effort: ["\uCD94\uB860 \uC218\uC900", "\uCD94\uB860 \uAC15\uB3C4"],
1714
+ speed: ["\uC18D\uB3C4"],
1715
+ advanced: ["\uACE0\uAE09"]
1533
1716
  },
1534
1717
  configurationOptions: {
1718
+ instant: ["\uC989\uC2DC"],
1535
1719
  medium: ["\uC911\uAC04"],
1536
1720
  high: ["\uB192\uC74C"],
1537
1721
  extraHigh: ["\uB9E4\uC6B0 \uB192\uC74C"],
1722
+ max: ["\uCD5C\uB300"],
1723
+ ultra: ["\uC6B8\uD2B8\uB77C"],
1538
1724
  fast: ["\uBE60\uB984"]
1539
1725
  },
1540
1726
  composerTextbox: ["ChatGPT\uC640 \uCC44\uD305"],
@@ -1567,15 +1753,19 @@ var ko = {
1567
1753
  // src/dom/locale/lt.ts
1568
1754
  var lt = {
1569
1755
  configurationAxes: {
1756
+ power: ["Paj\u0117gumas"],
1570
1757
  model: ["Modelis"],
1571
- effort: ["Pastangos"],
1572
- speed: ["Greitis"]
1758
+ effort: ["Pastangos", "M\u0105stymo lygis"],
1759
+ speed: ["Greitis"],
1760
+ advanced: ["I\u0161pl\u0117stiniai"]
1573
1761
  },
1574
1762
  configurationOptions: {
1763
+ instant: ["Momentinis"],
1575
1764
  light: ["Lengvas"],
1576
1765
  medium: ["Vidutinis"],
1577
1766
  high: ["Auk\u0161tas"],
1578
1767
  extraHigh: ["Labai auk\u0161tas"],
1768
+ max: ["Maks."],
1579
1769
  standard: ["Standartinis"],
1580
1770
  fast: ["Greitas"]
1581
1771
  },
@@ -1610,15 +1800,20 @@ var lt = {
1610
1800
  // src/dom/locale/zh-Hans.ts
1611
1801
  var zhHans = {
1612
1802
  configurationAxes: {
1803
+ power: ["\u80FD\u529B"],
1613
1804
  model: ["\u6A21\u578B"],
1614
- effort: ["\u63A8\u7406\u5F3A\u5EA6"],
1615
- speed: ["\u901F\u5EA6"]
1805
+ effort: ["\u63A8\u7406\u5F3A\u5EA6", "\u601D\u8003\u5F3A\u5EA6"],
1806
+ speed: ["\u901F\u5EA6"],
1807
+ advanced: ["\u9AD8\u7EA7"]
1616
1808
  },
1617
1809
  configurationOptions: {
1810
+ instant: ["\u6781\u901F"],
1618
1811
  light: ["\u8F7B\u5EA6"],
1619
1812
  medium: ["\u4E2D"],
1620
1813
  high: ["\u9AD8"],
1621
1814
  extraHigh: ["\u6781\u9AD8"],
1815
+ max: ["\u6700\u9AD8"],
1816
+ ultra: ["\u8D85\u9AD8"],
1622
1817
  standard: ["\u6807\u51C6"],
1623
1818
  fast: ["\u5FEB\u901F"]
1624
1819
  },
@@ -1640,6 +1835,10 @@ var zhHans = {
1640
1835
  pro: ["\u4E13\u4E1A"]
1641
1836
  },
1642
1837
  modeOpenerExtra: ["\u914D\u7F6E\u2026"],
1838
+ experienceOptions: {
1839
+ chat: ["\u804A\u5929"],
1840
+ work: ["\u5DE5\u4F5C"]
1841
+ },
1643
1842
  tools: {
1644
1843
  web_search: ["\u7F51\u9875\u641C\u7D22"],
1645
1844
  deep_research: ["\u6DF1\u5EA6\u7814\u7A76"],
@@ -1655,13 +1854,17 @@ var ur = {
1655
1854
  configurationAxes: {
1656
1855
  model: ["\u0645\u0627\u0688\u0644"],
1657
1856
  effort: ["\u06A9\u0648\u0634\u0634"],
1658
- speed: ["\u0631\u0641\u062A\u0627\u0631"]
1857
+ speed: ["\u0631\u0641\u062A\u0627\u0631"],
1858
+ advanced: ["\u0627\u06CC\u0688\u0648\u0627\u0646\u0633\u0688"]
1659
1859
  },
1660
1860
  configurationOptions: {
1861
+ instant: ["\u0641\u0648\u0631\u06CC"],
1661
1862
  light: ["\u0644\u0627\u0626\u0679"],
1662
1863
  medium: ["\u0627\u0648\u0633\u0637"],
1663
1864
  high: ["\u06C1\u0627\u0626\u06CC"],
1664
1865
  extraHigh: ["\u0627\u06CC\u06A9\u0633\u0679\u0631\u0627 \u06C1\u0627\u0626\u06CC"],
1866
+ max: ["\u0632\u06CC\u0627\u062F\u06C1 \u0633\u06D2 \u0632\u06CC\u0627\u062F\u06C1"],
1867
+ ultra: ["\u0627\u0644\u0679\u0631\u0627"],
1665
1868
  standard: ["\u0627\u0633\u0679\u06CC\u0646\u0688\u0631\u0688"],
1666
1869
  fast: ["\u062A\u06CC\u0632"]
1667
1870
  },
@@ -1682,6 +1885,10 @@ var ur = {
1682
1885
  extraHigh: ["\u0627\u0646\u062A\u06C1\u0627\u0626\u06CC \u0627\u0639\u0644\u06CC\u0670", "\u0627\u06CC\u06A9\u0633\u0679\u0631\u0627 \u06C1\u0627\u0626\u06CC"]
1683
1886
  },
1684
1887
  modeOpenerExtra: ["\u06A9\u0646\u0641\u06CC\u06AF\u0631 \u06A9\u0631\u06CC\u06BA..."],
1888
+ experienceOptions: {
1889
+ chat: ["\u0686\u064E\u06CC\u0679"],
1890
+ work: ["\u06A9\u0627\u0645"]
1891
+ },
1685
1892
  tools: {
1686
1893
  web_search: ["\u0648\u06CC\u0628 \u067E\u0631 \u062A\u0644\u0627\u0634"],
1687
1894
  deep_research: ["\u0688\u06CC\u067E \u0631\u06CC\u0633\u0631\u0686"],
@@ -1695,15 +1902,20 @@ var ur = {
1695
1902
  // src/dom/locale/uk.ts
1696
1903
  var uk = {
1697
1904
  configurationAxes: {
1905
+ power: ["\u041F\u043E\u0442\u0443\u0436\u043D\u0456\u0441\u0442\u044C"],
1698
1906
  model: ["\u041C\u043E\u0434\u0435\u043B\u044C"],
1699
- effort: ["\u0417\u0443\u0441\u0438\u043B\u043B\u044F"],
1700
- speed: ["\u0428\u0432\u0438\u0434\u043A\u0456\u0441\u0442\u044C"]
1907
+ effort: ["\u0417\u0443\u0441\u0438\u043B\u043B\u044F", "\u041C\u0456\u0440\u043A\u0443\u0432\u0430\u043D\u043D\u044F"],
1908
+ speed: ["\u0428\u0432\u0438\u0434\u043A\u0456\u0441\u0442\u044C"],
1909
+ advanced: ["\u0414\u043E\u0434\u0430\u0442\u043A\u043E\u0432\u043E"]
1701
1910
  },
1702
1911
  configurationOptions: {
1912
+ instant: ["\u041C\u0438\u0442\u0442\u0454\u0432\u0438\u0439"],
1703
1913
  light: ["\u041D\u0438\u0437\u044C\u043A\u0438\u0439"],
1704
1914
  medium: ["\u0421\u0435\u0440\u0435\u0434\u043D\u0456\u0439"],
1705
1915
  high: ["\u0412\u0438\u0441\u043E\u043A\u0438\u0439"],
1706
1916
  extraHigh: ["\u041D\u0430\u0439\u0432\u0438\u0449\u0438\u0439"],
1917
+ max: ["\u041C\u0430\u043A\u0441."],
1918
+ ultra: ["\u0423\u043B\u044C\u0442\u0440\u0430"],
1707
1919
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u0438\u0439"],
1708
1920
  fast: ["\u0428\u0432\u0438\u0434\u043A\u0430"]
1709
1921
  },
@@ -1724,6 +1936,10 @@ var uk = {
1724
1936
  extraHigh: ["\u0414\u0443\u0436\u0435 \u0432\u0438\u0441\u043E\u043A\u0438\u0439", "\u041D\u0430\u0439\u0432\u0438\u0449\u0438\u0439"]
1725
1937
  },
1726
1938
  modeOpenerExtra: ["\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438\u2026"],
1939
+ experienceOptions: {
1940
+ chat: ["\u0427\u0430\u0442"],
1941
+ work: ["\u0420\u043E\u0431\u043E\u0442\u0430"]
1942
+ },
1727
1943
  tools: {
1728
1944
  web_search: ["\u041F\u043E\u0448\u0443\u043A \u0432 \u0406\u043D\u0442\u0435\u0440\u043D\u0435\u0442\u0456"],
1729
1945
  deep_research: ["\u0413\u043B\u0438\u0431\u043E\u043A\u043E \u0434\u043E\u0441\u043B\u0456\u0434\u0438\u0442\u0438"],
@@ -1737,15 +1953,19 @@ var uk = {
1737
1953
  // src/dom/locale/pt-BR.ts
1738
1954
  var ptBR = {
1739
1955
  configurationAxes: {
1956
+ power: ["Pot\xEAncia"],
1740
1957
  model: ["Modelo"],
1741
- effort: ["Esfor\xE7o"],
1742
- speed: ["Velocidade"]
1958
+ effort: ["Esfor\xE7o", "N\xEDvel de racioc\xEDnio"],
1959
+ speed: ["Velocidade"],
1960
+ advanced: ["Avan\xE7ado"]
1743
1961
  },
1744
1962
  configurationOptions: {
1963
+ instant: ["Instant\xE2neo"],
1745
1964
  light: ["Leve"],
1746
1965
  medium: ["M\xE9dio"],
1747
1966
  high: ["Alto"],
1748
1967
  extraHigh: ["Extra alto"],
1968
+ max: ["M\xE1ximo"],
1749
1969
  standard: ["Padr\xE3o"],
1750
1970
  fast: ["R\xE1pido"]
1751
1971
  },
@@ -1779,15 +1999,19 @@ var ptBR = {
1779
1999
  // src/dom/locale/pt-PT.ts
1780
2000
  var ptPT = {
1781
2001
  configurationAxes: {
2002
+ power: ["Capacidade"],
1782
2003
  model: ["Modelo"],
1783
2004
  effort: ["Esfor\xE7o"],
1784
- speed: ["Velocidade"]
2005
+ speed: ["Velocidade"],
2006
+ advanced: ["Avan\xE7ado"]
1785
2007
  },
1786
2008
  configurationOptions: {
2009
+ instant: ["Instant\xE2neo"],
1787
2010
  light: ["Leve"],
1788
2011
  medium: ["M\xE9dio"],
1789
2012
  high: ["Elevado"],
1790
2013
  extraHigh: ["Muito elevado"],
2014
+ max: ["M\xE1x."],
1791
2015
  standard: ["Padr\xE3o"],
1792
2016
  fast: ["R\xE1pido"]
1793
2017
  },
@@ -1821,14 +2045,18 @@ var ptPT = {
1821
2045
  // src/dom/locale/pl.ts
1822
2046
  var pl = {
1823
2047
  configurationAxes: {
1824
- effort: ["Nak\u0142ad pracy"],
1825
- speed: ["Szybko\u015B\u0107"]
2048
+ power: ["Moc"],
2049
+ effort: ["Nak\u0142ad pracy", "Wysi\u0142ek"],
2050
+ speed: ["Szybko\u015B\u0107"],
2051
+ advanced: ["Zaawansowane"]
1826
2052
  },
1827
2053
  configurationOptions: {
2054
+ instant: ["B\u0142yskawiczny"],
1828
2055
  light: ["Lekki"],
1829
2056
  medium: ["\u015Aredni"],
1830
2057
  high: ["Wysoki"],
1831
2058
  extraHigh: ["Bardzo wysoki"],
2059
+ max: ["Maks."],
1832
2060
  standard: ["Standardowy"],
1833
2061
  fast: ["Szybki"]
1834
2062
  },
@@ -1862,14 +2090,18 @@ var pl = {
1862
2090
  // src/dom/locale/sk.ts
1863
2091
  var sk = {
1864
2092
  configurationAxes: {
2093
+ power: ["V\xFDkon"],
1865
2094
  effort: ["\xDAsilie"],
1866
- speed: ["R\xFDchlos\u0165"]
2095
+ speed: ["R\xFDchlos\u0165"],
2096
+ advanced: ["Roz\u0161\xEDren\xE9"]
1867
2097
  },
1868
2098
  configurationOptions: {
2099
+ instant: ["Okam\u017Eit\xE1"],
1869
2100
  light: ["\u013Dahk\xE9"],
1870
2101
  medium: ["Stredn\xE1"],
1871
2102
  high: ["Vysok\xE1"],
1872
2103
  extraHigh: ["Ve\u013Emi vysok\xE1"],
2104
+ max: ["Maxim\xE1lne"],
1873
2105
  standard: ["\u0160tandardn\xE1"],
1874
2106
  fast: ["R\xFDchla"]
1875
2107
  },
@@ -1903,14 +2135,17 @@ var sk = {
1903
2135
  // src/dom/locale/ro.ts
1904
2136
  var ro = {
1905
2137
  configurationAxes: {
2138
+ power: ["Capacitate"],
1906
2139
  effort: ["Efort"],
1907
- speed: ["Vitez\u0103"]
2140
+ speed: ["Vitez\u0103"],
2141
+ advanced: ["Avansat"]
1908
2142
  },
1909
2143
  configurationOptions: {
1910
2144
  light: ["U\u0219or"],
1911
2145
  medium: ["Medie"],
1912
2146
  high: ["Ridicat\u0103"],
1913
2147
  extraHigh: ["Foarte ridicat\u0103"],
2148
+ max: ["Maxim"],
1914
2149
  fast: ["Rapid"]
1915
2150
  },
1916
2151
  composerTextbox: ["\xCEntreab\u0103 orice"],
@@ -1942,15 +2177,19 @@ var ro = {
1942
2177
  // src/dom/locale/nb.ts
1943
2178
  var nb = {
1944
2179
  configurationAxes: {
2180
+ power: ["Styrke"],
1945
2181
  model: ["Modell"],
1946
- effort: ["Innsats"],
1947
- speed: ["Hastighet"]
2182
+ effort: ["Innsats", "Resonneringsniv\xE5"],
2183
+ speed: ["Hastighet"],
2184
+ advanced: ["Avansert"]
1948
2185
  },
1949
2186
  configurationOptions: {
2187
+ instant: ["\xD8yeblikkelig"],
1950
2188
  light: ["Lett"],
1951
2189
  medium: ["Middels"],
1952
2190
  high: ["H\xF8y"],
1953
2191
  extraHigh: ["Ekstra h\xF8y"],
2192
+ max: ["Maks"],
1954
2193
  fast: ["Rask"]
1955
2194
  },
1956
2195
  composerTextbox: ["Sp\xF8r om hva som helst"],
@@ -1983,15 +2222,20 @@ var nb = {
1983
2222
  // src/dom/locale/ml.ts
1984
2223
  var ml = {
1985
2224
  configurationAxes: {
2225
+ power: ["\u0D2A\u0D35\u0D7C"],
1986
2226
  model: ["\u0D2E\u0D4B\u0D21\u0D7D"],
1987
2227
  effort: ["\u0D36\u0D4D\u0D30\u0D2E\u0D02"],
1988
- speed: ["\u0D35\u0D47\u0D17\u0D24"]
2228
+ speed: ["\u0D35\u0D47\u0D17\u0D24"],
2229
+ advanced: ["\u0D35\u0D3F\u0D2A\u0D41\u0D32\u0D2E\u0D3E\u0D2F\u0D24\u0D4D"]
1989
2230
  },
1990
2231
  configurationOptions: {
2232
+ instant: ["\u0D24\u0D7D\u0D15\u0D4D\u0D37\u0D23\u0D02"],
1991
2233
  light: ["\u0D32\u0D33\u0D3F\u0D24\u0D02"],
1992
2234
  medium: ["\u0D07\u0D1F\u0D24\u0D4D\u0D24\u0D30\u0D02"],
1993
2235
  high: ["\u0D09\u0D2F\u0D7C\u0D28\u0D4D\u0D28\u0D24\u0D4D"],
1994
2236
  extraHigh: ["\u0D05\u0D24\u0D4D\u0D2F\u0D27\u0D3F\u0D15\u0D02 \u0D09\u0D2F\u0D7C\u0D28\u0D4D\u0D28\u0D24\u0D4D"],
2237
+ max: ["\u0D2A\u0D30\u0D2E\u0D3E\u0D35\u0D27\u0D3F"],
2238
+ ultra: ["\u0D05\u0D7E\u0D1F\u0D4D\u0D30\u0D3E"],
1995
2239
  standard: ["\u0D05\u0D1F\u0D3F\u0D38\u0D4D\u0D25\u0D3E\u0D28\u0D02"],
1996
2240
  fast: ["\u0D35\u0D47\u0D17\u0D02"]
1997
2241
  },
@@ -2013,6 +2257,10 @@ var ml = {
2013
2257
  pro: ["\u0D2A\u0D4D\u0D30\u0D4B"]
2014
2258
  },
2015
2259
  modeOpenerExtra: ["\u0D15\u0D4B\u0D7A\u0D2B\u0D3F\u0D17\u0D7C \u0D1A\u0D46\u0D2F\u0D4D\u0D2F\u0D41\u0D15\u2026"],
2260
+ experienceOptions: {
2261
+ chat: ["\u0D1A\u0D3E\u0D31\u0D4D\u0D31\u0D4D"],
2262
+ work: ["\u0D1C\u0D4B\u0D32\u0D3F"]
2263
+ },
2016
2264
  tools: {
2017
2265
  web_search: ["\u0D35\u0D46\u0D2C\u0D4D \u0D24\u0D3F\u0D30\u0D2F\u0D7D"],
2018
2266
  deep_research: ["\u0D21\u0D40\u0D2A\u0D4D\u0D2A\u0D4D \u0D31\u0D3F\u0D38\u0D47\u0D7C\u0D1A\u0D4D\u0D1A\u0D4D"],
@@ -2027,14 +2275,17 @@ var ml = {
2027
2275
  var ru = {
2028
2276
  configurationAxes: {
2029
2277
  model: ["\u041C\u043E\u0434\u0435\u043B\u044C"],
2030
- effort: ["\u0423\u0440\u043E\u0432\u0435\u043D\u044C"],
2031
- speed: ["\u0421\u043A\u043E\u0440\u043E\u0441\u0442\u044C"]
2278
+ 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"],
2279
+ speed: ["\u0421\u043A\u043E\u0440\u043E\u0441\u0442\u044C"],
2280
+ advanced: ["\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043D\u043D\u044B\u0435"]
2032
2281
  },
2033
2282
  configurationOptions: {
2034
2283
  light: ["\u041D\u0438\u0437\u043A\u0438\u0439"],
2035
2284
  medium: ["\u0421\u0440\u0435\u0434\u043D\u0438\u0439"],
2036
2285
  high: ["\u0412\u044B\u0441\u043E\u043A\u0438\u0439"],
2037
2286
  extraHigh: ["\u041E\u0447\u0435\u043D\u044C \u0432\u044B\u0441\u043E\u043A\u0438\u0439"],
2287
+ max: ["\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u044B\u0439"],
2288
+ ultra: ["\u0423\u043B\u044C\u0442\u0440\u0430"],
2038
2289
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442\u043D\u044B\u0439"],
2039
2290
  fast: ["\u0411\u044B\u0441\u0442\u0440\u043E"]
2040
2291
  },
@@ -2054,6 +2305,10 @@ var ru = {
2054
2305
  extraHigh: ["\u041E\u0447\u0435\u043D\u044C \u0432\u044B\u0441\u043E\u043A\u0438\u0439"]
2055
2306
  },
2056
2307
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F..."],
2308
+ experienceOptions: {
2309
+ chat: ["\u0427\u0430\u0442"],
2310
+ work: ["\u0420\u0430\u0431\u043E\u0442\u0430"]
2311
+ },
2057
2312
  tools: {
2058
2313
  web_search: ["\u041F\u043E\u0438\u0441\u043A \u0432 \u0441\u0435\u0442\u0438"],
2059
2314
  deep_research: ["\u0413\u043B\u0443\u0431\u043E\u043A\u043E\u0435 \u0438\u0441\u0441\u043B\u0435\u0434\u043E\u0432\u0430\u043D\u0438\u0435"],
@@ -2067,15 +2322,20 @@ var ru = {
2067
2322
  // src/dom/locale/pa.ts
2068
2323
  var pa = {
2069
2324
  configurationAxes: {
2325
+ power: ["\u0A2A\u0A3E\u0A35\u0A30"],
2070
2326
  model: ["\u0A2E\u0A3E\u0A21\u0A32"],
2071
2327
  effort: ["\u0A15\u0A4B\u0A38\u0A3C\u0A3F\u0A38\u0A3C"],
2072
- speed: ["\u0A17\u0A24\u0A40"]
2328
+ speed: ["\u0A17\u0A24\u0A40"],
2329
+ advanced: ["\u0A09\u0A71\u0A28\u0A24"]
2073
2330
  },
2074
2331
  configurationOptions: {
2332
+ instant: ["\u0A24\u0A41\u0A30\u0A70\u0A24"],
2075
2333
  light: ["\u0A39\u0A32\u0A15\u0A3E"],
2076
2334
  medium: ["\u0A2E\u0A40\u0A21\u0A40\u0A05\u0A2E"],
2077
2335
  high: ["\u0A39\u0A3E\u0A08"],
2078
2336
  extraHigh: ["\u0A10\u0A15\u0A38\u0A1F\u0A4D\u0A30\u0A3E \u0A39\u0A3E\u0A08"],
2337
+ max: ["\u0A05\u0A27\u0A3F\u0A15\u0A24\u0A2E"],
2338
+ ultra: ["\u0A05\u0A32\u0A1F\u0A30\u0A3E"],
2079
2339
  standard: ["\u0A2E\u0A3F\u0A06\u0A30\u0A40"],
2080
2340
  fast: ["\u0A24\u0A47\u0A1C\u0A3C"]
2081
2341
  },
@@ -2097,6 +2357,10 @@ var pa = {
2097
2357
  pro: ["\u0A2A\u0A4D\u0A30\u0A4B"]
2098
2358
  },
2099
2359
  modeOpenerExtra: ["\u0A15\u0A4C\u0A28\u0A2B\u0A3F\u0A17\u0A30..."],
2360
+ experienceOptions: {
2361
+ chat: ["\u0A1A\u0A48\u0A1F"],
2362
+ work: ["\u0A35\u0A30\u0A15"]
2363
+ },
2100
2364
  tools: {
2101
2365
  web_search: ["\u0A35\u0A48\u0A71\u0A2C \u0A16\u0A4B\u0A1C"],
2102
2366
  deep_research: ["\u0A21\u0A42\u0A70\u0A18\u0A40 \u0A16\u0A4B\u0A1C"],
@@ -2110,15 +2374,20 @@ var pa = {
2110
2374
  // src/dom/locale/mr.ts
2111
2375
  var mr = {
2112
2376
  configurationAxes: {
2377
+ power: ["\u092A\u0949\u0935\u0930"],
2113
2378
  model: ["\u092E\u0949\u0921\u0947\u0932"],
2114
2379
  effort: ["\u092A\u094D\u0930\u092F\u0924\u094D\u0928"],
2115
- speed: ["\u0935\u0947\u0917"]
2380
+ speed: ["\u0935\u0947\u0917"],
2381
+ advanced: ["\u092A\u094D\u0930\u0917\u0924"]
2116
2382
  },
2117
2383
  configurationOptions: {
2384
+ instant: ["\u091D\u091F\u092A\u091F"],
2118
2385
  light: ["\u0939\u0932\u0915\u093E"],
2119
2386
  medium: ["\u092E\u0927\u094D\u092F\u092E"],
2120
2387
  high: ["\u0909\u091A\u094D\u091A"],
2121
2388
  extraHigh: ["\u0905\u0924\u094D\u092F\u0941\u091A\u094D\u091A"],
2389
+ max: ["\u0915\u092E\u093E\u0932"],
2390
+ ultra: ["\u0905\u0932\u094D\u091F\u094D\u0930\u093E"],
2122
2391
  standard: ["\u0938\u094D\u091F\u0901\u0921\u0930\u094D\u0921"],
2123
2392
  fast: ["\u091C\u0932\u0926"]
2124
2393
  },
@@ -2140,6 +2409,10 @@ var mr = {
2140
2409
  pro: ["\u092A\u094D\u0930\u094B"]
2141
2410
  },
2142
2411
  modeOpenerExtra: ["\u0915\u0949\u0928\u094D\u092B\u093F\u0917\u0930 \u0915\u0930\u093E..."],
2412
+ experienceOptions: {
2413
+ chat: ["\u091A\u0945\u091F"],
2414
+ work: ["\u0915\u093E\u092E"]
2415
+ },
2143
2416
  tools: {
2144
2417
  web_search: ["\u0935\u0947\u092C\u0935\u0930 \u0936\u094B\u0927"],
2145
2418
  deep_research: ["\u0938\u0916\u094B\u0932 \u0938\u0902\u0936\u094B\u0927\u0928"],
@@ -2153,14 +2426,18 @@ var mr = {
2153
2426
  // src/dom/locale/tr.ts
2154
2427
  var tr = {
2155
2428
  configurationAxes: {
2156
- effort: ["D\xFCzey"],
2157
- speed: ["H\u0131z"]
2429
+ power: ["G\xFC\xE7"],
2430
+ effort: ["D\xFCzey", "\xC7aba"],
2431
+ speed: ["H\u0131z"],
2432
+ advanced: ["Geli\u015Fmi\u015F"]
2158
2433
  },
2159
2434
  configurationOptions: {
2435
+ instant: ["H\u0131zl\u0131"],
2160
2436
  light: ["S\u0131n\u0131rl\u0131"],
2161
2437
  medium: ["Orta"],
2162
2438
  high: ["Y\xFCksek"],
2163
2439
  extraHigh: ["\xC7ok Y\xFCksek"],
2440
+ max: ["Maks"],
2164
2441
  standard: ["Standart"],
2165
2442
  fast: ["H\u0131zl\u0131"]
2166
2443
  },
@@ -2181,6 +2458,10 @@ var tr = {
2181
2458
  extraHigh: ["\xC7ok Y\xFCksek"]
2182
2459
  },
2183
2460
  modeOpenerExtra: ["Yap\u0131land\u0131r..."],
2461
+ experienceOptions: {
2462
+ chat: ["Sohbet"],
2463
+ work: ["\xC7al\u0131\u015Fma"]
2464
+ },
2184
2465
  tools: {
2185
2466
  web_search: ["Web aramas\u0131"],
2186
2467
  deep_research: ["Derin ara\u015Ft\u0131rma"],
@@ -2194,15 +2475,19 @@ var tr = {
2194
2475
  // src/dom/locale/sw.ts
2195
2476
  var sw = {
2196
2477
  configurationAxes: {
2197
- model: ["Modeli"],
2198
- effort: ["Juhudi"],
2199
- speed: ["Kasi"]
2478
+ power: ["Umahiri"],
2479
+ model: ["Modeli", "Mfumo"],
2480
+ effort: ["Juhudi", "Kiwango cha uchambuzi"],
2481
+ speed: ["Kasi"],
2482
+ advanced: ["Za kina"]
2200
2483
  },
2201
2484
  configurationOptions: {
2485
+ instant: ["Papo hapo"],
2202
2486
  light: ["Nyepesi"],
2203
2487
  medium: ["Wastani"],
2204
2488
  high: ["Juu"],
2205
2489
  extraHigh: ["Juu Zaidi"],
2490
+ max: ["Juu kabisa"],
2206
2491
  standard: ["Kawaida"],
2207
2492
  fast: ["Haraka"]
2208
2493
  },
@@ -2236,15 +2521,20 @@ var sw = {
2236
2521
  // src/dom/locale/te.ts
2237
2522
  var te = {
2238
2523
  configurationAxes: {
2524
+ power: ["\u0C2A\u0C35\u0C30\u0C4D"],
2239
2525
  model: ["\u0C2E\u0C4B\u0C21\u0C32\u0C4D"],
2240
- effort: ["\u0C2A\u0C4D\u0C30\u0C2F\u0C24\u0C4D\u0C28\u0C02"],
2241
- speed: ["\u0C35\u0C47\u0C17\u0C02"]
2526
+ effort: ["\u0C2A\u0C4D\u0C30\u0C2F\u0C24\u0C4D\u0C28\u0C02", "\u0C06\u0C32\u0C4B\u0C1A\u0C28"],
2527
+ speed: ["\u0C35\u0C47\u0C17\u0C02"],
2528
+ advanced: ["\u0C05\u0C27\u0C41\u0C28\u0C3E\u0C24\u0C28\u0C02"]
2242
2529
  },
2243
2530
  configurationOptions: {
2531
+ instant: ["\u0C24\u0C15\u0C4D\u0C37\u0C23\u0C02"],
2244
2532
  light: ["\u0C32\u0C48\u0C1F\u0C4D"],
2245
2533
  medium: ["\u0C2E\u0C40\u0C21\u0C3F\u0C2F\u0C02"],
2246
2534
  high: ["\u0C39\u0C48"],
2247
2535
  extraHigh: ["\u0C0E\u0C15\u0C4D\u0C38\u0C4D\u200C\u0C1F\u0C4D\u0C30\u0C3E \u0C39\u0C48"],
2536
+ max: ["\u0C17\u0C30\u0C3F\u0C37\u0C4D\u0C20\u0C02"],
2537
+ ultra: ["\u0C05\u0C32\u0C4D\u0C1F\u0C4D\u0C30\u0C3E"],
2248
2538
  standard: ["\u0C38\u0C4D\u0C1F\u0C3E\u0C02\u0C21\u0C30\u0C4D\u0C21\u0C4D"],
2249
2539
  fast: ["\u0C35\u0C47\u0C17\u0C35\u0C02\u0C24\u0C02"]
2250
2540
  },
@@ -2266,6 +2556,10 @@ var te = {
2266
2556
  pro: ["\u0C2A\u0C4D\u0C30\u0C4B"]
2267
2557
  },
2268
2558
  modeOpenerExtra: ["\u0C15\u0C3E\u0C28\u0C4D\u0C2B\u0C3F\u0C17\u0C30\u0C4D \u0C1A\u0C47\u0C2F\u0C02\u0C21\u0C3F"],
2559
+ experienceOptions: {
2560
+ chat: ["\u0C1A\u0C3E\u0C1F\u0C4D"],
2561
+ work: ["\u0C35\u0C30\u0C4D\u0C15\u0C4D"]
2562
+ },
2269
2563
  tools: {
2270
2564
  web_search: ["\u0C35\u0C46\u0C2C\u0C4D\u200C\u0C32\u0C4B \u0C35\u0C46\u0C24\u0C15\u0C21\u0C02"],
2271
2565
  deep_research: ["\u0C38\u0C02\u0C2A\u0C42\u0C30\u0C4D\u0C23 \u0C2A\u0C30\u0C3F\u0C36\u0C4B\u0C27\u0C28"],
@@ -2279,7 +2573,7 @@ var te = {
2279
2573
  // src/dom/locale/tl.ts
2280
2574
  var tl = {
2281
2575
  configurationAxes: {
2282
- effort: ["Pagsisikap"],
2576
+ effort: ["Pagsisikap", "Pag-iisip"],
2283
2577
  speed: ["Bilis"]
2284
2578
  },
2285
2579
  configurationOptions: {
@@ -2307,9 +2601,14 @@ var tl = {
2307
2601
  // src/dom/locale/th.ts
2308
2602
  var th = {
2309
2603
  configurationAxes: {
2604
+ power: ["\u0E23\u0E30\u0E14\u0E31\u0E1A\u0E04\u0E27\u0E32\u0E21\u0E2A\u0E32\u0E21\u0E32\u0E23\u0E16"],
2310
2605
  model: ["\u0E42\u0E21\u0E40\u0E14\u0E25"],
2311
2606
  effort: ["\u0E23\u0E30\u0E14\u0E31\u0E1A\u0E01\u0E32\u0E23\u0E04\u0E34\u0E14"],
2312
- speed: ["\u0E04\u0E27\u0E32\u0E21\u0E40\u0E23\u0E47\u0E27"]
2607
+ speed: ["\u0E04\u0E27\u0E32\u0E21\u0E40\u0E23\u0E47\u0E27"],
2608
+ advanced: ["\u0E02\u0E31\u0E49\u0E19\u0E2A\u0E39\u0E07"]
2609
+ },
2610
+ configurationOptions: {
2611
+ instant: ["\u0E17\u0E31\u0E19\u0E17\u0E35"]
2313
2612
  },
2314
2613
  composerTextbox: ["\u0E16\u0E32\u0E21\u0E2D\u0E30\u0E44\u0E23\u0E01\u0E47\u0E44\u0E14\u0E49"],
2315
2614
  sendButton: ["\u0E2A\u0E48\u0E07\u0E04\u0E33\u0E2A\u0E31\u0E48\u0E07"],
@@ -2341,15 +2640,20 @@ var th = {
2341
2640
  // src/dom/locale/bn.ts
2342
2641
  var bn = {
2343
2642
  configurationAxes: {
2643
+ power: ["\u0995\u09CD\u09B7\u09AE\u09A4\u09BE"],
2344
2644
  model: ["\u09AE\u09A1\u09C7\u09B2"],
2345
2645
  effort: ["\u09AA\u09CD\u09B0\u099A\u09C7\u09B7\u09CD\u099F\u09BE"],
2346
- speed: ["\u0997\u09A4\u09BF"]
2646
+ speed: ["\u0997\u09A4\u09BF"],
2647
+ advanced: ["\u0989\u09A8\u09CD\u09A8\u09A4"]
2347
2648
  },
2348
2649
  configurationOptions: {
2650
+ instant: ["\u09A4\u09BE\u09CE\u0995\u09CD\u09B7\u09A3\u09BF\u0995"],
2349
2651
  light: ["\u09B2\u09BE\u0987\u099F"],
2350
2652
  medium: ["\u09AE\u09BE\u099D\u09BE\u09B0\u09BF"],
2351
2653
  high: ["\u0989\u099A\u09CD\u099A"],
2352
2654
  extraHigh: ["\u0985\u09A4\u09BF \u0989\u099A\u09CD\u099A"],
2655
+ max: ["\u09B8\u09B0\u09CD\u09AC\u09CB\u099A\u09CD\u099A"],
2656
+ ultra: ["\u0986\u09B2\u09CD\u099F\u09CD\u09B0\u09BE"],
2353
2657
  standard: ["\u09B8\u09CD\u099F\u09CD\u09AF\u09BE\u09A8\u09CD\u09A1\u09BE\u09B0\u09CD\u09A1"],
2354
2658
  fast: ["\u09A6\u09CD\u09B0\u09C1\u09A4"]
2355
2659
  },
@@ -2371,6 +2675,10 @@ var bn = {
2371
2675
  pro: ["\u09AA\u09CD\u09B0\u09CB"]
2372
2676
  },
2373
2677
  modeOpenerExtra: ["\u0995\u09A8\u09AB\u09BF\u0997\u09BE\u09B0 \u0995\u09B0\u09C1\u09A8..."],
2678
+ experienceOptions: {
2679
+ chat: ["\u099A\u09CD\u09AF\u09BE\u099F"],
2680
+ work: ["\u0993\u09AF\u09BC\u09BE\u09B0\u09CD\u0995"]
2681
+ },
2374
2682
  tools: {
2375
2683
  web_search: ["\u0993\u09AF\u09BC\u09C7\u09AC \u09B8\u09A8\u09CD\u09A7\u09BE\u09A8"],
2376
2684
  deep_research: ["\u0997\u09AD\u09C0\u09B0 \u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8"],
@@ -2384,14 +2692,18 @@ var bn = {
2384
2692
  // src/dom/locale/ms.ts
2385
2693
  var ms = {
2386
2694
  configurationAxes: {
2695
+ power: ["Kuasa"],
2387
2696
  effort: ["Usaha"],
2388
- speed: ["Kelajuan"]
2697
+ speed: ["Kelajuan"],
2698
+ advanced: ["Lanjutan"]
2389
2699
  },
2390
2700
  configurationOptions: {
2701
+ instant: ["Segera"],
2391
2702
  light: ["Ringan"],
2392
2703
  medium: ["Sederhana"],
2393
2704
  high: ["Tinggi"],
2394
2705
  extraHigh: ["Sangat Tinggi"],
2706
+ max: ["Sangat Tinggi"],
2395
2707
  fast: ["Pantas"]
2396
2708
  },
2397
2709
  composerTextbox: ["Tanya apa-apa sahaja..."],
@@ -2411,6 +2723,10 @@ var ms = {
2411
2723
  extraHigh: ["Sangat Tinggi"]
2412
2724
  },
2413
2725
  modeOpenerExtra: ["Konfigurasikan\u2026"],
2726
+ experienceOptions: {
2727
+ chat: ["Sembang"],
2728
+ work: ["Kerja"]
2729
+ },
2414
2730
  tools: {
2415
2731
  web_search: ["Carian web"],
2416
2732
  deep_research: ["Kajian mendalam"],
@@ -2424,15 +2740,19 @@ var ms = {
2424
2740
  // src/dom/locale/so.ts
2425
2741
  var so = {
2426
2742
  configurationAxes: {
2743
+ power: ["Awood"],
2427
2744
  model: ["Moodel"],
2428
2745
  effort: ["Dadaal"],
2429
- speed: ["Xawaare"]
2746
+ speed: ["Xawaare"],
2747
+ advanced: ["Horumarsan"]
2430
2748
  },
2431
2749
  configurationOptions: {
2750
+ instant: ["Degdeg"],
2432
2751
  light: ["Fudud"],
2433
2752
  medium: ["Dhexdhexaad"],
2434
2753
  high: ["Sare"],
2435
2754
  extraHigh: ["Aad U Sarreeya"],
2755
+ max: ["Ugu badan"],
2436
2756
  standard: ["Caadi"],
2437
2757
  fast: ["Degdeg"]
2438
2758
  },
@@ -2453,6 +2773,10 @@ var so = {
2453
2773
  extraHigh: ["Aad u sarreeya", "Aad U Sarreeya"]
2454
2774
  },
2455
2775
  modeOpenerExtra: ["Ku xidh..."],
2776
+ experienceOptions: {
2777
+ chat: ["Sheekaysi"],
2778
+ work: ["Shaqo"]
2779
+ },
2456
2780
  tools: {
2457
2781
  web_search: ["Raadi shakabada"],
2458
2782
  deep_research: ["Cilmi baadhid qoto dheer"],
@@ -2466,10 +2790,13 @@ var so = {
2466
2790
  // src/dom/locale/nl.ts
2467
2791
  var nl = {
2468
2792
  configurationAxes: {
2793
+ power: ["Rekenkracht"],
2469
2794
  effort: ["Inspanning"],
2470
- speed: ["Snelheid"]
2795
+ speed: ["Snelheid"],
2796
+ advanced: ["Geavanceerd"]
2471
2797
  },
2472
2798
  configurationOptions: {
2799
+ instant: ["Direct"],
2473
2800
  light: ["Licht"],
2474
2801
  medium: ["Gemiddeld"],
2475
2802
  high: ["Hoog"],
@@ -2500,18 +2827,20 @@ var nl = {
2500
2827
  create_image: ["Maak een afbeelding"]
2501
2828
  },
2502
2829
  signedInMarkers: ["Nieuwe chat", "Chats doorzoeken", "Recente items", "Chatgeschiedenis", "Projecten", "Stel een vraag"],
2503
- responseActions: ["Reactie kopi\xEBren"],
2504
- stopControl: ["Prompt versturen"]
2830
+ responseActions: ["Reactie kopi\xEBren"]
2505
2831
  };
2506
2832
 
2507
2833
  // src/dom/locale/sv.ts
2508
2834
  var sv = {
2509
2835
  configurationAxes: {
2836
+ power: ["Prestanda"],
2510
2837
  model: ["Modell"],
2511
2838
  effort: ["Resonemangsniv\xE5"],
2512
- speed: ["Hastighet"]
2839
+ speed: ["Hastighet"],
2840
+ advanced: ["Avancerat"]
2513
2841
  },
2514
2842
  configurationOptions: {
2843
+ instant: ["Direkt"],
2515
2844
  light: ["L\xE5g"],
2516
2845
  medium: ["Balanserad"],
2517
2846
  high: ["H\xF6g"],
@@ -2548,15 +2877,19 @@ var sv = {
2548
2877
  // src/dom/locale/lv.ts
2549
2878
  var lv = {
2550
2879
  configurationAxes: {
2880
+ power: ["Jauda"],
2551
2881
  model: ["Modelis"],
2552
2882
  effort: ["P\u016Bles"],
2553
- speed: ["\u0100trums"]
2883
+ speed: ["\u0100trums"],
2884
+ advanced: ["Papildu"]
2554
2885
  },
2555
2886
  configurationOptions: {
2887
+ instant: ["T\u016Bl\u012Bt\u0113js"],
2556
2888
  light: ["Viegls"],
2557
2889
  medium: ["Vid\u0113js"],
2558
2890
  high: ["Augsts"],
2559
2891
  extraHigh: ["\u013Boti augsts"],
2892
+ max: ["Maks."],
2560
2893
  standard: ["Standarta"],
2561
2894
  fast: ["\u0100trs"]
2562
2895
  },
@@ -2590,15 +2923,19 @@ var lv = {
2590
2923
  // src/dom/locale/mk.ts
2591
2924
  var mk = {
2592
2925
  configurationAxes: {
2926
+ power: ["\u041C\u043E\u045C\u043D\u043E\u0441\u0442"],
2593
2927
  model: ["\u041C\u043E\u0434\u0435\u043B"],
2594
2928
  effort: ["\u041D\u0430\u043F\u043E\u0440"],
2595
- speed: ["\u0411\u0440\u0437\u0438\u043D\u0430"]
2929
+ speed: ["\u0411\u0440\u0437\u0438\u043D\u0430"],
2930
+ advanced: ["\u041D\u0430\u043F\u0440\u0435\u0434\u043D\u043E"]
2596
2931
  },
2597
2932
  configurationOptions: {
2598
2933
  light: ["\u041B\u0435\u0441\u043D\u043E"],
2599
2934
  medium: ["\u0421\u0440\u0435\u0434\u043D\u0430"],
2600
2935
  high: ["\u0412\u0438\u0441\u043E\u043A\u0430"],
2601
- extraHigh: ["\u0415\u043A\u0441\u0442\u0440\u0430 \u0432\u0438\u0441\u043E\u043A\u0430"],
2936
+ extraHigh: ["\u0415\u043A\u0441\u0442\u0440\u0430 \u0432\u0438\u0441\u043E\u043A\u0430", "\u041C\u043D\u043E\u0433\u0443 \u0432\u0438\u0441\u043E\u043A\u0430"],
2937
+ max: ["\u041C\u0430\u043A\u0441"],
2938
+ ultra: ["\u0423\u043B\u0442\u0440\u0430"],
2602
2939
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0434\u0435\u043D"],
2603
2940
  fast: ["\u0411\u0440\u0437\u043E"]
2604
2941
  },
@@ -2618,6 +2955,10 @@ var mk = {
2618
2955
  extraHigh: ["\u041C\u043D\u043E\u0433\u0443 \u0432\u0438\u0441\u043E\u043A\u043E", "\u041C\u043D\u043E\u0433\u0443 \u0432\u0438\u0441\u043E\u043A\u0430"]
2619
2956
  },
2620
2957
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0458..."],
2958
+ experienceOptions: {
2959
+ chat: ["\u0420\u0430\u0437\u0433\u043E\u0432\u043E\u0440"],
2960
+ work: ["\u0420\u0430\u0431\u043E\u0442\u0430"]
2961
+ },
2621
2962
  tools: {
2622
2963
  web_search: ["\u041F\u0440\u0435\u0431\u0430\u0440\u0443\u0432\u0430\u045A\u0435 \u043D\u0430 \u0438\u043D\u0442\u0435\u0440\u043D\u0435\u0442"],
2623
2964
  deep_research: ["\u0414\u043B\u0430\u0431\u043E\u043A\u043E \u0438\u0441\u0442\u0440\u0430\u0436\u0443\u0432\u0430\u045A\u0435"],
@@ -2631,14 +2972,19 @@ var mk = {
2631
2972
  // src/dom/locale/sq.ts
2632
2973
  var sq = {
2633
2974
  configurationAxes: {
2634
- effort: ["P\xEBrpjekje"],
2635
- speed: ["Shpejt\xEBsi"]
2975
+ power: ["Fuqia"],
2976
+ model: ["Modeli"],
2977
+ effort: ["P\xEBrpjekje", "Arsyetim"],
2978
+ speed: ["Shpejt\xEBsi"],
2979
+ advanced: ["T\xEB avancuara"]
2636
2980
  },
2637
2981
  configurationOptions: {
2638
- light: ["I leht\xEB"],
2982
+ instant: ["I menj\xEBhersh\xEBm"],
2983
+ light: ["I leht\xEB", "E leht\xEB"],
2639
2984
  medium: ["Mesatare"],
2640
2985
  high: ["E lart\xEB"],
2641
2986
  extraHigh: ["Tep\xEBr e lart\xEB"],
2987
+ max: ["Maks."],
2642
2988
  fast: ["I shpejt\xEB"]
2643
2989
  },
2644
2990
  composerTextbox: ["Pyet p\xEBr \xE7do gj\xEB"],
@@ -2658,6 +3004,10 @@ var sq = {
2658
3004
  extraHigh: ["Shum\xEB i lart\xEB", "Tep\xEBr e lart\xEB"]
2659
3005
  },
2660
3006
  modeOpenerExtra: ["Konfiguro..."],
3007
+ experienceOptions: {
3008
+ chat: ["Bised\xEB"],
3009
+ work: ["Pun\xEB"]
3010
+ },
2661
3011
  tools: {
2662
3012
  web_search: ["K\xEBrkim n\xEB ueb"],
2663
3013
  deep_research: ["K\xEBrkim i thell\xEB"],
@@ -2671,14 +3021,18 @@ var sq = {
2671
3021
  // src/dom/locale/sl.ts
2672
3022
  var sl = {
2673
3023
  configurationAxes: {
3024
+ power: ["Mo\u010D"],
2674
3025
  effort: ["Napor"],
2675
- speed: ["Hitrost"]
3026
+ speed: ["Hitrost"],
3027
+ advanced: ["Napredno"]
2676
3028
  },
2677
3029
  configurationOptions: {
3030
+ instant: ["Takoj"],
2678
3031
  light: ["Osnovno"],
2679
3032
  medium: ["Srednje"],
2680
3033
  high: ["Visoko"],
2681
3034
  extraHigh: ["Zelo visoko"],
3035
+ max: ["Najve\u010D"],
2682
3036
  standard: ["Standardno"],
2683
3037
  fast: ["Hitro"]
2684
3038
  },
@@ -2699,6 +3053,10 @@ var sl = {
2699
3053
  extraHigh: ["Zelo visoko"]
2700
3054
  },
2701
3055
  modeOpenerExtra: ["Konfiguracija \u2026"],
3056
+ experienceOptions: {
3057
+ chat: ["Klepet"],
3058
+ work: ["Delo"]
3059
+ },
2702
3060
  tools: {
2703
3061
  web_search: ["Iskanje po spletu"],
2704
3062
  deep_research: ["Poglobljeno raziskovanje"],
@@ -2712,15 +3070,19 @@ var sl = {
2712
3070
  // src/dom/locale/sr.ts
2713
3071
  var sr = {
2714
3072
  configurationAxes: {
3073
+ power: ["\u0421\u043D\u0430\u0433\u0430"],
2715
3074
  model: ["\u041C\u043E\u0434\u0435\u043B"],
2716
- effort: ["\u041D\u0438\u0432\u043E"],
2717
- speed: ["\u0411\u0440\u0437\u0438\u043D\u0430"]
3075
+ effort: ["\u041D\u0438\u0432\u043E", "\u041D\u0430\u043F\u043E\u0440"],
3076
+ speed: ["\u0411\u0440\u0437\u0438\u043D\u0430"],
3077
+ advanced: ["\u041D\u0430\u043F\u0440\u0435\u0434\u043D\u043E"]
2718
3078
  },
2719
3079
  configurationOptions: {
2720
3080
  light: ["\u041B\u0430\u0433\u0430\u043D\u043E"],
2721
3081
  medium: ["\u0421\u0440\u0435\u0434\u045A\u0435"],
2722
3082
  high: ["\u0412\u0438\u0441\u043E\u043A\u043E"],
2723
3083
  extraHigh: ["\u0412\u0435\u043E\u043C\u0430 \u0432\u0438\u0441\u043E\u043A\u043E"],
3084
+ max: ["\u041C\u0430\u043A\u0441"],
3085
+ ultra: ["\u0423\u043B\u0442\u0440\u0430"],
2724
3086
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0434\u043D\u043E"],
2725
3087
  fast: ["\u0411\u0440\u0437\u043E"]
2726
3088
  },
@@ -2740,6 +3102,10 @@ var sr = {
2740
3102
  extraHigh: ["\u0412\u0435\u043E\u043C\u0430 \u0432\u0438\u0441\u043E\u043A\u043E"]
2741
3103
  },
2742
3104
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0448\u0438..."],
3105
+ experienceOptions: {
3106
+ chat: ["\u040B\u0430\u0441\u043A\u0430\u045A\u0435"],
3107
+ work: ["\u041F\u043E\u0441\u0430\u043E"]
3108
+ },
2743
3109
  tools: {
2744
3110
  web_search: ["\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u0432\u0435\u0431\u0430"],
2745
3111
  deep_research: ["\u0414\u0443\u0431\u0438\u043D\u0441\u043A\u043E \u0438\u0441\u0442\u0440\u0430\u0436\u0438\u0432\u0430\u045A\u0435"],
@@ -2753,15 +3119,20 @@ var sr = {
2753
3119
  // src/dom/locale/mn.ts
2754
3120
  var mn = {
2755
3121
  configurationAxes: {
3122
+ power: ["\u0427\u0430\u0434\u0430\u043B"],
2756
3123
  model: ["\u0417\u0430\u0433\u0432\u0430\u0440"],
2757
- effort: ["\u0425\u04AF\u0447\u0438\u043D \u0447\u0430\u0440\u043C\u0430\u0439\u043B\u0442"],
2758
- speed: ["\u0425\u0443\u0440\u0434"]
3124
+ effort: ["\u0425\u04AF\u0447\u0438\u043D \u0447\u0430\u0440\u043C\u0430\u0439\u043B\u0442", "\u0422\u043E\u043E\u0446\u043E\u043E\u043B\u043E\u043B"],
3125
+ speed: ["\u0425\u0443\u0440\u0434"],
3126
+ advanced: ["\u0414\u044D\u0432\u0448\u0438\u043B\u0442\u044D\u0442"]
2759
3127
  },
2760
3128
  configurationOptions: {
3129
+ instant: ["\u0428\u0443\u0443\u0440\u0445\u0430\u0439"],
2761
3130
  light: ["\u0425\u04E9\u043D\u0433\u04E9\u043D"],
2762
3131
  medium: ["\u0414\u0443\u043D\u0434"],
2763
- high: ["\u0418\u0445"],
2764
- extraHigh: ["\u041C\u0430\u0448 \u0438\u0445"],
3132
+ high: ["\u0418\u0445", "\u04E8\u043D\u0434\u04E9\u0440"],
3133
+ extraHigh: ["\u041C\u0430\u0448 \u0438\u0445", "\u041C\u0430\u0448 \u04E9\u043D\u0434\u04E9\u0440"],
3134
+ max: ["\u0425\u0430\u043C\u0433\u0438\u0439\u043D \u0438\u0445"],
3135
+ ultra: ["\u0423\u043B\u044C\u0442\u0440\u0430"],
2765
3136
  standard: ["\u0421\u0442\u0430\u043D\u0434\u0430\u0440\u0442"],
2766
3137
  fast: ["\u0425\u0443\u0440\u0434\u0430\u043D"]
2767
3138
  },
@@ -2783,6 +3154,10 @@ var mn = {
2783
3154
  pro: ["\u041F\u0440\u043E"]
2784
3155
  },
2785
3156
  modeOpenerExtra: ["\u0422\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0445..."],
3157
+ experienceOptions: {
3158
+ chat: ["\u0427\u0430\u0442"],
3159
+ work: ["\u0410\u0436\u0438\u043B"]
3160
+ },
2786
3161
  tools: {
2787
3162
  web_search: ["\u0412\u0435\u0431 \u0445\u0430\u0439\u043B\u0442"],
2788
3163
  deep_research: ["\u0413\u04AF\u043D \u0441\u0443\u0434\u0430\u043B\u0433\u0430\u0430"],
@@ -2796,15 +3171,20 @@ var mn = {
2796
3171
  // src/dom/locale/my.ts
2797
3172
  var my = {
2798
3173
  configurationAxes: {
3174
+ power: ["\u1005\u103D\u1019\u103A\u1038\u1021\u102C\u1038"],
2799
3175
  model: ["\u1019\u1031\u102C\u103A\u1012\u101A\u103A"],
2800
3176
  effort: ["\u1021\u102C\u1038\u1011\u102F\u1010\u103A\u1019\u103E\u102F"],
2801
- speed: ["\u1021\u1019\u103C\u1014\u103A\u1014\u103E\u102F\u1014\u103A\u1038"]
3177
+ speed: ["\u1021\u1019\u103C\u1014\u103A\u1014\u103E\u102F\u1014\u103A\u1038"],
3178
+ advanced: ["\u1021\u1006\u1004\u1037\u103A\u1019\u103C\u1004\u1037\u103A"]
2802
3179
  },
2803
3180
  configurationOptions: {
3181
+ instant: ["\u1001\u103B\u1000\u103A\u1001\u103B\u1004\u103A\u1038"],
2804
3182
  light: ["\u1015\u1031\u102B\u1037\u1015\u102B\u1038"],
2805
3183
  medium: ["\u1021\u101C\u101A\u103A\u1021\u101C\u1010\u103A"],
2806
3184
  high: ["\u1021\u1019\u103C\u1004\u1037\u103A"],
2807
3185
  extraHigh: ["\u1021\u101C\u103D\u1014\u103A\u1019\u103C\u1004\u1037\u103A"],
3186
+ max: ["\u1021\u1019\u103C\u1004\u1037\u103A\u1006\u102F\u1036\u1038"],
3187
+ ultra: ["\u1021\u101A\u103A\u101C\u103A\u1011\u101B\u102C"],
2808
3188
  standard: ["\u1015\u102F\u1036\u1019\u103E\u1014\u103A"],
2809
3189
  fast: ["\u1021\u1019\u103C\u1014\u103A"]
2810
3190
  },
@@ -2825,6 +3205,9 @@ var my = {
2825
3205
  extraHigh: ["\u1021\u101C\u103D\u1014\u103A\u1019\u103C\u1004\u1037\u103A"]
2826
3206
  },
2827
3207
  modeOpenerExtra: ["\u1015\u103C\u102F\u1015\u103C\u1004\u103A\u1019\u103D\u1019\u103A\u1038\u1019\u1036\u101B\u1014\u103A"],
3208
+ experienceOptions: {
3209
+ work: ["\u1021\u101C\u102F\u1015\u103A"]
3210
+ },
2828
3211
  tools: {
2829
3212
  web_search: ["\u101D\u1018\u103A\u101B\u103E\u102C\u1016\u103D\u1031\u101B\u1014\u103A"],
2830
3213
  deep_research: ["\u1014\u1000\u103A\u1014\u1032\u101E\u1031\u102C \u101E\u102F\u1010\u1031\u101E\u1014"],
@@ -2838,15 +3221,20 @@ var my = {
2838
3221
  // src/dom/locale/ta.ts
2839
3222
  var ta = {
2840
3223
  configurationAxes: {
2841
- model: ["\u0BAE\u0BBE\u0BA4\u0BBF\u0BB0\u0BBF"],
2842
- effort: ["\u0BAE\u0BC1\u0BAF\u0BB1\u0BCD\u0B9A\u0BBF"],
2843
- speed: ["\u0BB5\u0BC7\u0B95\u0BAE\u0BCD"]
3224
+ power: ["\u0BA4\u0BBF\u0BB1\u0BA9\u0BCD"],
3225
+ model: ["\u0BAE\u0BBE\u0BA4\u0BBF\u0BB0\u0BBF", "\u0BAE\u0BBE\u0B9F\u0BB2\u0BCD"],
3226
+ effort: ["\u0BAE\u0BC1\u0BAF\u0BB1\u0BCD\u0B9A\u0BBF", "\u0B9A\u0BBF\u0BA8\u0BCD\u0BA4\u0BA9\u0BC8 \u0B85\u0BB3\u0BB5\u0BC1"],
3227
+ speed: ["\u0BB5\u0BC7\u0B95\u0BAE\u0BCD"],
3228
+ advanced: ["\u0BAE\u0BC7\u0BAE\u0BCD\u0BAA\u0B9F\u0BCD\u0B9F"]
2844
3229
  },
2845
3230
  configurationOptions: {
3231
+ instant: ["\u0B89\u0B9F\u0BA9\u0B9F\u0BBF"],
2846
3232
  light: ["\u0B95\u0BC1\u0BB1\u0BC8\u0BB5\u0BC1"],
2847
3233
  medium: ["\u0BAE\u0BBF\u0BA4\u0BAE\u0BBE\u0BA9"],
2848
3234
  high: ["\u0B85\u0BA4\u0BBF\u0B95\u0BAE\u0BBE\u0BA9"],
2849
3235
  extraHigh: ["\u0BAE\u0BBF\u0B95 \u0B85\u0BA4\u0BBF\u0B95\u0BAE\u0BBE\u0BA9"],
3236
+ max: ["\u0B85\u0BA4\u0BBF\u0B95\u0BAA\u0B9F\u0BCD\u0B9A\u0BAE\u0BCD"],
3237
+ ultra: ["\u0B85\u0BB2\u0BCD\u0B9F\u0BCD\u0BB0\u0BBE"],
2850
3238
  standard: ["\u0BB5\u0BB4\u0B95\u0BCD\u0B95\u0BAE\u0BBE\u0BA9"],
2851
3239
  fast: ["\u0BB5\u0BBF\u0BB0\u0BC8\u0BB5\u0BC1"]
2852
3240
  },
@@ -2868,6 +3256,10 @@ var ta = {
2868
3256
  pro: ["\u0BAA\u0BCD\u0BB0\u0BCB"]
2869
3257
  },
2870
3258
  modeOpenerExtra: ["\u0B95\u0B9F\u0BCD\u0B9F\u0BAE\u0BC8\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD..."],
3259
+ experienceOptions: {
3260
+ chat: ["\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8"],
3261
+ work: ["\u0BB5\u0BC7\u0BB2\u0BC8"]
3262
+ },
2871
3263
  tools: {
2872
3264
  web_search: ["\u0B87\u0BA3\u0BC8\u0BAF \u0BA4\u0BC7\u0B9F\u0BB2\u0BCD"],
2873
3265
  deep_research: ["\u0B86\u0BB4\u0BCD\u0BA8\u0BCD\u0BA4 \u0B86\u0BAF\u0BCD\u0BB5\u0BC1"],
@@ -2911,6 +3303,7 @@ var MODE_OPTION_IDS = [
2911
3303
  ];
2912
3304
  var EXPERIENCE_OPTION_IDS = ["chat", "work"];
2913
3305
  var CONFIGURATION_AXIS_IDS = [
3306
+ "power",
2914
3307
  "model",
2915
3308
  "intelligence",
2916
3309
  "effort",
@@ -3081,9 +3474,13 @@ async function readPageState(page) {
3081
3474
  const url = typeof rawUrl === "string" ? rawUrl : "";
3082
3475
  const rawTitle = typeof page.title === "function" ? await page.title().catch(() => void 0) : void 0;
3083
3476
  const title = typeof rawTitle === "string" ? rawTitle : void 0;
3084
- const visibleText = await readVisibleText(page);
3085
- const signedIn = isLikelySignedIn(visibleText);
3086
- const classifiedBlocker = classifyVisibleText(visibleText);
3477
+ const surface = await readPageSurfaceSnapshot(page);
3478
+ const visibleText = surface.visibleText;
3479
+ const blockerSurface = surface.blockerSurface;
3480
+ const fullPageBlocker = classifyVisibleText(visibleText);
3481
+ const classifiedBlocker = blockerSurface.hasConversationMessages ? classifyVisibleText(blockerSurface.text) : classifyVisibleText(blockerSurface.text) ?? fullPageBlocker;
3482
+ const loginWall = classifiedBlocker?.kind === "login_required" && isLikelyLoginWall(visibleText);
3483
+ const signedIn = isLikelySignedIn(visibleText) && !loginWall;
3087
3484
  const blocker = classifiedBlocker?.kind === "login_required" && signedIn ? void 0 : classifiedBlocker;
3088
3485
  const conversationId = parseConversationId(url);
3089
3486
  const state = {
@@ -3102,38 +3499,193 @@ async function readPageState(page) {
3102
3499
  }
3103
3500
  return state;
3104
3501
  }
3105
- async function readVisibleText(page) {
3502
+ async function readPageSurfaceSnapshot(page) {
3106
3503
  if (typeof page.evaluate === "function") {
3107
3504
  try {
3108
- return await withTimeout(
3109
- page.evaluate(() => document.body?.innerText ?? ""),
3110
- 1e3,
3111
- "Timed out while reading visible page text."
3112
- );
3505
+ const snapshot = await withTimeout(page.evaluate(() => {
3506
+ const messageSelector = "[data-message-author-role], [data-testid^='conversation-turn']";
3507
+ const systemSelector = [
3508
+ "[role='alert']",
3509
+ "[role='status']",
3510
+ "[role='dialog']",
3511
+ "[aria-live='assertive']",
3512
+ "[data-testid*='toast' i]",
3513
+ "[data-testid*='banner' i]",
3514
+ "[class*='toast' i]",
3515
+ "[class*='banner' i]"
3516
+ ].join(", ");
3517
+ const visible = (element) => {
3518
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
3519
+ const style = window.getComputedStyle(element);
3520
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none") return false;
3521
+ const rect = element.getBoundingClientRect();
3522
+ return rect.width > 0 || rect.height > 0;
3523
+ };
3524
+ 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(" ");
3525
+ return {
3526
+ visibleText: document.body?.innerText ?? "",
3527
+ blockerText,
3528
+ hasConversationMessages: Array.from(document.querySelectorAll(messageSelector)).some(visible)
3529
+ };
3530
+ }), 1e3, "Timed out while reading the visible ChatGPT page surface.");
3531
+ if (typeof snapshot === "string") {
3532
+ return {
3533
+ visibleText: snapshot,
3534
+ blockerSurface: { text: snapshot, hasConversationMessages: false }
3535
+ };
3536
+ }
3537
+ if (typeof snapshot === "object" && snapshot !== null && typeof snapshot.visibleText === "string" && typeof snapshot.blockerText === "string" && typeof snapshot.hasConversationMessages === "boolean") {
3538
+ const typed = snapshot;
3539
+ return {
3540
+ visibleText: typed.visibleText,
3541
+ blockerSurface: {
3542
+ text: typed.blockerText,
3543
+ hasConversationMessages: typed.hasConversationMessages
3544
+ }
3545
+ };
3546
+ }
3113
3547
  } catch {
3114
3548
  }
3115
3549
  }
3116
3550
  if (typeof page.content === "function") {
3117
3551
  try {
3118
- const html = await withTimeout(
3119
- page.content(),
3120
- 1e3,
3121
- "Timed out while reading page content."
3122
- );
3123
- return htmlToText(html);
3552
+ const html = await withTimeout(page.content(), 1e3, "Timed out while reading the serialized ChatGPT page surface.");
3553
+ return serializedPageSurface(html);
3124
3554
  } catch {
3125
- return "";
3126
3555
  }
3127
3556
  }
3128
- return "";
3557
+ return {
3558
+ visibleText: "",
3559
+ blockerSurface: { text: "", hasConversationMessages: false }
3560
+ };
3561
+ }
3562
+ function serializedPageSurface(html) {
3563
+ const stack = [];
3564
+ const blockerNodes = [];
3565
+ const voidElements = /* @__PURE__ */ new Set([
3566
+ "area",
3567
+ "base",
3568
+ "br",
3569
+ "col",
3570
+ "embed",
3571
+ "hr",
3572
+ "img",
3573
+ "input",
3574
+ "link",
3575
+ "meta",
3576
+ "param",
3577
+ "source",
3578
+ "track",
3579
+ "wbr"
3580
+ ]);
3581
+ let hasConversationMessages = false;
3582
+ let visibleText = "";
3583
+ 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);
3584
+ const hiddenInChain = (node) => {
3585
+ for (let current = node; current !== void 0; current = current.parent) {
3586
+ if (hidden(current.attributes)) return true;
3587
+ }
3588
+ return false;
3589
+ };
3590
+ const messageNode = (node) => {
3591
+ const authorRole = serializedAttribute(node.attributes, "data-message-author-role");
3592
+ const testId = serializedAttribute(node.attributes, "data-testid");
3593
+ return authorRole !== void 0 && authorRole.length > 0 || testId?.toLowerCase().startsWith("conversation-turn") === true;
3594
+ };
3595
+ const insideMessage = (node) => {
3596
+ for (let current = node; current !== void 0; current = current.parent) {
3597
+ if (messageNode(current)) return true;
3598
+ }
3599
+ return false;
3600
+ };
3601
+ const systemSurface = (node) => {
3602
+ const role = serializedAttribute(node.attributes, "role")?.toLowerCase();
3603
+ const ariaLive = serializedAttribute(node.attributes, "aria-live")?.toLowerCase();
3604
+ const testId = serializedAttribute(node.attributes, "data-testid")?.toLowerCase() ?? "";
3605
+ const className = serializedAttribute(node.attributes, "class")?.toLowerCase() ?? "";
3606
+ return role === "alert" || role === "status" || role === "dialog" || ariaLive === "assertive" || testId.includes("toast") || testId.includes("banner") || className.includes("toast") || className.includes("banner");
3607
+ };
3608
+ const ignoredInChain = (node) => {
3609
+ for (let current = node; current !== void 0; current = current.parent) {
3610
+ if (current.tag === "script" || current.tag === "style" || current.tag === "template") return true;
3611
+ }
3612
+ return false;
3613
+ };
3614
+ for (const match of html.matchAll(/<!--[\s\S]*?-->|<![^>]*>|<\/?[a-z0-9-]+\b[^>]*>|[^<]+/gi)) {
3615
+ const token = match[0];
3616
+ const closing = /^<\/([a-z0-9-]+)/i.exec(token);
3617
+ if (closing?.[1] !== void 0) {
3618
+ const tag = closing[1].toLowerCase();
3619
+ const index = stack.map((node) => node.tag).lastIndexOf(tag);
3620
+ if (index >= 0) stack.splice(index);
3621
+ continue;
3622
+ }
3623
+ const opening = /^<([a-z0-9-]+)\b([^>]*)>/i.exec(token);
3624
+ if (opening?.[1] !== void 0) {
3625
+ const node = {
3626
+ tag: opening[1].toLowerCase(),
3627
+ attributes: opening[2] ?? "",
3628
+ parent: stack.at(-1),
3629
+ blockerText: ""
3630
+ };
3631
+ const ignored = ignoredInChain(node);
3632
+ if (messageNode(node) && !hiddenInChain(node) && !ignored) hasConversationMessages = true;
3633
+ if (systemSurface(node) && !hiddenInChain(node) && !insideMessage(node) && !ignored) {
3634
+ const ariaLabel = serializedAttribute(node.attributes, "aria-label");
3635
+ if (ariaLabel !== void 0) node.blockerText = ` ${ariaLabel}`;
3636
+ blockerNodes.push(node);
3637
+ }
3638
+ if (!voidElements.has(node.tag) && !/\/\s*>$/.test(token)) stack.push(node);
3639
+ continue;
3640
+ }
3641
+ const currentNode = stack.at(-1);
3642
+ if (!hiddenInChain(currentNode) && !ignoredInChain(currentNode)) {
3643
+ visibleText += ` ${token}`;
3644
+ for (const node of blockerNodes) {
3645
+ for (let current = currentNode; current !== void 0; current = current.parent) {
3646
+ if (current === node) {
3647
+ node.blockerText += ` ${token}`;
3648
+ break;
3649
+ }
3650
+ }
3651
+ }
3652
+ }
3653
+ }
3654
+ return {
3655
+ visibleText: htmlToText(visibleText),
3656
+ blockerSurface: {
3657
+ text: blockerNodes.map((node) => htmlToText(node.blockerText)).filter(Boolean).join(" "),
3658
+ hasConversationMessages
3659
+ }
3660
+ };
3661
+ }
3662
+ function serializedAttribute(attributes, name) {
3663
+ const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3664
+ const match = new RegExp(`\\b${escapedName}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s"'=<>\`]+))`, "i").exec(attributes);
3665
+ return match?.[1] ?? match?.[2] ?? match?.[3];
3129
3666
  }
3130
3667
  function htmlToText(html) {
3131
- 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();
3668
+ 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();
3669
+ }
3670
+ function stripHiddenMarkup(html) {
3671
+ let visible = html;
3672
+ 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;
3673
+ for (let pass = 0; pass < 4; pass += 1) {
3674
+ const next = visible.replace(hiddenElement, " ");
3675
+ if (next === visible) break;
3676
+ visible = next;
3677
+ }
3678
+ return visible;
3132
3679
  }
3133
3680
  function isLikelySignedIn(visibleText) {
3134
3681
  const markers = localeLabels.signedInMarkers.map(escapeRegExp).join("|");
3135
3682
  return new RegExp(`\\b(${markers})\\b`, "i").test(visibleText);
3136
3683
  }
3684
+ function isLikelyLoginWall(visibleText) {
3685
+ const labels = localeLabels.loginBlocker.map(escapeRegExp).join("|");
3686
+ const matches = visibleText.match(new RegExp(`(?:${labels})`, "gi")) ?? [];
3687
+ return matches.length >= 2 || /\bsign\s?up\b|\bcreate (?:an )?account\b/i.test(visibleText);
3688
+ }
3137
3689
 
3138
3690
  // src/dom/artifacts.ts
3139
3691
  async function listPageArtifacts(page, args = {}) {
@@ -3356,6 +3908,14 @@ function sendButton(page) {
3356
3908
  }
3357
3909
  return page.getByRole("button", { name: anyLabelPattern(localeLabels.sendButton) });
3358
3910
  }
3911
+ function stopGenerationButton(page) {
3912
+ if (typeof page.getByRole !== "function") {
3913
+ return requiredLocator(page, "button[aria-label*='Stop'], button[title*='Stop']");
3914
+ }
3915
+ return page.getByRole("button", {
3916
+ name: new RegExp(`^(?:${localeLabels.stopControl.map(escapeRegExp).join("|")})$`, "i")
3917
+ });
3918
+ }
3359
3919
  function searchChatsButton(page) {
3360
3920
  if (typeof page.getByRole !== "function") {
3361
3921
  return requiredLocator(page, "button");
@@ -3394,7 +3954,7 @@ function requiredLocator(page, selector) {
3394
3954
  }
3395
3955
 
3396
3956
  // src/errors.ts
3397
- 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.";
3957
+ 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.";
3398
3958
  var BROWSER_BRIDGE_REMEDIATION = [
3399
3959
  {
3400
3960
  label: "Ordinary shell",
@@ -3403,7 +3963,7 @@ var BROWSER_BRIDGE_REMEDIATION = [
3403
3963
  },
3404
3964
  {
3405
3965
  label: "Codex Chrome bootstrap",
3406
- 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 }).',
3966
+ 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 }).',
3407
3967
  userActionRequired: false
3408
3968
  },
3409
3969
  {
@@ -4179,8 +4739,8 @@ function normalizeExtractedMessage(message, args = {}) {
4179
4739
  }
4180
4740
 
4181
4741
  // src/commands/context.ts
4182
- async function contextFromPage(page, partial = {}) {
4183
- if (page === void 0) {
4742
+ async function contextFromPage(page, partial = {}, options = {}) {
4743
+ if (page === void 0 || options.minimal === true) {
4184
4744
  return { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...partial };
4185
4745
  }
4186
4746
  const url = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => partial.url) : partial.url;
@@ -4212,15 +4772,34 @@ async function contextFromPage(page, partial = {}) {
4212
4772
  return context;
4213
4773
  }
4214
4774
 
4215
- // src/browser/attach.ts
4775
+ // src/browser/chatgpt-url.ts
4216
4776
  var CHATGPT_HOME = "https://chatgpt.com/";
4217
4777
  var CHATGPT_HOSTS = /* @__PURE__ */ new Set(["chatgpt.com", "www.chatgpt.com", "chat.openai.com"]);
4778
+ function isChatGPTUrl(value) {
4779
+ if (value === void 0) return false;
4780
+ try {
4781
+ const url = new URL(value);
4782
+ return url.protocol === "https:" && url.port === "" && url.username === "" && url.password === "" && CHATGPT_HOSTS.has(url.hostname);
4783
+ } catch {
4784
+ return false;
4785
+ }
4786
+ }
4787
+ function requireChatGPTUrl(value, label) {
4788
+ if (!isChatGPTUrl(value)) {
4789
+ throw new Error(`${label} must use HTTPS on an allowlisted ChatGPT origin with the default port.`);
4790
+ }
4791
+ return value;
4792
+ }
4793
+
4794
+ // src/browser/attach.ts
4218
4795
  var MAX_EXISTING_TAB_DIAGNOSTIC_CANDIDATES = 10;
4219
4796
  var MAX_EXISTING_TAB_DIAGNOSTIC_FIELD_LENGTH = 240;
4220
4797
  async function attachChatGPTBrowser(env, args = {}) {
4221
4798
  const browser = await getBrowser(env);
4222
4799
  const page = await getOrCreateChatGPTPage(browser, env, args);
4800
+ await assertPageOnChatGPTOrigin(page);
4223
4801
  const state = await readPageState(page);
4802
+ if (!isChatGPTUrl(state.url)) throw unsafeChatGPTOriginError();
4224
4803
  if (state.blocker?.kind === "login_required") {
4225
4804
  throw new LoginRequiredError(state.blocker.visibleText);
4226
4805
  }
@@ -4283,6 +4862,7 @@ async function tryBrowserGetPreferredListed(browsers) {
4283
4862
  }
4284
4863
  async function getOrCreateChatGPTPage(browser, env, args) {
4285
4864
  const targetUrl = args.url ?? CHATGPT_HOME;
4865
+ assertSafeChatGPTNavigation(targetUrl);
4286
4866
  const explicitExistingPolicy = normalizeExplicitExistingTabPolicy(args);
4287
4867
  if (env.page !== void 0) {
4288
4868
  const cached = normalizePage(env.page);
@@ -4340,7 +4920,7 @@ function normalizeExplicitExistingTabPolicy(args) {
4340
4920
  if (args.existingTab === true) {
4341
4921
  return {
4342
4922
  target: { type: "selected", host: "chatgpt" },
4343
- ifMissing: "create",
4923
+ ifMissing: "block",
4344
4924
  ifMultiple: "first",
4345
4925
  requireChatGPT: true
4346
4926
  };
@@ -4378,6 +4958,23 @@ async function selectExistingTab(browser, policy) {
4378
4958
  }
4379
4959
  }
4380
4960
  }
4961
+ if (typeof browser.tabs?.list === "function") {
4962
+ const controlled = await Promise.resolve(browser.tabs.list.call(browser.tabs)).catch(() => []);
4963
+ const matches = [];
4964
+ for (const candidate of controlled) {
4965
+ const page = await hydrateTab(browser, candidate);
4966
+ if (await pageMatchesExistingTarget(page, policy)) matches.push(page);
4967
+ }
4968
+ if (matches.length === 1 || matches.length > 1 && (policy.ifMultiple ?? "block") === "first") {
4969
+ return { page: matches[0] };
4970
+ }
4971
+ if (matches.length > 1) {
4972
+ throw new ExistingTabSelectionError(
4973
+ "Multiple already-controlled ChatGPT tabs matched the requested existing-tab target.",
4974
+ "existing_tab_ambiguous"
4975
+ );
4976
+ }
4977
+ }
4381
4978
  return userMatch.diagnostics === void 0 ? { diagnostics: diagnosticsForUnavailableUserTabs(policy) } : userMatch;
4382
4979
  }
4383
4980
  async function selectExistingUserTab(browser, policy, collectDiagnostics) {
@@ -4405,6 +5002,7 @@ async function selectExistingUserTab(browser, policy, collectDiagnostics) {
4405
5002
  }
4406
5003
  const selected = matches[0];
4407
5004
  const page = normalizePage(await claimTab.call(browser.user, selected));
5005
+ await assertPageOnChatGPTOrigin(page);
4408
5006
  return diagnostics === void 0 ? { page } : { page, diagnostics };
4409
5007
  }
4410
5008
  function userTabMatchesTarget(tab, policy) {
@@ -4520,23 +5118,15 @@ async function pageMatchesExistingTarget(page, policy) {
4520
5118
  return userTabMatchesTarget(tab, policy);
4521
5119
  }
4522
5120
  async function findExistingChatGPTTab(browser) {
4523
- const userTab = await selectExistingUserTab(browser, {
4524
- target: { type: "selected", host: "chatgpt" },
4525
- ifMultiple: "first",
4526
- requireChatGPT: true
4527
- }, false).catch(() => ({ page: void 0 }));
4528
- if (userTab.page !== void 0) {
4529
- return userTab.page;
4530
- }
4531
5121
  const selected = browser.tabs?.selected;
4532
5122
  if (typeof selected === "function") {
4533
5123
  try {
4534
5124
  const current = await selected.call(browser.tabs);
4535
5125
  if (current !== void 0) {
4536
- const normalized2 = normalizePage(current);
5126
+ const normalized = normalizePage(current);
4537
5127
  try {
4538
- if ((await normalized2.url?.())?.includes("chatgpt.com") === true) {
4539
- return normalized2;
5128
+ if (isChatGPTUrl(await normalized.url?.())) {
5129
+ return normalized;
4540
5130
  }
4541
5131
  } catch {
4542
5132
  }
@@ -4545,19 +5135,31 @@ async function findExistingChatGPTTab(browser) {
4545
5135
  }
4546
5136
  }
4547
5137
  const list = browser.tabs?.list;
4548
- if (typeof list !== "function") {
4549
- return void 0;
4550
- }
4551
- const tabs = await list.call(browser.tabs);
4552
- const normalized = await Promise.all(tabs.map((tab) => hydrateTab(browser, tab)));
4553
- for (const tab of normalized) {
4554
- try {
4555
- if ((await tab.url?.())?.includes("chatgpt.com") === true) {
4556
- return tab;
5138
+ if (typeof list === "function") {
5139
+ const tabs = await list.call(browser.tabs);
5140
+ const normalized = await Promise.all(tabs.map((tab) => hydrateTab(browser, tab)));
5141
+ for (const tab of normalized) {
5142
+ try {
5143
+ if (isChatGPTUrl(await tab.url?.())) {
5144
+ return tab;
5145
+ }
5146
+ } catch {
4557
5147
  }
4558
- } catch {
4559
5148
  }
4560
5149
  }
5150
+ const userTab = await selectExistingUserTab(browser, {
5151
+ target: { type: "selected", host: "chatgpt" },
5152
+ ifMultiple: "first",
5153
+ requireChatGPT: true
5154
+ }, false).catch((error) => {
5155
+ if (error instanceof ChatGPTControlError && error.blockerDetails.code === "unsafe_chatgpt_origin") {
5156
+ throw error;
5157
+ }
5158
+ return { page: void 0 };
5159
+ });
5160
+ if (userTab.page !== void 0) {
5161
+ return userTab.page;
5162
+ }
4561
5163
  return void 0;
4562
5164
  }
4563
5165
  var ExistingTabSelectionError = class extends ChatGPTControlError {
@@ -4595,16 +5197,6 @@ function targetRequiresChatGPT(target) {
4595
5197
  return true;
4596
5198
  }
4597
5199
  }
4598
- function isChatGPTUrl(url) {
4599
- if (url === void 0) {
4600
- return false;
4601
- }
4602
- try {
4603
- return CHATGPT_HOSTS.has(new URL(url).hostname);
4604
- } catch {
4605
- return false;
4606
- }
4607
- }
4608
5200
  function urlMatches(actual, expected) {
4609
5201
  if (actual === void 0) {
4610
5202
  return false;
@@ -4656,6 +5248,7 @@ function userTabCandidateLabel(tab) {
4656
5248
  return `tab ${tab.id} - ${tab.title ?? "Untitled"} - ${tab.url ?? "unknown URL"}`;
4657
5249
  }
4658
5250
  async function createTab(browser, url) {
5251
+ assertSafeChatGPTNavigation(url);
4659
5252
  if (typeof browser.tabs?.create === "function") {
4660
5253
  const tab = await browser.tabs.create(url);
4661
5254
  const page = await hydrateTab(browser, tab);
@@ -4673,18 +5266,39 @@ async function createTab(browser, url) {
4673
5266
  if (typeof page.goto === "function") {
4674
5267
  await page.goto(url);
4675
5268
  }
5269
+ await assertPageOnChatGPTOrigin(page);
4676
5270
  return page;
4677
5271
  }
4678
5272
  return void 0;
4679
5273
  }
5274
+ function assertSafeChatGPTNavigation(url) {
5275
+ if (isChatGPTUrl(url)) return;
5276
+ throw unsafeChatGPTOriginError(
5277
+ "ChatGPT navigation requires HTTPS on an allowlisted ChatGPT origin with the default port."
5278
+ );
5279
+ }
4680
5280
  async function ensurePageAt(page, url) {
4681
5281
  const currentUrl = await Promise.resolve(page.url?.()).catch(() => "");
4682
- if (currentUrl?.includes("chatgpt.com") === true) {
5282
+ if (isChatGPTUrl(currentUrl)) {
4683
5283
  return;
4684
5284
  }
4685
5285
  if (typeof page.goto === "function") {
4686
5286
  await page.goto(url);
4687
5287
  }
5288
+ await assertPageOnChatGPTOrigin(page);
5289
+ }
5290
+ async function assertPageOnChatGPTOrigin(page) {
5291
+ const actualUrl = await Promise.resolve(page.url?.()).catch(() => void 0);
5292
+ if (!isChatGPTUrl(actualUrl)) throw unsafeChatGPTOriginError();
5293
+ }
5294
+ function unsafeChatGPTOriginError(message = "The browser did not remain on a supported ChatGPT origin after navigation or attachment.") {
5295
+ return new ChatGPTControlError(
5296
+ message,
5297
+ "selector_drift",
5298
+ false,
5299
+ void 0,
5300
+ { code: "unsafe_chatgpt_origin" }
5301
+ );
4688
5302
  }
4689
5303
  function normalizeBrowser(browser) {
4690
5304
  if (browser === void 0 || browser === null || typeof browser !== "object") {
@@ -4755,7 +5369,7 @@ async function bootstrap(env, args = {}) {
4755
5369
  return resultError(error instanceof Error ? error : new Error(String(error)));
4756
5370
  }
4757
5371
  }
4758
- async function ensurePage(env) {
5372
+ async function ensurePage(env, options = {}) {
4759
5373
  if (env.page === void 0) {
4760
5374
  return bootstrap(env, { preferExistingTab: true });
4761
5375
  }
@@ -4763,7 +5377,40 @@ async function ensurePage(env) {
4763
5377
  if (affinity !== void 0) {
4764
5378
  return affinity;
4765
5379
  }
4766
- return resultOk({}, await contextFromPage(env.page, tabContext(env)));
5380
+ const origin = await verifyChatGPTOrigin(env);
5381
+ if (origin !== void 0) {
5382
+ return origin;
5383
+ }
5384
+ return resultOk({}, await contextFromPage(
5385
+ env.page,
5386
+ tabContext(env),
5387
+ { minimal: options.minimalContext === true }
5388
+ ));
5389
+ }
5390
+ async function verifyChatGPTOrigin(env) {
5391
+ if (env.page === void 0) return void 0;
5392
+ const actualUrl = await Promise.resolve(env.page.url?.()).catch(() => void 0);
5393
+ if (isChatGPTUrl(actualUrl)) return void 0;
5394
+ return {
5395
+ ok: false,
5396
+ status: "blocked",
5397
+ warnings: [],
5398
+ blocker: {
5399
+ kind: "selector_drift",
5400
+ code: "unsafe_chatgpt_origin",
5401
+ message: "ChatGPT command refused to operate because the controlled tab is not on an allowlisted ChatGPT origin.",
5402
+ visibleText: actualUrl ?? "The current tab URL could not be verified.",
5403
+ remediation: [
5404
+ {
5405
+ label: "Reopen ChatGPT",
5406
+ instruction: "Run session.bootstrap against https://chatgpt.com or claim an exact supported ChatGPT tab before retrying.",
5407
+ userActionRequired: false
5408
+ }
5409
+ ],
5410
+ resumable: false
5411
+ },
5412
+ context: await contextFromPage(env.page, tabContext(env))
5413
+ };
4767
5414
  }
4768
5415
  async function verifyTabAffinity(env) {
4769
5416
  if (env.expectedTabId === void 0 || env.page === void 0) {
@@ -5233,13 +5880,29 @@ function isFullyQualifiedWindowsPath(value) {
5233
5880
  return /^[A-Za-z]:[\\/]/.test(value) || /^\\\\[^\\]+\\[^\\]+[\\/]/.test(value);
5234
5881
  }
5235
5882
 
5236
- // src/commands/files.ts
5237
- var CODEX_UPLOAD_PERMISSION_FIX = "Codex Settings > Computer Use > Chrome > Permissions > Uploads: set to Always allow, or add chatgpt.com to the allowed upload domains.";
5238
- var CHROME_FILE_URL_PERMISSION_FIX = "Chrome chrome://extensions > Codex extension > Details: enable Allow access to file URLs.";
5239
- var DEFAULT_MAX_BYTES_PER_FILE = 512 * 1024 * 1024;
5240
- var DEFAULT_MAX_TOTAL_BYTES = 2 * 1024 * 1024 * 1024;
5241
- async function preflightFiles(env, args) {
5242
- const maxBytesPerFile = args.maxBytesPerFile ?? DEFAULT_MAX_BYTES_PER_FILE;
5883
+ // src/commands/deadline.ts
5884
+ function createDeadline(timeoutMs, startedAtMs = Date.now()) {
5885
+ const safeTimeoutMs = Math.max(0, timeoutMs);
5886
+ return {
5887
+ startedAtMs,
5888
+ timeoutMs: safeTimeoutMs,
5889
+ expiresAtMs: startedAtMs + safeTimeoutMs
5890
+ };
5891
+ }
5892
+ function remainingMs(deadline, nowMs = Date.now()) {
5893
+ return Math.max(0, deadline.expiresAtMs - nowMs);
5894
+ }
5895
+ function childTimeoutMs(deadline, capMs, nowMs = Date.now()) {
5896
+ return Math.max(0, Math.min(Math.max(0, capMs), remainingMs(deadline, nowMs)));
5897
+ }
5898
+
5899
+ // src/commands/files.ts
5900
+ var CODEX_UPLOAD_PERMISSION_FIX = "Codex Settings > Computer Use > Chrome > Permissions > Uploads: set to Always allow, or add chatgpt.com to the allowed upload domains.";
5901
+ var CHROME_FILE_URL_PERMISSION_FIX = "Chrome chrome://extensions > Codex extension > Details: enable Allow access to file URLs.";
5902
+ var DEFAULT_MAX_BYTES_PER_FILE = 512 * 1024 * 1024;
5903
+ var DEFAULT_MAX_TOTAL_BYTES = 2 * 1024 * 1024 * 1024;
5904
+ async function preflightFiles(env, args) {
5905
+ const maxBytesPerFile = args.maxBytesPerFile ?? DEFAULT_MAX_BYTES_PER_FILE;
5243
5906
  const maxTotalBytes = args.maxTotalBytes ?? DEFAULT_MAX_TOTAL_BYTES;
5244
5907
  const files = [];
5245
5908
  const warnings = [];
@@ -5342,6 +6005,7 @@ async function preflightFiles(env, args) {
5342
6005
  return resultOk({ files, totalBytes }, filePreflightContext(env), warnings);
5343
6006
  }
5344
6007
  async function attachFiles(env, args) {
6008
+ const deadline = createDeadline(Math.max(1, args.timeoutMs ?? 3e4));
5345
6009
  const preflightArgs = { paths: args.paths };
5346
6010
  if (args.includeDiagnostics === true && args.includeHashes !== void 0) {
5347
6011
  preflightArgs.includeHashes = args.includeHashes;
@@ -5350,50 +6014,57 @@ async function attachFiles(env, args) {
5350
6014
  if (!preflight.ok || preflight.data === void 0) {
5351
6015
  return preflight;
5352
6016
  }
5353
- const boot = await ensurePage(env);
6017
+ let boot;
6018
+ try {
6019
+ boot = await withinAttachmentDeadline(
6020
+ deadline,
6021
+ () => ensurePage(env, { minimalContext: true }),
6022
+ "ChatGPT page verification"
6023
+ );
6024
+ } catch (error) {
6025
+ if (error instanceof AttachmentDeadlineError || remainingMs(deadline) <= 0) {
6026
+ return attachmentDeadlineResult(error);
6027
+ }
6028
+ return resultError(error instanceof Error ? error : new Error(String(error)));
6029
+ }
5354
6030
  if (!boot.ok) {
5355
6031
  return boot;
5356
6032
  }
5357
6033
  const page = env.page;
6034
+ const mutationState = { handoffStarted: false };
5358
6035
  try {
5359
6036
  const files = preflight.data.files.map((file) => ({
5360
6037
  path: file.path,
5361
6038
  name: file.name,
5362
6039
  bytes: file.bytes
5363
6040
  }));
5364
- await uploadFiles(page, files, args.timeoutMs ?? 3e4);
5365
- const browserInput = args.includeDiagnostics === true ? await readBrowserInputDiagnostic(page).catch(() => void 0) : void 0;
5366
- await page.waitForTimeout?.(args.timeoutMs === void 0 ? 1e3 : Math.min(args.timeoutMs, 3e3));
5367
- const readiness = await waitForAttachedFilesReady(page, files, args.timeoutMs ?? 3e4);
6041
+ const rawBaseline = await withinNativeAttachmentDeadline(
6042
+ deadline,
6043
+ (timeoutMs) => readAttachmentEvidenceBaseline(page, timeoutMs),
6044
+ "Pre-upload attachment baseline",
6045
+ 2e3
6046
+ ).catch(() => ({ supported: false, inputFiles: [], attachmentLabels: [] }));
6047
+ const baseline = rawBaseline !== null && typeof rawBaseline === "object" && Array.isArray(rawBaseline.inputFiles) && Array.isArray(rawBaseline.attachmentLabels) ? rawBaseline : { supported: false, inputFiles: [], attachmentLabels: [] };
6048
+ await uploadFiles(page, files, deadline, mutationState);
6049
+ const browserInput = args.includeDiagnostics === true ? await withinNativeAttachmentDeadline(
6050
+ deadline,
6051
+ (timeoutMs) => readBrowserInputDiagnostic(page, timeoutMs),
6052
+ "Browser input diagnostic",
6053
+ 2e3
6054
+ ).catch(() => void 0) : void 0;
6055
+ await attachmentDelay(
6056
+ page,
6057
+ deadline,
6058
+ Math.min(250, Math.max(1, Math.floor(remainingMs(deadline) / 4)))
6059
+ );
6060
+ const readiness = await waitForAttachedFilesReady(page, files, baseline, deadline);
5368
6061
  if (!readiness.ready) {
5369
- const blocker = {
5370
- kind: "upload_failed",
5371
- code: "attachment_processing",
5372
- message: "ChatGPT still appears to be processing the attached file, so the prompt was not submitted.",
5373
- remediation: [
5374
- {
5375
- label: "Wait for upload",
5376
- instruction: "Wait until the visible attachment finishes uploading or processing, then retry the askWithFiles call.",
5377
- userActionRequired: false
5378
- },
5379
- {
5380
- label: "Retry smaller file",
5381
- instruction: "If processing never finishes, retry with a smaller file or a different supported file type.",
5382
- userActionRequired: true
5383
- }
5384
- ],
5385
- resumable: true
5386
- };
5387
- if (readiness.processingText !== void 0) {
5388
- blocker.visibleText = readiness.processingText;
5389
- }
5390
- return {
5391
- ok: false,
5392
- status: "blocked",
5393
- warnings: [],
5394
- blocker,
5395
- context: await contextFromPage(page)
5396
- };
6062
+ return attachmentOutcomeIndeterminate(
6063
+ files,
6064
+ [],
6065
+ await attachmentContext(page, deadline),
6066
+ readiness.processingText
6067
+ );
5397
6068
  }
5398
6069
  const data = { files };
5399
6070
  if (args.includeDiagnostics === true) {
@@ -5402,9 +6073,49 @@ async function attachFiles(env, args) {
5402
6073
  data.diagnostics.browserInput = browserInput;
5403
6074
  }
5404
6075
  }
5405
- return resultOk(data, await contextFromPage(page), preflight.warnings);
6076
+ return resultOk(data, await attachmentContext(page, deadline), preflight.warnings);
5406
6077
  } catch (error) {
5407
- if (isUploadBridgeBlocker(error)) {
6078
+ if (mutationState.handoffStarted) {
6079
+ const permissionFailure = isUploadPermissionBlocker(error);
6080
+ return attachmentOutcomeIndeterminate(
6081
+ preflight.data.files,
6082
+ [error instanceof Error ? error.message : String(error)],
6083
+ await attachmentContext(page, deadline),
6084
+ permissionFailure ? uploadPermissionDetails(error) : void 0,
6085
+ permissionFailure ? uploadPermissionRemediation() : void 0
6086
+ );
6087
+ }
6088
+ if (error instanceof AttachmentDeadlineError || remainingMs(deadline) <= 0) {
6089
+ return attachmentDeadlineResult(error);
6090
+ }
6091
+ if (isUploadTransportFailure(error)) {
6092
+ return {
6093
+ ok: false,
6094
+ status: "blocked",
6095
+ warnings: [],
6096
+ blocker: {
6097
+ kind: "browser_bridge_unavailable",
6098
+ code: "upload_transport_failed",
6099
+ 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.",
6100
+ visibleText: error instanceof Error ? error.message : String(error),
6101
+ remediation: [
6102
+ {
6103
+ label: "Retry live attachment",
6104
+ instruction: "Retry the attachment from the live Codex Chrome runtime; the operation is safe to resume because file attachment did not complete.",
6105
+ userActionRequired: false
6106
+ },
6107
+ {
6108
+ label: "Restart bridge if repeated",
6109
+ instruction: "If the bridge disconnects again, restart Chrome or Codex before retrying. Do not change upload permissions unless Chrome explicitly reports a permission denial.",
6110
+ userActionRequired: true
6111
+ }
6112
+ ],
6113
+ resumable: true
6114
+ },
6115
+ context: await attachmentContext(page, deadline)
6116
+ };
6117
+ }
6118
+ if (isUploadPermissionBlocker(error)) {
5408
6119
  return {
5409
6120
  ok: false,
5410
6121
  status: "blocked",
@@ -5417,12 +6128,68 @@ async function attachFiles(env, args) {
5417
6128
  remediation: uploadPermissionRemediation(),
5418
6129
  resumable: true
5419
6130
  },
5420
- context: await contextFromPage(page)
6131
+ context: await attachmentContext(page, deadline)
5421
6132
  };
5422
6133
  }
5423
- return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
6134
+ if (isUploadPathFailure(error)) {
6135
+ return {
6136
+ ok: false,
6137
+ status: "blocked",
6138
+ warnings: [],
6139
+ blocker: {
6140
+ kind: "upload_failed",
6141
+ code: "upload_path_unavailable",
6142
+ message: "None of the browser's supported ChatGPT file-attachment paths completed. Callers must not submit the prompt.",
6143
+ visibleText: error instanceof Error ? error.message : String(error),
6144
+ remediation: [
6145
+ {
6146
+ label: "Retry live attachment",
6147
+ 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.",
6148
+ userActionRequired: false
6149
+ }
6150
+ ],
6151
+ resumable: true
6152
+ },
6153
+ context: await attachmentContext(page, deadline)
6154
+ };
6155
+ }
6156
+ return resultError(error instanceof Error ? error : new Error(String(error)), await attachmentContext(page, deadline));
5424
6157
  }
5425
6158
  }
6159
+ function attachmentDeadlineResult(error) {
6160
+ return {
6161
+ ok: false,
6162
+ status: "timeout",
6163
+ warnings: error === void 0 ? [] : [error instanceof Error ? error.message : String(error)],
6164
+ blocker: {
6165
+ kind: "upload_failed",
6166
+ code: "attachment_deadline_exhausted",
6167
+ message: "ChatGPT file attachment did not complete before the caller's single operation deadline. The prompt was not submitted.",
6168
+ resumable: true
6169
+ },
6170
+ context: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
6171
+ };
6172
+ }
6173
+ function attachmentOutcomeIndeterminate(files, warnings, context, visibleText, remediation) {
6174
+ const blocker = {
6175
+ kind: "upload_failed",
6176
+ code: "attachment_outcome_indeterminate",
6177
+ 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.",
6178
+ resumable: false
6179
+ };
6180
+ if (visibleText !== void 0) blocker.visibleText = visibleText;
6181
+ if (remediation !== void 0) blocker.remediation = remediation;
6182
+ return {
6183
+ ok: false,
6184
+ status: "partial",
6185
+ data: {
6186
+ files: files.map((file) => ({ path: file.path, name: file.name, bytes: file.bytes }))
6187
+ },
6188
+ warnings,
6189
+ blocker,
6190
+ context
6191
+ };
6192
+ }
5426
6193
  function filePreflightBlocker(args) {
5427
6194
  return {
5428
6195
  ok: false,
@@ -5533,44 +6300,120 @@ function guessFileType(extension) {
5533
6300
  function isNodeError(error) {
5534
6301
  return error instanceof Error && "code" in error;
5535
6302
  }
5536
- async function waitForAttachedFilesReady(page, files, timeoutMs) {
5537
- const started = Date.now();
6303
+ async function readAttachmentEvidenceBaseline(page, timeoutMs) {
6304
+ if (typeof page.evaluate !== "function") {
6305
+ return { supported: false, inputFiles: [], attachmentLabels: [] };
6306
+ }
6307
+ return page.evaluate(() => {
6308
+ const visible = (element) => {
6309
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
6310
+ const style = window.getComputedStyle(element);
6311
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
6312
+ const rect = element.getBoundingClientRect();
6313
+ return rect.width > 0 || rect.height > 0;
6314
+ };
6315
+ const textboxes = Array.from(document.querySelectorAll(
6316
+ "textarea, [contenteditable='true'], [role='textbox']"
6317
+ )).filter(visible);
6318
+ 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))];
6319
+ if (composers.length !== 1) {
6320
+ return { supported: false, inputFiles: [], attachmentLabels: [] };
6321
+ }
6322
+ const composer = composers[0];
6323
+ const allInputs = Array.from(composer.querySelectorAll("input[type='file']")).filter((input) => !input.disabled && input.getAttribute("aria-disabled") !== "true");
6324
+ const preferred = allInputs.filter((input) => input.id === "upload-files");
6325
+ const nonImage = allInputs.filter((input) => input.getAttribute("accept") !== "image/*");
6326
+ const inputs = preferred.length > 0 ? preferred : nonImage.length > 0 ? nonImage : allInputs;
6327
+ if (inputs.length !== 1) {
6328
+ return { supported: false, inputFiles: [], attachmentLabels: [] };
6329
+ }
6330
+ const attachmentSelector = [
6331
+ "[data-testid*='attachment' i]",
6332
+ "[data-testid*='file' i]",
6333
+ "[aria-label*='attachment' i]",
6334
+ "[aria-label*='upload' i]",
6335
+ "[aria-label*='file' i]",
6336
+ "[class*='attachment' i]",
6337
+ "[class*='upload' i]",
6338
+ "[class*='file' i]",
6339
+ "[role='progressbar']"
6340
+ ].join(", ");
6341
+ const labels = Array.from(composer.querySelectorAll(attachmentSelector)).filter(visible).map((element) => [
6342
+ element.textContent ?? "",
6343
+ element.getAttribute("aria-label") ?? "",
6344
+ element.getAttribute("title") ?? ""
6345
+ ].join(" ").replace(/\s+/g, " ").trim().toLocaleLowerCase()).filter(Boolean);
6346
+ return {
6347
+ supported: true,
6348
+ inputFiles: Array.from(inputs[0].files ?? []).map((file) => `${file.name.toLocaleLowerCase()}\0${file.size}`),
6349
+ attachmentLabels: labels
6350
+ };
6351
+ }, void 0, { timeoutMs });
6352
+ }
6353
+ async function waitForAttachedFilesReady(page, files, baseline, deadline) {
5538
6354
  let lastProcessingText;
5539
- while (Date.now() - started < timeoutMs) {
5540
- const snapshot = await readAttachmentReadiness(page, files).catch(() => void 0);
5541
- if (snapshot === void 0) {
5542
- return { ready: true };
6355
+ let sawProcessing = false;
6356
+ while (remainingMs(deadline) > 0) {
6357
+ const snapshot = await withinNativeAttachmentDeadline(
6358
+ deadline,
6359
+ (timeoutMs) => readAttachmentReadiness(page, files, baseline, timeoutMs),
6360
+ "Attachment readiness inspection",
6361
+ 2e3
6362
+ ).catch(() => void 0);
6363
+ if (snapshot === void 0 || snapshot.supported === false) {
6364
+ return { ready: false, reason: "unverified" };
5543
6365
  }
5544
- const allNamesVisible = snapshot.files.length > 0 && snapshot.files.every((file) => file.visible);
6366
+ const allNamesVisible = snapshot.files.length === files.length && snapshot.files.every((file) => file.visible);
5545
6367
  if (!snapshot.processing && allNamesVisible) {
5546
6368
  return { ready: true };
5547
6369
  }
5548
- if (!snapshot.processing && Date.now() - started >= Math.min(timeoutMs, 1e3)) {
5549
- return { ready: true };
5550
- }
6370
+ sawProcessing ||= snapshot.processing;
5551
6371
  if (snapshot.processingText !== void 0) {
5552
6372
  lastProcessingText = snapshot.processingText;
5553
6373
  }
5554
- await page.waitForTimeout?.(250);
6374
+ const pollBudget = remainingMs(deadline);
6375
+ if (pollBudget <= 10) break;
6376
+ await attachmentDelay(page, deadline, Math.min(250, pollBudget - 10));
5555
6377
  }
5556
- const blocked2 = { ready: false };
6378
+ const blocked2 = {
6379
+ ready: false,
6380
+ reason: sawProcessing ? "processing" : "unverified"
6381
+ };
5557
6382
  if (lastProcessingText !== void 0) {
5558
6383
  blocked2.processingText = lastProcessingText;
5559
6384
  }
5560
6385
  return blocked2;
5561
6386
  }
5562
- async function readAttachmentReadiness(page, files) {
6387
+ async function readAttachmentReadiness(page, files, baseline, timeoutMs) {
5563
6388
  if (typeof page.evaluate !== "function") {
5564
6389
  return void 0;
5565
6390
  }
5566
- return page.evaluate((fileNames) => {
5567
- const visibleText = document.body?.innerText ?? "";
6391
+ return page.evaluate((args) => {
6392
+ const expectedFiles = args.expectedFiles;
5568
6393
  const normalize = (value) => value.toLocaleLowerCase();
5569
- const normalizedVisibleText = normalize(visibleText);
5570
- const files2 = fileNames.map((name) => ({
5571
- name,
5572
- visible: normalizedVisibleText.includes(normalize(name))
5573
- }));
6394
+ const visible = (element) => {
6395
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
6396
+ const style = window.getComputedStyle(element);
6397
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
6398
+ const rect = element.getBoundingClientRect();
6399
+ return rect.width > 0 || rect.height > 0;
6400
+ };
6401
+ const textboxes = Array.from(document.querySelectorAll(
6402
+ "textarea, [contenteditable='true'], [role='textbox']"
6403
+ )).filter(visible);
6404
+ 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))];
6405
+ if (composers.length !== 1) {
6406
+ return { supported: false, files: expectedFiles.map((file) => ({ name: file.name, visible: false })), processing: false };
6407
+ }
6408
+ const composer = composers[0];
6409
+ const allInputs = Array.from(composer.querySelectorAll("input[type='file']")).filter((input2) => !input2.disabled && input2.getAttribute("aria-disabled") !== "true");
6410
+ const preferred = allInputs.filter((input2) => input2.id === "upload-files");
6411
+ const nonImage = allInputs.filter((input2) => input2.getAttribute("accept") !== "image/*");
6412
+ const inputs = preferred.length > 0 ? preferred : nonImage.length > 0 ? nonImage : allInputs;
6413
+ if (inputs.length !== 1) {
6414
+ return { supported: false, files: expectedFiles.map((file) => ({ name: file.name, visible: false })), processing: false };
6415
+ }
6416
+ const input = inputs[0];
5574
6417
  const attachmentSelectors = [
5575
6418
  "[data-testid*='attachment' i]",
5576
6419
  "[data-testid*='file' i]",
@@ -5582,88 +6425,163 @@ async function readAttachmentReadiness(page, files) {
5582
6425
  "[class*='file' i]",
5583
6426
  "[role='progressbar']"
5584
6427
  ].join(", ");
5585
- const attachmentText = Array.from(document.querySelectorAll(attachmentSelectors)).map((element) => [
6428
+ const attachmentElements = Array.from(composer.querySelectorAll(attachmentSelectors)).filter(visible);
6429
+ const attachmentText = attachmentElements.map((element) => [
5586
6430
  element.textContent ?? "",
5587
6431
  element.getAttribute("aria-label") ?? "",
5588
6432
  element.getAttribute("title") ?? ""
5589
6433
  ].join(" ")).join(" ");
5590
- const relevantText = attachmentText.length > 0 ? attachmentText : visibleText;
5591
- const processingMatch = /\b(uploading|processing|attaching|preparing|reading|scanning|analyzing)\b/i.exec(relevantText);
6434
+ const inputFiles = Array.from(input.files ?? []).map((file) => ({
6435
+ name: normalize(file.name),
6436
+ size: file.size,
6437
+ signature: `${normalize(file.name)}\0${file.size}`
6438
+ }));
6439
+ const attachmentLabels = attachmentElements.map((element) => normalize([
6440
+ element.textContent ?? "",
6441
+ element.getAttribute("aria-label") ?? "",
6442
+ element.getAttribute("title") ?? ""
6443
+ ].join(" ")));
6444
+ const occurrence = (values, index) => values.slice(0, index + 1).filter((value) => value === values[index]).length;
6445
+ const inputSignatures = inputFiles.map((file) => file.signature);
6446
+ 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));
6447
+ 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));
6448
+ const usedInputs = /* @__PURE__ */ new Set();
6449
+ const usedLabels = /* @__PURE__ */ new Set();
6450
+ const visibleFiles = expectedFiles.map((expected) => {
6451
+ const expectedName = normalize(expected.name);
6452
+ const inputIndex = inputFiles.findIndex(
6453
+ (candidate, index) => !usedInputs.has(index) && newInputIndices.has(index) && candidate.name === expectedName && candidate.size === expected.bytes
6454
+ );
6455
+ if (inputIndex >= 0) {
6456
+ usedInputs.add(inputIndex);
6457
+ return { name: expected.name, visible: true };
6458
+ }
6459
+ const labelIndex = attachmentLabels.findIndex(
6460
+ (label, index) => !usedLabels.has(index) && newLabelIndices.has(index) && label.includes(expectedName)
6461
+ );
6462
+ if (labelIndex >= 0) usedLabels.add(labelIndex);
6463
+ return { name: expected.name, visible: labelIndex >= 0 };
6464
+ });
6465
+ const processingMatch = /\b(uploading|processing|attaching|preparing|reading|scanning|analyzing)\b/i.exec(attachmentText);
5592
6466
  const snapshot = {
5593
- files: files2,
6467
+ supported: true,
6468
+ files: visibleFiles,
5594
6469
  processing: processingMatch !== null
5595
6470
  };
5596
6471
  if (processingMatch !== null) {
5597
- snapshot.processingText = relevantText.slice(0, 500);
6472
+ snapshot.processingText = attachmentText.slice(0, 500);
5598
6473
  }
5599
6474
  return snapshot;
5600
- }, files.map((file) => file.name));
6475
+ }, {
6476
+ expectedFiles: files.map((file) => ({ name: file.name, bytes: file.bytes })),
6477
+ baseline
6478
+ }, { timeoutMs });
5601
6479
  }
5602
- async function uploadFiles(page, files, timeoutMs) {
6480
+ async function uploadFiles(page, files, deadline, mutationState) {
5603
6481
  const paths = files.map((file) => file.path);
5604
6482
  const errors = [];
5605
- const attempts = [
5606
- {
6483
+ let activeComposerInput;
6484
+ try {
6485
+ activeComposerInput = await resolveUniqueActiveComposerFileInput(page, deadline);
6486
+ } catch (error) {
6487
+ errors.push(`active-composer-input: ${error instanceof Error ? error.message : String(error)}`);
6488
+ }
6489
+ const attempts = [];
6490
+ if (activeComposerInput !== void 0) {
6491
+ const resolvedInput = activeComposerInput;
6492
+ attempts.push({
5607
6493
  name: "visible-chatgpt-file-input",
5608
6494
  run: async () => {
5609
- await clickFileChooserTarget(page, "#upload-files", paths, timeoutMs, { requireVisible: true });
6495
+ if (!await locatorIsRendered(resolvedInput, deadline)) {
6496
+ throw new Error("The active-composer upload target is hidden.");
6497
+ }
6498
+ await clickFileChooserLocator(page, resolvedInput, paths, deadline, mutationState);
5610
6499
  }
5611
- },
6500
+ });
6501
+ }
6502
+ attempts.push(
5612
6503
  {
5613
6504
  name: "add-photos-files-menu-item",
5614
6505
  run: async () => {
5615
- await clickChatGPTAddPhotosMenuItem(page, paths, timeoutMs);
6506
+ await clickChatGPTAddPhotosMenuItem(page, paths, deadline, mutationState);
5616
6507
  }
5617
6508
  },
5618
6509
  {
5619
6510
  name: "generic-add-files-button",
5620
6511
  run: async () => {
5621
- await clickFileChooserLocator(page, addFilesButton(page), paths, timeoutMs);
6512
+ const control = addFilesButton(page);
6513
+ await assertControlInUniqueActiveComposer(control, deadline, "Generic Add files control");
6514
+ await clickFileChooserLocator(page, control, paths, deadline, mutationState);
5622
6515
  }
5623
6516
  },
5624
6517
  {
5625
- name: "direct-file-input-set",
6518
+ name: "cdp-file-input-chooser",
5626
6519
  run: async () => {
5627
- await setHiddenFileInput(page, files);
6520
+ await clickHiddenFileInputWithCdp(page, paths, deadline, mutationState);
5628
6521
  }
5629
6522
  }
5630
- ];
6523
+ );
6524
+ if (activeComposerInput !== void 0) {
6525
+ const resolvedInput = activeComposerInput;
6526
+ attempts.push({
6527
+ name: "direct-file-input-set",
6528
+ run: async () => {
6529
+ await setResolvedFileInput(resolvedInput, files, deadline, mutationState);
6530
+ }
6531
+ });
6532
+ }
5631
6533
  for (const attempt of attempts) {
6534
+ if (remainingMs(deadline) <= 0) {
6535
+ errors.push(`${attempt.name}: skipped because the single attachment deadline was exhausted`);
6536
+ break;
6537
+ }
5632
6538
  try {
5633
6539
  await attempt.run();
5634
6540
  return;
5635
6541
  } catch (error) {
6542
+ if (mutationState.handoffStarted) {
6543
+ throw error;
6544
+ }
6545
+ if (isUploadPermissionBlocker(error) || isUploadTransportFailure(error)) {
6546
+ throw error;
6547
+ }
5636
6548
  errors.push(`${attempt.name}: ${error instanceof Error ? error.message : String(error)}`);
5637
6549
  }
5638
6550
  }
5639
6551
  throw new Error(`No ChatGPT upload path completed.
5640
6552
  ${errors.join("\n")}`);
5641
6553
  }
5642
- async function clickChatGPTAddPhotosMenuItem(page, paths, timeoutMs) {
5643
- const addPhotosFilesText = localeLabels.addPhotosFilesMenuItem[0];
5644
- const menuItem = requiredLocator(page, "div[role='menuitem']").filter?.({ hasText: addPhotosFilesText });
5645
- if (await locatorCount(menuItem) !== 1) {
6554
+ async function clickChatGPTAddPhotosMenuItem(page, paths, deadline, mutationState) {
6555
+ const addPhotosFilesLabels = localeLabels.addPhotosFilesMenuItem;
6556
+ let menuItem = await findChatGPTUploadMenuItem(page, addPhotosFilesLabels, deadline);
6557
+ if (menuItem === void 0) {
5646
6558
  const plusButton = requiredLocator(page, "#composer-plus-btn, button[aria-label='Add files and more']");
5647
- if (await locatorCount(plusButton) !== 1) {
6559
+ if (await locatorCount(plusButton, deadline) !== 1) {
5648
6560
  throw new Error("ChatGPT Add files button was not uniquely available.");
5649
6561
  }
5650
- await plusButton.click?.({ timeoutMs: Math.min(timeoutMs, 1e4) });
5651
- await page.waitForTimeout?.(250);
5652
- }
5653
- const refreshedMenuItem = requiredLocator(page, "div[role='menuitem']").filter?.({ hasText: addPhotosFilesText });
5654
- await clickFileChooserLocator(page, refreshedMenuItem, paths, timeoutMs);
5655
- }
5656
- async function clickFileChooserTarget(page, selector, paths, timeoutMs, options = {}) {
5657
- const locator = requiredLocator(page, selector);
5658
- if (await locatorCount(locator) !== 1) {
5659
- throw new Error(`Upload target was not uniquely available: ${selector}`);
6562
+ await assertControlInUniqueActiveComposer(plusButton, deadline, "ChatGPT Add files control");
6563
+ if (plusButton.click === void 0) throw new Error("ChatGPT Add files button does not expose click().");
6564
+ await withinNativeAttachmentDeadline(
6565
+ deadline,
6566
+ (timeoutMs) => plusButton.click({ timeoutMs }),
6567
+ "ChatGPT Add files control click",
6568
+ 1e4
6569
+ );
6570
+ await attachmentDelay(page, deadline, 250);
5660
6571
  }
5661
- if (options.requireVisible === true && locator.isVisible !== void 0 && !await locator.isVisible({ timeoutMs: 1e3 })) {
5662
- throw new Error(`Upload target is hidden: ${selector}`);
6572
+ menuItem = await findChatGPTUploadMenuItem(page, addPhotosFilesLabels, deadline);
6573
+ if (menuItem === void 0) {
6574
+ throw new Error("ChatGPT's visible Add photos & files upload row was not uniquely available.");
5663
6575
  }
5664
- await clickFileChooserLocator(page, locator, paths, timeoutMs);
6576
+ const refreshedMenuItem = menuItem;
6577
+ await clickFileChooserLocator(page, refreshedMenuItem, paths, deadline, mutationState);
6578
+ }
6579
+ async function findChatGPTUploadMenuItem(page, addPhotosFilesLabels, deadline) {
6580
+ const pattern = new RegExp(addPhotosFilesLabels.map(escapeRegExp).join("|"), "i");
6581
+ const candidate = requiredLocator(page, "div[tabindex='0']").filter?.({ hasText: pattern });
6582
+ return await locatorCount(candidate, deadline) === 1 ? candidate : void 0;
5665
6583
  }
5666
- async function clickFileChooserLocator(page, locator, paths, timeoutMs) {
6584
+ async function clickFileChooserLocator(page, locator, paths, deadline, mutationState) {
5667
6585
  if (locator === void 0) {
5668
6586
  throw new Error("Upload locator was not available.");
5669
6587
  }
@@ -5673,26 +6591,131 @@ async function clickFileChooserLocator(page, locator, paths, timeoutMs) {
5673
6591
  if (typeof locator.click !== "function") {
5674
6592
  throw new Error("Upload locator does not expose click().");
5675
6593
  }
5676
- const chooserPromise = waitForFileChooser(page, timeoutMs);
6594
+ const chooserPromise = waitForFileChooser(page, deadline).then(
6595
+ (chooser2) => ({ ok: true, chooser: chooser2 }),
6596
+ (error) => ({ ok: false, error })
6597
+ );
5677
6598
  try {
5678
- await locator.click({ timeoutMs: Math.min(timeoutMs, 1e4) });
6599
+ await withinNativeAttachmentDeadline(
6600
+ deadline,
6601
+ (timeoutMs) => locator.click({ timeoutMs }),
6602
+ "ChatGPT upload-control click",
6603
+ 1e4
6604
+ );
5679
6605
  } catch (error) {
5680
- await chooserPromise.catch(() => void 0);
6606
+ await chooserPromise;
5681
6607
  throw error;
5682
6608
  }
5683
- const chooser = await chooserPromise;
5684
- await validateChooserMultiplicity(chooser, paths);
6609
+ const chooserResult = await chooserPromise;
6610
+ if (!chooserResult.ok) {
6611
+ throw chooserResult.error;
6612
+ }
6613
+ const chooser = chooserResult.chooser;
6614
+ await validateChooserTarget(chooser, deadline, "scoped-composer-trigger");
6615
+ await withinAttachmentDeadline(
6616
+ deadline,
6617
+ () => validateChooserMultiplicity(chooser, paths),
6618
+ "File-chooser multiplicity validation"
6619
+ );
5685
6620
  try {
5686
- await chooser.setFiles(paths);
6621
+ mutationState.handoffStarted = true;
6622
+ await withinNativeAttachmentDeadline(
6623
+ deadline,
6624
+ (timeoutMs) => chooser.setFiles(paths, { timeoutMs }),
6625
+ "File-chooser handoff",
6626
+ 15e3
6627
+ );
5687
6628
  } catch (error) {
5688
6629
  throw new Error(`fileChooser.setFiles failed. ${error instanceof Error ? error.message : String(error)}`);
5689
6630
  }
5690
6631
  }
5691
- async function waitForFileChooser(page, timeoutMs) {
5692
- const rawChooser = await page.waitForEvent?.("filechooser", {
5693
- timeout: timeoutMs,
5694
- timeoutMs
5695
- });
6632
+ async function clickHiddenFileInputWithCdp(page, paths, deadline, mutationState) {
6633
+ if (typeof page.waitForEvent !== "function") {
6634
+ throw new Error("The active browser page does not expose file chooser events.");
6635
+ }
6636
+ const rawCapability = await withinAttachmentDeadline(
6637
+ deadline,
6638
+ () => Promise.resolve(page.capabilities?.get?.("cdp")),
6639
+ "Scoped CDP upload capability resolution"
6640
+ );
6641
+ const cdp = rawCapability;
6642
+ if (typeof cdp?.send !== "function") {
6643
+ throw new Error("The active browser page does not expose the scoped CDP capability needed to click a hidden file input.");
6644
+ }
6645
+ const chooserPromise = waitForFileChooser(page, deadline).then(
6646
+ (chooser) => ({ ok: true, chooser }),
6647
+ (error) => ({ ok: false, error })
6648
+ );
6649
+ try {
6650
+ const evaluation = await withinNativeAttachmentDeadline(deadline, (timeoutMs) => Promise.resolve(cdp.send("Runtime.evaluate", {
6651
+ expression: `(() => {
6652
+ const visible = element => {
6653
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']")) return false;
6654
+ const style = getComputedStyle(element);
6655
+ const rect = element.getBoundingClientRect();
6656
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0"
6657
+ && (rect.width > 0 || rect.height > 0);
6658
+ };
6659
+ const textboxes = [...document.querySelectorAll("textarea, [contenteditable='true'], [role='textbox']")].filter(visible);
6660
+ const composers = [...new Set(textboxes.map(textbox =>
6661
+ textbox.closest("form")
6662
+ ?? textbox.closest("[data-testid*='composer' i]")
6663
+ ?? textbox.closest("[aria-label*='composer' i]")
6664
+ ?? textbox.closest("[class*='composer' i]")
6665
+ ).filter(Boolean))];
6666
+ if (composers.length !== 1) return { ok: false, reason: "active composer was not unique" };
6667
+ const all = [...composers[0].querySelectorAll("input[type='file']")]
6668
+ .filter(input => !input.disabled && input.getAttribute("aria-disabled") !== "true");
6669
+ const preferred = all.filter(input => input.id === "upload-files");
6670
+ const nonImage = all.filter(input => input.getAttribute("accept") !== "image/*");
6671
+ const candidates = preferred.length ? preferred : nonImage.length ? nonImage : all;
6672
+ if (candidates.length !== 1) return { ok: false, reason: "active composer file input was not unique" };
6673
+ candidates[0].click();
6674
+ return { ok: true };
6675
+ })()`,
6676
+ userGesture: true,
6677
+ awaitPromise: true,
6678
+ returnByValue: true
6679
+ }, {
6680
+ timeoutMs
6681
+ })), "Scoped CDP file-input click", 1e4);
6682
+ const wrappedValue = evaluation?.result?.value;
6683
+ const value = wrappedValue ?? evaluation;
6684
+ if (value?.ok !== true) {
6685
+ throw new Error(`Scoped CDP file-input click was refused: ${value?.reason ?? "no success result"}.`);
6686
+ }
6687
+ } catch (error) {
6688
+ await chooserPromise;
6689
+ throw error;
6690
+ }
6691
+ const chooserResult = await chooserPromise;
6692
+ if (!chooserResult.ok) {
6693
+ throw chooserResult.error;
6694
+ }
6695
+ await validateChooserTarget(chooserResult.chooser, deadline, "scoped-cdp-input");
6696
+ await withinAttachmentDeadline(
6697
+ deadline,
6698
+ () => validateChooserMultiplicity(chooserResult.chooser, paths),
6699
+ "File-chooser multiplicity validation"
6700
+ );
6701
+ try {
6702
+ mutationState.handoffStarted = true;
6703
+ await withinNativeAttachmentDeadline(
6704
+ deadline,
6705
+ (timeoutMs) => chooserResult.chooser.setFiles(paths, { timeoutMs }),
6706
+ "File-chooser handoff",
6707
+ 15e3
6708
+ );
6709
+ } catch (error) {
6710
+ throw new Error(`fileChooser.setFiles failed. ${error instanceof Error ? error.message : String(error)}`);
6711
+ }
6712
+ }
6713
+ async function waitForFileChooser(page, deadline) {
6714
+ const rawChooser = await withinNativeAttachmentDeadline(
6715
+ deadline,
6716
+ (timeoutMs) => Promise.resolve(page.waitForEvent?.("filechooser", { timeoutMs })),
6717
+ "File-chooser event wait"
6718
+ );
5696
6719
  if (!isFileChooserLike(rawChooser)) {
5697
6720
  throw new Error("File chooser event did not return a setFiles-capable chooser.");
5698
6721
  }
@@ -5710,12 +6733,116 @@ async function validateChooserMultiplicity(chooser, paths) {
5710
6733
  function isFileChooserLike(value) {
5711
6734
  return value !== null && typeof value === "object" && typeof value.setFiles === "function";
5712
6735
  }
5713
- async function locatorCount(locator) {
5714
- if (locator === void 0 || typeof locator.count !== "function") {
6736
+ async function validateChooserTarget(chooser, deadline, _triggerProof) {
6737
+ if (typeof chooser.element !== "function") {
6738
+ return;
6739
+ }
6740
+ const element = await withinAttachmentDeadline(
6741
+ deadline,
6742
+ () => Promise.resolve(chooser.element()),
6743
+ "File-chooser backing-input resolution"
6744
+ );
6745
+ if (typeof element?.evaluate !== "function") {
6746
+ throw new Error("The file chooser backing input could not be inspected safely.");
6747
+ }
6748
+ const scoped = await withinNativeAttachmentDeadline(deadline, (timeoutMs) => element.evaluate((candidate) => {
6749
+ const visible = (node) => {
6750
+ if (node.hidden || node.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
6751
+ const style = window.getComputedStyle(node);
6752
+ const rect = node.getBoundingClientRect();
6753
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && style.pointerEvents !== "none" && (rect.width > 0 || rect.height > 0);
6754
+ };
6755
+ const textboxes = Array.from(document.querySelectorAll(
6756
+ "textarea, [contenteditable='true'], [role='textbox']"
6757
+ )).filter(visible);
6758
+ 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))];
6759
+ if (composers.length !== 1 || !composers[0].contains(candidate)) return false;
6760
+ const all = Array.from(composers[0].querySelectorAll("input[type='file']")).filter((input) => !input.disabled && input.getAttribute("aria-disabled") !== "true");
6761
+ const preferred = all.filter((input) => input.id === "upload-files");
6762
+ const nonImage = all.filter((input) => input.getAttribute("accept") !== "image/*");
6763
+ const resolved = preferred.length > 0 ? preferred : nonImage.length > 0 ? nonImage : all;
6764
+ return resolved.length === 1 && resolved[0] === candidate;
6765
+ }, void 0, { timeoutMs }), "File-chooser active-composer identity check", 2e3);
6766
+ if (!scoped) {
6767
+ throw new Error("The file chooser backing input was not the unique active-composer upload target.");
6768
+ }
6769
+ }
6770
+ async function locatorCount(locator, deadline) {
6771
+ if (locator === void 0) {
5715
6772
  return 0;
5716
6773
  }
6774
+ if (deadline !== void 0 && typeof locator.allTextContents === "function") {
6775
+ const values = await withinNativeAttachmentDeadline(
6776
+ deadline,
6777
+ (timeoutMs) => locator.allTextContents({ timeoutMs }),
6778
+ "Locator enumeration",
6779
+ 2e3
6780
+ );
6781
+ return values.length;
6782
+ }
6783
+ if (typeof locator.count !== "function") return 0;
6784
+ if (deadline !== void 0) {
6785
+ return withinAttachmentDeadline(deadline, () => locator.count(), "Locator enumeration");
6786
+ }
5717
6787
  return locator.count();
5718
6788
  }
6789
+ async function locatorIsRendered(locator, deadline) {
6790
+ if (typeof locator.evaluate !== "function") return false;
6791
+ return withinNativeAttachmentDeadline(deadline, (timeoutMs) => locator.evaluate((element) => {
6792
+ const node = element;
6793
+ if (node.hidden || node.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
6794
+ const style = window.getComputedStyle(node);
6795
+ const rect = node.getBoundingClientRect();
6796
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && style.pointerEvents !== "none" && (rect.width > 0 || rect.height > 0);
6797
+ }, void 0, { timeoutMs }), "Active-composer file-input visibility check", 1e3);
6798
+ }
6799
+ function attachmentBudget(deadline) {
6800
+ const budget = remainingMs(deadline);
6801
+ if (budget <= 0) {
6802
+ throw new AttachmentDeadlineError("Attachment operation");
6803
+ }
6804
+ return budget;
6805
+ }
6806
+ var AttachmentDeadlineError = class extends Error {
6807
+ constructor(label) {
6808
+ super(`${label} exceeded the single attachment deadline.`);
6809
+ this.name = "AttachmentDeadlineError";
6810
+ }
6811
+ };
6812
+ async function withinAttachmentDeadline(deadline, operation, label) {
6813
+ const budget = attachmentBudget(deadline);
6814
+ try {
6815
+ return await withTimeout(operation(), budget, `${label} exceeded the single attachment deadline.`);
6816
+ } catch (error) {
6817
+ if (remainingMs(deadline) <= 0 || error instanceof Error && error.message.includes("exceeded the single attachment deadline")) {
6818
+ throw new AttachmentDeadlineError(label);
6819
+ }
6820
+ throw error;
6821
+ }
6822
+ }
6823
+ async function withinNativeAttachmentDeadline(deadline, operation, label, capMs = Number.POSITIVE_INFINITY) {
6824
+ const timeoutMs = Math.min(capMs, attachmentBudget(deadline));
6825
+ try {
6826
+ return await operation(timeoutMs);
6827
+ } catch (error) {
6828
+ if (remainingMs(deadline) <= 0) {
6829
+ throw new AttachmentDeadlineError(label);
6830
+ }
6831
+ throw error;
6832
+ }
6833
+ }
6834
+ async function attachmentDelay(_page, deadline, requestedMs) {
6835
+ const budget = attachmentBudget(deadline);
6836
+ const delayMs = Math.min(Math.max(0, requestedMs), Math.max(0, budget - 1));
6837
+ if (delayMs <= 0) {
6838
+ if (requestedMs > 0) throw new AttachmentDeadlineError("Attachment settling delay");
6839
+ return;
6840
+ }
6841
+ await new Promise((resolve3) => setTimeout(resolve3, delayMs));
6842
+ }
6843
+ async function attachmentContext(page, _deadline) {
6844
+ return contextFromPage(page, {}, { minimal: true });
6845
+ }
5719
6846
  async function downloadLatestFile(env, args) {
5720
6847
  const boot = await ensurePage(env);
5721
6848
  if (!boot.ok) {
@@ -5806,7 +6933,8 @@ async function tryGeneratedFilePreviewDownload(page, args) {
5806
6933
  }
5807
6934
  const assistant = assistantMessages.nth?.(selected.assistantIndex) ?? assistantMessages;
5808
6935
  const role = selected.tag === "button" ? "button" : "link";
5809
- const affordance = assistant.getByRole?.(role, { name: selected.filename, exact: true }) ?? assistant.locator?.(`${selected.tag}[aria-label="${escapeCssAttribute(selected.filename)}"]`);
6936
+ const controlLabel = selected.controlLabel ?? selected.filename;
6937
+ const affordance = assistant.getByRole?.(role, { name: controlLabel, exact: true }) ?? assistant.locator?.(`${selected.tag}[aria-label="${escapeCssAttribute(controlLabel)}"]`);
5810
6938
  const affordanceCount = await locatorCountWithTimeout(
5811
6939
  affordance,
5812
6940
  localGuardTimeout(timeoutMs, 5e3),
@@ -5826,8 +6954,14 @@ async function tryGeneratedFilePreviewDownload(page, args) {
5826
6954
  return resultOk(downloaded2, await contextFromPage(page));
5827
6955
  }
5828
6956
  await affordance.click({ timeoutMs: localGuardTimeout(timeoutMs, 1e4) });
5829
- const preview = requiredLocator(page, `section[aria-label="${escapeCssAttribute(selected.filename)}"]`);
5830
- const download = await waitForPreviewDownloadControl(page, preview, timeoutMs);
6957
+ const labelledPreview = requiredLocator(page, `section[aria-label="${escapeCssAttribute(selected.filename)}"]`);
6958
+ const workbookPreviews = requiredLocator(page, "section[data-testid^='popcorn-']");
6959
+ const workbookPreview = workbookPreviews.filter?.({ hasText: selected.filename }) ?? workbookPreviews;
6960
+ const download = await waitForPreviewDownloadControl(
6961
+ page,
6962
+ [labelledPreview, workbookPreview],
6963
+ timeoutMs
6964
+ );
5831
6965
  if (download === void 0) {
5832
6966
  throw new Error(`The artifact preview for ${selected.filename} did not expose a visible Download control.`);
5833
6967
  }
@@ -5846,7 +6980,7 @@ async function tryGeneratedFilePreviewDownload(page, args) {
5846
6980
  async function inspectGeneratedFileAffordances(page, timeoutMs) {
5847
6981
  if (typeof page.evaluate === "function") {
5848
6982
  const fromDom = await withTimeout(
5849
- page.evaluate(() => {
6983
+ page.evaluate((downloadLabels) => {
5850
6984
  const visible = (element) => {
5851
6985
  let current = element;
5852
6986
  while (current !== null) {
@@ -5860,14 +6994,32 @@ async function inspectGeneratedFileAffordances(page, timeoutMs) {
5860
6994
  return true;
5861
6995
  };
5862
6996
  const fileLike = (value) => /^[^\\/\r\n]{1,255}\.[a-z0-9][a-z0-9._-]{0,15}$/i.test(value);
6997
+ const normalizedFilename = (value) => {
6998
+ const trimmed = value.trim();
6999
+ const lowered = trimmed.toLocaleLowerCase();
7000
+ const prefix = downloadLabels.map((label) => label.trim()).filter(Boolean).sort((left, right) => right.length - left.length).find((label) => lowered.startsWith(`${label.toLocaleLowerCase()} `));
7001
+ return prefix === void 0 ? trimmed : trimmed.slice(prefix.length).trim();
7002
+ };
5863
7003
  const assistants = Array.from(document.querySelectorAll("[data-message-author-role='assistant']"));
5864
- return assistants.flatMap((assistant, assistantIndex) => Array.from(assistant.querySelectorAll("button[aria-label], a[download], a[href*='/backend-api/files/']")).filter(visible).map((element) => ({
5865
- assistantIndex,
5866
- filename: (element.getAttribute("aria-label") ?? element.textContent ?? "").trim(),
5867
- tag: element.tagName.toLocaleLowerCase(),
5868
- text: (element.textContent ?? "").trim()
5869
- })).filter((item) => (item.tag === "button" || item.tag === "a") && fileLike(item.filename) && item.filename === item.text).map(({ assistantIndex: assistantIndex2, filename, tag }) => ({ assistantIndex: assistantIndex2, filename, tag })));
5870
- }),
7004
+ return assistants.flatMap(
7005
+ (assistant, assistantIndex) => Array.from(assistant.querySelectorAll("button[aria-label], a[download], a[href*='/backend-api/files/']")).filter(visible).map((element) => {
7006
+ const controlLabel = (element.getAttribute("aria-label") ?? element.textContent ?? "").trim();
7007
+ const text = (element.textContent ?? "").trim();
7008
+ return {
7009
+ assistantIndex,
7010
+ filename: normalizedFilename(controlLabel),
7011
+ controlLabel,
7012
+ tag: element.tagName.toLocaleLowerCase(),
7013
+ textFilename: normalizedFilename(text)
7014
+ };
7015
+ }).filter((item) => (item.tag === "button" || item.tag === "a") && fileLike(item.filename) && item.filename === item.textFilename).map(({ assistantIndex: index, filename, controlLabel, tag }) => ({
7016
+ assistantIndex: index,
7017
+ filename,
7018
+ ...controlLabel === filename ? {} : { controlLabel },
7019
+ tag
7020
+ }))
7021
+ );
7022
+ }, [...localeLabels.download]),
5871
7023
  timeoutMs,
5872
7024
  "Timed out while inspecting generated-file buttons."
5873
7025
  ).catch(() => void 0);
@@ -5883,14 +7035,30 @@ async function inspectGeneratedFileAffordances(page, timeoutMs) {
5883
7035
  const buttonPattern = /<(button|a)\b[^>]*\baria-label=(['"])(.*?)\2[^>]*>([\s\S]*?)<\/\1>/gi;
5884
7036
  let match;
5885
7037
  while ((match = buttonPattern.exec(html)) !== null) {
5886
- const filename = decodeBasicHtml(match[3] ?? "").trim();
7038
+ const controlLabel = decodeBasicHtml(match[3] ?? "").trim();
5887
7039
  const text = decodeBasicHtml((match[4] ?? "").replace(/<[^>]+>/g, " ")).replace(/\s+/g, " ").trim();
5888
- if (/^[^\\/\r\n]{1,255}\.[a-z0-9][a-z0-9._-]{0,15}$/i.test(filename) && filename === text) {
5889
- candidates.push({ assistantIndex: 0, filename, tag: (match[1] ?? "button").toLocaleLowerCase() });
7040
+ const filename = normalizeGeneratedFileControlLabel(controlLabel);
7041
+ const textFilename = normalizeGeneratedFileControlLabel(text);
7042
+ if (/^[^\\/\r\n]{1,255}\.[a-z0-9][a-z0-9._-]{0,15}$/i.test(filename) && filename === textFilename) {
7043
+ candidates.push({
7044
+ assistantIndex: 0,
7045
+ filename,
7046
+ ...controlLabel === filename ? {} : { controlLabel },
7047
+ tag: (match[1] ?? "button").toLocaleLowerCase()
7048
+ });
5890
7049
  }
5891
7050
  }
5892
7051
  return candidates;
5893
7052
  }
7053
+ function normalizeGeneratedFileControlLabel(value) {
7054
+ return stripLocalizedDownloadPrefix(value, localeLabels.download);
7055
+ }
7056
+ function stripLocalizedDownloadPrefix(value, labels) {
7057
+ const trimmed = value.trim();
7058
+ const lowered = trimmed.toLocaleLowerCase();
7059
+ const prefix = labels.map((label) => label.trim()).filter(Boolean).sort((left, right) => right.length - left.length).find((label) => lowered.startsWith(`${label.toLocaleLowerCase()} `));
7060
+ return prefix === void 0 ? trimmed : trimmed.slice(prefix.length).trim();
7061
+ }
5894
7062
  function selectGeneratedFileAffordance(candidates, args) {
5895
7063
  let scoped = candidates;
5896
7064
  const from = args.from;
@@ -5912,13 +7080,15 @@ function filenameMatches(filename, pattern) {
5912
7080
  return filename.toLocaleLowerCase().includes(pattern.toLocaleLowerCase());
5913
7081
  }
5914
7082
  }
5915
- async function waitForPreviewDownloadControl(page, preview, timeoutMs) {
5916
- const deadline = Date.now() + Math.min(timeoutMs, 15e3);
7083
+ async function waitForPreviewDownloadControl(page, previews, timeoutMs) {
7084
+ const deadline = Date.now() + Math.min(timeoutMs, 6e4);
5917
7085
  while (Date.now() < deadline) {
5918
- for (const label of localeLabels.download) {
5919
- const control = preview.getByRole?.("button", { name: label, exact: true }) ?? preview.locator?.(`button[aria-label="${escapeCssAttribute(label)}"]`);
5920
- if (await locatorCountWithTimeout(control, localGuardTimeout(timeoutMs, 2e3), "artifact_preview_download_count_timeout") === 1) {
5921
- return control;
7086
+ for (const preview of previews) {
7087
+ for (const label of localeLabels.download) {
7088
+ const control = preview.getByRole?.("button", { name: label, exact: true }) ?? preview.locator?.(`button[aria-label="${escapeCssAttribute(label)}"]`);
7089
+ if (await locatorCountWithTimeout(control, localGuardTimeout(timeoutMs, 2e3), "artifact_preview_download_count_timeout") === 1) {
7090
+ return control;
7091
+ }
5922
7092
  }
5923
7093
  }
5924
7094
  if (typeof page.waitForTimeout === "function") {
@@ -5935,26 +7105,96 @@ function escapeCssAttribute(value) {
5935
7105
  function decodeBasicHtml(value) {
5936
7106
  return value.replace(/&quot;/gi, '"').replace(/&#39;|&apos;/gi, "'").replace(/&lt;/gi, "<").replace(/&gt;/gi, ">").replace(/&amp;/gi, "&");
5937
7107
  }
5938
- async function setHiddenFileInput(page, files) {
5939
- if (page === void 0) {
5940
- throw new Error("No active page is available for file upload.");
7108
+ async function resolveUniqueActiveComposerFileInput(page, deadline) {
7109
+ const candidates = requiredLocator(page, cssSelectors.hiddenFileInputs);
7110
+ if (typeof candidates.count !== "function") {
7111
+ throw new Error("ChatGPT file inputs could not be enumerated safely.");
5941
7112
  }
5942
- const input = requiredLocator(page, cssSelectors.hiddenFileInputs).last?.() ?? requiredLocator(page, cssSelectors.hiddenFileInputs);
7113
+ const count = await locatorCount(candidates, deadline);
7114
+ const eligible = [];
7115
+ for (let index = 0; index < count; index += 1) {
7116
+ const input = count === 1 ? candidates : candidates.nth?.(index);
7117
+ if (input === void 0 || typeof input.evaluate !== "function") continue;
7118
+ const scoped = await withinNativeAttachmentDeadline(deadline, (timeoutMs) => input.evaluate((element) => {
7119
+ const candidate = element;
7120
+ const visible = (node) => {
7121
+ if (node.hidden || node.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
7122
+ const style = window.getComputedStyle(node);
7123
+ const rect = node.getBoundingClientRect();
7124
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && (rect.width > 0 || rect.height > 0);
7125
+ };
7126
+ const textboxes = Array.from(document.querySelectorAll(
7127
+ "textarea, [contenteditable='true'], [role='textbox']"
7128
+ )).filter(visible);
7129
+ 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))];
7130
+ if (composers.length !== 1 || !composers[0].contains(candidate)) return false;
7131
+ const all = Array.from(composers[0].querySelectorAll("input[type='file']")).filter((input2) => !input2.disabled && input2.getAttribute("aria-disabled") !== "true");
7132
+ const preferred = all.filter((input2) => input2.id === "upload-files");
7133
+ const nonImage = all.filter((input2) => input2.getAttribute("accept") !== "image/*");
7134
+ const resolved = preferred.length > 0 ? preferred : nonImage.length > 0 ? nonImage : all;
7135
+ return resolved.length === 1 && resolved[0] === candidate;
7136
+ }, void 0, { timeoutMs }), `File-input ${index + 1} scope check`, 2e3);
7137
+ if (scoped) eligible.push(input);
7138
+ }
7139
+ if (eligible.length !== 1) {
7140
+ throw new Error("The active browser exposes no sanctioned native file handoff because the active composer file input was not uniquely available.");
7141
+ }
7142
+ return eligible[0];
7143
+ }
7144
+ async function assertControlInUniqueActiveComposer(control, deadline, label) {
7145
+ if (control === void 0 || typeof control.evaluate !== "function") {
7146
+ throw new Error(`${label} could not be scoped to the active composer.`);
7147
+ }
7148
+ const scoped = await withinNativeAttachmentDeadline(deadline, (timeoutMs) => control.evaluate((element) => {
7149
+ const visible = (node) => {
7150
+ if (node.hidden || node.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
7151
+ const style = window.getComputedStyle(node);
7152
+ const rect = node.getBoundingClientRect();
7153
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && (rect.width > 0 || rect.height > 0);
7154
+ };
7155
+ const textboxes = Array.from(document.querySelectorAll(
7156
+ "textarea, [contenteditable='true'], [role='textbox']"
7157
+ )).filter(visible);
7158
+ 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))];
7159
+ return composers.length === 1 && composers[0].contains(element);
7160
+ }, void 0, { timeoutMs }), `${label} scope check`, 2e3);
7161
+ if (!scoped) throw new Error(`${label} was outside the unique active composer.`);
7162
+ }
7163
+ async function setResolvedFileInput(input, files, deadline, mutationState) {
5943
7164
  if (typeof input.setInputFiles !== "function") {
5944
- await setFilesViaDomDataTransfer(page, files);
5945
- return;
5946
- }
5947
- await input.setInputFiles(files.map((file) => file.path));
7165
+ throw new Error("The active browser exposes no sanctioned native file handoff for ChatGPT's file input.");
7166
+ }
7167
+ mutationState.handoffStarted = true;
7168
+ await withinNativeAttachmentDeadline(
7169
+ deadline,
7170
+ (timeoutMs) => input.setInputFiles(files.map((file) => file.path), { timeoutMs }),
7171
+ "Direct file-input handoff",
7172
+ 15e3
7173
+ );
5948
7174
  }
5949
- async function readBrowserInputDiagnostic(page) {
7175
+ async function readBrowserInputDiagnostic(page, timeoutMs) {
5950
7176
  if (typeof page.evaluate !== "function") {
5951
7177
  return void 0;
5952
7178
  }
5953
7179
  return page.evaluate(() => {
5954
- const input = document.querySelector("#upload-files") || document.querySelector("input[type='file']:not([accept='image/*'])") || document.querySelector("input[type='file']");
5955
- if (!input) {
5956
- return { files: [] };
5957
- }
7180
+ const visible = (element) => {
7181
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
7182
+ const style = window.getComputedStyle(element);
7183
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
7184
+ const rect = element.getBoundingClientRect();
7185
+ return rect.width > 0 || rect.height > 0;
7186
+ };
7187
+ const textboxes = Array.from(document.querySelectorAll(
7188
+ "textarea, [contenteditable='true'], [role='textbox']"
7189
+ )).filter(visible);
7190
+ 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))];
7191
+ if (composers.length !== 1) return void 0;
7192
+ const allInputs = Array.from(composers[0].querySelectorAll("input[type='file']")).filter((input2) => !input2.disabled && input2.getAttribute("aria-disabled") !== "true");
7193
+ const preferred = allInputs.filter((input2) => input2.id === "upload-files");
7194
+ const nonImage = allInputs.filter((input2) => input2.getAttribute("accept") !== "image/*");
7195
+ const inputs = preferred.length > 0 ? preferred : nonImage.length > 0 ? nonImage : allInputs;
7196
+ if (inputs.length !== 1) return void 0;
7197
+ const input = inputs[0];
5958
7198
  return {
5959
7199
  files: Array.from(input.files ?? []).map((file) => {
5960
7200
  const diagnostic2 = {
@@ -5967,46 +7207,10 @@ async function readBrowserInputDiagnostic(page) {
5967
7207
  if (file.lastModified !== 0) {
5968
7208
  diagnostic2.lastModified = file.lastModified;
5969
7209
  }
5970
- return diagnostic2;
5971
- })
5972
- };
5973
- });
5974
- }
5975
- async function setFilesViaDomDataTransfer(page, files) {
5976
- const totalBytes = files.reduce((sum, file) => sum + file.bytes, 0);
5977
- const maxInlineBytes = 25 * 1024 * 1024;
5978
- if (totalBytes > maxInlineBytes) {
5979
- throw new Error(`No file chooser or setInputFiles support is available for large uploads. ${CODEX_UPLOAD_PERMISSION_FIX} ${CHROME_FILE_URL_PERMISSION_FIX}`);
5980
- }
5981
- if (typeof page.evaluate !== "function") {
5982
- 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}`);
5983
- }
5984
- const payload = await Promise.all(files.map(async (file) => ({
5985
- name: file.name,
5986
- bytesBase64: (await readFile(file.path)).toString("base64"),
5987
- type: guessMimeType(file.name)
5988
- })));
5989
- await page.evaluate(
5990
- async (payload2) => {
5991
- const input = document.querySelector("#upload-files") || document.querySelector("input[type='file']:not([accept='image/*'])") || document.querySelector("input[type='file']");
5992
- if (!input) {
5993
- throw new Error("No ChatGPT file input found in the DOM.");
5994
- }
5995
- const dataTransfer = new DataTransfer();
5996
- for (const item of payload2) {
5997
- const binary = atob(item.bytesBase64);
5998
- const bytes = new Uint8Array(binary.length);
5999
- for (let index = 0; index < binary.length; index += 1) {
6000
- bytes[index] = binary.charCodeAt(index);
6001
- }
6002
- dataTransfer.items.add(new File([bytes], item.name, { type: item.type }));
6003
- }
6004
- input.files = dataTransfer.files;
6005
- input.dispatchEvent(new Event("input", { bubbles: true }));
6006
- input.dispatchEvent(new Event("change", { bubbles: true }));
6007
- },
6008
- payload
6009
- );
7210
+ return diagnostic2;
7211
+ })
7212
+ };
7213
+ }, void 0, { timeoutMs });
6010
7214
  }
6011
7215
  function guessMimeType(name) {
6012
7216
  if (/\.txt$/i.test(name)) return "text/plain";
@@ -6016,9 +7220,17 @@ function guessMimeType(name) {
6016
7220
  if (/\.md$/i.test(name)) return "text/markdown";
6017
7221
  return "application/octet-stream";
6018
7222
  }
6019
- function isUploadBridgeBlocker(error) {
7223
+ function isUploadPermissionBlocker(error) {
7224
+ const message = error instanceof Error ? error.message : String(error);
7225
+ 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);
7226
+ }
7227
+ function isUploadTransportFailure(error) {
7228
+ const message = error instanceof Error ? error.message : String(error);
7229
+ return /native pipe closed before response|browser bridge.*(?:closed|disconnect)|connection (?:was )?closed|target page, context or browser has been closed/i.test(message);
7230
+ }
7231
+ function isUploadPathFailure(error) {
6020
7232
  const message = error instanceof Error ? error.message : String(error);
6021
- 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);
7233
+ return /No ChatGPT upload path completed/i.test(message);
6022
7234
  }
6023
7235
  function uploadPermissionMessage(error) {
6024
7236
  const message = error instanceof Error ? error.message : String(error);
@@ -7013,6 +8225,8 @@ var REQUIRED_LOCALE_KEYS = [
7013
8225
  ];
7014
8226
  var REQUIRED_TOOL_IDS = ["web_search", "deep_research", "create_image"];
7015
8227
  var REQUIRED_MODE_OPTION_IDS = ["latest", "instant", "thinking", "extended", "medium", "high", "extraHigh", "pro"];
8228
+ var REQUIRED_CONFIGURATION_AXIS_IDS = ["power", "model", "intelligence", "effort", "speed", "advanced"];
8229
+ var REQUIRED_CONFIGURATION_OPTION_IDS = ["instant", "light", "medium", "high", "extraHigh", "max", "ultra", "pro", "standard", "fast"];
7016
8230
  async function doctor(env, args = {}) {
7017
8231
  const wanted = args.check ?? DEFAULT_CHECKS;
7018
8232
  const checks = {};
@@ -7213,8 +8427,12 @@ function localizationCheck(env) {
7213
8427
  const requiredKeysMissing = REQUIRED_LOCALE_KEYS.filter((key) => localeLabels[key].length === 0);
7214
8428
  const missingToolIds = REQUIRED_TOOL_IDS.filter((id2) => (localeLabels.tools[id2]?.length ?? 0) === 0);
7215
8429
  const missingModeOptionIds = REQUIRED_MODE_OPTION_IDS.filter((id2) => (localeLabels.modeOptions[id2]?.length ?? 0) === 0);
8430
+ const missingConfigurationAxisIds = REQUIRED_CONFIGURATION_AXIS_IDS.filter((id2) => (localeLabels.configurationAxes[id2]?.length ?? 0) === 0);
8431
+ const missingConfigurationOptionIds = REQUIRED_CONFIGURATION_OPTION_IDS.filter((id2) => (localeLabels.configurationOptions[id2]?.length ?? 0) === 0);
7216
8432
  const toolIds = Object.keys(localeLabels.tools);
7217
8433
  const modeOptionIds = Object.keys(localeLabels.modeOptions);
8434
+ const configurationAxisIds = Object.keys(localeLabels.configurationAxes);
8435
+ const configurationOptionIds = Object.keys(localeLabels.configurationOptions);
7218
8436
  const proAliases = [...localeLabels.modeOptions.pro];
7219
8437
  const supportsProExtendedAlias = proAliases.some((alias) => /pro\s*(?:•\s*)?extended/i.test(alias)) && proAliases.some((alias) => /extended\s+pro/i.test(alias));
7220
8438
  const runningStateLocalizationSupport = runningStateSupport();
@@ -7226,15 +8444,19 @@ function localizationCheck(env) {
7226
8444
  registeredLocaleCount: localeCoverageSummary.registeredLocaleCount,
7227
8445
  nonEnglishLocaleCount: localeCoverageSummary.nonEnglishLocaleCount
7228
8446
  };
7229
- 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";
7230
- 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);
8447
+ 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";
8448
+ 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);
7231
8449
  const details = {
7232
8450
  englishCanonicalPresent,
7233
8451
  requiredKeysMissing,
7234
8452
  missingToolIds,
7235
8453
  missingModeOptionIds,
8454
+ missingConfigurationAxisIds,
8455
+ missingConfigurationOptionIds,
7236
8456
  toolIds,
7237
8457
  modeOptionIds,
8458
+ configurationAxisIds,
8459
+ configurationOptionIds,
7238
8460
  proAliases,
7239
8461
  supportsProExtendedAlias,
7240
8462
  runningStateLabelCoverage,
@@ -7242,7 +8464,7 @@ function localizationCheck(env) {
7242
8464
  pageAvailable: env.page !== void 0,
7243
8465
  runtimeSelectorCoverage: "registry_only_stage_2"
7244
8466
  };
7245
- if (englishCanonicalPresent && requiredKeysMissing.length === 0 && missingToolIds.length === 0 && missingModeOptionIds.length === 0) {
8467
+ if (englishCanonicalPresent && requiredKeysMissing.length === 0 && missingToolIds.length === 0 && missingModeOptionIds.length === 0 && missingConfigurationAxisIds.length === 0 && missingConfigurationOptionIds.length === 0) {
7246
8468
  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";
7247
8469
  return unknown(`The locale registry is loaded; localized runtime selector coverage is registry-only in Stage 2 and ${runningStateMessage}.`, void 0, details);
7248
8470
  }
@@ -7358,48 +8580,83 @@ import { createHash as createHash2 } from "node:crypto";
7358
8580
 
7359
8581
  // src/dom/generation-state.ts
7360
8582
  var EMPTY_GENERATION_STATE = {
8583
+ observed: false,
7361
8584
  active: false,
7362
8585
  stopped: false,
7363
8586
  signals: []
7364
8587
  };
7365
- async function readAssistantGenerationState(page) {
8588
+ async function readAssistantGenerationState(page, options = {}) {
8589
+ const expiresAtMs = options.timeoutMs === void 0 ? void 0 : Date.now() + Math.max(1, options.timeoutMs);
7366
8590
  if (typeof page.evaluate === "function") {
7367
- return page.evaluate((args) => {
7368
- const normalize = (value) => (value ?? "").trim().toLowerCase();
7369
- const isVisible = (element) => {
7370
- const style = window.getComputedStyle(element);
7371
- return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && element.getAttribute("aria-hidden") !== "true";
7372
- };
7373
- const visibleButtons = Array.from(document.querySelectorAll("button")).filter((button) => isVisible(button) && button.disabled !== true && button.getAttribute("aria-disabled") !== "true");
7374
- const buttonTexts = visibleButtons.map((button) => [
7375
- button.innerText,
7376
- button.textContent,
7377
- button.getAttribute("aria-label"),
7378
- button.getAttribute("title")
7379
- ].map(normalize).filter(Boolean).join(" ")).filter(Boolean);
7380
- const bodyText = normalize(document.body?.innerText);
7381
- const haystacks = [bodyText, ...buttonTexts];
7382
- const matchingSignals = (phrases) => haystacks.flatMap(
7383
- (text) => phrases.map((phrase) => phrase.toLowerCase()).filter((phrase) => text.includes(phrase))
7384
- );
7385
- const activeSignals = matchingSignals(args.stop);
7386
- const stoppedSignals = matchingSignals(args.stopped);
7387
- return {
7388
- active: activeSignals.length > 0,
7389
- stopped: stoppedSignals.length > 0,
7390
- signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals, ...buttonTexts.filter((text) => /stop|cancel|stopped|answering|thinking/i.test(text))])].slice(0, 5)
7391
- };
7392
- }, {
7393
- stop: [...localeLabels.stopControl],
7394
- stopped: [...localeLabels.stoppedAssistant]
7395
- }).catch(() => EMPTY_GENERATION_STATE);
8591
+ const evaluateOptions = remainingGenerationStateOptions(expiresAtMs);
8592
+ if (expiresAtMs !== void 0 && evaluateOptions === void 0) return EMPTY_GENERATION_STATE;
8593
+ try {
8594
+ return await page.evaluate((args) => {
8595
+ const normalize = (value) => (value ?? "").replace(/\s+/g, " ").trim().toLowerCase();
8596
+ const isVisible = (element) => {
8597
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) {
8598
+ return false;
8599
+ }
8600
+ const style = window.getComputedStyle(element);
8601
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none") {
8602
+ return false;
8603
+ }
8604
+ const rect = element.getBoundingClientRect();
8605
+ return (rect.width > 0 || rect.height > 0) && style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0";
8606
+ };
8607
+ const values = (element) => [
8608
+ element.getAttribute("aria-label"),
8609
+ element.getAttribute("title"),
8610
+ element.innerText,
8611
+ element.textContent
8612
+ ].map(normalize).filter(Boolean);
8613
+ const matchingLabels2 = (element, phrases) => {
8614
+ const elementValues = values(element);
8615
+ return phrases.filter((phrase) => elementValues.includes(normalize(phrase)));
8616
+ };
8617
+ const textboxes = Array.from(document.querySelectorAll(
8618
+ "textarea, [contenteditable='true'], [role='textbox']"
8619
+ )).filter(isVisible);
8620
+ 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))];
8621
+ const isScopedStopControl = (button) => activeComposers.length === 1 && activeComposers[0].contains(button);
8622
+ 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);
8623
+ const activeSignals = [...new Set(visibleStopButtons.flatMap((button) => matchingLabels2(button, args.stop)))];
8624
+ const turns = Array.from(document.querySelectorAll("[data-testid^='conversation-turn']"));
8625
+ const latestAssistant = Array.from(document.querySelectorAll("[data-message-author-role='assistant']")).at(-1);
8626
+ const latestTurn = latestAssistant?.closest("[data-testid^='conversation-turn']") ?? turns.at(-1);
8627
+ const stoppedSignals = latestTurn === void 0 ? [] : [...new Set(Array.from(latestTurn.querySelectorAll(
8628
+ "button, [role='status'], [aria-label], [title], p, span, div"
8629
+ )).filter((element) => isVisible(element)).flatMap((element) => matchingLabels2(element, args.stopped)))];
8630
+ return {
8631
+ observed: true,
8632
+ active: activeSignals.length > 0,
8633
+ stopped: stoppedSignals.length > 0,
8634
+ signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals])].slice(0, 5)
8635
+ };
8636
+ }, {
8637
+ stop: [...localeLabels.stopControl],
8638
+ stopped: [...localeLabels.stoppedAssistant],
8639
+ send: [...localeLabels.sendButton]
8640
+ }, evaluateOptions);
8641
+ } catch {
8642
+ }
7396
8643
  }
7397
8644
  if (typeof page.content === "function") {
7398
- const html = await page.content().catch(() => "");
7399
- return generationStateFromText(html);
8645
+ const contentOptions = remainingGenerationStateOptions(expiresAtMs);
8646
+ if (expiresAtMs !== void 0 && contentOptions === void 0) return EMPTY_GENERATION_STATE;
8647
+ try {
8648
+ return generationStateFromHtml(await page.content(contentOptions));
8649
+ } catch {
8650
+ return EMPTY_GENERATION_STATE;
8651
+ }
7400
8652
  }
7401
8653
  return EMPTY_GENERATION_STATE;
7402
8654
  }
8655
+ function remainingGenerationStateOptions(expiresAtMs) {
8656
+ if (expiresAtMs === void 0) return void 0;
8657
+ const timeoutMs = expiresAtMs - Date.now();
8658
+ return timeoutMs > 0 ? { timeoutMs } : void 0;
8659
+ }
7403
8660
  async function latestAssistantTurnHasResponseActions(page) {
7404
8661
  if (typeof page.evaluate === "function") {
7405
8662
  const scoped = await page.evaluate((phrases) => {
@@ -7436,15 +8693,116 @@ async function latestAssistantTurnHasResponseActions(page) {
7436
8693
  return true;
7437
8694
  }
7438
8695
  }
7439
- function generationStateFromText(text) {
7440
- const normalized = text.toLowerCase();
7441
- const activeSignals = localeLabels.stopControl.filter((phrase) => normalized.includes(phrase.toLowerCase()));
7442
- const stoppedSignals = localeLabels.stoppedAssistant.filter((phrase) => normalized.includes(phrase.toLowerCase()));
8696
+ function generationStateFromHtml(html) {
8697
+ const normalize = (value) => value.replace(/<[^>]*>/g, " ").replace(/&nbsp;/gi, " ").replace(/\s+/g, " ").trim().toLowerCase();
8698
+ 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);
8699
+ const candidateValues = (tag, text) => {
8700
+ const values = [text];
8701
+ for (const attribute of ["aria-label", "title"]) {
8702
+ const match = new RegExp(`\\b${attribute}\\s*=\\s*["']([^"']*)["']`, "i").exec(tag);
8703
+ if (match?.[1] !== void 0) values.push(match[1]);
8704
+ }
8705
+ return values.map(normalize).filter(Boolean);
8706
+ };
8707
+ const exactMatches = (values, phrases) => phrases.filter((phrase) => values.includes(normalize(phrase)));
8708
+ const activeSignals = serializedStopButtonCandidates(html).filter((candidate) => candidate.scoped && !candidate.hidden && !candidate.disabled).flatMap((candidate) => {
8709
+ const values = candidateValues(candidate.attributes, candidate.text);
8710
+ return exactMatches(values, localeLabels.sendButton).length > 0 ? [] : exactMatches(values, localeLabels.stopControl);
8711
+ });
8712
+ const latestTurnStart = Math.max(
8713
+ html.toLowerCase().lastIndexOf('data-message-author-role="assistant"'),
8714
+ html.toLowerCase().lastIndexOf("data-message-author-role='assistant'")
8715
+ );
8716
+ const latestAssistantHtml = latestTurnStart >= 0 ? html.slice(latestTurnStart) : "";
8717
+ const stoppedSignals = [...latestAssistantHtml.matchAll(
8718
+ /<(?:button|p|span|div)\b([^>]*)>([\s\S]*?)<\/(?:button|p|span|div)>/gi
8719
+ )].filter((match) => !isHiddenTag(match[1] ?? "")).flatMap((match) => exactMatches(candidateValues(match[1] ?? "", match[2] ?? ""), localeLabels.stoppedAssistant));
7443
8720
  return {
8721
+ observed: true,
7444
8722
  active: activeSignals.length > 0,
7445
8723
  stopped: stoppedSignals.length > 0,
7446
- signals: [...activeSignals, ...stoppedSignals].slice(0, 5)
8724
+ signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals])].slice(0, 5)
8725
+ };
8726
+ }
8727
+ function serializedStopButtonCandidates(html) {
8728
+ const stack = [];
8729
+ const buttons = [];
8730
+ const activeComposers = /* @__PURE__ */ new Set();
8731
+ const voidElements = /* @__PURE__ */ new Set([
8732
+ "area",
8733
+ "base",
8734
+ "br",
8735
+ "col",
8736
+ "embed",
8737
+ "hr",
8738
+ "img",
8739
+ "input",
8740
+ "link",
8741
+ "meta",
8742
+ "param",
8743
+ "source",
8744
+ "track",
8745
+ "wbr"
8746
+ ]);
8747
+ 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);
8748
+ const hiddenInChain = (node) => {
8749
+ for (let current = node; current !== void 0; current = current.parent) {
8750
+ if (hidden(current.attributes)) return true;
8751
+ }
8752
+ return false;
7447
8753
  };
8754
+ const isComposerMetadata = (node) => /\b(?:data-testid|aria-label|class)\s*=\s*["'][^"']*composer/i.test(node.attributes);
8755
+ const isTextbox = (node) => node.tag === "textarea" || /\bcontenteditable\s*=\s*["']?true/i.test(node.attributes) || /\brole\s*=\s*["']textbox["']/i.test(node.attributes);
8756
+ for (const match of html.matchAll(/<!--[\s\S]*?-->|<![^>]*>|<\/?[a-z0-9-]+\b[^>]*>|[^<]+/gi)) {
8757
+ const token = match[0];
8758
+ const closing = /^<\/([a-z0-9-]+)/i.exec(token);
8759
+ if (closing?.[1] !== void 0) {
8760
+ const tag = closing[1].toLowerCase();
8761
+ const index = stack.map((node) => node.tag).lastIndexOf(tag);
8762
+ if (index >= 0) stack.splice(index);
8763
+ continue;
8764
+ }
8765
+ const opening = /^<([a-z0-9-]+)\b([^>]*)>/i.exec(token);
8766
+ if (opening?.[1] !== void 0) {
8767
+ const node = {
8768
+ tag: opening[1].toLowerCase(),
8769
+ attributes: opening[2] ?? "",
8770
+ parent: stack.at(-1),
8771
+ text: ""
8772
+ };
8773
+ if (node.tag === "button") buttons.push(node);
8774
+ if (isTextbox(node) && !hiddenInChain(node)) {
8775
+ const ancestors = [...stack].reverse();
8776
+ const composer = ancestors.find((ancestor) => ancestor.tag === "form") ?? ancestors.find(isComposerMetadata);
8777
+ if (composer !== void 0 && !hiddenInChain(composer)) activeComposers.add(composer);
8778
+ }
8779
+ if (!voidElements.has(node.tag) && !/\/\s*>$/.test(token)) stack.push(node);
8780
+ continue;
8781
+ }
8782
+ for (let index = stack.length - 1; index >= 0; index -= 1) {
8783
+ if (stack[index].tag === "button") {
8784
+ stack[index].text += ` ${token}`;
8785
+ break;
8786
+ }
8787
+ }
8788
+ }
8789
+ const activeComposer = activeComposers.size === 1 ? [...activeComposers][0] : void 0;
8790
+ return buttons.map((button) => {
8791
+ let scoped = false;
8792
+ for (let current = button.parent; current !== void 0; current = current.parent) {
8793
+ if (current === activeComposer) {
8794
+ scoped = true;
8795
+ break;
8796
+ }
8797
+ }
8798
+ return {
8799
+ attributes: button.attributes,
8800
+ text: button.text,
8801
+ scoped,
8802
+ hidden: hiddenInChain(button),
8803
+ disabled: /\bdisabled(?:\s|=|$)/i.test(button.attributes) || /\baria-disabled\s*=\s*["']?true/i.test(button.attributes)
8804
+ };
8805
+ });
7448
8806
  }
7449
8807
 
7450
8808
  // src/dom/wait-snapshot.ts
@@ -7487,27 +8845,43 @@ async function readWaitDomSnapshot(page) {
7487
8845
  const trimmedForTransient = normalizedText.replace(/[.。…]+$/g, "").trim().toLowerCase();
7488
8846
  const transient = args.transient.some((phrase) => trimmedForTransient === phrase.toLowerCase()) || /^analyzing (?:the )?images?$/.test(trimmedForTransient) || /^processing (?:the )?images?$/.test(trimmedForTransient) || /^reading (?:the )?images?$/.test(trimmedForTransient);
7489
8847
  const isVisible = (element) => {
8848
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) {
8849
+ return false;
8850
+ }
7490
8851
  const style = window.getComputedStyle(element);
7491
- return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && element.getAttribute("aria-hidden") !== "true";
8852
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none") {
8853
+ return false;
8854
+ }
8855
+ const rect = element.getBoundingClientRect();
8856
+ return rect.width > 0 || rect.height > 0;
7492
8857
  };
7493
- const visibleButtons = Array.from(document.querySelectorAll("button")).filter((button) => isVisible(button) && button.disabled !== true && button.getAttribute("aria-disabled") !== "true");
7494
- const buttonTexts = visibleButtons.map((button) => [
7495
- button.innerText,
7496
- button.textContent,
7497
- button.getAttribute("aria-label"),
7498
- button.getAttribute("title")
7499
- ].map(normalizeLower).filter(Boolean).join(" ")).filter(Boolean);
7500
- const bodyText = normalizeLower(document.body?.innerText);
7501
- const haystacks = [bodyText, ...buttonTexts];
7502
- const matchingSignals = (phrases) => haystacks.flatMap(
7503
- (text) => phrases.map((phrase) => phrase.toLowerCase()).filter((phrase) => text.includes(phrase))
7504
- );
7505
- const activeSignals = matchingSignals(args.stop);
7506
- const stoppedSignals = matchingSignals(args.stopped);
8858
+ const elementValues = (element) => [
8859
+ element.getAttribute("aria-label"),
8860
+ element.getAttribute("title"),
8861
+ element.innerText,
8862
+ element.textContent
8863
+ ].map(normalizeLower).filter(Boolean);
8864
+ const matchingLabels2 = (element, phrases) => {
8865
+ const values = elementValues(element);
8866
+ return phrases.filter((phrase) => values.includes(normalizeLower(phrase)));
8867
+ };
8868
+ const isScopedStopControl = (button) => {
8869
+ if (button.matches("[data-testid='stop-button'], [data-testid*='stop' i]")) return true;
8870
+ if (button.closest("[data-testid*='composer' i], [aria-label*='composer' i]") !== null) return true;
8871
+ const form = button.closest("form");
8872
+ return form?.querySelector("textarea, [contenteditable='true'], [role='textbox']") !== null;
8873
+ };
8874
+ 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);
8875
+ const activeSignals = [...new Set(visibleStopButtons.flatMap((button) => matchingLabels2(button, args.stop)))];
8876
+ const latestAssistantTurn = latestAssistant?.closest("[data-testid^='conversation-turn']") ?? Array.from(document.querySelectorAll("[data-testid^='conversation-turn']")).at(-1);
8877
+ const stoppedSignals = latestAssistantTurn === void 0 ? [] : [...new Set(Array.from(latestAssistantTurn.querySelectorAll(
8878
+ "button, [role='status'], [aria-label], [title], p, span, div"
8879
+ )).filter((element) => isVisible(element)).flatMap((element) => matchingLabels2(element, args.stopped)))];
7507
8880
  const generation = {
8881
+ observed: true,
7508
8882
  active: activeSignals.length > 0,
7509
8883
  stopped: stoppedSignals.length > 0,
7510
- signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals, ...buttonTexts.filter((text) => /stop|cancel|stopped|answering|thinking/i.test(text))])].slice(0, 5)
8884
+ signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals])].slice(0, 5)
7511
8885
  };
7512
8886
  const turns = Array.from(document.querySelectorAll("[data-testid^='conversation-turn']"));
7513
8887
  let hasResponseActions;
@@ -7542,26 +8916,11 @@ async function readWaitDomSnapshot(page) {
7542
8916
  transient: [...localeLabels.transientAssistant],
7543
8917
  stop: [...localeLabels.stopControl],
7544
8918
  stopped: [...localeLabels.stoppedAssistant],
8919
+ send: [...localeLabels.sendButton],
7545
8920
  actions: [...localeLabels.responseActions]
7546
8921
  });
7547
8922
  }
7548
8923
 
7549
- // src/commands/deadline.ts
7550
- function createDeadline(timeoutMs, startedAtMs = Date.now()) {
7551
- const safeTimeoutMs = Math.max(0, timeoutMs);
7552
- return {
7553
- startedAtMs,
7554
- timeoutMs: safeTimeoutMs,
7555
- expiresAtMs: startedAtMs + safeTimeoutMs
7556
- };
7557
- }
7558
- function remainingMs(deadline, nowMs = Date.now()) {
7559
- return Math.max(0, deadline.expiresAtMs - nowMs);
7560
- }
7561
- function childTimeoutMs(deadline, capMs, nowMs = Date.now()) {
7562
- return Math.max(0, Math.min(Math.max(0, capMs), remainingMs(deadline, nowMs)));
7563
- }
7564
-
7565
8924
  // src/commands/output.ts
7566
8925
  function commandOutputText(data) {
7567
8926
  if (!isRecord2(data)) return void 0;
@@ -7653,7 +9012,7 @@ var ProbeTimeoutError = class extends Error {
7653
9012
 
7654
9013
  // src/commands/messages.ts
7655
9014
  function isResponseComplete(snapshot) {
7656
- return snapshot.latestText.trim().length > 0 && !isTransientAssistantText(snapshot.latestText) && snapshot.textStableForMs >= snapshot.stableMs && !snapshot.generation.active && !snapshot.generation.stopped && snapshot.hasResponseActions;
9015
+ return snapshot.latestText.trim().length > 0 && !isTransientAssistantText(snapshot.latestText) && snapshot.textStableForMs >= snapshot.stableMs && snapshot.generation.observed && !snapshot.generation.active && !snapshot.generation.stopped && snapshot.hasResponseActions;
7657
9016
  }
7658
9017
  async function composeMessage(env, args) {
7659
9018
  const boot = await ensurePage(env);
@@ -7782,6 +9141,282 @@ async function submitMessage(env, args = {}) {
7782
9141
  return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
7783
9142
  }
7784
9143
  }
9144
+ async function stopGeneration(env, args = {}) {
9145
+ const timeoutMs = Math.max(1, args.timeoutMs ?? 5e3);
9146
+ const deadline = createDeadline(timeoutMs);
9147
+ if (args.confirmStop !== true) {
9148
+ return {
9149
+ ok: false,
9150
+ status: "needs_confirmation",
9151
+ warnings: [],
9152
+ blocker: {
9153
+ kind: "confirmation",
9154
+ code: "stop_generation_confirmation_required",
9155
+ fieldPath: "confirmStop",
9156
+ message: "Stopping the visible ChatGPT response requires an explicit caller decision.",
9157
+ resumable: true
9158
+ },
9159
+ context: env.page === void 0 ? { timestamp: (/* @__PURE__ */ new Date()).toISOString() } : await stopContext(env.page, deadline)
9160
+ };
9161
+ }
9162
+ let boot;
9163
+ try {
9164
+ boot = await withinStopDeadline(
9165
+ deadline,
9166
+ () => ensurePage(env, { minimalContext: true }),
9167
+ "ChatGPT page verification"
9168
+ );
9169
+ } catch (error) {
9170
+ return stopDeadlineResult(error);
9171
+ }
9172
+ if (!boot.ok) return boot;
9173
+ const page = env.page;
9174
+ const warnings = /* @__PURE__ */ new Set();
9175
+ let stopActivationStarted = false;
9176
+ let beforeActivation;
9177
+ try {
9178
+ const beforeProbeTimeoutMs = Math.min(1e3, Math.max(1, remainingMs(deadline)));
9179
+ const beforeResult = await readStopGenerationState(page, deadline, beforeProbeTimeoutMs);
9180
+ addWarnings(warnings, beforeResult.warnings);
9181
+ if (!beforeResult.ok || !beforeResult.value.observed) {
9182
+ if (remainingMs(deadline) <= 0) {
9183
+ return stopDeadlineResult(void 0, void 0, [...warnings]);
9184
+ }
9185
+ return {
9186
+ ok: false,
9187
+ status: "blocked",
9188
+ warnings: [...warnings],
9189
+ blocker: {
9190
+ kind: "selector_drift",
9191
+ code: "stop_generation_state_unavailable",
9192
+ message: "ChatGPT generation state could not be inspected safely, so no control was clicked.",
9193
+ resumable: true
9194
+ },
9195
+ context: await stopContext(page, deadline)
9196
+ };
9197
+ }
9198
+ const before = beforeResult.value;
9199
+ beforeActivation = before;
9200
+ if (!before.active) {
9201
+ return resultOk({
9202
+ wasGenerating: false,
9203
+ stopped: false,
9204
+ signalsBefore: before.signals,
9205
+ signalsAfter: before.signals
9206
+ }, await stopContext(page, deadline), [...warnings]);
9207
+ }
9208
+ const resolution = await resolveStopControl(page, deadline);
9209
+ if (!resolution.ok) {
9210
+ return {
9211
+ ok: false,
9212
+ status: "blocked",
9213
+ data: { wasGenerating: true, stopped: false, signalsBefore: before.signals, signalsAfter: before.signals },
9214
+ warnings: [...warnings],
9215
+ blocker: {
9216
+ kind: "selector_drift",
9217
+ code: resolution.code,
9218
+ message: resolution.message,
9219
+ resumable: true
9220
+ },
9221
+ context: await stopContext(page, deadline)
9222
+ };
9223
+ }
9224
+ stopActivationStarted = true;
9225
+ await withinNativeStopDeadline(
9226
+ deadline,
9227
+ (timeoutMs2) => resolution.control.click?.({ timeoutMs: timeoutMs2 }) ?? Promise.reject(new Error("The resolved Stop control does not support click().")),
9228
+ "Stop control click"
9229
+ );
9230
+ let after = EMPTY_GENERATION_STATE;
9231
+ while (remainingMs(deadline) > 0) {
9232
+ const afterProbeTimeoutMs = Math.min(1e3, Math.max(1, remainingMs(deadline)));
9233
+ const afterResult = await readStopGenerationState(page, deadline, afterProbeTimeoutMs);
9234
+ addWarnings(warnings, afterResult.warnings);
9235
+ if (afterResult.ok) {
9236
+ after = afterResult.value;
9237
+ if (after.observed && !after.active) {
9238
+ return resultOk({
9239
+ wasGenerating: true,
9240
+ stopped: true,
9241
+ signalsBefore: before.signals,
9242
+ signalsAfter: after.signals
9243
+ }, await stopContext(page, deadline), [...warnings]);
9244
+ }
9245
+ }
9246
+ await sleepWithinDeadline(page, deadline, 100);
9247
+ }
9248
+ const data = {
9249
+ wasGenerating: true,
9250
+ stopped: false,
9251
+ signalsBefore: before.signals,
9252
+ signalsAfter: after.signals
9253
+ };
9254
+ return stopDeadlineResult(void 0, data, [...warnings]);
9255
+ } catch (error) {
9256
+ if (remainingMs(deadline) <= 0 || error instanceof StopDeadlineError) {
9257
+ const data = stopActivationStarted && beforeActivation !== void 0 ? {
9258
+ wasGenerating: true,
9259
+ stopped: false,
9260
+ signalsBefore: beforeActivation.signals,
9261
+ signalsAfter: beforeActivation.signals
9262
+ } : void 0;
9263
+ return stopDeadlineResult(error, data, [...warnings]);
9264
+ }
9265
+ return resultError(error instanceof Error ? error : new Error(String(error)), await stopContext(page, deadline));
9266
+ }
9267
+ }
9268
+ async function readStopGenerationState(page, deadline, capMs) {
9269
+ const timeoutMs = Math.min(capMs, remainingMs(deadline));
9270
+ if (timeoutMs <= 0) {
9271
+ return {
9272
+ ok: false,
9273
+ timedOut: true,
9274
+ warnings: ["Skipped generation state DOM probe because no deadline budget remained."]
9275
+ };
9276
+ }
9277
+ try {
9278
+ const value = await readAssistantGenerationState(page, { timeoutMs });
9279
+ return { ok: true, value, warnings: [] };
9280
+ } catch (error) {
9281
+ return {
9282
+ ok: false,
9283
+ warnings: [`generation state DOM probe failed: ${error instanceof Error ? error.message : String(error)}`]
9284
+ };
9285
+ }
9286
+ }
9287
+ async function resolveStopControl(page, deadline) {
9288
+ const candidates = stopGenerationButton(page);
9289
+ if (typeof candidates.count !== "function") {
9290
+ return {
9291
+ ok: false,
9292
+ code: "stop_generation_control_unavailable",
9293
+ message: "ChatGPT is generating, but the Stop-control candidate set could not be enumerated safely."
9294
+ };
9295
+ }
9296
+ const count = await stopControlCount(candidates, deadline);
9297
+ if (count === 0) {
9298
+ return {
9299
+ ok: false,
9300
+ code: "stop_generation_control_unavailable",
9301
+ message: "ChatGPT is generating, but no visible Stop control was found."
9302
+ };
9303
+ }
9304
+ if (count > 8) {
9305
+ return {
9306
+ ok: false,
9307
+ code: "stop_generation_control_ambiguous",
9308
+ message: `ChatGPT exposed ${count} Stop-control candidates; refusing to choose among an unexpectedly broad set.`
9309
+ };
9310
+ }
9311
+ const eligible = [];
9312
+ for (let index = 0; index < count; index += 1) {
9313
+ const control = count === 1 ? candidates : typeof candidates.nth === "function" ? candidates.nth(index) : void 0;
9314
+ if (control === void 0 || typeof control.evaluate !== "function") {
9315
+ continue;
9316
+ }
9317
+ const evaluationTimeoutMs = Math.min(1e3, Math.max(1, remainingMs(deadline)));
9318
+ const scoped = await withinNativeStopDeadline(deadline, (timeoutMs) => control.evaluate((element) => {
9319
+ const button = element;
9320
+ if (button.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
9321
+ if (button.disabled || button.getAttribute("aria-disabled") === "true") return false;
9322
+ const visible = (node) => {
9323
+ if (node.hidden || node.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
9324
+ const style = window.getComputedStyle(node);
9325
+ const rect = node.getBoundingClientRect();
9326
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && style.pointerEvents !== "none" && (rect.width > 0 || rect.height > 0);
9327
+ };
9328
+ const textboxes = Array.from(document.querySelectorAll(
9329
+ "textarea, [contenteditable='true'], [role='textbox']"
9330
+ )).filter(visible);
9331
+ 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))];
9332
+ return activeComposers.length === 1 && activeComposers[0].contains(button);
9333
+ }, void 0, { timeoutMs }), `Stop control ${index + 1} visibility and scope check`, evaluationTimeoutMs);
9334
+ if (scoped) eligible.push(control);
9335
+ }
9336
+ if (eligible.length === 1) {
9337
+ return { ok: true, control: eligible[0] };
9338
+ }
9339
+ if (eligible.length > 1) {
9340
+ return {
9341
+ ok: false,
9342
+ code: "stop_generation_control_ambiguous",
9343
+ message: `ChatGPT exposed ${eligible.length} visible Stop controls in active composer regions; no control was clicked.`
9344
+ };
9345
+ }
9346
+ return {
9347
+ ok: false,
9348
+ code: "stop_generation_control_unavailable",
9349
+ message: "ChatGPT is generating, but no uniquely scoped visible Stop control could be activated."
9350
+ };
9351
+ }
9352
+ async function stopControlCount(candidates, deadline) {
9353
+ if (typeof candidates.allTextContents === "function") {
9354
+ const values = await withinNativeStopDeadline(
9355
+ deadline,
9356
+ (timeoutMs) => candidates.allTextContents({ timeoutMs }),
9357
+ "Stop control enumeration",
9358
+ 1e3
9359
+ );
9360
+ return values.length;
9361
+ }
9362
+ return withinStopDeadline(deadline, () => candidates.count(), "Stop control enumeration");
9363
+ }
9364
+ async function withinStopDeadline(deadline, operation, label) {
9365
+ const budget = remainingMs(deadline);
9366
+ if (budget <= 0) throw new StopDeadlineError(label);
9367
+ try {
9368
+ return await withTimeout(operation(), budget, `${label} exceeded the messages.stop deadline.`);
9369
+ } catch (error) {
9370
+ if (remainingMs(deadline) <= 0) throw new StopDeadlineError(label);
9371
+ throw error;
9372
+ }
9373
+ }
9374
+ async function withinNativeStopDeadline(deadline, operation, label, capMs = 2e3) {
9375
+ const timeoutMs = Math.min(capMs, remainingMs(deadline));
9376
+ if (timeoutMs <= 0) throw new StopDeadlineError(label);
9377
+ try {
9378
+ return await operation(timeoutMs);
9379
+ } catch (error) {
9380
+ if (remainingMs(deadline) <= 0 || isNativeBrowserTimeout(error)) {
9381
+ throw new StopDeadlineError(label);
9382
+ }
9383
+ throw error;
9384
+ }
9385
+ }
9386
+ function isNativeBrowserTimeout(error) {
9387
+ return error instanceof Error && /timed?\s*out|timeout/i.test(error.message);
9388
+ }
9389
+ async function sleepWithinDeadline(_page, deadline, requestedMs) {
9390
+ const waitMs = Math.min(requestedMs, Math.max(0, remainingMs(deadline) - 1));
9391
+ if (waitMs <= 0) return;
9392
+ await new Promise((resolve3) => setTimeout(resolve3, waitMs));
9393
+ }
9394
+ async function stopContext(page, _deadline) {
9395
+ return contextFromPage(page, {}, { minimal: true });
9396
+ }
9397
+ function stopDeadlineResult(error, data, warnings = []) {
9398
+ 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.";
9399
+ const result = {
9400
+ ok: false,
9401
+ status: "timeout",
9402
+ warnings: error === void 0 ? warnings : [...warnings, error instanceof Error ? error.message : String(error)],
9403
+ blocker: {
9404
+ kind: "selector_drift",
9405
+ code: data?.wasGenerating === true ? "stop_generation_unverified" : "stop_generation_deadline_exhausted",
9406
+ message,
9407
+ resumable: data?.wasGenerating !== true
9408
+ },
9409
+ context: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
9410
+ };
9411
+ if (data !== void 0) result.data = data;
9412
+ return result;
9413
+ }
9414
+ var StopDeadlineError = class extends Error {
9415
+ constructor(label) {
9416
+ super(`${label} could not complete before the messages.stop deadline.`);
9417
+ this.name = "StopDeadlineError";
9418
+ }
9419
+ };
7785
9420
  async function clickSendControl(page) {
7786
9421
  try {
7787
9422
  await sendButton(page).click?.();
@@ -7973,7 +9608,7 @@ async function waitForMessage(env, args = {}) {
7973
9608
  context: await contextFromPage(page)
7974
9609
  });
7975
9610
  }
7976
- const metadataComplete = targetReached && snapshot.text.length > 0 && !snapshot.text.transient && Date.now() - lastChangedAt >= stableMs && !snapshot.generation.active && !snapshot.generation.stopped && hasResponseActions;
9611
+ const metadataComplete = targetReached && snapshot.text.length > 0 && !snapshot.text.transient && Date.now() - lastChangedAt >= stableMs && snapshot.generation.observed && !snapshot.generation.active && !snapshot.generation.stopped && hasResponseActions;
7977
9612
  if (metadataComplete) {
7978
9613
  const latestText = normalizeWhitespace(await fetchLatestAssistantText(page) ?? "");
7979
9614
  const fetchedMetadata = waitTextMetadata(latestText);
@@ -8697,7 +10332,8 @@ async function setMode(env, args) {
8697
10332
  return selectorDrift(page, "No unique ChatGPT mode menu opener was found.");
8698
10333
  }
8699
10334
  await page.waitForTimeout?.(250);
8700
- const candidates = await enumerateVisibleMenuItems(page);
10335
+ let candidates = await enumerateVisibleMenuItems(page);
10336
+ const observedCandidates = [...candidates];
8701
10337
  const selected = [];
8702
10338
  if (requested.length > 0 && shouldRejectAsWrongModeMenu(candidates)) {
8703
10339
  const candidateLabels2 = candidates.map((candidate) => candidate.label);
@@ -8710,9 +10346,20 @@ async function setMode(env, args) {
8710
10346
  };
8711
10347
  }
8712
10348
  for (const request of requested) {
8713
- const match = findModeMenuItem(candidates, request);
10349
+ let match = findModeMenuItem(candidates, request);
8714
10350
  if (match === void 0) {
8715
- const candidateLabels2 = candidates.map((candidate) => candidate.label);
10351
+ const sliderSelection = await selectModeWithPowerSlider(page, request);
10352
+ if (sliderSelection !== void 0) {
10353
+ selected.push(sliderSelection);
10354
+ continue;
10355
+ }
10356
+ const nested = await openEffortSubmenu(page, candidates, request);
10357
+ observedCandidates.push(...nested);
10358
+ candidates = nested;
10359
+ match = findModeMenuItem(candidates, request);
10360
+ }
10361
+ if (match === void 0) {
10362
+ const candidateLabels2 = dedupeLabels(observedCandidates.map((candidate) => candidate.label));
8716
10363
  return {
8717
10364
  ok: false,
8718
10365
  status: "unsupported",
@@ -8721,12 +10368,12 @@ async function setMode(env, args) {
8721
10368
  context: await contextFromPage(page)
8722
10369
  };
8723
10370
  }
8724
- if (!await clickMenuItem(page, match.label)) {
10371
+ if (!await clickResolvedMenuItem(page, match)) {
8725
10372
  return selectorDrift(page, `Mode option "${match.label}" was visible but could not be clicked.`, candidates.map((candidate) => candidate.label));
8726
10373
  }
8727
10374
  selected.push(match.label);
8728
10375
  }
8729
- let candidateLabels = candidates.map((candidate) => candidate.label);
10376
+ let candidateLabels = dedupeLabels(observedCandidates.map((candidate) => candidate.label));
8730
10377
  if (requestedVersion !== void 0) {
8731
10378
  const versionResult = await selectModelVersion(page, requestedVersion, candidates, args.timeoutMs ?? 3e4);
8732
10379
  candidateLabels = dedupeLabels([...candidateLabels, ...versionResult.candidates]);
@@ -8747,6 +10394,59 @@ async function setMode(env, args) {
8747
10394
  return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
8748
10395
  }
8749
10396
  }
10397
+ async function selectModeWithPowerSlider(page, request) {
10398
+ const wanted = request.modeId === void 0 ? void 0 : CANONICAL_INTELLIGENCE_ORDER.get(request.modeId);
10399
+ const slider = page.locator?.("[role='slider'][aria-valuemin='0'][aria-valuemax='4']");
10400
+ 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) {
10401
+ return void 0;
10402
+ }
10403
+ const state = await slider.evaluate((element) => ({
10404
+ min: Number(element.getAttribute("aria-valuemin")),
10405
+ max: Number(element.getAttribute("aria-valuemax")),
10406
+ now: Number(element.getAttribute("aria-valuenow"))
10407
+ })).catch(() => void 0);
10408
+ 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) {
10409
+ return void 0;
10410
+ }
10411
+ const key = wanted > state.now ? "ArrowRight" : "ArrowLeft";
10412
+ for (let step = 0; step < Math.abs(wanted - state.now); step += 1) {
10413
+ await slider.press(key);
10414
+ }
10415
+ await page.waitForTimeout?.(150);
10416
+ return findUniqueVisibleLabelForRequest(await visibleModeButtonLabelList(page), request);
10417
+ }
10418
+ async function openEffortSubmenu(page, rootItems, request) {
10419
+ const axisLabels = [
10420
+ ...localeLabels.configurationAxes.effort,
10421
+ ...localeLabels.configurationAxes.intelligence
10422
+ ].map(normalizeForLabelMatch);
10423
+ const effortRows = (items) => items.filter((item) => {
10424
+ if (item.role === "menuitemradio") return false;
10425
+ const normalized = normalizeForLabelMatch(item.label);
10426
+ return axisLabels.some((axis) => normalized === axis || normalized.startsWith(`${axis} `));
10427
+ });
10428
+ let visibleRootItems = rootItems;
10429
+ let rows = effortRows(visibleRootItems);
10430
+ if (rows.length === 0) {
10431
+ const advancedLabels = localeLabels.configurationAxes.advanced.map(normalizeForLabelMatch);
10432
+ const advancedRows = visibleRootItems.filter((item) => {
10433
+ const normalized = normalizeForLabelMatch(item.label);
10434
+ return advancedLabels.some((label) => normalized === label || visibleLabelMatches(item.label, label));
10435
+ });
10436
+ if (advancedRows.length !== 1 || !await clickResolvedMenuItem(page, advancedRows[0])) {
10437
+ return [];
10438
+ }
10439
+ await page.waitForTimeout?.(250);
10440
+ visibleRootItems = await enumerateVisibleMenuItems(page);
10441
+ rows = effortRows(visibleRootItems);
10442
+ }
10443
+ if (rows.length !== 1 || !await clickResolvedMenuItem(page, rows[0])) {
10444
+ return [];
10445
+ }
10446
+ await page.waitForTimeout?.(250);
10447
+ const nested = await enumerateVisibleMenuItems(page);
10448
+ return findModeMenuItem(nested, request) === void 0 ? [] : nested;
10449
+ }
8750
10450
  async function modeVerificationWarnings(page, requested, selected) {
8751
10451
  if (requested.length === 0) {
8752
10452
  return [];
@@ -8838,7 +10538,7 @@ async function selectTool(env, args) {
8838
10538
  context: await contextFromPage(page)
8839
10539
  };
8840
10540
  }
8841
- if (!await clickMenuItem(page, match.label)) {
10541
+ if (!await clickMenuItem(page, match)) {
8842
10542
  return selectorDrift(page, `Tool "${match.label}" was visible but could not be clicked.`, candidates.map((candidate) => candidate.label));
8843
10543
  }
8844
10544
  return resultOk({ selected: match.label, candidates: candidates.map((candidate) => candidate.label) }, await contextFromPage(page));
@@ -8906,25 +10606,25 @@ function shouldRejectAsWrongModeMenu(items) {
8906
10606
  }
8907
10607
  return items.some((item) => isThreadActionLabel(item.label));
8908
10608
  }
8909
- async function clickMenuItem(page, label) {
8910
- if (await clickModelSwitcherMenuItem(page, label)) {
8911
- return true;
8912
- }
8913
- if (await clickMenuItemByPointer(page, label)) {
10609
+ async function clickMenuItem(page, item) {
10610
+ if (await clickModelSwitcherMenuItem(page, item)) {
8914
10611
  return true;
8915
10612
  }
8916
- if (await clickMenuItemByDom(page, label)) {
10613
+ if (await clickMenuItemByPointer(page, item)) {
8917
10614
  return true;
8918
10615
  }
8919
- const roleLocator = page.locator?.("[role='menuitem'], [role='menuitemradio'], [role='option']")?.filter?.({ hasText: label });
8920
- if (await clickIfUnique(roleLocator)) {
8921
- return true;
10616
+ if (item.role !== void 0) {
10617
+ const accessibleName = item.ariaLabel ?? item.label;
10618
+ if (await clickIfUniqueMenuControl(
10619
+ page.getByRole?.(item.role, { name: accessibleName, exact: true }),
10620
+ item
10621
+ )) return true;
8922
10622
  }
8923
- const textLocator = page.getByText?.(label, { exact: true });
8924
- return clickIfUnique(textLocator);
10623
+ const roleLocator = page.locator?.("[role='menuitem'], [role='menuitemradio'], [role='option']")?.filter?.({ hasText: new RegExp(`^\\s*${escapeRegExp3(item.label)}\\s*$`, "i") });
10624
+ return clickIfUniqueMenuControl(roleLocator, item);
8925
10625
  }
8926
- async function clickMenuItemByPointer(page, label) {
8927
- const point = await menuItemCenter(page, { label });
10626
+ async function clickMenuItemByPointer(page, item) {
10627
+ const point = await menuItemCenter(page, item);
8928
10628
  if (point === void 0) {
8929
10629
  return false;
8930
10630
  }
@@ -8939,43 +10639,27 @@ async function clickMenuItemByPointer(page, label) {
8939
10639
  }
8940
10640
  return false;
8941
10641
  }
8942
- async function clickModelSwitcherMenuItem(page, label) {
10642
+ async function clickModelSwitcherMenuItem(page, item) {
8943
10643
  if (typeof page.evaluate !== "function" || typeof page.locator !== "function") {
8944
10644
  return false;
8945
10645
  }
8946
10646
  const testId = await page.evaluate((wanted) => {
8947
- const normalizedWanted = wanted.replace(/\s+/g, " ").trim().toLowerCase();
10647
+ const normalizedWanted = wanted.label.replace(/\s+/g, " ").trim().toLowerCase();
8948
10648
  const candidates = Array.from(document.querySelectorAll("[data-testid^='model-switcher-']"));
8949
10649
  const matches = candidates.filter((node) => {
8950
10650
  const element = node;
8951
10651
  const candidateTestId = element.getAttribute("data-testid") ?? "";
8952
10652
  if (candidateTestId.endsWith("-effort")) return false;
10653
+ if (wanted.testId !== void 0 && candidateTestId !== wanted.testId) return false;
8953
10654
  const text = (element.innerText ?? element.textContent ?? "").replace(/\s+/g, " ").trim().toLowerCase();
8954
10655
  return text === normalizedWanted;
8955
10656
  }).map((node) => node.getAttribute("data-testid")).filter((value) => value !== null);
8956
10657
  return matches.length === 1 ? matches[0] : void 0;
8957
- }, label).catch(() => void 0);
10658
+ }, item.testId === void 0 ? { label: item.label } : { label: item.label, testId: item.testId }).catch(() => void 0);
8958
10659
  if (testId === void 0) {
8959
10660
  return false;
8960
10661
  }
8961
- return clickIfUnique(page.locator(`[data-testid="${escapeAttributeValue(testId)}"]`));
8962
- }
8963
- async function clickMenuItemByDom(page, label) {
8964
- if (typeof page.evaluate !== "function") {
8965
- return false;
8966
- }
8967
- return page.evaluate((wanted) => {
8968
- const normalizedWanted = wanted.replace(/\s+/g, " ").trim().toLowerCase();
8969
- const candidates = Array.from(document.querySelectorAll("[role='menuitem'], [role='menuitemradio'], [role='option']"));
8970
- const matches = candidates.filter((node) => {
8971
- const element = node;
8972
- const text = (element.innerText ?? element.textContent ?? "").replace(/\s+/g, " ").trim().toLowerCase();
8973
- return text === normalizedWanted;
8974
- });
8975
- if (matches.length !== 1) return false;
8976
- matches[0].click();
8977
- return true;
8978
- }, label).catch(() => false);
10662
+ return clickIfUniqueMenuControl(page.locator(`[data-testid="${escapeAttributeValue(testId)}"]`), item);
8979
10663
  }
8980
10664
  async function clickIfUnique(locator) {
8981
10665
  if (locator === void 0 || typeof locator.count !== "function" || typeof locator.click !== "function") {
@@ -8988,6 +10672,32 @@ async function clickIfUnique(locator) {
8988
10672
  await locator.click();
8989
10673
  return true;
8990
10674
  }
10675
+ async function clickIfUniqueMenuControl(locator, item) {
10676
+ if (locator === void 0 || typeof locator.count !== "function" || typeof locator.evaluate !== "function" || typeof locator.click !== "function") {
10677
+ return false;
10678
+ }
10679
+ if (await locator.count().catch(() => 0) !== 1) return false;
10680
+ const safe = await locator.evaluate((element) => {
10681
+ const control = element;
10682
+ if (control.disabled || control.getAttribute("aria-disabled") === "true") return false;
10683
+ if (control.hidden || control.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
10684
+ const style = window.getComputedStyle(control);
10685
+ const rect = control.getBoundingClientRect();
10686
+ if (rect.width <= 0 || rect.height <= 0 || style.display === "none" || style.visibility === "hidden" || style.opacity === "0" || style.pointerEvents === "none") return false;
10687
+ const containers = Array.from(document.querySelectorAll(
10688
+ "[role='menu'], [role='listbox'], [data-radix-popper-content-wrapper]"
10689
+ )).filter((container) => {
10690
+ if (container.hidden || container.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
10691
+ const containerStyle = window.getComputedStyle(container);
10692
+ const containerRect = container.getBoundingClientRect();
10693
+ return containerRect.width > 0 && containerRect.height > 0 && containerStyle.display !== "none" && containerStyle.visibility !== "hidden" && containerStyle.opacity !== "0";
10694
+ });
10695
+ return containers.length > 0 && containers.some((container) => container.contains(control));
10696
+ }).catch(() => false);
10697
+ if (!safe) return false;
10698
+ await locator.click();
10699
+ return true;
10700
+ }
8991
10701
  function toolLabels(tool) {
8992
10702
  const known = localeLabels.tools[tool];
8993
10703
  return known !== void 0 ? [...known] : [tool];
@@ -9071,6 +10781,9 @@ function findUniqueVisibleLabel(labels, wanted) {
9071
10781
  const fuzzy = labels.filter((label) => visibleLabelMatches(normalizeLabel(label), normalized));
9072
10782
  return fuzzy.length === 1 ? fuzzy[0] : void 0;
9073
10783
  }
10784
+ function escapeRegExp3(value) {
10785
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10786
+ }
9074
10787
  function escapeAttributeValue(value) {
9075
10788
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
9076
10789
  }
@@ -9111,17 +10824,19 @@ function isModelVersionSubmenuOpener(item) {
9111
10824
  return item.hasPopup === true || item.role !== "menuitemradio" && MODEL_VERSION_FAMILY_PATTERN.test(item.label);
9112
10825
  }
9113
10826
  async function clickResolvedMenuItem(page, item) {
9114
- if (item.testId !== void 0 && await clickIfUnique(
9115
- page.locator?.(`[data-testid="${escapeAttributeValue(item.testId)}"]`)
10827
+ if (item.testId !== void 0 && await clickIfUniqueMenuControl(
10828
+ page.locator?.(`[data-testid="${escapeAttributeValue(item.testId)}"]`),
10829
+ item
9116
10830
  )) {
9117
10831
  return true;
9118
10832
  }
9119
- if (item.role !== void 0 && await clickIfUnique(
9120
- page.getByRole?.(item.role, { name: item.label, exact: true })
10833
+ if (item.role !== void 0 && await clickIfUniqueMenuControl(
10834
+ page.getByRole?.(item.role, { name: item.ariaLabel ?? item.label, exact: true }),
10835
+ item
9121
10836
  )) {
9122
10837
  return true;
9123
10838
  }
9124
- return clickMenuItem(page, item.label);
10839
+ return clickMenuItem(page, item);
9125
10840
  }
9126
10841
  async function openModelVersionSubmenu(page, candidates) {
9127
10842
  const submenuOpeners = candidates.filter((item) => item.hasPopup === true || MODEL_VERSION_FAMILY_PATTERN.test(item.label));
@@ -9135,7 +10850,7 @@ async function openModelVersionSubmenu(page, candidates) {
9135
10850
  return true;
9136
10851
  }
9137
10852
  }
9138
- if (await clickMenuItem(page, candidate.label)) {
10853
+ if (await clickMenuItem(page, candidate)) {
9139
10854
  await page.waitForTimeout?.(250);
9140
10855
  if (await modelVersionMenuItemsAreVisible(page)) {
9141
10856
  return true;
@@ -9172,18 +10887,26 @@ async function menuItemCenter(page, item, roles = ["menuitem", "menuitemradio",
9172
10887
  const normalize = (value) => value.replace(/\s+/g, " ").trim().toLowerCase();
9173
10888
  const normalizedLabel = normalize(target2.label);
9174
10889
  const roleSelector = target2.roles.map((role) => `[role='${role}']`).join(",");
10890
+ const visible = (element) => {
10891
+ if (element.hidden || element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return false;
10892
+ const rect2 = element.getBoundingClientRect();
10893
+ const style = window.getComputedStyle(element);
10894
+ return rect2.width > 0 && rect2.height > 0 && style.visibility !== "hidden" && style.display !== "none" && style.opacity !== "0" && style.pointerEvents !== "none";
10895
+ };
10896
+ const containers = Array.from(document.querySelectorAll(
10897
+ "[role='menu'], [role='listbox'], [data-radix-popper-content-wrapper]"
10898
+ )).filter(visible);
9175
10899
  const matches = Array.from(document.querySelectorAll(roleSelector)).filter((node) => {
9176
10900
  const element = node;
9177
10901
  if (target2.testId !== void 0 && element.getAttribute("data-testid") !== target2.testId) {
9178
10902
  return false;
9179
10903
  }
10904
+ if (element.disabled || element.getAttribute("aria-disabled") === "true") return false;
9180
10905
  const label = normalize(element.innerText ?? element.textContent ?? "");
9181
10906
  if (label !== normalizedLabel) {
9182
10907
  return false;
9183
10908
  }
9184
- const rect2 = element.getBoundingClientRect();
9185
- const style = window.getComputedStyle(element);
9186
- return rect2.width > 0 && rect2.height > 0 && style.visibility !== "hidden" && style.display !== "none" && style.opacity !== "0";
10909
+ return visible(element) && containers.length > 0 && containers.some((container) => container.contains(element));
9187
10910
  });
9188
10911
  if (matches.length !== 1) return void 0;
9189
10912
  const rect = matches[0].getBoundingClientRect();
@@ -9261,6 +10984,11 @@ async function visibleModeButtonLabelList(page) {
9261
10984
  ));
9262
10985
  return Array.from(document.querySelectorAll("button, [role='button']")).map((node) => {
9263
10986
  const element = node;
10987
+ if (element.hidden || element.getAttribute("aria-hidden") === "true" || typeof element.closest === "function" && element.closest("[hidden], [inert], [aria-hidden='true']") !== null) return "";
10988
+ const style = typeof window?.getComputedStyle === "function" ? window.getComputedStyle(element) : void 0;
10989
+ if (style?.display === "none" || style?.visibility === "hidden" || style?.opacity === "0" || style?.pointerEvents === "none") return "";
10990
+ const rect = typeof element.getBoundingClientRect === "function" ? element.getBoundingClientRect() : { width: 1, height: 1 };
10991
+ if (rect.width <= 0 && rect.height <= 0) return "";
9264
10992
  if (scopedRoots.length > 0 && !scopedRoots.some((root) => root.contains(node))) return "";
9265
10993
  const visibleText = (element.innerText ?? element.textContent ?? "").replace(/\s+/g, " ").trim();
9266
10994
  const ariaLabel = (element.getAttribute("aria-label") ?? "").replace(/\s+/g, " ").trim();
@@ -9698,6 +11426,7 @@ async function inspectConfiguration(env, args = {}) {
9698
11426
  };
9699
11427
  }
9700
11428
  const experience = detected.data.experience;
11429
+ const initialPanel = await readConfigurationPanel(page);
9701
11430
  const rootOpened = experience !== "unknown" && await waitForConfigurationRoot(
9702
11431
  page,
9703
11432
  experience,
@@ -9711,6 +11440,9 @@ async function inspectConfiguration(env, args = {}) {
9711
11440
  await page.waitForTimeout?.(150);
9712
11441
  }
9713
11442
  const panel = await readConfigurationPanel(page);
11443
+ if (panel.openerLabel === void 0 && initialPanel.openerLabel !== void 0) {
11444
+ panel.openerLabel = initialPanel.openerLabel;
11445
+ }
9714
11446
  const rootItems = rootOpened ? await enumerateVisibleMenuItems(page) : [];
9715
11447
  const data = configurationInspectionFromSurface(
9716
11448
  experience,
@@ -10077,14 +11809,12 @@ async function openConfigurationRoot(page, experience) {
10077
11809
  }
10078
11810
  return true;
10079
11811
  };
10080
- const composerRoots = Array.from(document.querySelectorAll(
10081
- "main form, main [data-testid*='composer' i], main [class*='composer' i]"
10082
- ));
11812
+ const formRoots = Array.from(document.querySelectorAll("main form"));
11813
+ const testIdRoots = Array.from(document.querySelectorAll("main [data-testid*='composer' i]"));
11814
+ const classRoots = Array.from(document.querySelectorAll("main [class*='composer' i]"));
11815
+ const composerRoots = formRoots.length > 0 ? formRoots : testIdRoots.length > 0 ? testIdRoots : classRoots;
10083
11816
  const main = document.querySelector("main");
10084
- const roots = Array.from(/* @__PURE__ */ new Set([
10085
- ...composerRoots,
10086
- ...main === null ? [] : [main]
10087
- ]));
11817
+ const roots = Array.from(new Set(composerRoots.length > 0 ? composerRoots : main === null ? [] : [main]));
10088
11818
  const controls = Array.from(new Set(roots.flatMap(
10089
11819
  (root) => Array.from(root.querySelectorAll("button, [role='button']"))
10090
11820
  ))).filter(visible);
@@ -10220,14 +11950,12 @@ async function readConfigurationPanel(page) {
10220
11950
  break;
10221
11951
  }
10222
11952
  }
10223
- const composerRoots = Array.from(document.querySelectorAll(
10224
- "main form, main [data-testid*='composer' i], main [class*='composer' i]"
10225
- ));
11953
+ const formRoots = Array.from(document.querySelectorAll("main form"));
11954
+ const testIdRoots = Array.from(document.querySelectorAll("main [data-testid*='composer' i]"));
11955
+ const classRoots = Array.from(document.querySelectorAll("main [class*='composer' i]"));
11956
+ const composerRoots = formRoots.length > 0 ? formRoots : testIdRoots.length > 0 ? testIdRoots : classRoots;
10226
11957
  const main = document.querySelector("main");
10227
- const openerRoots = Array.from(/* @__PURE__ */ new Set([
10228
- ...composerRoots,
10229
- ...main === null ? [] : [main]
10230
- ]));
11958
+ const openerRoots = Array.from(new Set(composerRoots.length > 0 ? composerRoots : main === null ? [] : [main]));
10231
11959
  const openerCandidates = Array.from(new Set(openerRoots.flatMap(
10232
11960
  (root) => Array.from(root.querySelectorAll("button, [role='button']"))
10233
11961
  ))).filter(visible).map((control) => {
@@ -10250,7 +11978,7 @@ async function readConfigurationPanel(page) {
10250
11978
  async function findWorkAxisRow(page, axis) {
10251
11979
  const labels = axis === "modelVersion" ? [] : localeLabels.configurationAxes[axis] ?? [];
10252
11980
  for (const label of labels) {
10253
- const pattern = new RegExp(`^${escapeRegExp3(label)}(?:\\s|$)`, "i");
11981
+ const pattern = new RegExp(`^${escapeRegExp4(label)}(?:\\s|$)`, "i");
10254
11982
  for (const role of ["button", "menuitem"]) {
10255
11983
  const locator = page.getByRole?.(role, { name: pattern });
10256
11984
  if (locator?.count !== void 0 && await locator.count().catch(() => 0) === 1) {
@@ -10264,12 +11992,28 @@ async function clickVisibleMenuItem(page, item) {
10264
11992
  if (item.testId !== void 0 && await clickIfUnique3(page.locator?.(`[data-testid="${escapeAttributeValue2(item.testId)}"]`))) {
10265
11993
  return true;
10266
11994
  }
10267
- for (const role of ["menuitemradio", "menuitem", "option"]) {
11995
+ const roles = [...new Set([
11996
+ item.role,
11997
+ "menuitemradio",
11998
+ "menuitem",
11999
+ "option"
12000
+ ].filter((role) => role !== void 0))];
12001
+ if (item.ariaLabel !== void 0) {
12002
+ for (const role of roles) {
12003
+ if (await clickIfUnique3(page.getByRole?.(role, { name: item.ariaLabel, exact: true }))) {
12004
+ return true;
12005
+ }
12006
+ }
12007
+ }
12008
+ for (const role of roles) {
10268
12009
  if (await clickIfUnique3(page.getByRole?.(role, { name: item.label, exact: true }))) {
10269
12010
  return true;
10270
12011
  }
10271
12012
  }
10272
- return clickIfUnique3(page.getByText?.(item.label, { exact: true }));
12013
+ const exactText = new RegExp(`^\\s*${escapeRegExp4(item.label)}\\s*$`, "i");
12014
+ return clickIfUnique3(page.locator?.(
12015
+ "button, [role='button'], [role='menuitem'], [role='menuitemradio'], [role='option']"
12016
+ )?.filter?.({ hasText: exactText }));
10273
12017
  }
10274
12018
  function findConfigurationOption(items, requested) {
10275
12019
  const normalizedRequested = normalizeConfigurationId(requested);
@@ -10448,7 +12192,7 @@ async function configurationFailure(page, before, desired, selected, message, co
10448
12192
  })
10449
12193
  };
10450
12194
  }
10451
- function escapeRegExp3(value) {
12195
+ function escapeRegExp4(value) {
10452
12196
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
10453
12197
  }
10454
12198
  function escapeAttributeValue2(value) {
@@ -10978,6 +12722,7 @@ var commandRisk = {
10978
12722
  "messages.wait": "low",
10979
12723
  "messages.readLatest": "medium",
10980
12724
  "messages.status": "medium",
12725
+ "messages.stop": "medium",
10981
12726
  "messages.waitAndRead": "medium",
10982
12727
  "artifacts.listLatest": "medium",
10983
12728
  "artifacts.wait": "low",
@@ -11088,6 +12833,7 @@ var descriptors = [
11088
12833
  primitive("messages.wait", "Wait for the latest assistant response to stabilize.", 12e4),
11089
12834
  primitive("messages.readLatest", "Read the latest message as Markdown, normalized text, blocks, or HTML.", 3e4),
11090
12835
  primitive("messages.status", "Read a compact latest-assistant progress snapshot without treating partial text as complete.", 5e3),
12836
+ primitive("messages.stop", "Stop the current visible ChatGPT response after explicit confirmation and verify generation became inactive.", 5e3),
11091
12837
  primitive("messages.waitAndRead", "Wait for completion and read the latest message.", 12e4),
11092
12838
  primitive("artifacts.listLatest", "Detect the latest visible generated ChatGPT artifact, such as an image-only result.", 3e4),
11093
12839
  primitive("artifacts.wait", "Wait for a visible generated ChatGPT artifact to appear and stabilize.", 12e4),
@@ -11261,6 +13007,7 @@ function primitiveArgs(name) {
11261
13007
  };
11262
13008
  if (name === "messages.readLatest") return { role: "assistant or user", format: "markdown, normalized_text, visible_text, html, blocks, or all" };
11263
13009
  if (name === "messages.status") return { maxPreviewChars: "maximum latest-assistant preview characters to return; defaults to 240" };
13010
+ if (name === "messages.stop") return { confirmStop: "must be true to stop a visible response", timeoutMs: "maximum time to verify generation became inactive" };
11264
13011
  if (name === "experience.detect") return { timeoutMs: "optional timeout for attaching to the ChatGPT page" };
11265
13012
  if (name === "experience.open") return { experience: "chat or work", timeoutMs: "optional verified-switch timeout" };
11266
13013
  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" };
@@ -11392,14 +13139,22 @@ function cloneDescriptor(descriptor) {
11392
13139
  var CHATGPT_HOME3 = "https://chatgpt.com/";
11393
13140
  async function ensureConversationTarget(page, target, options) {
11394
13141
  const targetUrl = absoluteConversationUrl(target);
13142
+ requireChatGPTUrl(targetUrl, "Conversation target URL");
11395
13143
  const expectedConversationId = parseConversationId(targetUrl);
11396
13144
  const currentUrl = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
11397
- if (expectedConversationId !== void 0 && parseConversationId(typeof currentUrl === "string" ? currentUrl : "") === expectedConversationId) {
13145
+ if (isChatGPTUrl(typeof currentUrl === "string" ? currentUrl : "") && expectedConversationId !== void 0 && parseConversationId(typeof currentUrl === "string" ? currentUrl : "") === expectedConversationId) {
11398
13146
  await waitForConversationHydrated(page, options.timeoutMs, expectedConversationId);
11399
13147
  return ensureResult(false, targetUrl, expectedConversationId);
11400
13148
  }
11401
13149
  await page.goto?.(targetUrl, { waitUntil: "domcontentloaded", timeout: options.timeoutMs });
13150
+ const navigatedUrl = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
13151
+ requireChatGPTUrl(typeof navigatedUrl === "string" ? navigatedUrl : "", "Conversation navigation result");
11402
13152
  await waitForConversationHydrated(page, options.timeoutMs, expectedConversationId);
13153
+ const finalUrl = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
13154
+ requireChatGPTUrl(typeof finalUrl === "string" ? finalUrl : "", "Hydrated conversation URL");
13155
+ if (expectedConversationId !== void 0 && parseConversationId(typeof finalUrl === "string" ? finalUrl : "") !== expectedConversationId) {
13156
+ throw new Error(`Visible Chat navigation did not reach conversation ${expectedConversationId}.`);
13157
+ }
11403
13158
  return ensureResult(true, targetUrl, expectedConversationId);
11404
13159
  }
11405
13160
  async function waitForConversationHydrated(page, timeoutMs, expectedConversationId) {
@@ -12064,6 +13819,8 @@ async function executeStep(step, env, previousResults) {
12064
13819
  return readLatest(env, step.args);
12065
13820
  case "messages.status":
12066
13821
  return messageStatus(env, step.args);
13822
+ case "messages.stop":
13823
+ return stopGeneration(env, step.args);
12067
13824
  case "messages.waitAndRead":
12068
13825
  return waitAndRead(env, step.args);
12069
13826
  case "artifacts.listLatest":
@@ -12902,6 +14659,7 @@ function createChatGPT(options = {}) {
12902
14659
  wait: (args) => waitForMessage(env, args),
12903
14660
  readLatest: (args) => readLatest(env, args),
12904
14661
  status: (args) => messageStatus(env, args),
14662
+ stop: (args) => stopGeneration(env, args),
12905
14663
  waitAndRead: (args) => waitAndRead(env, args)
12906
14664
  },
12907
14665
  files: {
@@ -13628,6 +15386,7 @@ var backendCommands = [
13628
15386
  "messages.wait",
13629
15387
  "messages.readLatest",
13630
15388
  "messages.status",
15389
+ "messages.stop",
13631
15390
  "messages.waitAndRead",
13632
15391
  "artifacts.listLatest",
13633
15392
  "artifacts.wait",
@@ -13894,6 +15653,8 @@ async function dispatchBackendCommand(client, request) {
13894
15653
  return client.messages.readLatest(emptyToUndefined(payload));
13895
15654
  case "messages.status":
13896
15655
  return client.messages.status(emptyToUndefined(payload));
15656
+ case "messages.stop":
15657
+ return client.messages.stop(payload);
13897
15658
  case "messages.waitAndRead":
13898
15659
  return client.messages.waitAndRead(payload);
13899
15660
  case "artifacts.listLatest":