codex-chatgpt-control 0.2.0-alpha.1 → 0.3.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/contracts/v1/fixtures/backend-capabilities.json +1 -0
  3. package/contracts/v1/fixtures/command-descriptors.json +33 -2
  4. package/contracts/v1/fixtures/doctor-scenario-preflight.json +12 -1
  5. package/contracts/v1/fixtures/help-root.json +1 -1
  6. package/contracts/v1/fixtures/reports-create-redacted.json +1 -1
  7. package/contracts/v1/parity-suite.json +8 -1
  8. package/dist/codex-chatgpt-control-backend.mjs +1199 -159
  9. package/dist/codex-chatgpt-control.bundle.mjs +1198 -156
  10. package/dist/src/backend/protocol.d.ts +1 -1
  11. package/dist/src/backend/protocol.js +1 -0
  12. package/dist/src/backend/session.js +2 -0
  13. package/dist/src/browser/clipboard.d.ts +11 -0
  14. package/dist/src/browser/clipboard.js +34 -7
  15. package/dist/src/browser/page-state.js +12 -2
  16. package/dist/src/client.d.ts +2 -1
  17. package/dist/src/client.js +3 -2
  18. package/dist/src/commands/context.js +3 -1
  19. package/dist/src/commands/conversation.d.ts +15 -0
  20. package/dist/src/commands/conversation.js +44 -0
  21. package/dist/src/commands/deadline.d.ts +8 -0
  22. package/dist/src/commands/deadline.js +14 -0
  23. package/dist/src/commands/doctor.js +9 -2
  24. package/dist/src/commands/files.js +62 -8
  25. package/dist/src/commands/messages.js +212 -72
  26. package/dist/src/commands/modes.d.ts +4 -1
  27. package/dist/src/commands/modes.js +215 -30
  28. package/dist/src/commands/probes.d.ts +15 -0
  29. package/dist/src/commands/probes.js +64 -0
  30. package/dist/src/commands/registry.js +34 -2
  31. package/dist/src/commands/reports.js +1 -1
  32. package/dist/src/commands/threads.js +2 -24
  33. package/dist/src/dom/generation-state.d.ts +7 -0
  34. package/dist/src/dom/generation-state.js +7 -1
  35. package/dist/src/dom/label-match.d.ts +3 -0
  36. package/dist/src/dom/label-match.js +25 -0
  37. package/dist/src/dom/locale/am.d.ts +6 -0
  38. package/dist/src/dom/locale/am.js +6 -0
  39. package/dist/src/dom/locale/ar.d.ts +7 -0
  40. package/dist/src/dom/locale/ar.js +7 -0
  41. package/dist/src/dom/locale/bg.d.ts +7 -0
  42. package/dist/src/dom/locale/bg.js +7 -0
  43. package/dist/src/dom/locale/bn.d.ts +7 -0
  44. package/dist/src/dom/locale/bn.js +7 -0
  45. package/dist/src/dom/locale/bs.d.ts +6 -0
  46. package/dist/src/dom/locale/bs.js +6 -0
  47. package/dist/src/dom/locale/ca.d.ts +6 -0
  48. package/dist/src/dom/locale/ca.js +6 -0
  49. package/dist/src/dom/locale/cs.d.ts +6 -0
  50. package/dist/src/dom/locale/cs.js +6 -0
  51. package/dist/src/dom/locale/da.d.ts +5 -0
  52. package/dist/src/dom/locale/da.js +5 -0
  53. package/dist/src/dom/locale/de.d.ts +6 -0
  54. package/dist/src/dom/locale/de.js +6 -0
  55. package/dist/src/dom/locale/el.d.ts +6 -0
  56. package/dist/src/dom/locale/el.js +6 -0
  57. package/dist/src/dom/locale/en.d.ts +14 -0
  58. package/dist/src/dom/locale/en.js +15 -0
  59. package/dist/src/dom/locale/es-419.d.ts +6 -0
  60. package/dist/src/dom/locale/es-419.js +6 -0
  61. package/dist/src/dom/locale/es-ES.d.ts +6 -0
  62. package/dist/src/dom/locale/es-ES.js +6 -0
  63. package/dist/src/dom/locale/et.d.ts +6 -0
  64. package/dist/src/dom/locale/et.js +6 -0
  65. package/dist/src/dom/locale/fa.d.ts +7 -0
  66. package/dist/src/dom/locale/fa.js +7 -0
  67. package/dist/src/dom/locale/fi.d.ts +6 -0
  68. package/dist/src/dom/locale/fi.js +6 -0
  69. package/dist/src/dom/locale/fr-CA.d.ts +6 -0
  70. package/dist/src/dom/locale/fr-CA.js +6 -0
  71. package/dist/src/dom/locale/fr-FR.d.ts +5 -0
  72. package/dist/src/dom/locale/fr-FR.js +5 -0
  73. package/dist/src/dom/locale/gu.d.ts +6 -0
  74. package/dist/src/dom/locale/gu.js +6 -0
  75. package/dist/src/dom/locale/hi.d.ts +6 -0
  76. package/dist/src/dom/locale/hi.js +6 -0
  77. package/dist/src/dom/locale/hr.d.ts +5 -0
  78. package/dist/src/dom/locale/hr.js +5 -0
  79. package/dist/src/dom/locale/hu.d.ts +6 -0
  80. package/dist/src/dom/locale/hu.js +6 -0
  81. package/dist/src/dom/locale/hy.d.ts +7 -0
  82. package/dist/src/dom/locale/hy.js +7 -0
  83. package/dist/src/dom/locale/id.d.ts +6 -0
  84. package/dist/src/dom/locale/id.js +6 -0
  85. package/dist/src/dom/locale/index.d.ts +5 -1
  86. package/dist/src/dom/locale/index.js +37 -0
  87. package/dist/src/dom/locale/is.d.ts +6 -0
  88. package/dist/src/dom/locale/is.js +6 -0
  89. package/dist/src/dom/locale/it.d.ts +6 -0
  90. package/dist/src/dom/locale/it.js +6 -0
  91. package/dist/src/dom/locale/ja.d.ts +6 -0
  92. package/dist/src/dom/locale/ja.js +6 -0
  93. package/dist/src/dom/locale/ka.d.ts +6 -0
  94. package/dist/src/dom/locale/ka.js +6 -0
  95. package/dist/src/dom/locale/kk.d.ts +6 -0
  96. package/dist/src/dom/locale/kk.js +6 -0
  97. package/dist/src/dom/locale/kn.d.ts +7 -0
  98. package/dist/src/dom/locale/kn.js +7 -0
  99. package/dist/src/dom/locale/ko.d.ts +6 -0
  100. package/dist/src/dom/locale/ko.js +6 -0
  101. package/dist/src/dom/locale/lt.d.ts +7 -0
  102. package/dist/src/dom/locale/lt.js +7 -0
  103. package/dist/src/dom/locale/lv.d.ts +6 -0
  104. package/dist/src/dom/locale/lv.js +6 -0
  105. package/dist/src/dom/locale/mk.d.ts +5 -0
  106. package/dist/src/dom/locale/mk.js +5 -0
  107. package/dist/src/dom/locale/ml.d.ts +7 -0
  108. package/dist/src/dom/locale/ml.js +7 -0
  109. package/dist/src/dom/locale/mn.d.ts +7 -0
  110. package/dist/src/dom/locale/mn.js +7 -0
  111. package/dist/src/dom/locale/mr.d.ts +7 -0
  112. package/dist/src/dom/locale/mr.js +7 -0
  113. package/dist/src/dom/locale/ms.d.ts +6 -0
  114. package/dist/src/dom/locale/ms.js +6 -0
  115. package/dist/src/dom/locale/my.d.ts +6 -0
  116. package/dist/src/dom/locale/my.js +6 -0
  117. package/dist/src/dom/locale/nb.d.ts +6 -0
  118. package/dist/src/dom/locale/nb.js +6 -0
  119. package/dist/src/dom/locale/nl.d.ts +6 -0
  120. package/dist/src/dom/locale/nl.js +6 -0
  121. package/dist/src/dom/locale/pa.d.ts +7 -0
  122. package/dist/src/dom/locale/pa.js +7 -0
  123. package/dist/src/dom/locale/pl.d.ts +6 -0
  124. package/dist/src/dom/locale/pl.js +6 -0
  125. package/dist/src/dom/locale/pt-BR.d.ts +6 -0
  126. package/dist/src/dom/locale/pt-BR.js +6 -0
  127. package/dist/src/dom/locale/pt-PT.d.ts +6 -0
  128. package/dist/src/dom/locale/pt-PT.js +6 -0
  129. package/dist/src/dom/locale/ro.d.ts +5 -0
  130. package/dist/src/dom/locale/ro.js +5 -0
  131. package/dist/src/dom/locale/ru.d.ts +3 -0
  132. package/dist/src/dom/locale/ru.js +3 -0
  133. package/dist/src/dom/locale/sk.d.ts +6 -0
  134. package/dist/src/dom/locale/sk.js +6 -0
  135. package/dist/src/dom/locale/sl.d.ts +6 -0
  136. package/dist/src/dom/locale/sl.js +6 -0
  137. package/dist/src/dom/locale/so.d.ts +6 -0
  138. package/dist/src/dom/locale/so.js +6 -0
  139. package/dist/src/dom/locale/sq.d.ts +6 -0
  140. package/dist/src/dom/locale/sq.js +6 -0
  141. package/dist/src/dom/locale/sr.d.ts +3 -0
  142. package/dist/src/dom/locale/sr.js +3 -0
  143. package/dist/src/dom/locale/sv.d.ts +6 -0
  144. package/dist/src/dom/locale/sv.js +6 -0
  145. package/dist/src/dom/locale/sw.d.ts +6 -0
  146. package/dist/src/dom/locale/sw.js +6 -0
  147. package/dist/src/dom/locale/ta.d.ts +7 -0
  148. package/dist/src/dom/locale/ta.js +7 -0
  149. package/dist/src/dom/locale/te.d.ts +7 -0
  150. package/dist/src/dom/locale/te.js +7 -0
  151. package/dist/src/dom/locale/th.d.ts +6 -0
  152. package/dist/src/dom/locale/th.js +6 -0
  153. package/dist/src/dom/locale/tr.d.ts +6 -0
  154. package/dist/src/dom/locale/tr.js +6 -0
  155. package/dist/src/dom/locale/types.d.ts +8 -1
  156. package/dist/src/dom/locale/uk.d.ts +6 -0
  157. package/dist/src/dom/locale/uk.js +6 -0
  158. package/dist/src/dom/locale/ur.d.ts +6 -0
  159. package/dist/src/dom/locale/ur.js +6 -0
  160. package/dist/src/dom/locale/vi.d.ts +6 -0
  161. package/dist/src/dom/locale/vi.js +6 -0
  162. package/dist/src/dom/locale/zh-HK.d.ts +7 -0
  163. package/dist/src/dom/locale/zh-HK.js +7 -0
  164. package/dist/src/dom/locale/zh-Hans.d.ts +7 -0
  165. package/dist/src/dom/locale/zh-Hans.js +7 -0
  166. package/dist/src/dom/locale/zh-TW.d.ts +7 -0
  167. package/dist/src/dom/locale/zh-TW.js +7 -0
  168. package/dist/src/dom/menus.js +13 -2
  169. package/dist/src/dom/wait-snapshot.d.ts +43 -0
  170. package/dist/src/dom/wait-snapshot.js +127 -0
  171. package/dist/src/safety/risk.d.ts +1 -0
  172. package/dist/src/safety/risk.js +1 -0
  173. package/dist/src/scripts/apply-intelligence-locale-captures.js +99 -13
  174. package/dist/src/types.d.ts +28 -0
  175. package/package.json +2 -2
  176. package/references/backend-protocol.md +6 -4
  177. package/references/localization.md +14 -4
  178. package/references/python-parity.md +5 -3
  179. package/references/troubleshooting.md +28 -5
@@ -251,8 +251,23 @@ var en = {
251
251
  imageContainerHint: ["image"],
252
252
  // --- Mode switcher (also the canonical public API keys) ---
253
253
  modeLabels: ["Latest", "Instant", "Thinking", "Extended", "Medium", "High", "Extra High", "Pro"],
254
+ modeOptions: {
255
+ latest: ["Latest"],
256
+ instant: ["Instant"],
257
+ thinking: ["Thinking"],
258
+ extended: ["Extended"],
259
+ medium: ["Medium"],
260
+ high: ["High"],
261
+ extraHigh: ["Extra High"],
262
+ pro: ["Pro", "Pro Extended", "Extended Pro"]
263
+ },
254
264
  /** Extra openers that surface the mode menu but are not selectable modes themselves. */
255
265
  modeOpenerExtra: ["Configure"],
266
+ // --- Thread/action menu rejection (wrong-menu veto for mode selection) ---
267
+ /** Exact thread/conversation action menu items; a menu containing these is not the mode menu. */
268
+ threadActionMenuItems: ["Archive", "Copy link", "Delete", "Move to project", "Rename", "Share"],
269
+ /** Action verbs that prefix a thread title in sidebar menus, e.g. "Pin <thread title>". */
270
+ threadActionPrefixes: ["Pin", "Unpin"],
256
271
  // --- Tool menu items, keyed by logical tool id ---
257
272
  tools: {
258
273
  web_search: ["Web search"],
@@ -291,6 +306,12 @@ var de = {
291
306
  addPhotosFilesMenuItem: ["Fotos und Dateien hinzuf\xFCgen"],
292
307
  copyResponse: ["Antwort kopieren"],
293
308
  modeLabels: ["Sofort", "Mittel", "Hoch", "Extra hoch"],
309
+ modeOptions: {
310
+ instant: ["Sofort"],
311
+ medium: ["Mittel"],
312
+ high: ["Hoch"],
313
+ extraHigh: ["Extra hoch"]
314
+ },
294
315
  modeOpenerExtra: ["Konfigurieren"],
295
316
  tools: {
296
317
  web_search: ["Websuche"],
@@ -312,6 +333,12 @@ var esES = {
312
333
  addPhotosFilesMenuItem: ["A\xF1adir fotos y archivos"],
313
334
  copyResponse: ["Copiar respuesta"],
314
335
  modeLabels: ["Instant\xE1nea", "Media", "Alta", "Muy alta"],
336
+ modeOptions: {
337
+ instant: ["Instant\xE1nea"],
338
+ medium: ["Media"],
339
+ high: ["Alta"],
340
+ extraHigh: ["Muy alta"]
341
+ },
315
342
  modeOpenerExtra: ["Configurar"],
316
343
  tools: {
317
344
  web_search: ["B\xFAsqueda en Internet"],
@@ -334,6 +361,11 @@ var frFR = {
334
361
  addPhotosFilesMenuItem: ["Ajouter des photos et fichiers"],
335
362
  copyResponse: ["Copier la r\xE9ponse"],
336
363
  modeLabels: ["Moyen", "Avanc\xE9", "Tr\xE8s \xE9lev\xE9"],
364
+ modeOptions: {
365
+ medium: ["Moyen"],
366
+ high: ["Avanc\xE9"],
367
+ extraHigh: ["Tr\xE8s \xE9lev\xE9"]
368
+ },
337
369
  modeOpenerExtra: ["Configurer"],
338
370
  tools: {
339
371
  web_search: ["Recherche sur le Web"],
@@ -356,6 +388,13 @@ var zhHK = {
356
388
  addPhotosFilesMenuItem: ["\u52A0\u5165\u76F8\u7247\u548C\u6A94\u6848"],
357
389
  copyResponse: ["\u8907\u88FD\u56DE\u8986"],
358
390
  modeLabels: ["\u5373\u6642", "\u5747\u8861", "\u9AD8", "\u6975\u9AD8", "\u5C08\u696D"],
391
+ modeOptions: {
392
+ instant: ["\u5373\u6642"],
393
+ medium: ["\u5747\u8861"],
394
+ high: ["\u9AD8"],
395
+ extraHigh: ["\u6975\u9AD8"],
396
+ pro: ["\u5C08\u696D"]
397
+ },
359
398
  modeOpenerExtra: ["\u8A2D\u5B9A"],
360
399
  tools: {
361
400
  web_search: ["\u7DB2\u7D61\u641C\u5C0B"],
@@ -378,6 +417,13 @@ var zhTW = {
378
417
  addPhotosFilesMenuItem: ["\u65B0\u589E\u7167\u7247\u548C\u6A94\u6848"],
379
418
  copyResponse: ["\u8907\u88FD\u56DE\u61C9"],
380
419
  modeLabels: ["\u5373\u6642", "\u4E2D\u7B49", "\u9AD8", "\u8D85\u9AD8", "\u5C08\u696D"],
420
+ modeOptions: {
421
+ instant: ["\u5373\u6642"],
422
+ medium: ["\u4E2D\u7B49"],
423
+ high: ["\u9AD8"],
424
+ extraHigh: ["\u8D85\u9AD8"],
425
+ pro: ["\u5C08\u696D"]
426
+ },
381
427
  modeOpenerExtra: ["\u8A2D\u5B9A"],
382
428
  tools: {
383
429
  web_search: ["\u7DB2\u9801\u641C\u5C0B"],
@@ -400,6 +446,12 @@ var ja = {
400
446
  addPhotosFilesMenuItem: ["\u5199\u771F\u3068\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0"],
401
447
  copyResponse: ["\u56DE\u7B54\u3092\u30B3\u30D4\u30FC\u3059\u308B"],
402
448
  modeLabels: ["\u6700\u901F", "\u6A19\u6E96", "\u9AD8", "\u6700\u9AD8"],
449
+ modeOptions: {
450
+ instant: ["\u6700\u901F"],
451
+ medium: ["\u6A19\u6E96"],
452
+ high: ["\u9AD8"],
453
+ extraHigh: ["\u6700\u9AD8"]
454
+ },
403
455
  modeOpenerExtra: ["\u8A2D\u5B9A\u3059\u308B"],
404
456
  tools: {
405
457
  web_search: ["\u30A6\u30A7\u30D6\u691C\u7D22"],
@@ -421,6 +473,12 @@ var it = {
421
473
  addPhotosFilesMenuItem: ["Aggiungi foto e file"],
422
474
  copyResponse: ["Copia risposta"],
423
475
  modeLabels: ["Istantanea", "Media", "Alta", "Extra elevata"],
476
+ modeOptions: {
477
+ instant: ["Istantanea"],
478
+ medium: ["Media"],
479
+ high: ["Alta"],
480
+ extraHigh: ["Extra elevata"]
481
+ },
424
482
  modeOpenerExtra: ["Configura"],
425
483
  tools: {
426
484
  web_search: ["Ricerca sul web"],
@@ -442,6 +500,12 @@ var vi = {
442
500
  addPhotosFilesMenuItem: ["Th\xEAm \u1EA3nh v\xE0 t\u1EC7p"],
443
501
  copyResponse: ["Sao ch\xE9p ph\u1EA3n h\u1ED3i"],
444
502
  modeLabels: ["T\u1EE9c th\xEC", "Trung b\xECnh", "Cao", "R\u1EA5t cao"],
503
+ modeOptions: {
504
+ instant: ["T\u1EE9c th\xEC"],
505
+ medium: ["Trung b\xECnh"],
506
+ high: ["Cao"],
507
+ extraHigh: ["R\u1EA5t cao"]
508
+ },
445
509
  modeOpenerExtra: ["\u0110\u1ECBnh c\u1EA5u h\xECnh"],
446
510
  tools: {
447
511
  web_search: ["T\xECm ki\u1EBFm tr\xEAn m\u1EA1ng"],
@@ -464,6 +528,12 @@ var am = {
464
528
  addPhotosFilesMenuItem: ["\u134E\u1276\u12CE\u127D\u1295 \u12A5\u1293 \u134B\u12ED\u120E\u127D\u1295 \u12EB\u12AD\u1209"],
465
529
  copyResponse: ["\u121D\u120B\u1239\u1295 \u12ED\u1245\u12F1"],
466
530
  modeLabels: ["\u1348\u1323\u1295", "\u1218\u12AB\u12A8\u1208\u129B", "\u12A8\u134D\u1270\u129B", "\u12A5\u1305\u130D \u12A8\u134D\u1270\u129B"],
531
+ modeOptions: {
532
+ instant: ["\u1348\u1323\u1295"],
533
+ medium: ["\u1218\u12AB\u12A8\u1208\u129B"],
534
+ high: ["\u12A8\u134D\u1270\u129B"],
535
+ extraHigh: ["\u12A5\u1305\u130D \u12A8\u134D\u1270\u129B"]
536
+ },
467
537
  modeOpenerExtra: ["\u12EB\u12CB\u1245\u1229"],
468
538
  tools: {
469
539
  web_search: ["\u12E8\u12F5\u122D \u134D\u1208\u130B"],
@@ -486,6 +556,13 @@ var ar = {
486
556
  addPhotosFilesMenuItem: ["\u0625\u0636\u0627\u0641\u0629 \u0635\u0648\u0631 \u0648\u0645\u0644\u0641\u0627\u062A"],
487
557
  copyResponse: ["\u0646\u0633\u062E \u0625\u062C\u0627\u0628\u0629"],
488
558
  modeLabels: ["\u0641\u0648\u0631\u064A", "\u0645\u062A\u0648\u0633\u0637", "\u0639\u0627\u0644\u064A", "\u0645\u0643\u062B\u0641 \u062C\u062F\u064B\u0627", "\u0627\u062D\u062A\u0631\u0627\u0641\u064A"],
559
+ modeOptions: {
560
+ instant: ["\u0641\u0648\u0631\u064A"],
561
+ medium: ["\u0645\u062A\u0648\u0633\u0637"],
562
+ high: ["\u0639\u0627\u0644\u064A"],
563
+ extraHigh: ["\u0645\u0643\u062B\u0641 \u062C\u062F\u064B\u0627"],
564
+ pro: ["\u0627\u062D\u062A\u0631\u0627\u0641\u064A"]
565
+ },
489
566
  modeOpenerExtra: ["\u062A\u0643\u0648\u064A\u0646"],
490
567
  tools: {
491
568
  web_search: ["\u0627\u0644\u0628\u062D\u062B \u0641\u064A \u0627\u0644\u0648\u064A\u0628"],
@@ -508,6 +585,13 @@ var bg = {
508
585
  addPhotosFilesMenuItem: ["\u0414\u043E\u0431\u0430\u0432\u044F\u043D\u0435 \u043D\u0430 \u0441\u043D\u0438\u043C\u043A\u0438 \u0438 \u0444\u0430\u0439\u043B\u043E\u0432\u0435"],
509
586
  copyResponse: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0439\u0442\u0435 \u043E\u0442\u0433\u043E\u0432\u043E\u0440\u0430"],
510
587
  modeLabels: ["\u041C\u0438\u0433\u043D\u043E\u0432\u0435\u043D", "\u0421\u0440\u0435\u0434\u0435\u043D", "\u0412\u0438\u0441\u043E\u043A", "\u041C\u043D\u043E\u0433\u043E \u0432\u0438\u0441\u043E\u043A\u043E", "\u041F\u0440\u043E"],
588
+ modeOptions: {
589
+ instant: ["\u041C\u0438\u0433\u043D\u043E\u0432\u0435\u043D"],
590
+ medium: ["\u0421\u0440\u0435\u0434\u0435\u043D"],
591
+ high: ["\u0412\u0438\u0441\u043E\u043A"],
592
+ extraHigh: ["\u041C\u043D\u043E\u0433\u043E \u0432\u0438\u0441\u043E\u043A\u043E"],
593
+ pro: ["\u041F\u0440\u043E"]
594
+ },
511
595
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0439\u0442\u0435"],
512
596
  tools: {
513
597
  web_search: ["\u0422\u044A\u0440\u0441\u0435\u043D\u0435 \u0432 \u0438\u043D\u0442\u0435\u0440\u043D\u0435\u0442"],
@@ -530,6 +614,12 @@ var bs = {
530
614
  addPhotosFilesMenuItem: ["Dodaj slike i datoteke"],
531
615
  copyResponse: ["Kopiraj odgovor"],
532
616
  modeLabels: ["Brzo", "Srednji", "Visoko", "Vrlo visoko"],
617
+ modeOptions: {
618
+ instant: ["Brzo"],
619
+ medium: ["Srednji"],
620
+ high: ["Visoko"],
621
+ extraHigh: ["Vrlo visoko"]
622
+ },
533
623
  modeOpenerExtra: ["Podesi"],
534
624
  tools: {
535
625
  web_search: ["Internet pretraga"],
@@ -552,6 +642,12 @@ var ca = {
552
642
  addPhotosFilesMenuItem: ["Afegeix fotos i fitxers"],
553
643
  copyResponse: ["Copia la resposta"],
554
644
  modeLabels: ["Instantani", "Mitj\xE0", "Alt", "Molt alt"],
645
+ modeOptions: {
646
+ instant: ["Instantani"],
647
+ medium: ["Mitj\xE0"],
648
+ high: ["Alt"],
649
+ extraHigh: ["Molt alt"]
650
+ },
555
651
  modeOpenerExtra: ["Configura\u2026"],
556
652
  tools: {
557
653
  web_search: ["Cerca a la xarxa"],
@@ -574,6 +670,12 @@ var cs = {
574
670
  addPhotosFilesMenuItem: ["P\u0159idat fotografie a soubory"],
575
671
  copyResponse: ["Zkop\xEDrovat odpov\u011B\u010F"],
576
672
  modeLabels: ["Okam\u017Eit\xE1", "St\u0159edn\xED", "Vysok\xE1", "Velmi vysok\xE1"],
673
+ modeOptions: {
674
+ instant: ["Okam\u017Eit\xE1"],
675
+ medium: ["St\u0159edn\xED"],
676
+ high: ["Vysok\xE1"],
677
+ extraHigh: ["Velmi vysok\xE1"]
678
+ },
577
679
  modeOpenerExtra: ["Konfigurovat\u2026"],
578
680
  tools: {
579
681
  web_search: ["Vyhled\xE1v\xE1n\xED na webu"],
@@ -596,6 +698,11 @@ var da = {
596
698
  addPhotosFilesMenuItem: ["Tilf\xF8j billeder og filer"],
597
699
  copyResponse: ["Kopi\xE9r svar"],
598
700
  modeLabels: ["\xD8jeblikkeligt", "H\xF8j", "Ekstra h\xF8j"],
701
+ modeOptions: {
702
+ instant: ["\xD8jeblikkeligt"],
703
+ high: ["H\xF8j"],
704
+ extraHigh: ["Ekstra h\xF8j"]
705
+ },
599
706
  modeOpenerExtra: ["Konfigurer ..."],
600
707
  tools: {
601
708
  web_search: ["Internets\xF8gning"],
@@ -618,6 +725,12 @@ var el = {
618
725
  addPhotosFilesMenuItem: ["\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03C6\u03C9\u03C4\u03BF\u03B3\u03C1\u03B1\u03C6\u03B9\u03CE\u03BD & \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD"],
619
726
  copyResponse: ["\u0391\u03BD\u03C4\u03B9\u03B3\u03C1\u03B1\u03C6\u03AE \u03B1\u03C0\u03AC\u03BD\u03C4\u03B7\u03C3\u03B7\u03C2"],
620
727
  modeLabels: ["\u0386\u03BC\u03B5\u03C3\u03B7", "\u039C\u03B5\u03C3\u03B1\u03AF\u03B1", "\u03A5\u03C8\u03B7\u03BB\u03AE", "\u03A0\u03BF\u03BB\u03CD \u03C5\u03C8\u03B7\u03BB\u03CC"],
728
+ modeOptions: {
729
+ instant: ["\u0386\u03BC\u03B5\u03C3\u03B7"],
730
+ medium: ["\u039C\u03B5\u03C3\u03B1\u03AF\u03B1"],
731
+ high: ["\u03A5\u03C8\u03B7\u03BB\u03AE"],
732
+ extraHigh: ["\u03A0\u03BF\u03BB\u03CD \u03C5\u03C8\u03B7\u03BB\u03CC"]
733
+ },
621
734
  modeOpenerExtra: ["\u0394\u03B9\u03B1\u03BC\u03CC\u03C1\u03C6\u03C9\u03C3\u03B7\u2026"],
622
735
  tools: {
623
736
  web_search: ["\u0391\u03BD\u03B1\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7 \u03C3\u03C4\u03BF\u03BD \u03B9\u03C3\u03C4\u03CC"],
@@ -640,6 +753,12 @@ var es419 = {
640
753
  addPhotosFilesMenuItem: ["Agregar fotos y archivos"],
641
754
  copyResponse: ["Copiar respuesta"],
642
755
  modeLabels: ["Instant\xE1nea", "Media", "Alta", "Muy alta"],
756
+ modeOptions: {
757
+ instant: ["Instant\xE1nea"],
758
+ medium: ["Media"],
759
+ high: ["Alta"],
760
+ extraHigh: ["Muy alta"]
761
+ },
643
762
  modeOpenerExtra: ["Configurar..."],
644
763
  tools: {
645
764
  web_search: ["Busca en la web"],
@@ -662,6 +781,12 @@ var et = {
662
781
  addPhotosFilesMenuItem: ["Lisa fotosid ja faile"],
663
782
  copyResponse: ["Kopeeri vastus"],
664
783
  modeLabels: ["Kohene", "Keskmine", "K\xF5rge", "V\xE4ga k\xF5rge"],
784
+ modeOptions: {
785
+ instant: ["Kohene"],
786
+ medium: ["Keskmine"],
787
+ high: ["K\xF5rge"],
788
+ extraHigh: ["V\xE4ga k\xF5rge"]
789
+ },
665
790
  modeOpenerExtra: ["Konfigureeri..."],
666
791
  tools: {
667
792
  web_search: ["Veebiotsing"],
@@ -684,6 +809,13 @@ var fa = {
684
809
  addPhotosFilesMenuItem: ["\u0627\u0641\u0632\u0648\u062F\u0646 \u062A\u0635\u0627\u0648\u06CC\u0631 \u0648 \u0641\u0627\u06CC\u0644\u200C\u0647\u0627"],
685
810
  copyResponse: ["\u06A9\u067E\u06CC \u06A9\u0631\u062F\u0646 \u067E\u0627\u0633\u062E"],
686
811
  modeLabels: ["\u0641\u0648\u0631\u06CC", "\u0645\u062A\u0648\u0633\u0637", "\u0628\u0627\u0644\u0627", "\u0628\u0633\u06CC\u0627\u0631 \u0632\u06CC\u0627\u062F", "\u062D\u0631\u0641\u0647\u200C\u0627\u06CC"],
812
+ modeOptions: {
813
+ instant: ["\u0641\u0648\u0631\u06CC"],
814
+ medium: ["\u0645\u062A\u0648\u0633\u0637"],
815
+ high: ["\u0628\u0627\u0644\u0627"],
816
+ extraHigh: ["\u0628\u0633\u06CC\u0627\u0631 \u0632\u06CC\u0627\u062F"],
817
+ pro: ["\u062D\u0631\u0641\u0647\u200C\u0627\u06CC"]
818
+ },
687
819
  modeOpenerExtra: ["\u067E\u06CC\u06A9\u0631\u0628\u0646\u062F\u06CC..."],
688
820
  tools: {
689
821
  web_search: ["\u062C\u0633\u062A\u062C\u0648\u06CC \u0648\u0628"],
@@ -706,6 +838,12 @@ var fi = {
706
838
  addPhotosFilesMenuItem: ["Lis\xE4\xE4 valokuvia & tiedostoja"],
707
839
  copyResponse: ["Kopioi vastaus"],
708
840
  modeLabels: ["V\xE4lit\xF6n", "Keskitaso", "Korkea", "Eritt\xE4in korkea"],
841
+ modeOptions: {
842
+ instant: ["V\xE4lit\xF6n"],
843
+ medium: ["Keskitaso"],
844
+ high: ["Korkea"],
845
+ extraHigh: ["Eritt\xE4in korkea"]
846
+ },
709
847
  modeOpenerExtra: ["M\xE4\xE4rit\xE4..."],
710
848
  tools: {
711
849
  web_search: ["Verkkohaku"],
@@ -728,6 +866,12 @@ var frCA = {
728
866
  addPhotosFilesMenuItem: ["Ajouter des photos et des fichiers"],
729
867
  copyResponse: ["Copier la r\xE9ponse"],
730
868
  modeLabels: ["Instantan\xE9", "Moyen", "\xC9lev\xE9", "Tr\xE8s \xE9lev\xE9"],
869
+ modeOptions: {
870
+ instant: ["Instantan\xE9"],
871
+ medium: ["Moyen"],
872
+ high: ["\xC9lev\xE9"],
873
+ extraHigh: ["Tr\xE8s \xE9lev\xE9"]
874
+ },
731
875
  modeOpenerExtra: ["Configurer..."],
732
876
  tools: {
733
877
  web_search: ["Recherche sur Internet"],
@@ -750,6 +894,12 @@ var gu = {
750
894
  addPhotosFilesMenuItem: ["\u0AAB\u0ACB\u0A9F\u0ABE \u0A85\u0AA8\u0AC7 \u0AAB\u0ABE\u0A87\u0AB2\u0ACB \u0A89\u0AAE\u0AC7\u0AB0\u0ACB"],
751
895
  copyResponse: ["\u0AAA\u0ACD\u0AB0\u0AA4\u0ABF\u0AAD\u0ABE\u0AB5 \u0A95\u0AC9\u0AAA\u0ABF \u0A95\u0AB0\u0ACB"],
752
896
  modeLabels: ["\u0AA4\u0AB0\u0AA4", "\u0AAE\u0AA7\u0ACD\u0AAF\u0AAE", "\u0A89\u0A9A\u0ACD\u0A9A", "\u0A85\u0AA4\u0ABF \u0A89\u0A9A\u0ACD\u0A9A"],
897
+ modeOptions: {
898
+ instant: ["\u0AA4\u0AB0\u0AA4"],
899
+ medium: ["\u0AAE\u0AA7\u0ACD\u0AAF\u0AAE"],
900
+ high: ["\u0A89\u0A9A\u0ACD\u0A9A"],
901
+ extraHigh: ["\u0A85\u0AA4\u0ABF \u0A89\u0A9A\u0ACD\u0A9A"]
902
+ },
753
903
  modeOpenerExtra: ["\u0A95\u0AA8\u0ACD\u0AAB\u0ABF\u0A97\u0AB0 \u0A95\u0AB0\u0ACB..."],
754
904
  tools: {
755
905
  web_search: ["\u0AB5\u0AC7\u0AAC \u0AB6\u0ACB\u0AA7"],
@@ -772,6 +922,12 @@ var hi = {
772
922
  addPhotosFilesMenuItem: ["\u092B\u093C\u094B\u091F\u094B \u0914\u0930 \u092B\u093C\u093E\u0907\u0932\u0947\u0902 \u091C\u094B\u0921\u093C\u0947\u0902"],
773
923
  copyResponse: ["\u091C\u0935\u093E\u092C \u0915\u094B \u0915\u0949\u092A\u0940 \u0915\u0930\u0947\u0902"],
774
924
  modeLabels: ["\u0924\u0941\u0930\u0902\u0924", "\u092E\u0927\u094D\u092F\u092E", "\u0909\u091A\u094D\u091A", "\u092C\u0939\u0941\u0924 \u0909\u091A\u094D\u091A"],
925
+ modeOptions: {
926
+ instant: ["\u0924\u0941\u0930\u0902\u0924"],
927
+ medium: ["\u092E\u0927\u094D\u092F\u092E"],
928
+ high: ["\u0909\u091A\u094D\u091A"],
929
+ extraHigh: ["\u092C\u0939\u0941\u0924 \u0909\u091A\u094D\u091A"]
930
+ },
775
931
  modeOpenerExtra: ["\u0915\u0949\u0928\u094D\u092B\u093C\u093F\u0917\u0930 \u0915\u0930\u0947\u0902..."],
776
932
  tools: {
777
933
  web_search: ["\u0935\u0947\u092C \u0938\u0930\u094D\u091A"],
@@ -794,6 +950,11 @@ var hr = {
794
950
  addPhotosFilesMenuItem: ["Dodaj fotografije i datoteke"],
795
951
  copyResponse: ["Kopiraj odgovor"],
796
952
  modeLabels: ["Srednje", "Visoko", "Vrlo visoka"],
953
+ modeOptions: {
954
+ medium: ["Srednje"],
955
+ high: ["Visoko"],
956
+ extraHigh: ["Vrlo visoka"]
957
+ },
797
958
  modeOpenerExtra: ["Konfiguriraj\u2026"],
798
959
  tools: {
799
960
  web_search: ["Mre\u017Eno pretra\u017Eivanje"],
@@ -816,6 +977,12 @@ var hu = {
816
977
  addPhotosFilesMenuItem: ["Fot\xF3k \xE9s f\xE1jlok hozz\xE1ad\xE1sa"],
817
978
  copyResponse: ["V\xE1lasz m\xE1sol\xE1sa"],
818
979
  modeLabels: ["Azonnali", "K\xF6zepes", "Magas", "Kiemelked\u0151en magas"],
980
+ modeOptions: {
981
+ instant: ["Azonnali"],
982
+ medium: ["K\xF6zepes"],
983
+ high: ["Magas"],
984
+ extraHigh: ["Kiemelked\u0151en magas"]
985
+ },
819
986
  modeOpenerExtra: ["Konfigur\xE1l\xE1s..."],
820
987
  tools: {
821
988
  web_search: ["Internetes keres\xE9s"],
@@ -838,6 +1005,13 @@ var hy = {
838
1005
  addPhotosFilesMenuItem: ["\u0531\u057E\u0565\u056C\u0561\u0581\u0576\u0565\u056C \u056C\u0578\u0582\u057D\u0561\u0576\u056F\u0561\u0580\u0576\u0565\u0580 \u0587 \u0586\u0561\u0575\u056C\u0565\u0580"],
839
1006
  copyResponse: ["\u054A\u0561\u057F\u0573\u0565\u0576\u0565\u056C \u057A\u0561\u057F\u0561\u057D\u056D\u0561\u0576\u0568"],
840
1007
  modeLabels: ["\u0531\u056F\u0576\u0569\u0561\u0580\u0569\u0561\u0575\u056B\u0576", "\u0544\u056B\u057B\u056B\u0576", "\u0532\u0561\u0580\u0571\u0580", "\u0547\u0561\u057F \u0562\u0561\u0580\u0571\u0580", "\u054A\u0580\u0578"],
1008
+ modeOptions: {
1009
+ instant: ["\u0531\u056F\u0576\u0569\u0561\u0580\u0569\u0561\u0575\u056B\u0576"],
1010
+ medium: ["\u0544\u056B\u057B\u056B\u0576"],
1011
+ high: ["\u0532\u0561\u0580\u0571\u0580"],
1012
+ extraHigh: ["\u0547\u0561\u057F \u0562\u0561\u0580\u0571\u0580"],
1013
+ pro: ["\u054A\u0580\u0578"]
1014
+ },
841
1015
  modeOpenerExtra: ["\u053F\u0561\u0566\u0574\u0561\u0571\u0587\u0565\u056C\u2024\u2024\u2024"],
842
1016
  tools: {
843
1017
  web_search: ["\u054E\u0565\u0562 \u0578\u0580\u0578\u0576\u0578\u0582\u0574"],
@@ -860,6 +1034,12 @@ var id = {
860
1034
  addPhotosFilesMenuItem: ["Tambah foto & file"],
861
1035
  copyResponse: ["Salin respons"],
862
1036
  modeLabels: ["Instan", "Sedang", "Tinggi", "Sangat Tinggi"],
1037
+ modeOptions: {
1038
+ instant: ["Instan"],
1039
+ medium: ["Sedang"],
1040
+ high: ["Tinggi"],
1041
+ extraHigh: ["Sangat Tinggi"]
1042
+ },
863
1043
  modeOpenerExtra: ["Konfigurasi..."],
864
1044
  tools: {
865
1045
  web_search: ["Pencarian web"],
@@ -882,6 +1062,12 @@ var is = {
882
1062
  addPhotosFilesMenuItem: ["B\xE6ta myndum og skr\xE1m vi\xF0"],
883
1063
  copyResponse: ["Afrita svar"],
884
1064
  modeLabels: ["Strax", "Mi\xF0lungs", "H\xE1tt", "Mj\xF6g h\xE1tt"],
1065
+ modeOptions: {
1066
+ instant: ["Strax"],
1067
+ medium: ["Mi\xF0lungs"],
1068
+ high: ["H\xE1tt"],
1069
+ extraHigh: ["Mj\xF6g h\xE1tt"]
1070
+ },
885
1071
  modeOpenerExtra: ["Stillir\u2026"],
886
1072
  tools: {
887
1073
  web_search: ["Vefleit"],
@@ -904,6 +1090,12 @@ var ka = {
904
1090
  addPhotosFilesMenuItem: ["\u10E4\u10DD\u10E2\u10DD\u10D4\u10D1\u10D8\u10E1 \u10D3\u10D0 \u10E4\u10D0\u10D8\u10DA\u10D4\u10D1\u10D8\u10E1 \u10D3\u10D0\u10DB\u10D0\u10E2\u10D4\u10D1\u10D0"],
905
1091
  copyResponse: ["\u10DE\u10D0\u10E1\u10E3\u10EE\u10D8\u10E1 \u10D9\u10DD\u10DE\u10D8\u10E0\u10D4\u10D1\u10D0"],
906
1092
  modeLabels: ["\u10DB\u10E7\u10D8\u10E1\u10D8\u10D4\u10E0\u10D8", "\u10E1\u10D0\u10E8\u10E3\u10D0\u10DA\u10DD", "\u10DB\u10D0\u10E6\u10D0\u10DA\u10D8", "\u10EB\u10D0\u10DA\u10D8\u10D0\u10DC \u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"],
1093
+ modeOptions: {
1094
+ instant: ["\u10DB\u10E7\u10D8\u10E1\u10D8\u10D4\u10E0\u10D8"],
1095
+ medium: ["\u10E1\u10D0\u10E8\u10E3\u10D0\u10DA\u10DD"],
1096
+ high: ["\u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"],
1097
+ extraHigh: ["\u10EB\u10D0\u10DA\u10D8\u10D0\u10DC \u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"]
1098
+ },
907
1099
  modeOpenerExtra: ["\u10D9\u10DD\u10DC\u10E4\u10D8\u10D2\u10E3\u10E0\u10D8\u10E0\u10D4\u10D1\u10D0\u2026"],
908
1100
  tools: {
909
1101
  web_search: ["\u10D5\u10D4\u10D1\u10E8\u10D8 \u10EB\u10D8\u10D4\u10D1\u10D0"],
@@ -926,6 +1118,12 @@ var kk = {
926
1118
  addPhotosFilesMenuItem: ["\u0424\u043E\u0442\u043E\u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 \u043C\u0435\u043D \u0444\u0430\u0439\u043B\u0434\u0430\u0440 \u049B\u043E\u0441\u0443"],
927
1119
  copyResponse: ["\u0416\u0430\u0443\u0430\u043F\u0442\u044B \u043A\u04E9\u0448\u0456\u0440\u0443"],
928
1120
  modeLabels: ["\u0416\u0435\u0434\u0435\u043B", "\u041E\u0440\u0442\u0430\u0448\u0430", "\u0416\u043E\u0493\u0430\u0440\u044B", "\u0410\u0441\u0430 \u0436\u043E\u0493\u0430\u0440\u044B"],
1121
+ modeOptions: {
1122
+ instant: ["\u0416\u0435\u0434\u0435\u043B"],
1123
+ medium: ["\u041E\u0440\u0442\u0430\u0448\u0430"],
1124
+ high: ["\u0416\u043E\u0493\u0430\u0440\u044B"],
1125
+ extraHigh: ["\u0410\u0441\u0430 \u0436\u043E\u0493\u0430\u0440\u044B"]
1126
+ },
929
1127
  modeOpenerExtra: ["\u041A\u043E\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F\u043B\u0430\u0443..."],
930
1128
  tools: {
931
1129
  web_search: ["\u0406\u0437\u0434\u0435\u0443"],
@@ -948,6 +1146,13 @@ var kn = {
948
1146
  addPhotosFilesMenuItem: ["\u0CAB\u0CCB\u0C9F\u0CCA \u0CAE\u0CA4\u0CCD\u0CA4\u0CC1 \u0CAB\u0CC8\u0CB2\u0CCD\u200C\u0C97\u0CB3\u0CA8\u0CCD\u0CA8\u0CC1 \u0CB8\u0CC7\u0CB0\u0CBF\u0CB8\u0CBF"],
949
1147
  copyResponse: ["\u0CAA\u0CCD\u0CB0\u0CA4\u0CBF\u0C95\u0CCD\u0CB0\u0CBF\u0CAF\u0CC6\u0CAF\u0CA8\u0CCD\u0CA8\u0CC1 \u0CA8\u0C95\u0CB2\u0CBF\u0CB8\u0CBF"],
950
1148
  modeLabels: ["\u0CA4\u0C95\u0CCD\u0CB7\u0CA3", "\u0CAE\u0CA7\u0CCD\u0CAF\u0CAE", "\u0C89\u0CA8\u0CCD\u0CA8\u0CA4", "\u0C85\u0CA4\u0CBF \u0CB9\u0CC6\u0C9A\u0CCD\u0C9A\u0CC1", "\u0CAA\u0CCD\u0CB0\u0CCA"],
1149
+ modeOptions: {
1150
+ instant: ["\u0CA4\u0C95\u0CCD\u0CB7\u0CA3"],
1151
+ medium: ["\u0CAE\u0CA7\u0CCD\u0CAF\u0CAE"],
1152
+ high: ["\u0C89\u0CA8\u0CCD\u0CA8\u0CA4"],
1153
+ extraHigh: ["\u0C85\u0CA4\u0CBF \u0CB9\u0CC6\u0C9A\u0CCD\u0C9A\u0CC1"],
1154
+ pro: ["\u0CAA\u0CCD\u0CB0\u0CCA"]
1155
+ },
951
1156
  modeOpenerExtra: ["\u0C95\u0CBE\u0CA8\u0CCD\u0CAB\u0CBF\u0C97\u0CB0\u0CCD \u0CAE\u0CBE\u0CA1\u0CBF..."],
952
1157
  tools: {
953
1158
  web_search: ["\u0CB5\u0CC6\u0CAC\u0CCD \u0CB8\u0CB0\u0CCD\u0C9A\u0CCD"],
@@ -970,6 +1175,12 @@ var ko = {
970
1175
  addPhotosFilesMenuItem: ["\uC0AC\uC9C4 \uBC0F \uD30C\uC77C \uCD94\uAC00"],
971
1176
  copyResponse: ["\uC751\uB2F5 \uBCF5\uC0AC"],
972
1177
  modeLabels: ["\uC989\uC2DC", "\uC911\uAC04", "\uB192\uC74C", "\uB9E4\uC6B0 \uB192\uC74C"],
1178
+ modeOptions: {
1179
+ instant: ["\uC989\uC2DC"],
1180
+ medium: ["\uC911\uAC04"],
1181
+ high: ["\uB192\uC74C"],
1182
+ extraHigh: ["\uB9E4\uC6B0 \uB192\uC74C"]
1183
+ },
973
1184
  modeOpenerExtra: ["\uAD6C\uC131\u2026"],
974
1185
  tools: {
975
1186
  web_search: ["\uC6F9 \uAC80\uC0C9"],
@@ -992,6 +1203,13 @@ var lt = {
992
1203
  addPhotosFilesMenuItem: ["Prid\u0117ti nuotrauk\u0173 ir fail\u0173"],
993
1204
  copyResponse: ["Kopijuoti atsakym\u0105"],
994
1205
  modeLabels: ["Momentinis", "Vidutinis", "Auk\u0161tas", "Ypa\u010D didelis", "Profesionalus"],
1206
+ modeOptions: {
1207
+ instant: ["Momentinis"],
1208
+ medium: ["Vidutinis"],
1209
+ high: ["Auk\u0161tas"],
1210
+ extraHigh: ["Ypa\u010D didelis"],
1211
+ pro: ["Profesionalus"]
1212
+ },
995
1213
  modeOpenerExtra: ["Konfig\u016Bruoti..."],
996
1214
  tools: {
997
1215
  web_search: ["\u017Diniatinklio paie\u0161ka"],
@@ -1014,6 +1232,13 @@ var zhHans = {
1014
1232
  addPhotosFilesMenuItem: ["\u6DFB\u52A0\u7167\u7247\u548C\u6587\u4EF6"],
1015
1233
  copyResponse: ["\u590D\u5236\u56DE\u590D"],
1016
1234
  modeLabels: ["\u6781\u901F", "\u5747\u8861", "\u9AD8\u7EA7", "\u8D85\u9AD8", "\u4E13\u4E1A"],
1235
+ modeOptions: {
1236
+ instant: ["\u6781\u901F"],
1237
+ medium: ["\u5747\u8861"],
1238
+ high: ["\u9AD8\u7EA7"],
1239
+ extraHigh: ["\u8D85\u9AD8"],
1240
+ pro: ["\u4E13\u4E1A"]
1241
+ },
1017
1242
  modeOpenerExtra: ["\u914D\u7F6E\u2026"],
1018
1243
  tools: {
1019
1244
  web_search: ["\u7F51\u9875\u641C\u7D22"],
@@ -1036,6 +1261,12 @@ var ur = {
1036
1261
  addPhotosFilesMenuItem: ["\u062A\u0635\u0648\u06CC\u0631\u06CC\u06BA \u0627\u0648\u0631 \u0641\u0627\u0626\u0644\u06CC\u06BA \u0634\u0627\u0645\u0644 \u06A9\u0631\u06CC\u06BA"],
1037
1262
  copyResponse: ["\u062C\u0648\u0627\u0628 \u06A9\u0627\u067E\u06CC \u06A9\u0631\u06CC\u06BA"],
1038
1263
  modeLabels: ["\u0641\u0648\u0631\u06CC", "\u0627\u0648\u0633\u0637", "\u0627\u0639\u0644\u06CC\u0670", "\u0627\u0646\u062A\u06C1\u0627\u0626\u06CC \u0627\u0639\u0644\u06CC\u0670"],
1264
+ modeOptions: {
1265
+ instant: ["\u0641\u0648\u0631\u06CC"],
1266
+ medium: ["\u0627\u0648\u0633\u0637"],
1267
+ high: ["\u0627\u0639\u0644\u06CC\u0670"],
1268
+ extraHigh: ["\u0627\u0646\u062A\u06C1\u0627\u0626\u06CC \u0627\u0639\u0644\u06CC\u0670"]
1269
+ },
1039
1270
  modeOpenerExtra: ["\u06A9\u0646\u0641\u06CC\u06AF\u0631 \u06A9\u0631\u06CC\u06BA..."],
1040
1271
  tools: {
1041
1272
  web_search: ["\u0648\u06CC\u0628 \u067E\u0631 \u062A\u0644\u0627\u0634"],
@@ -1058,6 +1289,12 @@ var uk = {
1058
1289
  addPhotosFilesMenuItem: ["\u0414\u043E\u0434\u0430\u0442\u0438 \u0441\u0432\u0456\u0442\u043B\u0438\u043D\u0438 \u0442\u0430 \u0444\u0430\u0439\u043B\u0438"],
1059
1290
  copyResponse: ["\u041A\u043E\u043F\u0456\u044E\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u044C"],
1060
1291
  modeLabels: ["\u041C\u0438\u0442\u0442\u0454\u0432\u0438\u0439", "\u0421\u0435\u0440\u0435\u0434\u043D\u0456\u0439", "\u0412\u0438\u0441\u043E\u043A\u0438\u0439", "\u0414\u0443\u0436\u0435 \u0432\u0438\u0441\u043E\u043A\u0438\u0439"],
1292
+ modeOptions: {
1293
+ instant: ["\u041C\u0438\u0442\u0442\u0454\u0432\u0438\u0439"],
1294
+ medium: ["\u0421\u0435\u0440\u0435\u0434\u043D\u0456\u0439"],
1295
+ high: ["\u0412\u0438\u0441\u043E\u043A\u0438\u0439"],
1296
+ extraHigh: ["\u0414\u0443\u0436\u0435 \u0432\u0438\u0441\u043E\u043A\u0438\u0439"]
1297
+ },
1061
1298
  modeOpenerExtra: ["\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438\u2026"],
1062
1299
  tools: {
1063
1300
  web_search: ["\u041F\u043E\u0448\u0443\u043A \u0432 \u0406\u043D\u0442\u0435\u0440\u043D\u0435\u0442\u0456"],
@@ -1080,6 +1317,12 @@ var ptBR = {
1080
1317
  addPhotosFilesMenuItem: ["Carregar fotos e arquivos"],
1081
1318
  copyResponse: ["Copiar resposta"],
1082
1319
  modeLabels: ["Instant\xE2neo", "M\xE9dio", "Alto", "Muito alta"],
1320
+ modeOptions: {
1321
+ instant: ["Instant\xE2neo"],
1322
+ medium: ["M\xE9dio"],
1323
+ high: ["Alto"],
1324
+ extraHigh: ["Muito alta"]
1325
+ },
1083
1326
  modeOpenerExtra: ["Configurar\u2026"],
1084
1327
  tools: {
1085
1328
  web_search: ["Busca na web"],
@@ -1102,6 +1345,12 @@ var ptPT = {
1102
1345
  addPhotosFilesMenuItem: ["Carregar fotos e ficheiros"],
1103
1346
  copyResponse: ["Copiar resposta"],
1104
1347
  modeLabels: ["Instant\xE2neo", "M\xE9dia", "Alta", "M\xE1ximo"],
1348
+ modeOptions: {
1349
+ instant: ["Instant\xE2neo"],
1350
+ medium: ["M\xE9dia"],
1351
+ high: ["Alta"],
1352
+ extraHigh: ["M\xE1ximo"]
1353
+ },
1105
1354
  modeOpenerExtra: ["Configurar..."],
1106
1355
  tools: {
1107
1356
  web_search: ["Procurar na web"],
@@ -1124,6 +1373,12 @@ var pl = {
1124
1373
  addPhotosFilesMenuItem: ["Prze\u015Blij zdj\u0119cia i pliki"],
1125
1374
  copyResponse: ["Kopiuj odpowied\u017A"],
1126
1375
  modeLabels: ["B\u0142yskawiczny", "\u015Aredni", "Zaawansowana", "Bardzo wysoki"],
1376
+ modeOptions: {
1377
+ instant: ["B\u0142yskawiczny"],
1378
+ medium: ["\u015Aredni"],
1379
+ high: ["Zaawansowana"],
1380
+ extraHigh: ["Bardzo wysoki"]
1381
+ },
1127
1382
  modeOpenerExtra: ["Skonfiguruj..."],
1128
1383
  tools: {
1129
1384
  web_search: ["Wyszukiwanie w sieci"],
@@ -1146,6 +1401,12 @@ var sk = {
1146
1401
  addPhotosFilesMenuItem: ["Nahra\u0165 fotografie a s\xFAbory"],
1147
1402
  copyResponse: ["Kop\xEDrova\u0165 odpove\u010F"],
1148
1403
  modeLabels: ["Okam\u017Eit\xE1", "Stredn\xE1", "Vysok\xE1", "Extra vysok\xE1"],
1404
+ modeOptions: {
1405
+ instant: ["Okam\u017Eit\xE1"],
1406
+ medium: ["Stredn\xE1"],
1407
+ high: ["Vysok\xE1"],
1408
+ extraHigh: ["Extra vysok\xE1"]
1409
+ },
1149
1410
  modeOpenerExtra: ["Konfigurova\u0165..."],
1150
1411
  tools: {
1151
1412
  web_search: ["Preh\u013Ead\xE1vaj web"],
@@ -1168,6 +1429,11 @@ var ro = {
1168
1429
  addPhotosFilesMenuItem: ["\xCEncarc\u0103 fotografii \u0219i fi\u0219iere"],
1169
1430
  copyResponse: ["Copiaz\u0103 r\u0103spunsul"],
1170
1431
  modeLabels: ["Mediu", "Ridicat", "Foarte ridicat\u0103"],
1432
+ modeOptions: {
1433
+ medium: ["Mediu"],
1434
+ high: ["Ridicat"],
1435
+ extraHigh: ["Foarte ridicat\u0103"]
1436
+ },
1171
1437
  modeOpenerExtra: ["Configureaz\u0103..."],
1172
1438
  tools: {
1173
1439
  web_search: ["C\u0103utare pe internet"],
@@ -1190,6 +1456,12 @@ var nb = {
1190
1456
  addPhotosFilesMenuItem: ["Last opp bilder og filer"],
1191
1457
  copyResponse: ["Kopier svar"],
1192
1458
  modeLabels: ["\xD8yeblikkelig", "Middels", "H\xF8y", "Ekstra h\xF8y"],
1459
+ modeOptions: {
1460
+ instant: ["\xD8yeblikkelig"],
1461
+ medium: ["Middels"],
1462
+ high: ["H\xF8y"],
1463
+ extraHigh: ["Ekstra h\xF8y"]
1464
+ },
1193
1465
  modeOpenerExtra: ["Konfigurer \u2026"],
1194
1466
  tools: {
1195
1467
  web_search: ["Netts\xF8k"],
@@ -1212,6 +1484,13 @@ var ml = {
1212
1484
  addPhotosFilesMenuItem: ["\u0D2B\u0D4B\u0D1F\u0D4D\u0D1F\u0D4B\u0D15\u0D33\u0D41\u0D02 \u0D2B\u0D2F\u0D32\u0D41\u0D15\u0D33\u0D41\u0D02 \u0D05\u0D2A\u0D4D\u200C\u0D32\u0D4B\u0D21\u0D4D \u0D1A\u0D46\u0D2F\u0D4D\u0D2F\u0D41\u0D15"],
1213
1485
  copyResponse: ["\u0D2E\u0D31\u0D41\u0D2A\u0D1F\u0D3F \u0D15\u0D4B\u0D2A\u0D4D\u0D2A\u0D3F \u0D1A\u0D46\u0D2F\u0D4D\u0D2F\u0D41\u0D15"],
1214
1486
  modeLabels: ["\u0D24\u0D7D\u0D15\u0D4D\u0D37\u0D23\u0D02", "\u0D07\u0D1F\u0D24\u0D4D\u0D24\u0D30\u0D02", "\u0D09\u0D2F\u0D7C\u0D28\u0D4D\u0D28\u0D24\u0D4D", "\u0D35\u0D33\u0D30\u0D46 \u0D09\u0D2F\u0D7C\u0D28\u0D4D\u0D28", "\u0D2A\u0D4D\u0D30\u0D4B"],
1487
+ modeOptions: {
1488
+ instant: ["\u0D24\u0D7D\u0D15\u0D4D\u0D37\u0D23\u0D02"],
1489
+ medium: ["\u0D07\u0D1F\u0D24\u0D4D\u0D24\u0D30\u0D02"],
1490
+ high: ["\u0D09\u0D2F\u0D7C\u0D28\u0D4D\u0D28\u0D24\u0D4D"],
1491
+ extraHigh: ["\u0D35\u0D33\u0D30\u0D46 \u0D09\u0D2F\u0D7C\u0D28\u0D4D\u0D28"],
1492
+ pro: ["\u0D2A\u0D4D\u0D30\u0D4B"]
1493
+ },
1215
1494
  modeOpenerExtra: ["\u0D15\u0D4B\u0D7A\u0D2B\u0D3F\u0D17\u0D7C \u0D1A\u0D46\u0D2F\u0D4D\u0D2F\u0D41\u0D15\u2026"],
1216
1495
  tools: {
1217
1496
  web_search: ["\u0D35\u0D46\u0D2C\u0D4D \u0D24\u0D3F\u0D30\u0D2F\u0D7D"],
@@ -1234,6 +1513,9 @@ var ru = {
1234
1513
  addPhotosFilesMenuItem: ["\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0444\u043E\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u0438 \u0438 \u0444\u0430\u0439\u043B\u044B"],
1235
1514
  copyResponse: ["\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043E\u0442\u0432\u0435\u0442"],
1236
1515
  modeLabels: ["\u041E\u0447\u0435\u043D\u044C \u0432\u044B\u0441\u043E\u043A\u0438\u0439"],
1516
+ modeOptions: {
1517
+ extraHigh: ["\u041E\u0447\u0435\u043D\u044C \u0432\u044B\u0441\u043E\u043A\u0438\u0439"]
1518
+ },
1237
1519
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F..."],
1238
1520
  tools: {
1239
1521
  web_search: ["\u041F\u043E\u0438\u0441\u043A \u0432 \u0441\u0435\u0442\u0438"],
@@ -1256,6 +1538,13 @@ var pa = {
1256
1538
  addPhotosFilesMenuItem: ["\u0A2B\u0A3C\u0A4B\u0A1F\u0A4B\u0A06\u0A02 \u0A05\u0A24\u0A47 \u0A2B\u0A3C\u0A3E\u0A08\u0A32\u0A3E\u0A02 \u0A05\u0A71\u0A2A\u0A32\u0A4B\u0A21 \u0A15\u0A30\u0A4B"],
1257
1539
  copyResponse: ["\u0A1C\u0A35\u0A3E\u0A2C \u0A15\u0A3E\u0A2A\u0A40 \u0A15\u0A30\u0A4B"],
1258
1540
  modeLabels: ["\u0A24\u0A41\u0A30\u0A70\u0A24", "\u0A2E\u0A71\u0A27\u0A2E", "\u0A09\u0A71\u0A1A", "\u0A05\u0A24\u0A3F \u0A09\u0A71\u0A1A", "\u0A2A\u0A4D\u0A30\u0A4B"],
1541
+ modeOptions: {
1542
+ instant: ["\u0A24\u0A41\u0A30\u0A70\u0A24"],
1543
+ medium: ["\u0A2E\u0A71\u0A27\u0A2E"],
1544
+ high: ["\u0A09\u0A71\u0A1A"],
1545
+ extraHigh: ["\u0A05\u0A24\u0A3F \u0A09\u0A71\u0A1A"],
1546
+ pro: ["\u0A2A\u0A4D\u0A30\u0A4B"]
1547
+ },
1259
1548
  modeOpenerExtra: ["\u0A15\u0A4C\u0A28\u0A2B\u0A3F\u0A17\u0A30..."],
1260
1549
  tools: {
1261
1550
  web_search: ["\u0A35\u0A48\u0A71\u0A2C \u0A16\u0A4B\u0A1C"],
@@ -1278,6 +1567,13 @@ var mr = {
1278
1567
  addPhotosFilesMenuItem: ["\u092B\u094B\u091F\u094B \u0906\u0923\u093F \u092B\u093E\u0907\u0932\u094D\u0938 \u0905\u092A\u0932\u094B\u0921 \u0915\u0930\u093E"],
1279
1568
  copyResponse: ["\u092A\u094D\u0930\u0924\u093F\u0938\u093E\u0926 \u0915\u0949\u092A\u0940 \u0915\u0930\u093E"],
1280
1569
  modeLabels: ["\u091D\u091F\u092A\u091F", "\u092E\u0927\u094D\u092F\u092E", "\u0909\u091A\u094D\u091A", "\u0905\u0924\u093F\u0909\u091A\u094D\u091A", "\u092A\u094D\u0930\u094B"],
1570
+ modeOptions: {
1571
+ instant: ["\u091D\u091F\u092A\u091F"],
1572
+ medium: ["\u092E\u0927\u094D\u092F\u092E"],
1573
+ high: ["\u0909\u091A\u094D\u091A"],
1574
+ extraHigh: ["\u0905\u0924\u093F\u0909\u091A\u094D\u091A"],
1575
+ pro: ["\u092A\u094D\u0930\u094B"]
1576
+ },
1281
1577
  modeOpenerExtra: ["\u0915\u0949\u0928\u094D\u092B\u093F\u0917\u0930 \u0915\u0930\u093E..."],
1282
1578
  tools: {
1283
1579
  web_search: ["\u0935\u0947\u092C\u0935\u0930 \u0936\u094B\u0927"],
@@ -1300,6 +1596,12 @@ var tr = {
1300
1596
  addPhotosFilesMenuItem: ["Foto\u011Fraf ve dosya y\xFCkle"],
1301
1597
  copyResponse: ["Yan\u0131t\u0131 kopyala"],
1302
1598
  modeLabels: ["An\u0131nda", "Orta", "Y\xFCksek", "\xC7ok Y\xFCksek"],
1599
+ modeOptions: {
1600
+ instant: ["An\u0131nda"],
1601
+ medium: ["Orta"],
1602
+ high: ["Y\xFCksek"],
1603
+ extraHigh: ["\xC7ok Y\xFCksek"]
1604
+ },
1303
1605
  modeOpenerExtra: ["Yap\u0131land\u0131r..."],
1304
1606
  tools: {
1305
1607
  web_search: ["Web aramas\u0131"],
@@ -1322,6 +1624,12 @@ var sw = {
1322
1624
  addPhotosFilesMenuItem: ["Pakia picha na mafaili"],
1323
1625
  copyResponse: ["Nakili jibu"],
1324
1626
  modeLabels: ["Papo hapo", "Wastani", "Juu", "Juu Zaidi"],
1627
+ modeOptions: {
1628
+ instant: ["Papo hapo"],
1629
+ medium: ["Wastani"],
1630
+ high: ["Juu"],
1631
+ extraHigh: ["Juu Zaidi"]
1632
+ },
1325
1633
  modeOpenerExtra: ["Sanidi..."],
1326
1634
  tools: {
1327
1635
  web_search: ["Utafutaji wa wavuti"],
@@ -1344,6 +1652,13 @@ var te = {
1344
1652
  addPhotosFilesMenuItem: ["\u0C2B\u0C4B\u0C1F\u0C4B\u0C32\u0C41 & \u0C2B\u0C48\u0C32\u0C4D\u200C\u0C32\u0C28\u0C41 \u0C05\u0C2A\u0C4D\u200C\u0C32\u0C4B\u0C21\u0C4D \u0C1A\u0C47\u0C2F\u0C02\u0C21\u0C3F"],
1345
1653
  copyResponse: ["\u0C2A\u0C4D\u0C30\u0C24\u0C3F\u0C38\u0C4D\u0C2A\u0C02\u0C26\u0C28\u0C28\u0C41 \u0C15\u0C3E\u0C2A\u0C40 \u0C1A\u0C47\u0C2F\u0C02\u0C21\u0C3F"],
1346
1654
  modeLabels: ["\u0C24\u0C15\u0C4D\u0C37\u0C23\u0C02", "\u0C2E\u0C27\u0C4D\u0C2F\u0C38\u0C4D\u0C25", "\u0C05\u0C27\u0C3F\u0C15", "\u0C05\u0C24\u0C4D\u0C2F\u0C27\u0C3F\u0C15", "\u0C2A\u0C4D\u0C30\u0C4B"],
1655
+ modeOptions: {
1656
+ instant: ["\u0C24\u0C15\u0C4D\u0C37\u0C23\u0C02"],
1657
+ medium: ["\u0C2E\u0C27\u0C4D\u0C2F\u0C38\u0C4D\u0C25"],
1658
+ high: ["\u0C05\u0C27\u0C3F\u0C15"],
1659
+ extraHigh: ["\u0C05\u0C24\u0C4D\u0C2F\u0C27\u0C3F\u0C15"],
1660
+ pro: ["\u0C2A\u0C4D\u0C30\u0C4B"]
1661
+ },
1347
1662
  modeOpenerExtra: ["\u0C15\u0C3E\u0C28\u0C4D\u0C2B\u0C3F\u0C17\u0C30\u0C4D \u0C1A\u0C47\u0C2F\u0C02\u0C21\u0C3F"],
1348
1663
  tools: {
1349
1664
  web_search: ["\u0C35\u0C46\u0C2C\u0C4D\u200C\u0C32\u0C4B \u0C35\u0C46\u0C24\u0C15\u0C21\u0C02"],
@@ -1386,6 +1701,12 @@ var th = {
1386
1701
  addPhotosFilesMenuItem: ["\u0E2D\u0E31\u0E1B\u0E42\u0E2B\u0E25\u0E14\u0E23\u0E39\u0E1B\u0E41\u0E25\u0E30\u0E44\u0E1F\u0E25\u0E4C"],
1387
1702
  copyResponse: ["\u0E04\u0E31\u0E14\u0E25\u0E2D\u0E01\u0E04\u0E33\u0E15\u0E2D\u0E1A"],
1388
1703
  modeLabels: ["\u0E17\u0E31\u0E19\u0E17\u0E35", "\u0E1B\u0E32\u0E19\u0E01\u0E25\u0E32\u0E07", "\u0E2A\u0E39\u0E07", "\u0E2A\u0E39\u0E07\u0E21\u0E32\u0E01"],
1704
+ modeOptions: {
1705
+ instant: ["\u0E17\u0E31\u0E19\u0E17\u0E35"],
1706
+ medium: ["\u0E1B\u0E32\u0E19\u0E01\u0E25\u0E32\u0E07"],
1707
+ high: ["\u0E2A\u0E39\u0E07"],
1708
+ extraHigh: ["\u0E2A\u0E39\u0E07\u0E21\u0E32\u0E01"]
1709
+ },
1389
1710
  modeOpenerExtra: ["\u0E01\u0E33\u0E2B\u0E19\u0E14\u0E04\u0E48\u0E32..."],
1390
1711
  tools: {
1391
1712
  web_search: ["\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E40\u0E27\u0E47\u0E1A"],
@@ -1408,6 +1729,13 @@ var bn = {
1408
1729
  addPhotosFilesMenuItem: ["\u09AB\u099F\u09CB \u098F\u09AC\u0982 \u09AB\u09BE\u0987\u09B2 \u0986\u09AA\u09B2\u09CB\u09A1 \u0995\u09B0\u09C1\u09A8"],
1409
1730
  copyResponse: ["\u0989\u09A4\u09CD\u09A4\u09B0 \u0995\u09AA\u09BF \u0995\u09B0\u09C1\u09A8"],
1410
1731
  modeLabels: ["\u09A4\u09BE\u09CE\u0995\u09CD\u09B7\u09A3\u09BF\u0995", "\u09AE\u09BE\u099D\u09BE\u09B0\u09BF", "\u0989\u099A\u09CD\u099A", "\u0985\u09A4\u09BF \u0989\u099A\u09CD\u099A", "\u09AA\u09CD\u09B0\u09CB"],
1732
+ modeOptions: {
1733
+ instant: ["\u09A4\u09BE\u09CE\u0995\u09CD\u09B7\u09A3\u09BF\u0995"],
1734
+ medium: ["\u09AE\u09BE\u099D\u09BE\u09B0\u09BF"],
1735
+ high: ["\u0989\u099A\u09CD\u099A"],
1736
+ extraHigh: ["\u0985\u09A4\u09BF \u0989\u099A\u09CD\u099A"],
1737
+ pro: ["\u09AA\u09CD\u09B0\u09CB"]
1738
+ },
1411
1739
  modeOpenerExtra: ["\u0995\u09A8\u09AB\u09BF\u0997\u09BE\u09B0 \u0995\u09B0\u09C1\u09A8..."],
1412
1740
  tools: {
1413
1741
  web_search: ["\u0993\u09AF\u09BC\u09C7\u09AC \u09B8\u09A8\u09CD\u09A7\u09BE\u09A8"],
@@ -1430,6 +1758,12 @@ var ms = {
1430
1758
  addPhotosFilesMenuItem: ["Muat naik foto & fail"],
1431
1759
  copyResponse: ["Salin tindak balas"],
1432
1760
  modeLabels: ["Segera", "Sederhana", "Tinggi", "Sangat Tinggi"],
1761
+ modeOptions: {
1762
+ instant: ["Segera"],
1763
+ medium: ["Sederhana"],
1764
+ high: ["Tinggi"],
1765
+ extraHigh: ["Sangat Tinggi"]
1766
+ },
1433
1767
  modeOpenerExtra: ["Konfigurasikan\u2026"],
1434
1768
  tools: {
1435
1769
  web_search: ["Carian web"],
@@ -1452,6 +1786,12 @@ var so = {
1452
1786
  addPhotosFilesMenuItem: ["Soo geli sawirada & faylasha"],
1453
1787
  copyResponse: ["Koobiyee jawaabta"],
1454
1788
  modeLabels: ["Degdeg", "Dhexdhexaad", "Sare", "Aad u sarreeya"],
1789
+ modeOptions: {
1790
+ instant: ["Degdeg"],
1791
+ medium: ["Dhexdhexaad"],
1792
+ high: ["Sare"],
1793
+ extraHigh: ["Aad u sarreeya"]
1794
+ },
1455
1795
  modeOpenerExtra: ["Ku xidh..."],
1456
1796
  tools: {
1457
1797
  web_search: ["Raadi shakabada"],
@@ -1474,6 +1814,12 @@ var nl = {
1474
1814
  addPhotosFilesMenuItem: ["Foto's en bestanden uploaden"],
1475
1815
  copyResponse: ["Reactie kopi\xEBren"],
1476
1816
  modeLabels: ["Direct", "Gemiddeld", "Hoog", "Extra hoog"],
1817
+ modeOptions: {
1818
+ instant: ["Direct"],
1819
+ medium: ["Gemiddeld"],
1820
+ high: ["Hoog"],
1821
+ extraHigh: ["Extra hoog"]
1822
+ },
1477
1823
  modeOpenerExtra: ["Configureren..."],
1478
1824
  tools: {
1479
1825
  web_search: ["Zoeken op internet"],
@@ -1496,6 +1842,12 @@ var sv = {
1496
1842
  addPhotosFilesMenuItem: ["Ladda upp foton och filer"],
1497
1843
  copyResponse: ["Kopiera svar"],
1498
1844
  modeLabels: ["Direkt", "Balanserad", "H\xF6g", "Extra h\xF6g"],
1845
+ modeOptions: {
1846
+ instant: ["Direkt"],
1847
+ medium: ["Balanserad"],
1848
+ high: ["H\xF6g"],
1849
+ extraHigh: ["Extra h\xF6g"]
1850
+ },
1499
1851
  modeOpenerExtra: ["Konfigurera \u2026"],
1500
1852
  tools: {
1501
1853
  web_search: ["Webbs\xF6kning"],
@@ -1518,6 +1870,12 @@ var lv = {
1518
1870
  addPhotosFilesMenuItem: ["Aug\u0161upiel\u0101d\u0113t foto un failus"],
1519
1871
  copyResponse: ["Kop\u0113t atbildi"],
1520
1872
  modeLabels: ["T\u016Bl\u012Bt\u0113js", "Vid\u0113js", "Augsts", "\u013Boti augsts"],
1873
+ modeOptions: {
1874
+ instant: ["T\u016Bl\u012Bt\u0113js"],
1875
+ medium: ["Vid\u0113js"],
1876
+ high: ["Augsts"],
1877
+ extraHigh: ["\u013Boti augsts"]
1878
+ },
1521
1879
  modeOpenerExtra: ["Konfigur\u0113t..."],
1522
1880
  tools: {
1523
1881
  web_search: ["Mekl\u0113\u0161ana t\u012Bmekl\u012B"],
@@ -1540,6 +1898,11 @@ var mk = {
1540
1898
  addPhotosFilesMenuItem: ["\u041F\u043E\u0441\u0442\u0430\u0432\u0438 \u0444\u043E\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u0438 \u0438 \u0434\u0430\u0442\u043E\u0442\u0435\u043A\u0438"],
1541
1899
  copyResponse: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0458 \u043E\u0434\u0433\u043E\u0432\u043E\u0440"],
1542
1900
  modeLabels: ["\u0421\u0440\u0435\u0434\u043D\u043E", "\u0412\u0438\u0441\u043E\u043A\u043E", "\u041C\u043D\u043E\u0433\u0443 \u0432\u0438\u0441\u043E\u043A\u043E"],
1901
+ modeOptions: {
1902
+ medium: ["\u0421\u0440\u0435\u0434\u043D\u043E"],
1903
+ high: ["\u0412\u0438\u0441\u043E\u043A\u043E"],
1904
+ extraHigh: ["\u041C\u043D\u043E\u0433\u0443 \u0432\u0438\u0441\u043E\u043A\u043E"]
1905
+ },
1543
1906
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0458..."],
1544
1907
  tools: {
1545
1908
  web_search: ["\u041F\u0440\u0435\u0431\u0430\u0440\u0443\u0432\u0430\u045A\u0435 \u043D\u0430 \u0438\u043D\u0442\u0435\u0440\u043D\u0435\u0442"],
@@ -1562,6 +1925,12 @@ var sq = {
1562
1925
  addPhotosFilesMenuItem: ["Ngarko foto dhe skedar\xEB"],
1563
1926
  copyResponse: ["Kopjo p\xEBrgjigjen"],
1564
1927
  modeLabels: ["I menj\xEBhersh\xEBm", "Mesatar", "Lart\xEB", "Shum\xEB i lart\xEB"],
1928
+ modeOptions: {
1929
+ instant: ["I menj\xEBhersh\xEBm"],
1930
+ medium: ["Mesatar"],
1931
+ high: ["Lart\xEB"],
1932
+ extraHigh: ["Shum\xEB i lart\xEB"]
1933
+ },
1565
1934
  modeOpenerExtra: ["Konfiguro..."],
1566
1935
  tools: {
1567
1936
  web_search: ["K\xEBrkim n\xEB ueb"],
@@ -1584,6 +1953,12 @@ var sl = {
1584
1953
  addPhotosFilesMenuItem: ["Nalo\u017Ei fotografije in datoteke"],
1585
1954
  copyResponse: ["Kopiraj odgovor"],
1586
1955
  modeLabels: ["Takoj", "Srednja", "Visoka", "Zelo visoko"],
1956
+ modeOptions: {
1957
+ instant: ["Takoj"],
1958
+ medium: ["Srednja"],
1959
+ high: ["Visoka"],
1960
+ extraHigh: ["Zelo visoko"]
1961
+ },
1587
1962
  modeOpenerExtra: ["Konfiguracija \u2026"],
1588
1963
  tools: {
1589
1964
  web_search: ["Iskanje po spletu"],
@@ -1606,6 +1981,9 @@ var sr = {
1606
1981
  addPhotosFilesMenuItem: ["\u041E\u0442\u043F\u0440\u0435\u043C\u0438 \u0444\u043E\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u0458\u0435 \u0438 \u0434\u0430\u0442\u043E\u0442\u0435\u043A\u0435"],
1607
1982
  copyResponse: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0458 \u043E\u0434\u0433\u043E\u0432\u043E\u0440"],
1608
1983
  modeLabels: ["\u0412\u0435\u043E\u043C\u0430 \u0432\u0438\u0441\u043E\u043A\u043E"],
1984
+ modeOptions: {
1985
+ extraHigh: ["\u0412\u0435\u043E\u043C\u0430 \u0432\u0438\u0441\u043E\u043A\u043E"]
1986
+ },
1609
1987
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0448\u0438..."],
1610
1988
  tools: {
1611
1989
  web_search: ["\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u0432\u0435\u0431\u0430"],
@@ -1628,6 +2006,13 @@ var mn = {
1628
2006
  addPhotosFilesMenuItem: ["\u0417\u0443\u0440\u0430\u0433 \u0431\u0430 \u0444\u0430\u0439\u043B \u0431\u0430\u0439\u0440\u0448\u0443\u0443\u043B\u0430\u0445"],
1629
2007
  copyResponse: ["\u0425\u0430\u0440\u0438\u0443\u043B\u0442 \u0445\u0443\u0443\u043B\u0430\u0445"],
1630
2008
  modeLabels: ["\u0428\u0443\u0443\u0440\u0445\u0430\u0439", "\u0414\u0443\u043D\u0434", "\u04E8\u043D\u0434\u04E9\u0440", "\u041C\u0430\u0448 \u04E9\u043D\u0434\u04E9\u0440", "\u041F\u0440\u043E"],
2009
+ modeOptions: {
2010
+ instant: ["\u0428\u0443\u0443\u0440\u0445\u0430\u0439"],
2011
+ medium: ["\u0414\u0443\u043D\u0434"],
2012
+ high: ["\u04E8\u043D\u0434\u04E9\u0440"],
2013
+ extraHigh: ["\u041C\u0430\u0448 \u04E9\u043D\u0434\u04E9\u0440"],
2014
+ pro: ["\u041F\u0440\u043E"]
2015
+ },
1631
2016
  modeOpenerExtra: ["\u0422\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0445..."],
1632
2017
  tools: {
1633
2018
  web_search: ["\u0412\u0435\u0431 \u0445\u0430\u0439\u043B\u0442"],
@@ -1650,6 +2035,12 @@ var my = {
1650
2035
  addPhotosFilesMenuItem: ["\u1013\u102C\u1010\u103A\u1015\u102F\u1036\u1019\u103B\u102C\u1038\u1014\u103E\u1004\u1037\u103A \u1016\u102D\u102F\u1004\u103A\u1019\u103B\u102C\u1038\u1000\u102D\u102F \u1010\u1004\u103A\u1015\u102B"],
1651
2036
  copyResponse: ["\u1010\u102F\u1036\u1037\u1015\u103C\u1014\u103A\u1019\u103E\u102F \u1000\u1030\u1038\u101A\u1030\u101B\u1014\u103A"],
1652
2037
  modeLabels: ["\u1001\u103B\u1000\u103A\u1001\u103B\u1004\u103A\u1038", "\u1021\u101C\u101A\u103A\u1021\u101C\u1010\u103A", "\u1019\u103C\u1004\u1037\u103A", "\u1021\u101C\u103D\u1014\u103A\u1019\u103C\u1004\u1037\u103A"],
2038
+ modeOptions: {
2039
+ instant: ["\u1001\u103B\u1000\u103A\u1001\u103B\u1004\u103A\u1038"],
2040
+ medium: ["\u1021\u101C\u101A\u103A\u1021\u101C\u1010\u103A"],
2041
+ high: ["\u1019\u103C\u1004\u1037\u103A"],
2042
+ extraHigh: ["\u1021\u101C\u103D\u1014\u103A\u1019\u103C\u1004\u1037\u103A"]
2043
+ },
1653
2044
  modeOpenerExtra: ["\u1015\u103C\u102F\u1015\u103C\u1004\u103A\u1019\u103D\u1019\u103A\u1038\u1019\u1036\u101B\u1014\u103A"],
1654
2045
  tools: {
1655
2046
  web_search: ["\u101D\u1018\u103A\u101B\u103E\u102C\u1016\u103D\u1031\u101B\u1014\u103A"],
@@ -1672,6 +2063,13 @@ var ta = {
1672
2063
  addPhotosFilesMenuItem: ["\u0BAA\u0B9F\u0B99\u0BCD\u0B95\u0BB3\u0BCD \u0BAE\u0BB1\u0BCD\u0BB1\u0BC1\u0BAE\u0BCD \u0B83\u0BAA\u0BC8\u0BB2\u0BCD\u0B95\u0BB3\u0BC8\u0BAA\u0BCD \u0BAA\u0BA4\u0BBF\u0BB5\u0BC7\u0BB1\u0BCD\u0BB1\u0BC1"],
1673
2064
  copyResponse: ["\u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0BA8\u0B95\u0BB2\u0BC6\u0B9F\u0BC1\u0B95\u0BCD\u0B95\u0BB2\u0BBE\u0BAE\u0BCD"],
1674
2065
  modeLabels: ["\u0B89\u0B9F\u0BA9\u0B9F\u0BBF", "\u0BA8\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BB0", "\u0B89\u0BAF\u0BB0\u0BCD", "\u0BAE\u0BBF\u0B95 \u0B89\u0BAF\u0BB0\u0BCD\u0BB5\u0BC1", "\u0BAA\u0BCD\u0BB0\u0BCB"],
2066
+ modeOptions: {
2067
+ instant: ["\u0B89\u0B9F\u0BA9\u0B9F\u0BBF"],
2068
+ medium: ["\u0BA8\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BB0"],
2069
+ high: ["\u0B89\u0BAF\u0BB0\u0BCD"],
2070
+ extraHigh: ["\u0BAE\u0BBF\u0B95 \u0B89\u0BAF\u0BB0\u0BCD\u0BB5\u0BC1"],
2071
+ pro: ["\u0BAA\u0BCD\u0BB0\u0BCB"]
2072
+ },
1675
2073
  modeOpenerExtra: ["\u0B95\u0B9F\u0BCD\u0B9F\u0BAE\u0BC8\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD..."],
1676
2074
  tools: {
1677
2075
  web_search: ["\u0B87\u0BA3\u0BC8\u0BAF \u0BA4\u0BC7\u0B9F\u0BB2\u0BCD"],
@@ -1685,6 +2083,16 @@ var ta = {
1685
2083
  // src/dom/locale/index.ts
1686
2084
  var locales = [en, de, esES, frFR, zhHK, zhTW, ja, it, vi, am, ar, bg, bs, ca, cs, da, el, es419, et, fa, fi, frCA, gu, hi, hr, hu, hy, id, is, ka, kk, kn, ko, lt, zhHans, ur, uk, ptBR, ptPT, pl, sk, ro, nb, ml, ru, pa, mr, tr, sw, te, tl, th, bn, ms, so, nl, sv, lv, mk, sq, sl, sr, mn, my, ta];
1687
2085
  var TOOL_IDS = ["web_search", "deep_research", "create_image"];
2086
+ var MODE_OPTION_IDS = [
2087
+ "latest",
2088
+ "instant",
2089
+ "thinking",
2090
+ "extended",
2091
+ "medium",
2092
+ "high",
2093
+ "extraHigh",
2094
+ "pro"
2095
+ ];
1688
2096
  function flattenKey(localeList, key) {
1689
2097
  const seen = /* @__PURE__ */ new Set();
1690
2098
  const result = [];
@@ -1719,6 +2127,24 @@ function flattenTool(localeList, toolId) {
1719
2127
  }
1720
2128
  return result;
1721
2129
  }
2130
+ function flattenModeOption(localeList, optionId) {
2131
+ const seen = /* @__PURE__ */ new Set();
2132
+ const result = [];
2133
+ for (const locale of localeList) {
2134
+ const modeOptions = locale["modeOptions"];
2135
+ if (modeOptions === void 0 || modeOptions === null) continue;
2136
+ const value = modeOptions[optionId];
2137
+ if (value === void 0 || value === null) continue;
2138
+ const candidates = typeof value === "string" ? [value] : value;
2139
+ for (const candidate of candidates) {
2140
+ if (candidate.length > 0 && !seen.has(candidate)) {
2141
+ seen.add(candidate);
2142
+ result.push(candidate);
2143
+ }
2144
+ }
2145
+ }
2146
+ return result;
2147
+ }
1722
2148
  var nonToolKeys = [
1723
2149
  "composerTextbox",
1724
2150
  "sendButton",
@@ -1737,6 +2163,8 @@ var nonToolKeys = [
1737
2163
  "imageContainerHint",
1738
2164
  "modeLabels",
1739
2165
  "modeOpenerExtra",
2166
+ "threadActionMenuItems",
2167
+ "threadActionPrefixes",
1740
2168
  "signedInMarkers",
1741
2169
  "transientAssistant",
1742
2170
  "stopControl",
@@ -1752,8 +2180,12 @@ var builtLabels = Object.fromEntries(
1752
2180
  var builtTools = Object.fromEntries(
1753
2181
  TOOL_IDS.map((id2) => [id2, flattenTool(locales, id2)])
1754
2182
  );
2183
+ var builtModeOptions = Object.fromEntries(
2184
+ MODE_OPTION_IDS.map((id2) => [id2, flattenModeOption(locales, id2)])
2185
+ );
1755
2186
  var localeLabels = {
1756
2187
  ...builtLabels,
2188
+ modeOptions: builtModeOptions,
1757
2189
  tools: builtTools
1758
2190
  };
1759
2191
  function escapeRegExp(value) {
@@ -1783,8 +2215,17 @@ function localGuardTimeout(timeoutMs, capMs) {
1783
2215
 
1784
2216
  // src/browser/page-state.ts
1785
2217
  function parseConversationId(url) {
1786
- const match = /\/c\/([A-Za-z0-9-]+)/.exec(url);
1787
- return match?.[1];
2218
+ let parsed;
2219
+ try {
2220
+ parsed = new URL(url, "https://chatgpt.com");
2221
+ } catch {
2222
+ return void 0;
2223
+ }
2224
+ const segments = parsed.pathname.split("/").filter(Boolean);
2225
+ if (segments[0] !== "c" || segments[1] === void 0 || segments[1].length === 0) {
2226
+ return void 0;
2227
+ }
2228
+ return segments[1];
1788
2229
  }
1789
2230
  async function readPageState(page) {
1790
2231
  const rawUrl = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
@@ -2369,16 +2810,36 @@ function getTabId(page) {
2369
2810
  import { execFile } from "node:child_process";
2370
2811
  import { promisify } from "node:util";
2371
2812
  var execFileAsync = promisify(execFile);
2813
+ function clipboardReadCommandsForPlatform(platform, env = {}) {
2814
+ if (platform === "darwin") {
2815
+ return [{ command: "pbpaste", args: [] }];
2816
+ }
2817
+ if (platform === "win32") {
2818
+ return [{ command: "powershell.exe", args: ["-NoProfile", "-Command", "Get-Clipboard -Raw"] }];
2819
+ }
2820
+ if (platform === "linux") {
2821
+ const waylandCommand = { command: "wl-paste", args: ["--no-newline"] };
2822
+ const x11Commands = [
2823
+ { command: "xclip", args: ["-selection", "clipboard", "-o"] },
2824
+ { command: "xsel", args: ["--clipboard", "--output"] }
2825
+ ];
2826
+ const isWayland = typeof env.WAYLAND_DISPLAY === "string" && env.WAYLAND_DISPLAY.length > 0;
2827
+ return isWayland ? [waylandCommand, ...x11Commands] : [...x11Commands, waylandCommand];
2828
+ }
2829
+ return [];
2830
+ }
2372
2831
  async function readSystemClipboard() {
2373
- if (typeof process === "undefined" || process.platform !== "darwin") {
2832
+ if (typeof process === "undefined") {
2374
2833
  return void 0;
2375
2834
  }
2376
- try {
2377
- const { stdout } = await execFileAsync("pbpaste", [], { timeout: 2e3, maxBuffer: 10 * 1024 * 1024 });
2378
- return stdout;
2379
- } catch {
2380
- return void 0;
2835
+ for (const { command, args } of clipboardReadCommandsForPlatform(process.platform, process.env)) {
2836
+ try {
2837
+ const { stdout } = await execFileAsync(command, args, { timeout: 2e3, maxBuffer: 10 * 1024 * 1024 });
2838
+ return stdout;
2839
+ } catch {
2840
+ }
2381
2841
  }
2842
+ return void 0;
2382
2843
  }
2383
2844
  async function waitForClipboardChange(before, timeoutMs, pollMs = 150) {
2384
2845
  const started = Date.now();
@@ -3928,7 +4389,7 @@ async function contextFromPage(page, partial = {}) {
3928
4389
  return { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...partial };
3929
4390
  }
3930
4391
  const url = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => partial.url) : partial.url;
3931
- const title = typeof page.title === "function" ? await page.title().catch(() => void 0) : partial.title;
4392
+ const title = typeof page.title === "function" ? await withTimeout(page.title(), 1e3, "Timed out while reading page title.").catch(() => partial.title) : partial.title;
3932
4393
  const [turnCount, assistantTurnCount] = await Promise.all([
3933
4394
  withTimeout(countPageMessages(page), 1e3, "Timed out while counting page messages.").catch(() => partial.turnCount),
3934
4395
  withTimeout(countPageMessages(page, "assistant"), 1e3, "Timed out while counting assistant messages.").catch(() => partial.assistantTurnCount)
@@ -3976,8 +4437,51 @@ async function bootstrap(env, args = {}) {
3976
4437
  }
3977
4438
  }
3978
4439
 
3979
- // src/commands/threads.ts
4440
+ // src/commands/conversation.ts
3980
4441
  var CHATGPT_HOME2 = "https://chatgpt.com/";
4442
+ async function ensureConversationTarget(page, target, options) {
4443
+ const targetUrl = absoluteConversationUrl(target);
4444
+ const expectedConversationId = parseConversationId(targetUrl);
4445
+ const currentUrl = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
4446
+ if (expectedConversationId !== void 0 && parseConversationId(typeof currentUrl === "string" ? currentUrl : "") === expectedConversationId) {
4447
+ await waitForConversationHydrated(page, options.timeoutMs, expectedConversationId);
4448
+ return ensureResult(false, targetUrl, expectedConversationId);
4449
+ }
4450
+ await page.goto?.(targetUrl, { waitUntil: "domcontentloaded", timeout: options.timeoutMs });
4451
+ await waitForConversationHydrated(page, options.timeoutMs, expectedConversationId);
4452
+ return ensureResult(true, targetUrl, expectedConversationId);
4453
+ }
4454
+ async function waitForConversationHydrated(page, timeoutMs, expectedConversationId) {
4455
+ const started = Date.now();
4456
+ do {
4457
+ const url = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
4458
+ const urlMatches2 = expectedConversationId === void 0 || parseConversationId(typeof url === "string" ? url : "") === expectedConversationId;
4459
+ const count = await countPageMessages(page).catch(() => 0);
4460
+ const latestAssistantText = await readLatestMessageText(page, "assistant").catch(() => void 0);
4461
+ const title = typeof page.title === "function" ? await page.title().catch(() => "") : "";
4462
+ if (urlMatches2 && ((latestAssistantText?.trim().length ?? 0) > 0 || count > 0 && title.length > 0 && title !== "ChatGPT")) {
4463
+ await page.waitForTimeout?.(250);
4464
+ return;
4465
+ }
4466
+ await page.waitForTimeout?.(500);
4467
+ } while (Date.now() - started < timeoutMs);
4468
+ }
4469
+ function absoluteConversationUrl(target) {
4470
+ if (target.href !== void 0 && target.href.startsWith("/")) {
4471
+ return new URL(target.href, CHATGPT_HOME2).toString();
4472
+ }
4473
+ return target.href ?? target.url;
4474
+ }
4475
+ function ensureResult(navigated, targetUrl, expectedConversationId) {
4476
+ const result = { navigated, targetUrl };
4477
+ if (expectedConversationId !== void 0) {
4478
+ result.expectedConversationId = expectedConversationId;
4479
+ }
4480
+ return result;
4481
+ }
4482
+
4483
+ // src/commands/threads.ts
4484
+ var CHATGPT_HOME3 = "https://chatgpt.com/";
3981
4485
  function extractThreadSearchResultsFromHtml(html) {
3982
4486
  const anchors = html.matchAll(/<a\b(?<attrs>[^>]*\bhref=["'](?<href>\/c\/[^"']+)["'][^>]*)>(?<body>[\s\S]*?)<\/a>/gi);
3983
4487
  const results = [];
@@ -4038,7 +4542,7 @@ async function newThread(env, args = {}) {
4038
4542
  try {
4039
4543
  await newChatButton(page).click?.();
4040
4544
  } catch {
4041
- await page.goto?.(CHATGPT_HOME2, { waitUntil: "domcontentloaded", timeout: args.timeoutMs ?? 3e4 });
4545
+ await page.goto?.(CHATGPT_HOME3, { waitUntil: "domcontentloaded", timeout: args.timeoutMs ?? 3e4 });
4042
4546
  }
4043
4547
  await page.waitForTimeout?.(500);
4044
4548
  const state = await readPageState(page);
@@ -4067,12 +4571,7 @@ async function openThread(env, args, previousResults) {
4067
4571
  context: await contextFromPage(page)
4068
4572
  };
4069
4573
  }
4070
- if (target.href !== void 0 && target.href.startsWith("/")) {
4071
- await page.goto?.(new URL(target.href, CHATGPT_HOME2).toString(), { waitUntil: "domcontentloaded", timeout: args.timeoutMs ?? 3e4 });
4072
- } else {
4073
- await page.goto?.(target.href ?? target.url, { waitUntil: "domcontentloaded", timeout: args.timeoutMs ?? 3e4 });
4074
- }
4075
- await waitForThreadHydrated(page, args.timeoutMs ?? 3e4, parseConversationId(target.url));
4574
+ await ensureConversationTarget(page, target, { timeoutMs: args.timeoutMs ?? 3e4 });
4076
4575
  const state = await readPageState(page);
4077
4576
  return resultOk(
4078
4577
  openThreadData(state.url, state.conversationId, state.title ?? target.title),
@@ -4093,21 +4592,21 @@ async function resolveOpenTarget(env, args, previousResults) {
4093
4592
  return { url: args.url };
4094
4593
  }
4095
4594
  if (args.conversationId !== void 0) {
4096
- return { url: new URL(`/c/${args.conversationId}`, CHATGPT_HOME2).toString() };
4595
+ return { url: new URL(`/c/${args.conversationId}`, CHATGPT_HOME3).toString() };
4097
4596
  }
4098
4597
  if (args.fromStep !== void 0 && previousResults !== void 0) {
4099
4598
  const previous = previousResults.get(args.fromStep);
4100
4599
  const data = previous?.data;
4101
4600
  const selected = selectSearchResult(data?.results ?? [], args.select ?? "first");
4102
4601
  if (selected !== void 0) {
4103
- return { href: selected.href, url: new URL(selected.href, CHATGPT_HOME2).toString(), title: selected.title };
4602
+ return { href: selected.href, url: new URL(selected.href, CHATGPT_HOME3).toString(), title: selected.title };
4104
4603
  }
4105
4604
  }
4106
4605
  if (args.title !== void 0) {
4107
4606
  const search = await searchThreads(env, { query: args.title, limit: 10 });
4108
4607
  const selected = selectSearchResult(search.data?.results ?? [], { title: args.title }) ?? search.data?.results[0];
4109
4608
  if (selected !== void 0) {
4110
- return { href: selected.href, url: new URL(selected.href, CHATGPT_HOME2).toString(), title: selected.title };
4609
+ return { href: selected.href, url: new URL(selected.href, CHATGPT_HOME3).toString(), title: selected.title };
4111
4610
  }
4112
4611
  }
4113
4612
  return void 0;
@@ -4240,22 +4739,9 @@ function filterResultsByQuery(results, query) {
4240
4739
  return haystack.includes(wanted) || wanted.includes(normalizeForMatch(result.title));
4241
4740
  });
4242
4741
  }
4243
- async function waitForThreadHydrated(page, timeoutMs, expectedConversationId) {
4244
- const started = Date.now();
4245
- await page.waitForTimeout?.(1e3);
4246
- while (Date.now() - started < timeoutMs) {
4247
- const url = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
4248
- const urlMatches2 = expectedConversationId === void 0 || url.includes(expectedConversationId);
4249
- const count = await countPageMessages(page).catch(() => 0);
4250
- const latestAssistantText = await readLatestMessageText(page, "assistant").catch(() => void 0);
4251
- const title = typeof page.title === "function" ? await page.title().catch(() => "") : "";
4252
- if (urlMatches2 && ((latestAssistantText?.trim().length ?? 0) > 0 || count > 0 && title.length > 0 && title !== "ChatGPT")) {
4253
- await page.waitForTimeout?.(250);
4254
- return;
4255
- }
4256
- await page.waitForTimeout?.(500);
4257
- }
4258
- }
4742
+
4743
+ // src/commands/messages.ts
4744
+ import { createHash as createHash2 } from "node:crypto";
4259
4745
 
4260
4746
  // src/dom/generation-state.ts
4261
4747
  var EMPTY_GENERATION_STATE = {
@@ -4348,6 +4834,121 @@ function generationStateFromText(text) {
4348
4834
  };
4349
4835
  }
4350
4836
 
4837
+ // src/dom/wait-snapshot.ts
4838
+ function waitTextMetadata(rawText) {
4839
+ const normalized = normalizeWhitespace(rawText ?? "");
4840
+ return {
4841
+ length: normalized.length,
4842
+ hash: fnv1a32Hex(normalized),
4843
+ transient: isTransientAssistantText(normalized)
4844
+ };
4845
+ }
4846
+ function fnv1a32Hex(text) {
4847
+ let hash = 2166136261;
4848
+ for (let index = 0; index < text.length; index += 1) {
4849
+ hash ^= text.charCodeAt(index);
4850
+ hash = Math.imul(hash, 16777619);
4851
+ }
4852
+ return (hash >>> 0).toString(16).padStart(8, "0");
4853
+ }
4854
+ async function readWaitDomSnapshot(page) {
4855
+ if (typeof page.evaluate !== "function") {
4856
+ return void 0;
4857
+ }
4858
+ return page.evaluate((args) => {
4859
+ const __combinedWaitSnapshot = true;
4860
+ void __combinedWaitSnapshot;
4861
+ const normalizeWs = (value) => value.replace(/\s+/g, " ").trim();
4862
+ const normalizeLower = (value) => (value ?? "").trim().toLowerCase();
4863
+ const nodes = Array.from(document.querySelectorAll("[data-message-author-role]"));
4864
+ const assistantNodes = nodes.filter((node) => node.getAttribute("data-message-author-role") === "assistant");
4865
+ const latestAssistant = assistantNodes.at(-1);
4866
+ const latestAssistantTurnIndex = latestAssistant === void 0 ? void 0 : nodes.indexOf(latestAssistant) + 1;
4867
+ const normalizedText = normalizeWs(latestAssistant?.innerText ?? latestAssistant?.textContent ?? "");
4868
+ let hash = 2166136261;
4869
+ for (let index = 0; index < normalizedText.length; index += 1) {
4870
+ hash ^= normalizedText.charCodeAt(index);
4871
+ hash = Math.imul(hash, 16777619);
4872
+ }
4873
+ const textHash = (hash >>> 0).toString(16).padStart(8, "0");
4874
+ const trimmedForTransient = normalizedText.replace(/[.。…]+$/g, "").trim().toLowerCase();
4875
+ const transient = args.transient.some((phrase) => trimmedForTransient === phrase.toLowerCase()) || /^analyzing (?:the )?images?$/.test(trimmedForTransient) || /^processing (?:the )?images?$/.test(trimmedForTransient) || /^reading (?:the )?images?$/.test(trimmedForTransient);
4876
+ const isVisible = (element) => {
4877
+ const style = window.getComputedStyle(element);
4878
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && element.getAttribute("aria-hidden") !== "true";
4879
+ };
4880
+ const visibleButtons = Array.from(document.querySelectorAll("button")).filter((button) => isVisible(button) && button.disabled !== true && button.getAttribute("aria-disabled") !== "true");
4881
+ const buttonTexts = visibleButtons.map((button) => [
4882
+ button.innerText,
4883
+ button.textContent,
4884
+ button.getAttribute("aria-label"),
4885
+ button.getAttribute("title")
4886
+ ].map(normalizeLower).filter(Boolean).join(" ")).filter(Boolean);
4887
+ const bodyText = normalizeLower(document.body?.innerText);
4888
+ const haystacks = [bodyText, ...buttonTexts];
4889
+ const matchingSignals = (phrases) => haystacks.flatMap(
4890
+ (text) => phrases.map((phrase) => phrase.toLowerCase()).filter((phrase) => text.includes(phrase))
4891
+ );
4892
+ const activeSignals = matchingSignals(args.stop);
4893
+ const stoppedSignals = matchingSignals(args.stopped);
4894
+ const generation = {
4895
+ active: activeSignals.length > 0,
4896
+ stopped: stoppedSignals.length > 0,
4897
+ signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals, ...buttonTexts.filter((text) => /stop|cancel|stopped|answering|thinking/i.test(text))])].slice(0, 5)
4898
+ };
4899
+ const turns = Array.from(document.querySelectorAll("[data-testid^='conversation-turn']"));
4900
+ let hasResponseActions;
4901
+ if (turns.length === 0) {
4902
+ hasResponseActions = void 0;
4903
+ } else {
4904
+ const latestTurn = [...turns].reverse().find(
4905
+ (turn) => turn.querySelector("[data-message-author-role='assistant']") !== null
4906
+ );
4907
+ if (latestTurn === void 0) {
4908
+ hasResponseActions = false;
4909
+ } else {
4910
+ const actionText = Array.from(latestTurn.querySelectorAll("button")).map((button) => [
4911
+ button.innerText,
4912
+ button.textContent,
4913
+ button.getAttribute("aria-label"),
4914
+ button.getAttribute("title")
4915
+ ].filter(Boolean).join(" ")).join(" ").toLowerCase();
4916
+ hasResponseActions = args.actions.some((phrase) => actionText.includes(phrase.toLowerCase()));
4917
+ }
4918
+ }
4919
+ const snapshot = {
4920
+ turnCount: nodes.length,
4921
+ assistantTurnCount: assistantNodes.length,
4922
+ text: { length: normalizedText.length, hash: textHash, transient },
4923
+ generation
4924
+ };
4925
+ if (latestAssistantTurnIndex !== void 0) snapshot.latestAssistantTurnIndex = latestAssistantTurnIndex;
4926
+ if (hasResponseActions !== void 0) snapshot.hasResponseActions = hasResponseActions;
4927
+ return snapshot;
4928
+ }, {
4929
+ transient: [...localeLabels.transientAssistant],
4930
+ stop: [...localeLabels.stopControl],
4931
+ stopped: [...localeLabels.stoppedAssistant],
4932
+ actions: [...localeLabels.responseActions]
4933
+ });
4934
+ }
4935
+
4936
+ // src/commands/deadline.ts
4937
+ function createDeadline(timeoutMs, startedAtMs = Date.now()) {
4938
+ const safeTimeoutMs = Math.max(0, timeoutMs);
4939
+ return {
4940
+ startedAtMs,
4941
+ timeoutMs: safeTimeoutMs,
4942
+ expiresAtMs: startedAtMs + safeTimeoutMs
4943
+ };
4944
+ }
4945
+ function remainingMs(deadline, nowMs = Date.now()) {
4946
+ return Math.max(0, deadline.expiresAtMs - nowMs);
4947
+ }
4948
+ function childTimeoutMs(deadline, capMs, nowMs = Date.now()) {
4949
+ return Math.max(0, Math.min(Math.max(0, capMs), remainingMs(deadline, nowMs)));
4950
+ }
4951
+
4351
4952
  // src/commands/output.ts
4352
4953
  function commandOutputText(data) {
4353
4954
  if (!isRecord(data)) return void 0;
@@ -4374,6 +4975,69 @@ function isRecord(value) {
4374
4975
  return typeof value === "object" && value !== null && !Array.isArray(value);
4375
4976
  }
4376
4977
 
4978
+ // src/commands/probes.ts
4979
+ function createSingleFlightProbe(name, probe) {
4980
+ let inFlight;
4981
+ return async (arg, deadline, options) => {
4982
+ if (inFlight !== void 0) {
4983
+ return {
4984
+ ok: false,
4985
+ skipped: true,
4986
+ warnings: [`Skipped ${name} DOM probe because previous browser-side work is still in flight.`]
4987
+ };
4988
+ }
4989
+ const timeoutMs = childTimeoutMs(deadline, options.timeoutMs);
4990
+ if (timeoutMs <= 0) {
4991
+ return {
4992
+ ok: false,
4993
+ timedOut: true,
4994
+ warnings: [`Skipped ${name} DOM probe because no deadline budget remained.`]
4995
+ };
4996
+ }
4997
+ const current = probe(arg);
4998
+ inFlight = current;
4999
+ current.finally(() => {
5000
+ if (inFlight === current) {
5001
+ inFlight = void 0;
5002
+ }
5003
+ }).catch(() => void 0);
5004
+ let timeout;
5005
+ try {
5006
+ const value = await Promise.race([
5007
+ current,
5008
+ new Promise((_resolve, reject) => {
5009
+ timeout = setTimeout(() => reject(new ProbeTimeoutError(timeoutMs)), timeoutMs);
5010
+ })
5011
+ ]);
5012
+ return { ok: true, value, warnings: [] };
5013
+ } catch (error) {
5014
+ if (error instanceof ProbeTimeoutError) {
5015
+ return {
5016
+ ok: false,
5017
+ timedOut: true,
5018
+ warnings: [`Timed out waiting ${timeoutMs}ms for ${name} DOM probe; this stopped SDK waiting but did not cancel browser-side work.`]
5019
+ };
5020
+ }
5021
+ return {
5022
+ ok: false,
5023
+ warnings: [`${name} DOM probe failed: ${error instanceof Error ? error.message : String(error)}`]
5024
+ };
5025
+ } finally {
5026
+ if (timeout !== void 0) {
5027
+ clearTimeout(timeout);
5028
+ }
5029
+ }
5030
+ };
5031
+ }
5032
+ var ProbeTimeoutError = class extends Error {
5033
+ constructor(timeoutMs) {
5034
+ super(`Probe timed out after ${timeoutMs}ms.`);
5035
+ this.timeoutMs = timeoutMs;
5036
+ this.name = "ProbeTimeoutError";
5037
+ }
5038
+ timeoutMs;
5039
+ };
5040
+
4377
5041
  // src/commands/messages.ts
4378
5042
  function isResponseComplete(snapshot) {
4379
5043
  return snapshot.latestText.trim().length > 0 && !isTransientAssistantText(snapshot.latestText) && snapshot.textStableForMs >= snapshot.stableMs && !snapshot.generation.active && !snapshot.generation.stopped && snapshot.hasResponseActions;
@@ -4581,7 +5245,14 @@ async function readVisibleTextForSubmit(page) {
4581
5245
  if (typeof page.evaluate !== "function") {
4582
5246
  return void 0;
4583
5247
  }
4584
- return page.evaluate(() => document.body?.innerText ?? "");
5248
+ return page.evaluate(() => {
5249
+ const composerForm = document.querySelector("main form") ?? document.querySelector("form");
5250
+ const scopedText = composerForm?.innerText;
5251
+ if (scopedText !== void 0 && scopedText.trim().length > 0) {
5252
+ return scopedText;
5253
+ }
5254
+ return document.body?.innerText ?? "";
5255
+ });
4585
5256
  }
4586
5257
  async function sendTimeoutWarnings(page) {
4587
5258
  const state = await readSendButtonState(page).catch(() => void 0);
@@ -4611,78 +5282,109 @@ async function waitForMessage(env, args = {}) {
4611
5282
  const stableMs = args.stableMs ?? (args.mode === "deep_research" ? 1e4 : 2e3);
4612
5283
  const pollMs = args.pollMs ?? 750;
4613
5284
  const started = Date.now();
4614
- let lastTargetText = "";
5285
+ const deadline = createDeadline(timeoutMs, started);
5286
+ const probeTimeoutMs = Math.max(50, Math.min(1e3, Math.max(pollMs, Math.floor(timeoutMs / 4))));
5287
+ const waitWarnings = /* @__PURE__ */ new Set();
5288
+ const waitSnapshotProbe = createSingleFlightProbe("wait snapshot", readWaitDomSnapshot);
5289
+ const pageStateProbe = createSingleFlightProbe("page state", readPageState);
5290
+ const PAGE_STATE_POLL_STRIDE = 4;
5291
+ let pollIndex = 0;
5292
+ let lastTargetKey = "";
4615
5293
  let lastChangedAt = Date.now();
5294
+ let lastObservedTextLength = 0;
4616
5295
  let latestAssistantCount = await countPageMessages(page, "assistant").catch(() => 0);
4617
5296
  while (Date.now() - started < timeoutMs) {
4618
- const state = await readPageState(page).catch(() => void 0);
4619
- if (state?.blocker !== void 0 && state.blocker.kind !== "modal") {
4620
- return {
4621
- ok: false,
4622
- status: "blocked",
4623
- warnings: [],
4624
- blocker: state.blocker,
4625
- context: await contextFromPage(page)
4626
- };
4627
- }
4628
- const progress = await readAssistantProgressSnapshot(page).catch(() => fallbackAssistantProgressSnapshot(page, latestAssistantCount));
4629
- latestAssistantCount = progress.assistantTurnCount;
4630
- const targetReached = waitTargetReached(args, progress);
4631
- const latestText = targetReached ? normalizeWhitespace(progress.latestText ?? "") : "";
4632
- if (latestText !== lastTargetText) {
4633
- lastTargetText = latestText;
5297
+ const probeResult = await waitSnapshotProbe(page, deadline, { timeoutMs: probeTimeoutMs });
5298
+ addWarnings(waitWarnings, probeResult.warnings);
5299
+ const snapshot = await waitSnapshotFromProbeResult(page, probeResult, latestAssistantCount);
5300
+ latestAssistantCount = snapshot.assistantTurnCount;
5301
+ const targetReached = waitTargetReached(args, snapshot);
5302
+ const targetKey = targetReached && snapshot.text.length > 0 ? `${snapshot.text.length}:${snapshot.text.hash}` : "";
5303
+ if (targetKey !== lastTargetKey) {
5304
+ lastTargetKey = targetKey;
4634
5305
  lastChangedAt = Date.now();
4635
5306
  }
4636
- const snapshot = {
4637
- latestText,
4638
- stableMs,
4639
- textStableForMs: Date.now() - lastChangedAt,
4640
- generation: await readAssistantGenerationState(page),
4641
- hasResponseActions: await latestAssistantTurnHasResponseActions(page)
4642
- };
4643
- if (targetReached && snapshot.generation.stopped && latestText.length > 0) {
5307
+ if (targetReached && snapshot.text.length > 0) {
5308
+ lastObservedTextLength = snapshot.text.length;
5309
+ }
5310
+ if (pollIndex % PAGE_STATE_POLL_STRIDE === 0) {
5311
+ const state = await pageStateFromProbe(pageStateProbe(page, deadline, { timeoutMs: probeTimeoutMs }), waitWarnings);
5312
+ if (state?.blocker !== void 0 && state.blocker.kind !== "modal") {
5313
+ return {
5314
+ ok: false,
5315
+ status: "blocked",
5316
+ warnings: [...waitWarnings],
5317
+ blocker: state.blocker,
5318
+ context: await contextFromPage(page)
5319
+ };
5320
+ }
5321
+ }
5322
+ pollIndex += 1;
5323
+ const hasResponseActions = await resolveResponseActions(page, snapshot);
5324
+ if (targetReached && snapshot.generation.stopped && snapshot.text.length > 0) {
5325
+ const stoppedText = normalizeWhitespace(await fetchLatestAssistantText(page) ?? "");
5326
+ const data = stoppedText.length > 0 ? waitDataFromText(args, false, stoppedText, latestAssistantCount, Date.now() - started) : waitDataWithoutText(latestAssistantCount, Date.now() - started);
5327
+ if (stoppedText.length === 0) {
5328
+ waitWarnings.add(`The interrupted assistant text (~${snapshot.text.length} chars observed) could not be re-read at wait exit; call messages.readLatest on the same thread to capture it.`);
5329
+ }
4644
5330
  return withCommandOutputText({
4645
5331
  ok: false,
4646
5332
  status: "partial",
4647
- data: {
4648
- complete: false,
4649
- responseText: latestText,
4650
- assistantTurnCount: latestAssistantCount,
4651
- elapsedMs: Date.now() - started
4652
- },
5333
+ data,
4653
5334
  warnings: [
5335
+ ...waitWarnings,
5336
+ ...stoppedText.length > 0 ? responseContentWarnings(args, false) : [],
4654
5337
  "ChatGPT generation appears to have been stopped or interrupted before completion.",
4655
5338
  ...snapshot.generation.signals.map((signal) => `Generation state signal: ${signal}`)
4656
5339
  ],
4657
5340
  context: await contextFromPage(page)
4658
5341
  });
4659
5342
  }
4660
- if (targetReached && isResponseComplete(snapshot)) {
4661
- return withCommandOutputText(resultOk(
4662
- { complete: true, responseText: latestText, assistantTurnCount: latestAssistantCount, elapsedMs: Date.now() - started },
4663
- await contextFromPage(page)
4664
- ));
5343
+ const metadataComplete = targetReached && snapshot.text.length > 0 && !snapshot.text.transient && Date.now() - lastChangedAt >= stableMs && !snapshot.generation.active && !snapshot.generation.stopped && hasResponseActions;
5344
+ if (metadataComplete) {
5345
+ const latestText = normalizeWhitespace(await fetchLatestAssistantText(page) ?? "");
5346
+ const fetchedMetadata = waitTextMetadata(latestText);
5347
+ const completionSnapshot = {
5348
+ latestText,
5349
+ stableMs,
5350
+ textStableForMs: Date.now() - lastChangedAt,
5351
+ generation: snapshot.generation,
5352
+ hasResponseActions
5353
+ };
5354
+ if (fetchedMetadata.hash === snapshot.text.hash && isResponseComplete(completionSnapshot)) {
5355
+ const data = waitDataFromText(args, true, latestText, latestAssistantCount, Date.now() - started);
5356
+ return withCommandOutputText(resultOk(
5357
+ data,
5358
+ await contextFromPage(page),
5359
+ [...waitWarnings, ...responseContentWarnings(args, true)]
5360
+ ));
5361
+ }
5362
+ if (latestText.length > 0) {
5363
+ lastTargetKey = `${fetchedMetadata.length}:${fetchedMetadata.hash}`;
5364
+ lastChangedAt = Date.now();
5365
+ lastObservedTextLength = fetchedMetadata.length;
5366
+ }
4665
5367
  }
4666
5368
  await sleep(page, pollMs);
4667
5369
  }
4668
- if (lastTargetText.length > 0) {
4669
- return withCommandOutputText({
4670
- ok: false,
4671
- status: "partial",
4672
- data: {
4673
- complete: false,
4674
- responseText: lastTargetText,
4675
- assistantTurnCount: latestAssistantCount,
4676
- elapsedMs: Date.now() - started
4677
- },
4678
- warnings: ["Timed out after receiving partial assistant text."],
4679
- context: await contextFromPage(page)
4680
- });
5370
+ if (lastObservedTextLength > 0) {
5371
+ const partialText = await fetchLatestAssistantText(page);
5372
+ if (partialText !== void 0 && normalizeWhitespace(partialText).length > 0) {
5373
+ const data = waitDataFromText(args, false, normalizeWhitespace(partialText), latestAssistantCount, Date.now() - started);
5374
+ return withCommandOutputText({
5375
+ ok: false,
5376
+ status: "partial",
5377
+ data,
5378
+ warnings: [...waitWarnings, ...responseContentWarnings(args, false), "Timed out after receiving partial assistant text."],
5379
+ context: await contextFromPage(page)
5380
+ });
5381
+ }
5382
+ waitWarnings.add(`Partial assistant text (${lastObservedTextLength} chars) was observed during polling but could not be re-read at wait exit.`);
4681
5383
  }
4682
5384
  return {
4683
5385
  ok: false,
4684
5386
  status: "timeout",
4685
- warnings: [],
5387
+ warnings: [...waitWarnings],
4686
5388
  error: {
4687
5389
  name: "WaitTimeout",
4688
5390
  message: "No assistant response appeared before the timeout.",
@@ -4691,6 +5393,94 @@ async function waitForMessage(env, args = {}) {
4691
5393
  context: await contextFromPage(page)
4692
5394
  };
4693
5395
  }
5396
+ async function fetchLatestAssistantText(page) {
5397
+ const first = await readLatestMessageText(page, "assistant").catch(() => void 0);
5398
+ if (first !== void 0) {
5399
+ return first;
5400
+ }
5401
+ await sleep(page, 150);
5402
+ return readLatestMessageText(page, "assistant").catch(() => void 0);
5403
+ }
5404
+ function waitDataWithoutText(assistantTurnCount, elapsedMs) {
5405
+ return { complete: false, assistantTurnCount, elapsedMs };
5406
+ }
5407
+ async function resolveResponseActions(page, snapshot) {
5408
+ if (snapshot.hasResponseActions !== void 0) {
5409
+ return snapshot.hasResponseActions;
5410
+ }
5411
+ try {
5412
+ const copyButtons = copyResponseButtons(page);
5413
+ const count = await copyButtons.count?.();
5414
+ if (count !== void 0) {
5415
+ return count > 0;
5416
+ }
5417
+ return await copyButtons.isVisible?.() === true;
5418
+ } catch {
5419
+ return false;
5420
+ }
5421
+ }
5422
+ async function waitSnapshotFromProbeResult(page, result, previousAssistantTurnCount) {
5423
+ if (result.ok && result.value !== void 0) {
5424
+ return result.value;
5425
+ }
5426
+ if (!result.ok && (result.timedOut === true || result.skipped === true)) {
5427
+ return {
5428
+ turnCount: 0,
5429
+ assistantTurnCount: previousAssistantTurnCount,
5430
+ text: waitTextMetadata(""),
5431
+ generation: EMPTY_GENERATION_STATE,
5432
+ hasResponseActions: false
5433
+ };
5434
+ }
5435
+ return fallbackWaitSnapshot(page, previousAssistantTurnCount);
5436
+ }
5437
+ async function fallbackWaitSnapshot(page, previousAssistantTurnCount) {
5438
+ const progress = await fallbackAssistantProgressSnapshot(page, previousAssistantTurnCount);
5439
+ const generation = await readAssistantGenerationState(page).catch(() => EMPTY_GENERATION_STATE);
5440
+ const hasResponseActions = await latestAssistantTurnHasResponseActions(page).catch(() => false);
5441
+ const snapshot = {
5442
+ turnCount: progress.turnCount ?? 0,
5443
+ assistantTurnCount: progress.assistantTurnCount,
5444
+ text: waitTextMetadata(progress.latestText),
5445
+ generation,
5446
+ hasResponseActions
5447
+ };
5448
+ if (progress.latestAssistantTurnIndex !== void 0) {
5449
+ snapshot.latestAssistantTurnIndex = progress.latestAssistantTurnIndex;
5450
+ }
5451
+ return snapshot;
5452
+ }
5453
+ function waitDataFromText(args, complete, responseText, assistantTurnCount, elapsedMs) {
5454
+ const data = {
5455
+ complete,
5456
+ assistantTurnCount,
5457
+ elapsedMs
5458
+ };
5459
+ if (args.responseContent === "metadata") {
5460
+ data.responseContent = "metadata";
5461
+ data.responseChars = responseText.length;
5462
+ data.responseSha256 = createHash2("sha256").update(responseText).digest("hex");
5463
+ return data;
5464
+ }
5465
+ data.responseText = responseText;
5466
+ return data;
5467
+ }
5468
+ function responseContentWarnings(args, complete) {
5469
+ if (args.responseContent !== "metadata") return [];
5470
+ return [
5471
+ complete ? "Assistant response text was omitted because responseContent is metadata; call readLatest to capture the completed answer." : "Partial assistant text was omitted because responseContent is metadata; call wait again on the same thread or readLatest after completion."
5472
+ ];
5473
+ }
5474
+ async function pageStateFromProbe(probe, warnings) {
5475
+ const result = await probe;
5476
+ addWarnings(warnings, result.warnings);
5477
+ return result.ok ? result.value : void 0;
5478
+ }
5479
+ function addWarnings(target, warnings) {
5480
+ for (const warning of warnings) {
5481
+ target.add(warning);
5482
+ }
5483
+ }
4694
5484
  async function readLatest(env, args = {}) {
4695
5485
  const boot = await ensurePage2(env);
4696
5486
  if (!boot.ok) {
@@ -4933,25 +5723,6 @@ ${language}
4933
5723
  ${language}
4934
5724
  ` : "\n").replace(/`([^`]+)`/g, "$1").replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/__([^_]+)__/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/_([^_]+)_/g, "$1");
4935
5725
  }
4936
- async function readAssistantProgressSnapshot(page) {
4937
- if (typeof page.evaluate === "function") {
4938
- return page.evaluate(() => {
4939
- const nodes = Array.from(document.querySelectorAll("[data-message-author-role]"));
4940
- const assistantNodes = nodes.filter((node) => node.getAttribute("data-message-author-role") === "assistant");
4941
- const latestAssistant = assistantNodes.at(-1);
4942
- const latestAssistantTurnIndex = latestAssistant === void 0 ? void 0 : nodes.indexOf(latestAssistant) + 1;
4943
- const snapshot = {
4944
- turnCount: nodes.length,
4945
- assistantTurnCount: assistantNodes.length
4946
- };
4947
- const latestText = latestAssistant?.innerText ?? latestAssistant?.textContent ?? void 0;
4948
- if (latestText !== void 0) snapshot.latestText = latestText;
4949
- if (latestAssistantTurnIndex !== void 0) snapshot.latestAssistantTurnIndex = latestAssistantTurnIndex;
4950
- return snapshot;
4951
- });
4952
- }
4953
- return fallbackAssistantProgressSnapshot(page, 0);
4954
- }
4955
5726
  async function fallbackAssistantProgressSnapshot(page, previousAssistantTurnCount) {
4956
5727
  const messages = await readMessages(page, { format: "normalized_text" }).catch(() => void 0);
4957
5728
  if (messages !== void 0) {
@@ -5499,6 +6270,7 @@ async function sleep2(page, ms2) {
5499
6270
  // src/commands/files.ts
5500
6271
  import { access, readFile as readFile3, stat as stat4 } from "node:fs/promises";
5501
6272
  import { constants } from "node:fs";
6273
+ import { createHash as createHash3 } from "node:crypto";
5502
6274
  import path2 from "node:path";
5503
6275
 
5504
6276
  // src/platform/local-paths.ts
@@ -5613,7 +6385,17 @@ async function preflightFiles(env, args) {
5613
6385
  message: `File attachment exceeds the configured per-file preflight limit: ${absolute} (${fileStat.size}/${maxBytesPerFile} bytes)`
5614
6386
  });
5615
6387
  }
5616
- const metadata = fileMetadata(absolute, fileStat.size);
6388
+ if (fileStat.size === 0) {
6389
+ return filePreflightBlocker({
6390
+ env,
6391
+ status: "blocked",
6392
+ kind: "upload_failed",
6393
+ code: "file_empty",
6394
+ fieldPath,
6395
+ message: `File attachment path is zero bytes and ChatGPT rejects empty attachments: ${absolute}`
6396
+ });
6397
+ }
6398
+ const metadata = await fileMetadata(absolute, fileStat.size, args.includeHashes === true);
5617
6399
  files.push(metadata);
5618
6400
  }
5619
6401
  const totalBytes = files.reduce((sum, file) => sum + file.bytes, 0);
@@ -5631,7 +6413,11 @@ async function preflightFiles(env, args) {
5631
6413
  return resultOk({ files, totalBytes }, filePreflightContext(env), warnings);
5632
6414
  }
5633
6415
  async function attachFiles(env, args) {
5634
- const preflight = await preflightFiles(env, { paths: args.paths });
6416
+ const preflightArgs = { paths: args.paths };
6417
+ if (args.includeDiagnostics === true && args.includeHashes !== void 0) {
6418
+ preflightArgs.includeHashes = args.includeHashes;
6419
+ }
6420
+ const preflight = await preflightFiles(env, preflightArgs);
5635
6421
  if (!preflight.ok || preflight.data === void 0) {
5636
6422
  return preflight;
5637
6423
  }
@@ -5647,6 +6433,7 @@ async function attachFiles(env, args) {
5647
6433
  bytes: file.bytes
5648
6434
  }));
5649
6435
  await uploadFiles(page, files, args.timeoutMs ?? 3e4);
6436
+ const browserInput = args.includeDiagnostics === true ? await readBrowserInputDiagnostic(page).catch(() => void 0) : void 0;
5650
6437
  await page.waitForTimeout?.(args.timeoutMs === void 0 ? 1e3 : Math.min(args.timeoutMs, 3e3));
5651
6438
  const readiness = await waitForAttachedFilesReady(page, files, args.timeoutMs ?? 3e4);
5652
6439
  if (!readiness.ready) {
@@ -5679,7 +6466,14 @@ async function attachFiles(env, args) {
5679
6466
  context: await contextFromPage(page)
5680
6467
  };
5681
6468
  }
5682
- return resultOk({ files }, await contextFromPage(page), preflight.warnings);
6469
+ const data = { files };
6470
+ if (args.includeDiagnostics === true) {
6471
+ data.diagnostics = { preflight: preflight.data };
6472
+ if (browserInput !== void 0) {
6473
+ data.diagnostics.browserInput = browserInput;
6474
+ }
6475
+ }
6476
+ return resultOk(data, await contextFromPage(page), preflight.warnings);
5683
6477
  } catch (error) {
5684
6478
  if (isUploadBridgeBlocker(error)) {
5685
6479
  return {
@@ -5718,10 +6512,10 @@ function filePreflightBlocker(args) {
5718
6512
  function filePreflightContext(env) {
5719
6513
  return { timestamp: (env.now?.() ?? /* @__PURE__ */ new Date()).toISOString() };
5720
6514
  }
5721
- function fileMetadata(absolute, bytes) {
6515
+ async function fileMetadata(absolute, bytes, includeHash = false) {
5722
6516
  const extension = extensionForHostPath(absolute);
5723
6517
  const { mimeType, category } = guessFileType(extension);
5724
- return {
6518
+ const metadata = {
5725
6519
  path: absolute,
5726
6520
  name: basenameForHostPath(absolute),
5727
6521
  bytes,
@@ -5729,6 +6523,10 @@ function fileMetadata(absolute, bytes) {
5729
6523
  mimeType,
5730
6524
  category
5731
6525
  };
6526
+ if (includeHash) {
6527
+ metadata.sha256 = createHash3("sha256").update(await readFile3(absolute)).digest("hex");
6528
+ }
6529
+ return metadata;
5732
6530
  }
5733
6531
  function extensionForHostPath(value) {
5734
6532
  return process.platform === "win32" ? path2.win32.extname(value).toLowerCase() : path2.posix.extname(value).toLowerCase();
@@ -5737,9 +6535,6 @@ function collectFilePreflightWarnings(files, warnings) {
5737
6535
  const byPath = /* @__PURE__ */ new Map();
5738
6536
  const byName = /* @__PURE__ */ new Map();
5739
6537
  for (const file of files) {
5740
- if (file.bytes === 0) {
5741
- warnings.push(`Zero-byte file will be attached if ChatGPT accepts it: ${file.name}`);
5742
- }
5743
6538
  const pathCount = (byPath.get(file.path) ?? 0) + 1;
5744
6539
  byPath.set(file.path, pathCount);
5745
6540
  if (pathCount === 2) {
@@ -6058,6 +6853,32 @@ async function setHiddenFileInput(page, files) {
6058
6853
  }
6059
6854
  await input.setInputFiles(files.map((file) => file.path));
6060
6855
  }
6856
+ async function readBrowserInputDiagnostic(page) {
6857
+ if (typeof page.evaluate !== "function") {
6858
+ return void 0;
6859
+ }
6860
+ return page.evaluate(() => {
6861
+ const input = document.querySelector("#upload-files") || document.querySelector("input[type='file']:not([accept='image/*'])") || document.querySelector("input[type='file']");
6862
+ if (!input) {
6863
+ return { files: [] };
6864
+ }
6865
+ return {
6866
+ files: Array.from(input.files ?? []).map((file) => {
6867
+ const diagnostic2 = {
6868
+ name: file.name,
6869
+ size: file.size
6870
+ };
6871
+ if (file.type.length > 0) {
6872
+ diagnostic2.type = file.type;
6873
+ }
6874
+ if (file.lastModified !== 0) {
6875
+ diagnostic2.lastModified = file.lastModified;
6876
+ }
6877
+ return diagnostic2;
6878
+ })
6879
+ };
6880
+ });
6881
+ }
6061
6882
  async function ensurePage4(env) {
6062
6883
  if (env.page !== void 0) {
6063
6884
  return resultOk({}, await contextFromPage(env.page));
@@ -6875,6 +7696,31 @@ async function ensurePage5(env) {
6875
7696
  return bootstrap(env, { preferExistingTab: true });
6876
7697
  }
6877
7698
 
7699
+ // src/dom/label-match.ts
7700
+ function normalizeForLabelMatch(text) {
7701
+ return normalizeWhitespace(text.normalize("NFKC")).toLocaleLowerCase();
7702
+ }
7703
+ function visibleLabelMatches(label, wanted) {
7704
+ const normalizedLabel = normalizeForLabelMatch(label);
7705
+ const normalizedWanted = normalizeForLabelMatch(wanted);
7706
+ if (normalizedWanted.length === 0) {
7707
+ return false;
7708
+ }
7709
+ if (normalizedLabel === normalizedWanted) {
7710
+ return true;
7711
+ }
7712
+ if (isShortLatinToken(normalizedWanted)) {
7713
+ return new RegExp(`(^|[^\\p{L}\\p{N}])${escapeRegExp2(normalizedWanted)}([^\\p{L}\\p{N}]|$)`, "iu").test(normalizedLabel);
7714
+ }
7715
+ return normalizedLabel.includes(normalizedWanted);
7716
+ }
7717
+ function isShortLatinToken(value) {
7718
+ return value.length <= 3 && /^[a-z0-9]+$/i.test(value);
7719
+ }
7720
+ function escapeRegExp2(value) {
7721
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7722
+ }
7723
+
6878
7724
  // src/dom/menus.ts
6879
7725
  function extractMenuItemsFromText(text) {
6880
7726
  return text.split(/\n| {2,}| • /).map((label) => normalizeWhitespace(label)).filter(Boolean).map((label) => ({ label, normalized: normalizeLabel(label) }));
@@ -6901,7 +7747,10 @@ async function enumerateVisibleMenuItems(page) {
6901
7747
  if (ariaLabel !== null) item.ariaLabel = ariaLabel;
6902
7748
  return item;
6903
7749
  };
6904
- const roleItems = Array.from(document.querySelectorAll("[role='menuitem'], [role='menuitemradio'], [role='option']")).map(toItem).filter((item) => item.label.length > 0);
7750
+ const allRoleNodes = Array.from(document.querySelectorAll("[role='menuitem'], [role='menuitemradio'], [role='option']"));
7751
+ const containers = Array.from(document.querySelectorAll("[role='menu'], [role='listbox'], [data-radix-popper-content-wrapper]")).filter((container) => typeof container.contains === "function");
7752
+ const scopedRoleNodes = containers.length > 0 ? allRoleNodes.filter((node) => containers.some((container) => container.contains(node))) : allRoleNodes;
7753
+ const roleItems = (scopedRoleNodes.length > 0 ? scopedRoleNodes : allRoleNodes).map(toItem).filter((item) => item.label.length > 0);
6905
7754
  if (roleItems.length > 0) {
6906
7755
  return { items: roleItems, labels: [], split: false };
6907
7756
  }
@@ -6918,13 +7767,16 @@ function findUniqueMenuItem(items, wanted) {
6918
7767
  if (exact.length === 1) {
6919
7768
  return exact[0];
6920
7769
  }
6921
- const fuzzy = items.filter((item) => item.normalized.includes(normalized));
7770
+ const fuzzy = items.filter((item) => visibleLabelMatches(item.label, wanted));
6922
7771
  return fuzzy.length === 1 ? fuzzy[0] : void 0;
6923
7772
  }
6924
7773
 
6925
7774
  // src/commands/modes.ts
6926
7775
  var DEFAULT_MODE_EFFORT = "Thinking";
6927
- var CURRENT_MODE_LABELS = [...localeLabels.modeLabels];
7776
+ var CURRENT_MODE_LABELS = dedupeLabels([
7777
+ ...localeLabels.modeLabels,
7778
+ ...Object.values(localeLabels.modeOptions).flat()
7779
+ ]);
6928
7780
  var MODE_OPENER_LABELS = [...CURRENT_MODE_LABELS.filter((label) => label !== "Pro"), ...localeLabels.modeOpenerExtra];
6929
7781
  var MODEL_VERSION_FAMILY_PATTERN = /^gpt[\s-]/i;
6930
7782
  var MODEL_VERSION_LABEL_PATTERN = /^(?:o\d+|\d+(?:\.\d+)?)$/i;
@@ -6932,9 +7784,31 @@ var CANONICAL_INTELLIGENCE_ORDER = /* @__PURE__ */ new Map([
6932
7784
  ["instant", 0],
6933
7785
  ["medium", 1],
6934
7786
  ["high", 2],
6935
- ["extra high", 3],
7787
+ ["extraHigh", 3],
6936
7788
  ["pro", 4]
6937
7789
  ]);
7790
+ var MODE_OPTION_IDS2 = [
7791
+ "latest",
7792
+ "instant",
7793
+ "thinking",
7794
+ "extended",
7795
+ "medium",
7796
+ "high",
7797
+ "extraHigh",
7798
+ "pro"
7799
+ ];
7800
+ var MODE_ID_ALIASES = {
7801
+ latest: ["latest"],
7802
+ instant: ["instant"],
7803
+ thinking: ["thinking"],
7804
+ extended: ["extended"],
7805
+ medium: ["medium"],
7806
+ high: ["high"],
7807
+ extraHigh: ["extra high", "extra-high", "extra_high", "extrahigh"],
7808
+ pro: ["pro"]
7809
+ };
7810
+ var THREAD_ACTION_MENU_LABELS = new Set(localeLabels.threadActionMenuItems.map(normalizeForLabelMatch));
7811
+ var THREAD_ACTION_PREFIXES = localeLabels.threadActionPrefixes.map(normalizeForLabelMatch).filter((prefix) => prefix.length > 0);
6938
7812
  async function setMode(env, args) {
6939
7813
  const boot = await ensurePage6(env);
6940
7814
  if (!boot.ok) {
@@ -6942,9 +7816,9 @@ async function setMode(env, args) {
6942
7816
  }
6943
7817
  const page = env.page;
6944
7818
  try {
6945
- const requested = requestedModeLabels(args);
7819
+ const requested = requestedModeSelections(args);
6946
7820
  const requestedVersion = requestedModelVersion(args);
6947
- const requestedForOpening = requestedVersion === void 0 ? requested : [...requested, requestedVersion];
7821
+ const requestedForOpening = requestedVersion === void 0 ? requested : [...requested, requestedModeSelection(requestedVersion)];
6948
7822
  const opened = await waitForModeMenu(page, requestedForOpening, args.timeoutMs ?? 3e4);
6949
7823
  if (requestedVersion === void 0 && opened.alreadySelected.length === requested.length) {
6950
7824
  return resultOk({ selected: opened.alreadySelected, candidates: opened.modeButtons }, await contextFromPage(page));
@@ -6955,15 +7829,25 @@ async function setMode(env, args) {
6955
7829
  await page.waitForTimeout?.(250);
6956
7830
  const candidates = await enumerateVisibleMenuItems(page);
6957
7831
  const selected = [];
6958
- for (const item of requested) {
6959
- const match = findModeMenuItem(candidates, item);
7832
+ if (requested.length > 0 && shouldRejectAsWrongModeMenu(candidates)) {
7833
+ const candidateLabels2 = candidates.map((candidate) => candidate.label);
7834
+ return {
7835
+ ok: false,
7836
+ status: "unsupported",
7837
+ warnings: [],
7838
+ blocker: selectorDriftBlocker("Visible menu appears to be a thread/action menu, not the ChatGPT mode menu.", candidateLabels2),
7839
+ context: await contextFromPage(page)
7840
+ };
7841
+ }
7842
+ for (const request of requested) {
7843
+ const match = findModeMenuItem(candidates, request);
6960
7844
  if (match === void 0) {
6961
7845
  const candidateLabels2 = candidates.map((candidate) => candidate.label);
6962
7846
  return {
6963
7847
  ok: false,
6964
7848
  status: "unsupported",
6965
7849
  warnings: [],
6966
- blocker: selectorDriftBlocker(`Mode option "${item}" was not found or was ambiguous.`, candidateLabels2),
7850
+ blocker: selectorDriftBlocker(`Mode option "${request.requested}" was not found or was ambiguous.`, candidateLabels2),
6967
7851
  context: await contextFromPage(page)
6968
7852
  };
6969
7853
  }
@@ -6987,7 +7871,42 @@ async function setMode(env, args) {
6987
7871
  }
6988
7872
  selected.push(versionResult.selected);
6989
7873
  }
6990
- return resultOk({ selected, candidates: candidateLabels }, await contextFromPage(page));
7874
+ const verificationWarnings = await modeVerificationWarnings(page, requested, selected);
7875
+ return resultOk({ selected, candidates: candidateLabels }, await contextFromPage(page), verificationWarnings);
7876
+ } catch (error) {
7877
+ return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
7878
+ }
7879
+ }
7880
+ async function modeVerificationWarnings(page, requested, selected) {
7881
+ if (requested.length === 0) {
7882
+ return [];
7883
+ }
7884
+ await page.waitForTimeout?.(250);
7885
+ const visibleButtons = await visibleModeButtonLabelList(page);
7886
+ if (visibleButtons.length === 0) {
7887
+ return [
7888
+ `Mode selection is unverified: no mode-labelled composer control was visible after selecting ${selected.map((label) => JSON.stringify(label)).join(", ")}. Use modes.get or inspect modeStep before treating this as a verified mode.`
7889
+ ];
7890
+ }
7891
+ const unverified = requested.filter((request) => findUniqueVisibleLabelForRequest(visibleButtons, request) === void 0);
7892
+ if (unverified.length === 0) {
7893
+ return [];
7894
+ }
7895
+ return [
7896
+ `Mode selection is unverified: requested ${unverified.map((request) => JSON.stringify(request.requested)).join(", ")} is not reflected by the visible mode controls (${visibleButtons.join(", ")}). Use modes.get or inspect modeStep before treating this as a verified mode.`
7897
+ ];
7898
+ }
7899
+ async function getMode(env, args = {}) {
7900
+ void args;
7901
+ const boot = await ensurePage6(env);
7902
+ if (!boot.ok) {
7903
+ return boot;
7904
+ }
7905
+ const page = env.page;
7906
+ try {
7907
+ const modes = await visibleModeButtonLabelList(page);
7908
+ const warnings = modes.length === 0 ? ["No mode-labelled composer control is currently visible, so the active ChatGPT mode could not be read."] : [];
7909
+ return resultOk({ modes }, await contextFromPage(page), warnings);
6991
7910
  } catch (error) {
6992
7911
  return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
6993
7912
  }
@@ -7002,7 +7921,7 @@ async function waitForModeMenu(page, requested, timeoutMs) {
7002
7921
  return { opened: false, alreadySelected, modeButtons };
7003
7922
  }
7004
7923
  const openMenuItems = await enumerateVisibleMenuItems(page);
7005
- if (looksLikeModeMenu(openMenuItems.map((item) => item.label))) {
7924
+ if (looksLikeModeMenu(openMenuItems)) {
7006
7925
  return { opened: true, alreadySelected: [], modeButtons };
7007
7926
  }
7008
7927
  if (await clickModeOpener(page, modeButtons)) {
@@ -7082,12 +8001,47 @@ async function clickModeOpener(page, modeButtons) {
7082
8001
  }
7083
8002
  return clickFirstUniqueButton(page, MODE_OPENER_LABELS);
7084
8003
  }
7085
- function looksLikeModeMenu(labels) {
7086
- return labels.some((label) => {
7087
- const normalized = normalizeLabel(label);
7088
- return CURRENT_MODE_LABELS.some((modeLabel) => visibleLabelMatches(normalized, normalizeLabel(modeLabel)));
8004
+ function isThreadActionLabel(label) {
8005
+ const normalized = normalizeForLabelMatch(label);
8006
+ if (THREAD_ACTION_MENU_LABELS.has(normalized)) {
8007
+ return true;
8008
+ }
8009
+ return THREAD_ACTION_PREFIXES.some((prefix) => normalized.startsWith(`${prefix} `));
8010
+ }
8011
+ function hasStructuralModeEvidence(item) {
8012
+ if (item.testId?.startsWith("model-switcher-") === true) {
8013
+ return true;
8014
+ }
8015
+ return MODEL_VERSION_FAMILY_PATTERN.test(item.label) || MODEL_VERSION_LABEL_PATTERN.test(item.label);
8016
+ }
8017
+ function isModeMenuEvidence(item) {
8018
+ if (hasStructuralModeEvidence(item)) {
8019
+ return true;
8020
+ }
8021
+ if (isThreadActionLabel(item.label)) {
8022
+ return false;
8023
+ }
8024
+ const normalized = normalizeForLabelMatch(item.label);
8025
+ return CURRENT_MODE_LABELS.some((modeLabel) => {
8026
+ const normalizedMode = normalizeForLabelMatch(modeLabel);
8027
+ if (normalized === normalizedMode) {
8028
+ return true;
8029
+ }
8030
+ return !isShortLatinToken(normalizedMode) && visibleLabelMatches(normalized, normalizedMode);
7089
8031
  });
7090
8032
  }
8033
+ function looksLikeModeMenu(items) {
8034
+ return items.some((item) => isModeMenuEvidence(item));
8035
+ }
8036
+ function shouldRejectAsWrongModeMenu(items) {
8037
+ if (items.length === 0) {
8038
+ return false;
8039
+ }
8040
+ if (items.some((item) => isModeMenuEvidence(item))) {
8041
+ return false;
8042
+ }
8043
+ return items.some((item) => isThreadActionLabel(item.label));
8044
+ }
7091
8045
  async function clickMenuItem(page, label) {
7092
8046
  if (await clickModelSwitcherMenuItem(page, label)) {
7093
8047
  return true;
@@ -7174,26 +8128,72 @@ function toolLabels(tool) {
7174
8128
  const known = localeLabels.tools[tool];
7175
8129
  return known !== void 0 ? [...known] : [tool];
7176
8130
  }
7177
- function findModeMenuItem(candidates, wanted) {
7178
- const exact = findUniqueMenuItem(candidates, wanted);
7179
- if (exact !== void 0) {
7180
- return exact;
8131
+ function findModeMenuItem(candidates, request) {
8132
+ const selectable = candidates.filter((candidate) => !isThreadActionLabel(candidate.label));
8133
+ for (const wanted of request.labels) {
8134
+ const match = findUniqueModeMenuItem(selectable, wanted);
8135
+ if (match !== void 0) {
8136
+ return match;
8137
+ }
7181
8138
  }
7182
- const wantedIndex = CANONICAL_INTELLIGENCE_ORDER.get(normalizeLabel(wanted));
8139
+ const wantedIndex = request.modeId === void 0 ? void 0 : CANONICAL_INTELLIGENCE_ORDER.get(request.modeId);
7183
8140
  if (wantedIndex === void 0) {
7184
8141
  return void 0;
7185
8142
  }
7186
- const intelligenceItems = candidates.filter(
8143
+ const intelligenceItems = selectable.filter(
7187
8144
  (candidate) => candidate.role === "menuitemradio" && !MODEL_VERSION_LABEL_PATTERN.test(candidate.label) && !MODEL_VERSION_FAMILY_PATTERN.test(candidate.label)
7188
8145
  );
7189
8146
  return intelligenceItems.length >= CANONICAL_INTELLIGENCE_ORDER.size ? intelligenceItems[wantedIndex] : void 0;
7190
8147
  }
7191
- function requestedModeLabels(args) {
8148
+ function findUniqueModeMenuItem(items, wanted) {
8149
+ const normalizedWanted = normalizeForLabelMatch(wanted);
8150
+ const exact = items.filter((item) => normalizeForLabelMatch(item.label) === normalizedWanted);
8151
+ if (exact.length === 1) {
8152
+ return exact[0];
8153
+ }
8154
+ const fuzzy = items.filter((item) => visibleLabelMatches(item.label, wanted));
8155
+ if (fuzzy.length !== 1) {
8156
+ return void 0;
8157
+ }
8158
+ const match = fuzzy[0];
8159
+ if (!isShortLatinToken(normalizedWanted)) {
8160
+ return match;
8161
+ }
8162
+ return hasStructuralModeEvidence(match) || match.role === "menuitemradio" ? match : void 0;
8163
+ }
8164
+ function requestedModeSelections(args) {
7192
8165
  const requested = [args.model, args.intelligence, args.effort].filter((value) => value !== void 0);
7193
8166
  if (requestedModelVersion(args) !== void 0 && requested.length === 0) {
7194
8167
  return [];
7195
8168
  }
7196
- return requested.length > 0 ? requested : [DEFAULT_MODE_EFFORT];
8169
+ return (requested.length > 0 ? requested : [DEFAULT_MODE_EFFORT]).map(requestedModeSelection);
8170
+ }
8171
+ function requestedModeSelection(requested) {
8172
+ const modeId = modeOptionIdFor(requested);
8173
+ const labels = modeId === void 0 ? [requested] : localeLabels.modeOptions[modeId];
8174
+ const request = {
8175
+ requested,
8176
+ labels: labels.length > 0 ? [...labels] : [requested]
8177
+ };
8178
+ if (modeId !== void 0) {
8179
+ request.modeId = modeId;
8180
+ }
8181
+ return request;
8182
+ }
8183
+ function modeOptionIdFor(value) {
8184
+ const normalized = normalizeModeLookupKey(value);
8185
+ for (const id2 of MODE_OPTION_IDS2) {
8186
+ if (MODE_ID_ALIASES[id2].some((alias) => normalizeModeLookupKey(alias) === normalized)) {
8187
+ return id2;
8188
+ }
8189
+ if (localeLabels.modeOptions[id2].some((label) => normalizeModeLookupKey(label) === normalized)) {
8190
+ return id2;
8191
+ }
8192
+ }
8193
+ return void 0;
8194
+ }
8195
+ function normalizeModeLookupKey(value) {
8196
+ return normalizeForLabelMatch(value).replace(/[_-]+/g, " ");
7197
8197
  }
7198
8198
  function requestedModelVersion(args) {
7199
8199
  return args.modelVersion ?? args.version;
@@ -7207,25 +8207,25 @@ function findUniqueVisibleLabel(labels, wanted) {
7207
8207
  const fuzzy = labels.filter((label) => visibleLabelMatches(normalizeLabel(label), normalized));
7208
8208
  return fuzzy.length === 1 ? fuzzy[0] : void 0;
7209
8209
  }
7210
- function visibleLabelMatches(label, wanted) {
7211
- if (wanted.length <= 3) {
7212
- return new RegExp(`(^|[^a-z0-9])${escapeRegExp2(wanted)}([^a-z0-9]|$)`, "i").test(label);
7213
- }
7214
- return label.includes(wanted);
7215
- }
7216
- function escapeRegExp2(value) {
7217
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7218
- }
7219
8210
  function escapeAttributeValue(value) {
7220
8211
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
7221
8212
  }
7222
8213
  function findAlreadySelectedModes(visibleButtons, requested) {
7223
- return requested.map((label) => findUniqueVisibleLabel(visibleButtons, label)).filter((label) => label !== void 0);
8214
+ return requested.map((request) => findUniqueVisibleLabelForRequest(visibleButtons, request)).filter((label) => label !== void 0);
8215
+ }
8216
+ function findUniqueVisibleLabelForRequest(labels, request) {
8217
+ for (const label of request.labels) {
8218
+ const found = findUniqueVisibleLabel(labels, label);
8219
+ if (found !== void 0) {
8220
+ return found;
8221
+ }
8222
+ }
8223
+ return void 0;
7224
8224
  }
7225
8225
  async function selectModelVersion(page, requestedVersion, currentCandidates, timeoutMs) {
7226
8226
  let candidates = await enumerateVisibleMenuItems(page);
7227
- if (!looksLikeModeMenu(candidates.map((candidate) => candidate.label))) {
7228
- const opened2 = await waitForModeMenu(page, [requestedVersion], timeoutMs);
8227
+ if (!looksLikeModeMenu(candidates)) {
8228
+ const opened2 = await waitForModeMenu(page, [{ requested: requestedVersion, labels: [requestedVersion] }], timeoutMs);
7229
8229
  if (opened2.opened) {
7230
8230
  await page.waitForTimeout?.(250);
7231
8231
  candidates = await enumerateVisibleMenuItems(page);
@@ -7816,6 +8816,7 @@ var REQUIRED_LOCALE_KEYS = [
7816
8816
  "rateLimitBlocker"
7817
8817
  ];
7818
8818
  var REQUIRED_TOOL_IDS = ["web_search", "deep_research", "create_image"];
8819
+ var REQUIRED_MODE_OPTION_IDS = ["latest", "instant", "thinking", "extended", "medium", "high", "extraHigh", "pro"];
7819
8820
  async function doctor(env, args = {}) {
7820
8821
  const wanted = args.check ?? DEFAULT_CHECKS;
7821
8822
  const checks = {};
@@ -8015,19 +9016,23 @@ async function filePreflightCheck(env, args) {
8015
9016
  function localizationCheck(env) {
8016
9017
  const requiredKeysMissing = REQUIRED_LOCALE_KEYS.filter((key) => localeLabels[key].length === 0);
8017
9018
  const missingToolIds = REQUIRED_TOOL_IDS.filter((id2) => (localeLabels.tools[id2]?.length ?? 0) === 0);
9019
+ const missingModeOptionIds = REQUIRED_MODE_OPTION_IDS.filter((id2) => (localeLabels.modeOptions[id2]?.length ?? 0) === 0);
8018
9020
  const toolIds = Object.keys(localeLabels.tools);
8019
- const englishCanonicalPresent = localeLabels.composerTextbox[0] === "Chat with ChatGPT" && localeLabels.sendButton[0] === "Send prompt" && localeLabels.modeLabels.includes("Thinking") && localeLabels.tools.web_search?.[0] === "Web search";
8020
- const labelCandidateCount = REQUIRED_LOCALE_KEYS.reduce((total, key) => total + localeLabels[key].length, 0) + Object.values(localeLabels.tools).reduce((total, values) => total + values.length, 0);
9021
+ const modeOptionIds = Object.keys(localeLabels.modeOptions);
9022
+ 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";
9023
+ 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);
8021
9024
  const details = {
8022
9025
  englishCanonicalPresent,
8023
9026
  requiredKeysMissing,
8024
9027
  missingToolIds,
9028
+ missingModeOptionIds,
8025
9029
  toolIds,
9030
+ modeOptionIds,
8026
9031
  labelCandidateCount,
8027
9032
  pageAvailable: env.page !== void 0,
8028
9033
  runtimeSelectorCoverage: "registry_only_stage_2"
8029
9034
  };
8030
- if (englishCanonicalPresent && requiredKeysMissing.length === 0 && missingToolIds.length === 0) {
9035
+ if (englishCanonicalPresent && requiredKeysMissing.length === 0 && missingToolIds.length === 0 && missingModeOptionIds.length === 0) {
8031
9036
  return unknown("The locale registry is loaded; localized runtime selector coverage is registry-only in Stage 2 and not fully proven.", void 0, details);
8032
9037
  }
8033
9038
  return blocked(
@@ -8149,7 +9154,7 @@ async function createRunReport(env, result, options = {}) {
8149
9154
  }, options);
8150
9155
  const report2 = {
8151
9156
  schemaVersion: 1,
8152
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
9157
+ createdAt,
8153
9158
  includeContent,
8154
9159
  summary,
8155
9160
  steps: result.steps?.map((step) => ({
@@ -8256,6 +9261,7 @@ var commandRisk = {
8256
9261
  "projects.sources.add": "medium",
8257
9262
  "response.copy": "medium",
8258
9263
  "modes.set": "medium",
9264
+ "modes.get": "low",
8259
9265
  "tools.select": "medium",
8260
9266
  "threads.delete": "high",
8261
9267
  "threads.archive": "high",
@@ -8355,6 +9361,7 @@ var descriptors = [
8355
9361
  primitive("projects.sources.add", "Append explicit local files to a visible ChatGPT Project Sources list after confirmMutation: true.", 18e4),
8356
9362
  primitive("response.copy", "Click Copy response and return clipboard Markdown, with DOM fallback.", 5e3),
8357
9363
  primitive("modes.set", "Select a visible model, intelligence, effort, or nested model-version candidate when unambiguous.", 3e4),
9364
+ primitive("modes.get", "Read the mode labels shown on the visible composer controls without changing them.", 3e4),
8358
9365
  primitive("tools.select", "Select a visible ChatGPT tool when unambiguous.", 3e4)
8359
9366
  ];
8360
9367
  function commandDescriptors() {
@@ -8491,13 +9498,30 @@ function reportArgs(name) {
8491
9498
  return { result: "CommandResult to persist", destDir: "optional report directory" };
8492
9499
  }
8493
9500
  function primitiveArgs(name) {
9501
+ if (name === "messages.wait") return {
9502
+ timeoutMs: "optional wait timeout",
9503
+ stableMs: "optional stability window before completion",
9504
+ pollMs: "optional polling interval",
9505
+ mode: "normal or deep_research",
9506
+ responseContent: "include for current behavior, metadata to omit assistant text and return chars/hash only"
9507
+ };
8494
9508
  if (name === "messages.readLatest") return { role: "assistant or user", format: "markdown, normalized_text, visible_text, html, blocks, or all" };
8495
9509
  if (name === "artifacts.listLatest") return { kind: "artifact kind; currently image", max: "maximum artifacts to return" };
8496
9510
  if (name === "artifacts.wait") return { kind: "artifact kind; currently image", afterArtifactCount: "baseline artifact count", requireDownload: "wait until a download affordance is visible" };
8497
9511
  if (name === "artifacts.downloadLatest") return { destDir: "download destination directory", prefer: "download_control or visible_image_source" };
8498
9512
  if (name === "response.copy") return { prefer: "clipboard or dom", format: "markdown, normalized_text, visible_text, html, blocks, or all" };
8499
9513
  if (name.startsWith("threads.search")) return { query: "history search query" };
8500
- if (name === "files.preflight") return { paths: "absolute local file paths", maxBytesPerFile: "optional local per-file byte limit", maxTotalBytes: "optional local total byte limit" };
9514
+ if (name === "files.preflight") return {
9515
+ paths: "absolute local file paths",
9516
+ maxBytesPerFile: "optional local per-file byte limit",
9517
+ maxTotalBytes: "optional local total byte limit",
9518
+ includeHashes: "optional SHA-256 metadata for diagnostics; file contents are not returned"
9519
+ };
9520
+ if (name === "files.attach") return {
9521
+ paths: "absolute local file paths",
9522
+ includeDiagnostics: "optional preflight and browser input file-size metadata",
9523
+ includeHashes: "optional SHA-256 metadata inside diagnostics; file contents are not returned"
9524
+ };
8501
9525
  if (name.startsWith("files.attach")) return { paths: "absolute local file paths" };
8502
9526
  if (name === "projects.sources.list") return { projectUrl: "ChatGPT Project URL such as https://chatgpt.com/g/g-p-.../project", existingTab: "optional exact existing-tab policy", timeoutMs: "optional browser timeout" };
8503
9527
  if (name === "projects.sources.planAdd") return { projectUrl: "ChatGPT Project URL", files: "explicit absolute local file paths", batchSize: "optional upload batch size" };
@@ -8512,6 +9536,11 @@ function primitiveArgs(name) {
8512
9536
  timeoutMs: "optional timeout for opening and selecting the visible mode menu"
8513
9537
  };
8514
9538
  }
9539
+ if (name === "modes.get") {
9540
+ return {
9541
+ timeoutMs: "optional timeout for attaching to the ChatGPT page"
9542
+ };
9543
+ }
8515
9544
  return {};
8516
9545
  }
8517
9546
  function primitiveExamples(name) {
@@ -8523,9 +9552,16 @@ function primitiveExamples(name) {
8523
9552
  `await chatgpt.askWithFiles({ mode: { model: "Pro" }, files: ["/absolute/host/path.jpg"], prompt: "Describe this image.", wait: true });`
8524
9553
  ];
8525
9554
  }
9555
+ if (name === "modes.get") {
9556
+ return [
9557
+ `await chatgpt.modes.get();`,
9558
+ `// Verify an expensive Pro consult before submitting: const current = await chatgpt.modes.get();`
9559
+ ];
9560
+ }
8526
9561
  if (name === "files.preflight") {
8527
9562
  return [
8528
- `await chatgpt.files.preflight({ paths: ["/absolute/host/path.md"] });`
9563
+ `await chatgpt.files.preflight({ paths: ["/absolute/host/path.md"] });`,
9564
+ `await chatgpt.files.preflight({ paths: ["/absolute/host/path.md"], includeHashes: true });`
8529
9565
  ];
8530
9566
  }
8531
9567
  if (name === "files.attach") {
@@ -9106,7 +10142,8 @@ function createChatGPT(options = {}) {
9106
10142
  downloadLatest: (args) => downloadLatestArtifact(env, args)
9107
10143
  },
9108
10144
  modes: {
9109
- set: (args) => setMode(env, args)
10145
+ set: (args) => setMode(env, args),
10146
+ get: (args) => getMode(env, args)
9110
10147
  },
9111
10148
  tools: {
9112
10149
  select: (args) => selectTool(env, args)
@@ -9787,6 +10824,7 @@ var backendCommands = [
9787
10824
  "projects.sources.planAdd",
9788
10825
  "projects.sources.add",
9789
10826
  "modes.set",
10827
+ "modes.get",
9790
10828
  "tools.select",
9791
10829
  "response.copy"
9792
10830
  ];
@@ -10488,6 +11526,8 @@ async function dispatchBackendCommand(client, request) {
10488
11526
  return client.projects.sources.add(payload);
10489
11527
  case "modes.set":
10490
11528
  return client.modes.set(payload);
11529
+ case "modes.get":
11530
+ return client.modes.get(emptyToUndefined(payload));
10491
11531
  case "tools.select":
10492
11532
  return client.tools.select(payload);
10493
11533
  case "response.copy":
@@ -10595,6 +11635,7 @@ export {
10595
11635
  bootstrap,
10596
11636
  buildProjectSourceAddPlan,
10597
11637
  classifyVisibleText,
11638
+ clipboardReadCommandsForPlatform,
10598
11639
  commandDescriptors,
10599
11640
  commandRisk,
10600
11641
  compactVisibleText,
@@ -10634,6 +11675,7 @@ export {
10634
11675
  findUniqueMenuItem,
10635
11676
  formatClipboardMarkdown,
10636
11677
  formatMessageHtml,
11678
+ getMode,
10637
11679
  helpText,
10638
11680
  htmlToText,
10639
11681
  interruptionFromCommandResult,