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
@@ -161,8 +161,23 @@ var en = {
161
161
  imageContainerHint: ["image"],
162
162
  // --- Mode switcher (also the canonical public API keys) ---
163
163
  modeLabels: ["Latest", "Instant", "Thinking", "Extended", "Medium", "High", "Extra High", "Pro"],
164
+ modeOptions: {
165
+ latest: ["Latest"],
166
+ instant: ["Instant"],
167
+ thinking: ["Thinking"],
168
+ extended: ["Extended"],
169
+ medium: ["Medium"],
170
+ high: ["High"],
171
+ extraHigh: ["Extra High"],
172
+ pro: ["Pro", "Pro Extended", "Extended Pro"]
173
+ },
164
174
  /** Extra openers that surface the mode menu but are not selectable modes themselves. */
165
175
  modeOpenerExtra: ["Configure"],
176
+ // --- Thread/action menu rejection (wrong-menu veto for mode selection) ---
177
+ /** Exact thread/conversation action menu items; a menu containing these is not the mode menu. */
178
+ threadActionMenuItems: ["Archive", "Copy link", "Delete", "Move to project", "Rename", "Share"],
179
+ /** Action verbs that prefix a thread title in sidebar menus, e.g. "Pin <thread title>". */
180
+ threadActionPrefixes: ["Pin", "Unpin"],
166
181
  // --- Tool menu items, keyed by logical tool id ---
167
182
  tools: {
168
183
  web_search: ["Web search"],
@@ -201,6 +216,12 @@ var de = {
201
216
  addPhotosFilesMenuItem: ["Fotos und Dateien hinzuf\xFCgen"],
202
217
  copyResponse: ["Antwort kopieren"],
203
218
  modeLabels: ["Sofort", "Mittel", "Hoch", "Extra hoch"],
219
+ modeOptions: {
220
+ instant: ["Sofort"],
221
+ medium: ["Mittel"],
222
+ high: ["Hoch"],
223
+ extraHigh: ["Extra hoch"]
224
+ },
204
225
  modeOpenerExtra: ["Konfigurieren"],
205
226
  tools: {
206
227
  web_search: ["Websuche"],
@@ -222,6 +243,12 @@ var esES = {
222
243
  addPhotosFilesMenuItem: ["A\xF1adir fotos y archivos"],
223
244
  copyResponse: ["Copiar respuesta"],
224
245
  modeLabels: ["Instant\xE1nea", "Media", "Alta", "Muy alta"],
246
+ modeOptions: {
247
+ instant: ["Instant\xE1nea"],
248
+ medium: ["Media"],
249
+ high: ["Alta"],
250
+ extraHigh: ["Muy alta"]
251
+ },
225
252
  modeOpenerExtra: ["Configurar"],
226
253
  tools: {
227
254
  web_search: ["B\xFAsqueda en Internet"],
@@ -244,6 +271,11 @@ var frFR = {
244
271
  addPhotosFilesMenuItem: ["Ajouter des photos et fichiers"],
245
272
  copyResponse: ["Copier la r\xE9ponse"],
246
273
  modeLabels: ["Moyen", "Avanc\xE9", "Tr\xE8s \xE9lev\xE9"],
274
+ modeOptions: {
275
+ medium: ["Moyen"],
276
+ high: ["Avanc\xE9"],
277
+ extraHigh: ["Tr\xE8s \xE9lev\xE9"]
278
+ },
247
279
  modeOpenerExtra: ["Configurer"],
248
280
  tools: {
249
281
  web_search: ["Recherche sur le Web"],
@@ -266,6 +298,13 @@ var zhHK = {
266
298
  addPhotosFilesMenuItem: ["\u52A0\u5165\u76F8\u7247\u548C\u6A94\u6848"],
267
299
  copyResponse: ["\u8907\u88FD\u56DE\u8986"],
268
300
  modeLabels: ["\u5373\u6642", "\u5747\u8861", "\u9AD8", "\u6975\u9AD8", "\u5C08\u696D"],
301
+ modeOptions: {
302
+ instant: ["\u5373\u6642"],
303
+ medium: ["\u5747\u8861"],
304
+ high: ["\u9AD8"],
305
+ extraHigh: ["\u6975\u9AD8"],
306
+ pro: ["\u5C08\u696D"]
307
+ },
269
308
  modeOpenerExtra: ["\u8A2D\u5B9A"],
270
309
  tools: {
271
310
  web_search: ["\u7DB2\u7D61\u641C\u5C0B"],
@@ -288,6 +327,13 @@ var zhTW = {
288
327
  addPhotosFilesMenuItem: ["\u65B0\u589E\u7167\u7247\u548C\u6A94\u6848"],
289
328
  copyResponse: ["\u8907\u88FD\u56DE\u61C9"],
290
329
  modeLabels: ["\u5373\u6642", "\u4E2D\u7B49", "\u9AD8", "\u8D85\u9AD8", "\u5C08\u696D"],
330
+ modeOptions: {
331
+ instant: ["\u5373\u6642"],
332
+ medium: ["\u4E2D\u7B49"],
333
+ high: ["\u9AD8"],
334
+ extraHigh: ["\u8D85\u9AD8"],
335
+ pro: ["\u5C08\u696D"]
336
+ },
291
337
  modeOpenerExtra: ["\u8A2D\u5B9A"],
292
338
  tools: {
293
339
  web_search: ["\u7DB2\u9801\u641C\u5C0B"],
@@ -310,6 +356,12 @@ var ja = {
310
356
  addPhotosFilesMenuItem: ["\u5199\u771F\u3068\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0"],
311
357
  copyResponse: ["\u56DE\u7B54\u3092\u30B3\u30D4\u30FC\u3059\u308B"],
312
358
  modeLabels: ["\u6700\u901F", "\u6A19\u6E96", "\u9AD8", "\u6700\u9AD8"],
359
+ modeOptions: {
360
+ instant: ["\u6700\u901F"],
361
+ medium: ["\u6A19\u6E96"],
362
+ high: ["\u9AD8"],
363
+ extraHigh: ["\u6700\u9AD8"]
364
+ },
313
365
  modeOpenerExtra: ["\u8A2D\u5B9A\u3059\u308B"],
314
366
  tools: {
315
367
  web_search: ["\u30A6\u30A7\u30D6\u691C\u7D22"],
@@ -331,6 +383,12 @@ var it = {
331
383
  addPhotosFilesMenuItem: ["Aggiungi foto e file"],
332
384
  copyResponse: ["Copia risposta"],
333
385
  modeLabels: ["Istantanea", "Media", "Alta", "Extra elevata"],
386
+ modeOptions: {
387
+ instant: ["Istantanea"],
388
+ medium: ["Media"],
389
+ high: ["Alta"],
390
+ extraHigh: ["Extra elevata"]
391
+ },
334
392
  modeOpenerExtra: ["Configura"],
335
393
  tools: {
336
394
  web_search: ["Ricerca sul web"],
@@ -352,6 +410,12 @@ var vi = {
352
410
  addPhotosFilesMenuItem: ["Th\xEAm \u1EA3nh v\xE0 t\u1EC7p"],
353
411
  copyResponse: ["Sao ch\xE9p ph\u1EA3n h\u1ED3i"],
354
412
  modeLabels: ["T\u1EE9c th\xEC", "Trung b\xECnh", "Cao", "R\u1EA5t cao"],
413
+ modeOptions: {
414
+ instant: ["T\u1EE9c th\xEC"],
415
+ medium: ["Trung b\xECnh"],
416
+ high: ["Cao"],
417
+ extraHigh: ["R\u1EA5t cao"]
418
+ },
355
419
  modeOpenerExtra: ["\u0110\u1ECBnh c\u1EA5u h\xECnh"],
356
420
  tools: {
357
421
  web_search: ["T\xECm ki\u1EBFm tr\xEAn m\u1EA1ng"],
@@ -374,6 +438,12 @@ var am = {
374
438
  addPhotosFilesMenuItem: ["\u134E\u1276\u12CE\u127D\u1295 \u12A5\u1293 \u134B\u12ED\u120E\u127D\u1295 \u12EB\u12AD\u1209"],
375
439
  copyResponse: ["\u121D\u120B\u1239\u1295 \u12ED\u1245\u12F1"],
376
440
  modeLabels: ["\u1348\u1323\u1295", "\u1218\u12AB\u12A8\u1208\u129B", "\u12A8\u134D\u1270\u129B", "\u12A5\u1305\u130D \u12A8\u134D\u1270\u129B"],
441
+ modeOptions: {
442
+ instant: ["\u1348\u1323\u1295"],
443
+ medium: ["\u1218\u12AB\u12A8\u1208\u129B"],
444
+ high: ["\u12A8\u134D\u1270\u129B"],
445
+ extraHigh: ["\u12A5\u1305\u130D \u12A8\u134D\u1270\u129B"]
446
+ },
377
447
  modeOpenerExtra: ["\u12EB\u12CB\u1245\u1229"],
378
448
  tools: {
379
449
  web_search: ["\u12E8\u12F5\u122D \u134D\u1208\u130B"],
@@ -396,6 +466,13 @@ var ar = {
396
466
  addPhotosFilesMenuItem: ["\u0625\u0636\u0627\u0641\u0629 \u0635\u0648\u0631 \u0648\u0645\u0644\u0641\u0627\u062A"],
397
467
  copyResponse: ["\u0646\u0633\u062E \u0625\u062C\u0627\u0628\u0629"],
398
468
  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"],
469
+ modeOptions: {
470
+ instant: ["\u0641\u0648\u0631\u064A"],
471
+ medium: ["\u0645\u062A\u0648\u0633\u0637"],
472
+ high: ["\u0639\u0627\u0644\u064A"],
473
+ extraHigh: ["\u0645\u0643\u062B\u0641 \u062C\u062F\u064B\u0627"],
474
+ pro: ["\u0627\u062D\u062A\u0631\u0627\u0641\u064A"]
475
+ },
399
476
  modeOpenerExtra: ["\u062A\u0643\u0648\u064A\u0646"],
400
477
  tools: {
401
478
  web_search: ["\u0627\u0644\u0628\u062D\u062B \u0641\u064A \u0627\u0644\u0648\u064A\u0628"],
@@ -418,6 +495,13 @@ var bg = {
418
495
  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"],
419
496
  copyResponse: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0439\u0442\u0435 \u043E\u0442\u0433\u043E\u0432\u043E\u0440\u0430"],
420
497
  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"],
498
+ modeOptions: {
499
+ instant: ["\u041C\u0438\u0433\u043D\u043E\u0432\u0435\u043D"],
500
+ medium: ["\u0421\u0440\u0435\u0434\u0435\u043D"],
501
+ high: ["\u0412\u0438\u0441\u043E\u043A"],
502
+ extraHigh: ["\u041C\u043D\u043E\u0433\u043E \u0432\u0438\u0441\u043E\u043A\u043E"],
503
+ pro: ["\u041F\u0440\u043E"]
504
+ },
421
505
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0439\u0442\u0435"],
422
506
  tools: {
423
507
  web_search: ["\u0422\u044A\u0440\u0441\u0435\u043D\u0435 \u0432 \u0438\u043D\u0442\u0435\u0440\u043D\u0435\u0442"],
@@ -440,6 +524,12 @@ var bs = {
440
524
  addPhotosFilesMenuItem: ["Dodaj slike i datoteke"],
441
525
  copyResponse: ["Kopiraj odgovor"],
442
526
  modeLabels: ["Brzo", "Srednji", "Visoko", "Vrlo visoko"],
527
+ modeOptions: {
528
+ instant: ["Brzo"],
529
+ medium: ["Srednji"],
530
+ high: ["Visoko"],
531
+ extraHigh: ["Vrlo visoko"]
532
+ },
443
533
  modeOpenerExtra: ["Podesi"],
444
534
  tools: {
445
535
  web_search: ["Internet pretraga"],
@@ -462,6 +552,12 @@ var ca = {
462
552
  addPhotosFilesMenuItem: ["Afegeix fotos i fitxers"],
463
553
  copyResponse: ["Copia la resposta"],
464
554
  modeLabels: ["Instantani", "Mitj\xE0", "Alt", "Molt alt"],
555
+ modeOptions: {
556
+ instant: ["Instantani"],
557
+ medium: ["Mitj\xE0"],
558
+ high: ["Alt"],
559
+ extraHigh: ["Molt alt"]
560
+ },
465
561
  modeOpenerExtra: ["Configura\u2026"],
466
562
  tools: {
467
563
  web_search: ["Cerca a la xarxa"],
@@ -484,6 +580,12 @@ var cs = {
484
580
  addPhotosFilesMenuItem: ["P\u0159idat fotografie a soubory"],
485
581
  copyResponse: ["Zkop\xEDrovat odpov\u011B\u010F"],
486
582
  modeLabels: ["Okam\u017Eit\xE1", "St\u0159edn\xED", "Vysok\xE1", "Velmi vysok\xE1"],
583
+ modeOptions: {
584
+ instant: ["Okam\u017Eit\xE1"],
585
+ medium: ["St\u0159edn\xED"],
586
+ high: ["Vysok\xE1"],
587
+ extraHigh: ["Velmi vysok\xE1"]
588
+ },
487
589
  modeOpenerExtra: ["Konfigurovat\u2026"],
488
590
  tools: {
489
591
  web_search: ["Vyhled\xE1v\xE1n\xED na webu"],
@@ -506,6 +608,11 @@ var da = {
506
608
  addPhotosFilesMenuItem: ["Tilf\xF8j billeder og filer"],
507
609
  copyResponse: ["Kopi\xE9r svar"],
508
610
  modeLabels: ["\xD8jeblikkeligt", "H\xF8j", "Ekstra h\xF8j"],
611
+ modeOptions: {
612
+ instant: ["\xD8jeblikkeligt"],
613
+ high: ["H\xF8j"],
614
+ extraHigh: ["Ekstra h\xF8j"]
615
+ },
509
616
  modeOpenerExtra: ["Konfigurer ..."],
510
617
  tools: {
511
618
  web_search: ["Internets\xF8gning"],
@@ -528,6 +635,12 @@ var el = {
528
635
  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"],
529
636
  copyResponse: ["\u0391\u03BD\u03C4\u03B9\u03B3\u03C1\u03B1\u03C6\u03AE \u03B1\u03C0\u03AC\u03BD\u03C4\u03B7\u03C3\u03B7\u03C2"],
530
637
  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"],
638
+ modeOptions: {
639
+ instant: ["\u0386\u03BC\u03B5\u03C3\u03B7"],
640
+ medium: ["\u039C\u03B5\u03C3\u03B1\u03AF\u03B1"],
641
+ high: ["\u03A5\u03C8\u03B7\u03BB\u03AE"],
642
+ extraHigh: ["\u03A0\u03BF\u03BB\u03CD \u03C5\u03C8\u03B7\u03BB\u03CC"]
643
+ },
531
644
  modeOpenerExtra: ["\u0394\u03B9\u03B1\u03BC\u03CC\u03C1\u03C6\u03C9\u03C3\u03B7\u2026"],
532
645
  tools: {
533
646
  web_search: ["\u0391\u03BD\u03B1\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7 \u03C3\u03C4\u03BF\u03BD \u03B9\u03C3\u03C4\u03CC"],
@@ -550,6 +663,12 @@ var es419 = {
550
663
  addPhotosFilesMenuItem: ["Agregar fotos y archivos"],
551
664
  copyResponse: ["Copiar respuesta"],
552
665
  modeLabels: ["Instant\xE1nea", "Media", "Alta", "Muy alta"],
666
+ modeOptions: {
667
+ instant: ["Instant\xE1nea"],
668
+ medium: ["Media"],
669
+ high: ["Alta"],
670
+ extraHigh: ["Muy alta"]
671
+ },
553
672
  modeOpenerExtra: ["Configurar..."],
554
673
  tools: {
555
674
  web_search: ["Busca en la web"],
@@ -572,6 +691,12 @@ var et = {
572
691
  addPhotosFilesMenuItem: ["Lisa fotosid ja faile"],
573
692
  copyResponse: ["Kopeeri vastus"],
574
693
  modeLabels: ["Kohene", "Keskmine", "K\xF5rge", "V\xE4ga k\xF5rge"],
694
+ modeOptions: {
695
+ instant: ["Kohene"],
696
+ medium: ["Keskmine"],
697
+ high: ["K\xF5rge"],
698
+ extraHigh: ["V\xE4ga k\xF5rge"]
699
+ },
575
700
  modeOpenerExtra: ["Konfigureeri..."],
576
701
  tools: {
577
702
  web_search: ["Veebiotsing"],
@@ -594,6 +719,13 @@ var fa = {
594
719
  addPhotosFilesMenuItem: ["\u0627\u0641\u0632\u0648\u062F\u0646 \u062A\u0635\u0627\u0648\u06CC\u0631 \u0648 \u0641\u0627\u06CC\u0644\u200C\u0647\u0627"],
595
720
  copyResponse: ["\u06A9\u067E\u06CC \u06A9\u0631\u062F\u0646 \u067E\u0627\u0633\u062E"],
596
721
  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"],
722
+ modeOptions: {
723
+ instant: ["\u0641\u0648\u0631\u06CC"],
724
+ medium: ["\u0645\u062A\u0648\u0633\u0637"],
725
+ high: ["\u0628\u0627\u0644\u0627"],
726
+ extraHigh: ["\u0628\u0633\u06CC\u0627\u0631 \u0632\u06CC\u0627\u062F"],
727
+ pro: ["\u062D\u0631\u0641\u0647\u200C\u0627\u06CC"]
728
+ },
597
729
  modeOpenerExtra: ["\u067E\u06CC\u06A9\u0631\u0628\u0646\u062F\u06CC..."],
598
730
  tools: {
599
731
  web_search: ["\u062C\u0633\u062A\u062C\u0648\u06CC \u0648\u0628"],
@@ -616,6 +748,12 @@ var fi = {
616
748
  addPhotosFilesMenuItem: ["Lis\xE4\xE4 valokuvia & tiedostoja"],
617
749
  copyResponse: ["Kopioi vastaus"],
618
750
  modeLabels: ["V\xE4lit\xF6n", "Keskitaso", "Korkea", "Eritt\xE4in korkea"],
751
+ modeOptions: {
752
+ instant: ["V\xE4lit\xF6n"],
753
+ medium: ["Keskitaso"],
754
+ high: ["Korkea"],
755
+ extraHigh: ["Eritt\xE4in korkea"]
756
+ },
619
757
  modeOpenerExtra: ["M\xE4\xE4rit\xE4..."],
620
758
  tools: {
621
759
  web_search: ["Verkkohaku"],
@@ -638,6 +776,12 @@ var frCA = {
638
776
  addPhotosFilesMenuItem: ["Ajouter des photos et des fichiers"],
639
777
  copyResponse: ["Copier la r\xE9ponse"],
640
778
  modeLabels: ["Instantan\xE9", "Moyen", "\xC9lev\xE9", "Tr\xE8s \xE9lev\xE9"],
779
+ modeOptions: {
780
+ instant: ["Instantan\xE9"],
781
+ medium: ["Moyen"],
782
+ high: ["\xC9lev\xE9"],
783
+ extraHigh: ["Tr\xE8s \xE9lev\xE9"]
784
+ },
641
785
  modeOpenerExtra: ["Configurer..."],
642
786
  tools: {
643
787
  web_search: ["Recherche sur Internet"],
@@ -660,6 +804,12 @@ var gu = {
660
804
  addPhotosFilesMenuItem: ["\u0AAB\u0ACB\u0A9F\u0ABE \u0A85\u0AA8\u0AC7 \u0AAB\u0ABE\u0A87\u0AB2\u0ACB \u0A89\u0AAE\u0AC7\u0AB0\u0ACB"],
661
805
  copyResponse: ["\u0AAA\u0ACD\u0AB0\u0AA4\u0ABF\u0AAD\u0ABE\u0AB5 \u0A95\u0AC9\u0AAA\u0ABF \u0A95\u0AB0\u0ACB"],
662
806
  modeLabels: ["\u0AA4\u0AB0\u0AA4", "\u0AAE\u0AA7\u0ACD\u0AAF\u0AAE", "\u0A89\u0A9A\u0ACD\u0A9A", "\u0A85\u0AA4\u0ABF \u0A89\u0A9A\u0ACD\u0A9A"],
807
+ modeOptions: {
808
+ instant: ["\u0AA4\u0AB0\u0AA4"],
809
+ medium: ["\u0AAE\u0AA7\u0ACD\u0AAF\u0AAE"],
810
+ high: ["\u0A89\u0A9A\u0ACD\u0A9A"],
811
+ extraHigh: ["\u0A85\u0AA4\u0ABF \u0A89\u0A9A\u0ACD\u0A9A"]
812
+ },
663
813
  modeOpenerExtra: ["\u0A95\u0AA8\u0ACD\u0AAB\u0ABF\u0A97\u0AB0 \u0A95\u0AB0\u0ACB..."],
664
814
  tools: {
665
815
  web_search: ["\u0AB5\u0AC7\u0AAC \u0AB6\u0ACB\u0AA7"],
@@ -682,6 +832,12 @@ var hi = {
682
832
  addPhotosFilesMenuItem: ["\u092B\u093C\u094B\u091F\u094B \u0914\u0930 \u092B\u093C\u093E\u0907\u0932\u0947\u0902 \u091C\u094B\u0921\u093C\u0947\u0902"],
683
833
  copyResponse: ["\u091C\u0935\u093E\u092C \u0915\u094B \u0915\u0949\u092A\u0940 \u0915\u0930\u0947\u0902"],
684
834
  modeLabels: ["\u0924\u0941\u0930\u0902\u0924", "\u092E\u0927\u094D\u092F\u092E", "\u0909\u091A\u094D\u091A", "\u092C\u0939\u0941\u0924 \u0909\u091A\u094D\u091A"],
835
+ modeOptions: {
836
+ instant: ["\u0924\u0941\u0930\u0902\u0924"],
837
+ medium: ["\u092E\u0927\u094D\u092F\u092E"],
838
+ high: ["\u0909\u091A\u094D\u091A"],
839
+ extraHigh: ["\u092C\u0939\u0941\u0924 \u0909\u091A\u094D\u091A"]
840
+ },
685
841
  modeOpenerExtra: ["\u0915\u0949\u0928\u094D\u092B\u093C\u093F\u0917\u0930 \u0915\u0930\u0947\u0902..."],
686
842
  tools: {
687
843
  web_search: ["\u0935\u0947\u092C \u0938\u0930\u094D\u091A"],
@@ -704,6 +860,11 @@ var hr = {
704
860
  addPhotosFilesMenuItem: ["Dodaj fotografije i datoteke"],
705
861
  copyResponse: ["Kopiraj odgovor"],
706
862
  modeLabels: ["Srednje", "Visoko", "Vrlo visoka"],
863
+ modeOptions: {
864
+ medium: ["Srednje"],
865
+ high: ["Visoko"],
866
+ extraHigh: ["Vrlo visoka"]
867
+ },
707
868
  modeOpenerExtra: ["Konfiguriraj\u2026"],
708
869
  tools: {
709
870
  web_search: ["Mre\u017Eno pretra\u017Eivanje"],
@@ -726,6 +887,12 @@ var hu = {
726
887
  addPhotosFilesMenuItem: ["Fot\xF3k \xE9s f\xE1jlok hozz\xE1ad\xE1sa"],
727
888
  copyResponse: ["V\xE1lasz m\xE1sol\xE1sa"],
728
889
  modeLabels: ["Azonnali", "K\xF6zepes", "Magas", "Kiemelked\u0151en magas"],
890
+ modeOptions: {
891
+ instant: ["Azonnali"],
892
+ medium: ["K\xF6zepes"],
893
+ high: ["Magas"],
894
+ extraHigh: ["Kiemelked\u0151en magas"]
895
+ },
729
896
  modeOpenerExtra: ["Konfigur\xE1l\xE1s..."],
730
897
  tools: {
731
898
  web_search: ["Internetes keres\xE9s"],
@@ -748,6 +915,13 @@ var hy = {
748
915
  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"],
749
916
  copyResponse: ["\u054A\u0561\u057F\u0573\u0565\u0576\u0565\u056C \u057A\u0561\u057F\u0561\u057D\u056D\u0561\u0576\u0568"],
750
917
  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"],
918
+ modeOptions: {
919
+ instant: ["\u0531\u056F\u0576\u0569\u0561\u0580\u0569\u0561\u0575\u056B\u0576"],
920
+ medium: ["\u0544\u056B\u057B\u056B\u0576"],
921
+ high: ["\u0532\u0561\u0580\u0571\u0580"],
922
+ extraHigh: ["\u0547\u0561\u057F \u0562\u0561\u0580\u0571\u0580"],
923
+ pro: ["\u054A\u0580\u0578"]
924
+ },
751
925
  modeOpenerExtra: ["\u053F\u0561\u0566\u0574\u0561\u0571\u0587\u0565\u056C\u2024\u2024\u2024"],
752
926
  tools: {
753
927
  web_search: ["\u054E\u0565\u0562 \u0578\u0580\u0578\u0576\u0578\u0582\u0574"],
@@ -770,6 +944,12 @@ var id = {
770
944
  addPhotosFilesMenuItem: ["Tambah foto & file"],
771
945
  copyResponse: ["Salin respons"],
772
946
  modeLabels: ["Instan", "Sedang", "Tinggi", "Sangat Tinggi"],
947
+ modeOptions: {
948
+ instant: ["Instan"],
949
+ medium: ["Sedang"],
950
+ high: ["Tinggi"],
951
+ extraHigh: ["Sangat Tinggi"]
952
+ },
773
953
  modeOpenerExtra: ["Konfigurasi..."],
774
954
  tools: {
775
955
  web_search: ["Pencarian web"],
@@ -792,6 +972,12 @@ var is = {
792
972
  addPhotosFilesMenuItem: ["B\xE6ta myndum og skr\xE1m vi\xF0"],
793
973
  copyResponse: ["Afrita svar"],
794
974
  modeLabels: ["Strax", "Mi\xF0lungs", "H\xE1tt", "Mj\xF6g h\xE1tt"],
975
+ modeOptions: {
976
+ instant: ["Strax"],
977
+ medium: ["Mi\xF0lungs"],
978
+ high: ["H\xE1tt"],
979
+ extraHigh: ["Mj\xF6g h\xE1tt"]
980
+ },
795
981
  modeOpenerExtra: ["Stillir\u2026"],
796
982
  tools: {
797
983
  web_search: ["Vefleit"],
@@ -814,6 +1000,12 @@ var ka = {
814
1000
  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"],
815
1001
  copyResponse: ["\u10DE\u10D0\u10E1\u10E3\u10EE\u10D8\u10E1 \u10D9\u10DD\u10DE\u10D8\u10E0\u10D4\u10D1\u10D0"],
816
1002
  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"],
1003
+ modeOptions: {
1004
+ instant: ["\u10DB\u10E7\u10D8\u10E1\u10D8\u10D4\u10E0\u10D8"],
1005
+ medium: ["\u10E1\u10D0\u10E8\u10E3\u10D0\u10DA\u10DD"],
1006
+ high: ["\u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"],
1007
+ extraHigh: ["\u10EB\u10D0\u10DA\u10D8\u10D0\u10DC \u10DB\u10D0\u10E6\u10D0\u10DA\u10D8"]
1008
+ },
817
1009
  modeOpenerExtra: ["\u10D9\u10DD\u10DC\u10E4\u10D8\u10D2\u10E3\u10E0\u10D8\u10E0\u10D4\u10D1\u10D0\u2026"],
818
1010
  tools: {
819
1011
  web_search: ["\u10D5\u10D4\u10D1\u10E8\u10D8 \u10EB\u10D8\u10D4\u10D1\u10D0"],
@@ -836,6 +1028,12 @@ var kk = {
836
1028
  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"],
837
1029
  copyResponse: ["\u0416\u0430\u0443\u0430\u043F\u0442\u044B \u043A\u04E9\u0448\u0456\u0440\u0443"],
838
1030
  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"],
1031
+ modeOptions: {
1032
+ instant: ["\u0416\u0435\u0434\u0435\u043B"],
1033
+ medium: ["\u041E\u0440\u0442\u0430\u0448\u0430"],
1034
+ high: ["\u0416\u043E\u0493\u0430\u0440\u044B"],
1035
+ extraHigh: ["\u0410\u0441\u0430 \u0436\u043E\u0493\u0430\u0440\u044B"]
1036
+ },
839
1037
  modeOpenerExtra: ["\u041A\u043E\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F\u043B\u0430\u0443..."],
840
1038
  tools: {
841
1039
  web_search: ["\u0406\u0437\u0434\u0435\u0443"],
@@ -858,6 +1056,13 @@ var kn = {
858
1056
  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"],
859
1057
  copyResponse: ["\u0CAA\u0CCD\u0CB0\u0CA4\u0CBF\u0C95\u0CCD\u0CB0\u0CBF\u0CAF\u0CC6\u0CAF\u0CA8\u0CCD\u0CA8\u0CC1 \u0CA8\u0C95\u0CB2\u0CBF\u0CB8\u0CBF"],
860
1058
  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"],
1059
+ modeOptions: {
1060
+ instant: ["\u0CA4\u0C95\u0CCD\u0CB7\u0CA3"],
1061
+ medium: ["\u0CAE\u0CA7\u0CCD\u0CAF\u0CAE"],
1062
+ high: ["\u0C89\u0CA8\u0CCD\u0CA8\u0CA4"],
1063
+ extraHigh: ["\u0C85\u0CA4\u0CBF \u0CB9\u0CC6\u0C9A\u0CCD\u0C9A\u0CC1"],
1064
+ pro: ["\u0CAA\u0CCD\u0CB0\u0CCA"]
1065
+ },
861
1066
  modeOpenerExtra: ["\u0C95\u0CBE\u0CA8\u0CCD\u0CAB\u0CBF\u0C97\u0CB0\u0CCD \u0CAE\u0CBE\u0CA1\u0CBF..."],
862
1067
  tools: {
863
1068
  web_search: ["\u0CB5\u0CC6\u0CAC\u0CCD \u0CB8\u0CB0\u0CCD\u0C9A\u0CCD"],
@@ -880,6 +1085,12 @@ var ko = {
880
1085
  addPhotosFilesMenuItem: ["\uC0AC\uC9C4 \uBC0F \uD30C\uC77C \uCD94\uAC00"],
881
1086
  copyResponse: ["\uC751\uB2F5 \uBCF5\uC0AC"],
882
1087
  modeLabels: ["\uC989\uC2DC", "\uC911\uAC04", "\uB192\uC74C", "\uB9E4\uC6B0 \uB192\uC74C"],
1088
+ modeOptions: {
1089
+ instant: ["\uC989\uC2DC"],
1090
+ medium: ["\uC911\uAC04"],
1091
+ high: ["\uB192\uC74C"],
1092
+ extraHigh: ["\uB9E4\uC6B0 \uB192\uC74C"]
1093
+ },
883
1094
  modeOpenerExtra: ["\uAD6C\uC131\u2026"],
884
1095
  tools: {
885
1096
  web_search: ["\uC6F9 \uAC80\uC0C9"],
@@ -902,6 +1113,13 @@ var lt = {
902
1113
  addPhotosFilesMenuItem: ["Prid\u0117ti nuotrauk\u0173 ir fail\u0173"],
903
1114
  copyResponse: ["Kopijuoti atsakym\u0105"],
904
1115
  modeLabels: ["Momentinis", "Vidutinis", "Auk\u0161tas", "Ypa\u010D didelis", "Profesionalus"],
1116
+ modeOptions: {
1117
+ instant: ["Momentinis"],
1118
+ medium: ["Vidutinis"],
1119
+ high: ["Auk\u0161tas"],
1120
+ extraHigh: ["Ypa\u010D didelis"],
1121
+ pro: ["Profesionalus"]
1122
+ },
905
1123
  modeOpenerExtra: ["Konfig\u016Bruoti..."],
906
1124
  tools: {
907
1125
  web_search: ["\u017Diniatinklio paie\u0161ka"],
@@ -924,6 +1142,13 @@ var zhHans = {
924
1142
  addPhotosFilesMenuItem: ["\u6DFB\u52A0\u7167\u7247\u548C\u6587\u4EF6"],
925
1143
  copyResponse: ["\u590D\u5236\u56DE\u590D"],
926
1144
  modeLabels: ["\u6781\u901F", "\u5747\u8861", "\u9AD8\u7EA7", "\u8D85\u9AD8", "\u4E13\u4E1A"],
1145
+ modeOptions: {
1146
+ instant: ["\u6781\u901F"],
1147
+ medium: ["\u5747\u8861"],
1148
+ high: ["\u9AD8\u7EA7"],
1149
+ extraHigh: ["\u8D85\u9AD8"],
1150
+ pro: ["\u4E13\u4E1A"]
1151
+ },
927
1152
  modeOpenerExtra: ["\u914D\u7F6E\u2026"],
928
1153
  tools: {
929
1154
  web_search: ["\u7F51\u9875\u641C\u7D22"],
@@ -946,6 +1171,12 @@ var ur = {
946
1171
  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"],
947
1172
  copyResponse: ["\u062C\u0648\u0627\u0628 \u06A9\u0627\u067E\u06CC \u06A9\u0631\u06CC\u06BA"],
948
1173
  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"],
1174
+ modeOptions: {
1175
+ instant: ["\u0641\u0648\u0631\u06CC"],
1176
+ medium: ["\u0627\u0648\u0633\u0637"],
1177
+ high: ["\u0627\u0639\u0644\u06CC\u0670"],
1178
+ extraHigh: ["\u0627\u0646\u062A\u06C1\u0627\u0626\u06CC \u0627\u0639\u0644\u06CC\u0670"]
1179
+ },
949
1180
  modeOpenerExtra: ["\u06A9\u0646\u0641\u06CC\u06AF\u0631 \u06A9\u0631\u06CC\u06BA..."],
950
1181
  tools: {
951
1182
  web_search: ["\u0648\u06CC\u0628 \u067E\u0631 \u062A\u0644\u0627\u0634"],
@@ -968,6 +1199,12 @@ var uk = {
968
1199
  addPhotosFilesMenuItem: ["\u0414\u043E\u0434\u0430\u0442\u0438 \u0441\u0432\u0456\u0442\u043B\u0438\u043D\u0438 \u0442\u0430 \u0444\u0430\u0439\u043B\u0438"],
969
1200
  copyResponse: ["\u041A\u043E\u043F\u0456\u044E\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u044C"],
970
1201
  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"],
1202
+ modeOptions: {
1203
+ instant: ["\u041C\u0438\u0442\u0442\u0454\u0432\u0438\u0439"],
1204
+ medium: ["\u0421\u0435\u0440\u0435\u0434\u043D\u0456\u0439"],
1205
+ high: ["\u0412\u0438\u0441\u043E\u043A\u0438\u0439"],
1206
+ extraHigh: ["\u0414\u0443\u0436\u0435 \u0432\u0438\u0441\u043E\u043A\u0438\u0439"]
1207
+ },
971
1208
  modeOpenerExtra: ["\u041D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438\u2026"],
972
1209
  tools: {
973
1210
  web_search: ["\u041F\u043E\u0448\u0443\u043A \u0432 \u0406\u043D\u0442\u0435\u0440\u043D\u0435\u0442\u0456"],
@@ -990,6 +1227,12 @@ var ptBR = {
990
1227
  addPhotosFilesMenuItem: ["Carregar fotos e arquivos"],
991
1228
  copyResponse: ["Copiar resposta"],
992
1229
  modeLabels: ["Instant\xE2neo", "M\xE9dio", "Alto", "Muito alta"],
1230
+ modeOptions: {
1231
+ instant: ["Instant\xE2neo"],
1232
+ medium: ["M\xE9dio"],
1233
+ high: ["Alto"],
1234
+ extraHigh: ["Muito alta"]
1235
+ },
993
1236
  modeOpenerExtra: ["Configurar\u2026"],
994
1237
  tools: {
995
1238
  web_search: ["Busca na web"],
@@ -1012,6 +1255,12 @@ var ptPT = {
1012
1255
  addPhotosFilesMenuItem: ["Carregar fotos e ficheiros"],
1013
1256
  copyResponse: ["Copiar resposta"],
1014
1257
  modeLabels: ["Instant\xE2neo", "M\xE9dia", "Alta", "M\xE1ximo"],
1258
+ modeOptions: {
1259
+ instant: ["Instant\xE2neo"],
1260
+ medium: ["M\xE9dia"],
1261
+ high: ["Alta"],
1262
+ extraHigh: ["M\xE1ximo"]
1263
+ },
1015
1264
  modeOpenerExtra: ["Configurar..."],
1016
1265
  tools: {
1017
1266
  web_search: ["Procurar na web"],
@@ -1034,6 +1283,12 @@ var pl = {
1034
1283
  addPhotosFilesMenuItem: ["Prze\u015Blij zdj\u0119cia i pliki"],
1035
1284
  copyResponse: ["Kopiuj odpowied\u017A"],
1036
1285
  modeLabels: ["B\u0142yskawiczny", "\u015Aredni", "Zaawansowana", "Bardzo wysoki"],
1286
+ modeOptions: {
1287
+ instant: ["B\u0142yskawiczny"],
1288
+ medium: ["\u015Aredni"],
1289
+ high: ["Zaawansowana"],
1290
+ extraHigh: ["Bardzo wysoki"]
1291
+ },
1037
1292
  modeOpenerExtra: ["Skonfiguruj..."],
1038
1293
  tools: {
1039
1294
  web_search: ["Wyszukiwanie w sieci"],
@@ -1056,6 +1311,12 @@ var sk = {
1056
1311
  addPhotosFilesMenuItem: ["Nahra\u0165 fotografie a s\xFAbory"],
1057
1312
  copyResponse: ["Kop\xEDrova\u0165 odpove\u010F"],
1058
1313
  modeLabels: ["Okam\u017Eit\xE1", "Stredn\xE1", "Vysok\xE1", "Extra vysok\xE1"],
1314
+ modeOptions: {
1315
+ instant: ["Okam\u017Eit\xE1"],
1316
+ medium: ["Stredn\xE1"],
1317
+ high: ["Vysok\xE1"],
1318
+ extraHigh: ["Extra vysok\xE1"]
1319
+ },
1059
1320
  modeOpenerExtra: ["Konfigurova\u0165..."],
1060
1321
  tools: {
1061
1322
  web_search: ["Preh\u013Ead\xE1vaj web"],
@@ -1078,6 +1339,11 @@ var ro = {
1078
1339
  addPhotosFilesMenuItem: ["\xCEncarc\u0103 fotografii \u0219i fi\u0219iere"],
1079
1340
  copyResponse: ["Copiaz\u0103 r\u0103spunsul"],
1080
1341
  modeLabels: ["Mediu", "Ridicat", "Foarte ridicat\u0103"],
1342
+ modeOptions: {
1343
+ medium: ["Mediu"],
1344
+ high: ["Ridicat"],
1345
+ extraHigh: ["Foarte ridicat\u0103"]
1346
+ },
1081
1347
  modeOpenerExtra: ["Configureaz\u0103..."],
1082
1348
  tools: {
1083
1349
  web_search: ["C\u0103utare pe internet"],
@@ -1100,6 +1366,12 @@ var nb = {
1100
1366
  addPhotosFilesMenuItem: ["Last opp bilder og filer"],
1101
1367
  copyResponse: ["Kopier svar"],
1102
1368
  modeLabels: ["\xD8yeblikkelig", "Middels", "H\xF8y", "Ekstra h\xF8y"],
1369
+ modeOptions: {
1370
+ instant: ["\xD8yeblikkelig"],
1371
+ medium: ["Middels"],
1372
+ high: ["H\xF8y"],
1373
+ extraHigh: ["Ekstra h\xF8y"]
1374
+ },
1103
1375
  modeOpenerExtra: ["Konfigurer \u2026"],
1104
1376
  tools: {
1105
1377
  web_search: ["Netts\xF8k"],
@@ -1122,6 +1394,13 @@ var ml = {
1122
1394
  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"],
1123
1395
  copyResponse: ["\u0D2E\u0D31\u0D41\u0D2A\u0D1F\u0D3F \u0D15\u0D4B\u0D2A\u0D4D\u0D2A\u0D3F \u0D1A\u0D46\u0D2F\u0D4D\u0D2F\u0D41\u0D15"],
1124
1396
  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"],
1397
+ modeOptions: {
1398
+ instant: ["\u0D24\u0D7D\u0D15\u0D4D\u0D37\u0D23\u0D02"],
1399
+ medium: ["\u0D07\u0D1F\u0D24\u0D4D\u0D24\u0D30\u0D02"],
1400
+ high: ["\u0D09\u0D2F\u0D7C\u0D28\u0D4D\u0D28\u0D24\u0D4D"],
1401
+ extraHigh: ["\u0D35\u0D33\u0D30\u0D46 \u0D09\u0D2F\u0D7C\u0D28\u0D4D\u0D28"],
1402
+ pro: ["\u0D2A\u0D4D\u0D30\u0D4B"]
1403
+ },
1125
1404
  modeOpenerExtra: ["\u0D15\u0D4B\u0D7A\u0D2B\u0D3F\u0D17\u0D7C \u0D1A\u0D46\u0D2F\u0D4D\u0D2F\u0D41\u0D15\u2026"],
1126
1405
  tools: {
1127
1406
  web_search: ["\u0D35\u0D46\u0D2C\u0D4D \u0D24\u0D3F\u0D30\u0D2F\u0D7D"],
@@ -1144,6 +1423,9 @@ var ru = {
1144
1423
  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"],
1145
1424
  copyResponse: ["\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043E\u0442\u0432\u0435\u0442"],
1146
1425
  modeLabels: ["\u041E\u0447\u0435\u043D\u044C \u0432\u044B\u0441\u043E\u043A\u0438\u0439"],
1426
+ modeOptions: {
1427
+ extraHigh: ["\u041E\u0447\u0435\u043D\u044C \u0432\u044B\u0441\u043E\u043A\u0438\u0439"]
1428
+ },
1147
1429
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044F..."],
1148
1430
  tools: {
1149
1431
  web_search: ["\u041F\u043E\u0438\u0441\u043A \u0432 \u0441\u0435\u0442\u0438"],
@@ -1166,6 +1448,13 @@ var pa = {
1166
1448
  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"],
1167
1449
  copyResponse: ["\u0A1C\u0A35\u0A3E\u0A2C \u0A15\u0A3E\u0A2A\u0A40 \u0A15\u0A30\u0A4B"],
1168
1450
  modeLabels: ["\u0A24\u0A41\u0A30\u0A70\u0A24", "\u0A2E\u0A71\u0A27\u0A2E", "\u0A09\u0A71\u0A1A", "\u0A05\u0A24\u0A3F \u0A09\u0A71\u0A1A", "\u0A2A\u0A4D\u0A30\u0A4B"],
1451
+ modeOptions: {
1452
+ instant: ["\u0A24\u0A41\u0A30\u0A70\u0A24"],
1453
+ medium: ["\u0A2E\u0A71\u0A27\u0A2E"],
1454
+ high: ["\u0A09\u0A71\u0A1A"],
1455
+ extraHigh: ["\u0A05\u0A24\u0A3F \u0A09\u0A71\u0A1A"],
1456
+ pro: ["\u0A2A\u0A4D\u0A30\u0A4B"]
1457
+ },
1169
1458
  modeOpenerExtra: ["\u0A15\u0A4C\u0A28\u0A2B\u0A3F\u0A17\u0A30..."],
1170
1459
  tools: {
1171
1460
  web_search: ["\u0A35\u0A48\u0A71\u0A2C \u0A16\u0A4B\u0A1C"],
@@ -1188,6 +1477,13 @@ var mr = {
1188
1477
  addPhotosFilesMenuItem: ["\u092B\u094B\u091F\u094B \u0906\u0923\u093F \u092B\u093E\u0907\u0932\u094D\u0938 \u0905\u092A\u0932\u094B\u0921 \u0915\u0930\u093E"],
1189
1478
  copyResponse: ["\u092A\u094D\u0930\u0924\u093F\u0938\u093E\u0926 \u0915\u0949\u092A\u0940 \u0915\u0930\u093E"],
1190
1479
  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"],
1480
+ modeOptions: {
1481
+ instant: ["\u091D\u091F\u092A\u091F"],
1482
+ medium: ["\u092E\u0927\u094D\u092F\u092E"],
1483
+ high: ["\u0909\u091A\u094D\u091A"],
1484
+ extraHigh: ["\u0905\u0924\u093F\u0909\u091A\u094D\u091A"],
1485
+ pro: ["\u092A\u094D\u0930\u094B"]
1486
+ },
1191
1487
  modeOpenerExtra: ["\u0915\u0949\u0928\u094D\u092B\u093F\u0917\u0930 \u0915\u0930\u093E..."],
1192
1488
  tools: {
1193
1489
  web_search: ["\u0935\u0947\u092C\u0935\u0930 \u0936\u094B\u0927"],
@@ -1210,6 +1506,12 @@ var tr = {
1210
1506
  addPhotosFilesMenuItem: ["Foto\u011Fraf ve dosya y\xFCkle"],
1211
1507
  copyResponse: ["Yan\u0131t\u0131 kopyala"],
1212
1508
  modeLabels: ["An\u0131nda", "Orta", "Y\xFCksek", "\xC7ok Y\xFCksek"],
1509
+ modeOptions: {
1510
+ instant: ["An\u0131nda"],
1511
+ medium: ["Orta"],
1512
+ high: ["Y\xFCksek"],
1513
+ extraHigh: ["\xC7ok Y\xFCksek"]
1514
+ },
1213
1515
  modeOpenerExtra: ["Yap\u0131land\u0131r..."],
1214
1516
  tools: {
1215
1517
  web_search: ["Web aramas\u0131"],
@@ -1232,6 +1534,12 @@ var sw = {
1232
1534
  addPhotosFilesMenuItem: ["Pakia picha na mafaili"],
1233
1535
  copyResponse: ["Nakili jibu"],
1234
1536
  modeLabels: ["Papo hapo", "Wastani", "Juu", "Juu Zaidi"],
1537
+ modeOptions: {
1538
+ instant: ["Papo hapo"],
1539
+ medium: ["Wastani"],
1540
+ high: ["Juu"],
1541
+ extraHigh: ["Juu Zaidi"]
1542
+ },
1235
1543
  modeOpenerExtra: ["Sanidi..."],
1236
1544
  tools: {
1237
1545
  web_search: ["Utafutaji wa wavuti"],
@@ -1254,6 +1562,13 @@ var te = {
1254
1562
  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"],
1255
1563
  copyResponse: ["\u0C2A\u0C4D\u0C30\u0C24\u0C3F\u0C38\u0C4D\u0C2A\u0C02\u0C26\u0C28\u0C28\u0C41 \u0C15\u0C3E\u0C2A\u0C40 \u0C1A\u0C47\u0C2F\u0C02\u0C21\u0C3F"],
1256
1564
  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"],
1565
+ modeOptions: {
1566
+ instant: ["\u0C24\u0C15\u0C4D\u0C37\u0C23\u0C02"],
1567
+ medium: ["\u0C2E\u0C27\u0C4D\u0C2F\u0C38\u0C4D\u0C25"],
1568
+ high: ["\u0C05\u0C27\u0C3F\u0C15"],
1569
+ extraHigh: ["\u0C05\u0C24\u0C4D\u0C2F\u0C27\u0C3F\u0C15"],
1570
+ pro: ["\u0C2A\u0C4D\u0C30\u0C4B"]
1571
+ },
1257
1572
  modeOpenerExtra: ["\u0C15\u0C3E\u0C28\u0C4D\u0C2B\u0C3F\u0C17\u0C30\u0C4D \u0C1A\u0C47\u0C2F\u0C02\u0C21\u0C3F"],
1258
1573
  tools: {
1259
1574
  web_search: ["\u0C35\u0C46\u0C2C\u0C4D\u200C\u0C32\u0C4B \u0C35\u0C46\u0C24\u0C15\u0C21\u0C02"],
@@ -1296,6 +1611,12 @@ var th = {
1296
1611
  addPhotosFilesMenuItem: ["\u0E2D\u0E31\u0E1B\u0E42\u0E2B\u0E25\u0E14\u0E23\u0E39\u0E1B\u0E41\u0E25\u0E30\u0E44\u0E1F\u0E25\u0E4C"],
1297
1612
  copyResponse: ["\u0E04\u0E31\u0E14\u0E25\u0E2D\u0E01\u0E04\u0E33\u0E15\u0E2D\u0E1A"],
1298
1613
  modeLabels: ["\u0E17\u0E31\u0E19\u0E17\u0E35", "\u0E1B\u0E32\u0E19\u0E01\u0E25\u0E32\u0E07", "\u0E2A\u0E39\u0E07", "\u0E2A\u0E39\u0E07\u0E21\u0E32\u0E01"],
1614
+ modeOptions: {
1615
+ instant: ["\u0E17\u0E31\u0E19\u0E17\u0E35"],
1616
+ medium: ["\u0E1B\u0E32\u0E19\u0E01\u0E25\u0E32\u0E07"],
1617
+ high: ["\u0E2A\u0E39\u0E07"],
1618
+ extraHigh: ["\u0E2A\u0E39\u0E07\u0E21\u0E32\u0E01"]
1619
+ },
1299
1620
  modeOpenerExtra: ["\u0E01\u0E33\u0E2B\u0E19\u0E14\u0E04\u0E48\u0E32..."],
1300
1621
  tools: {
1301
1622
  web_search: ["\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E40\u0E27\u0E47\u0E1A"],
@@ -1318,6 +1639,13 @@ var bn = {
1318
1639
  addPhotosFilesMenuItem: ["\u09AB\u099F\u09CB \u098F\u09AC\u0982 \u09AB\u09BE\u0987\u09B2 \u0986\u09AA\u09B2\u09CB\u09A1 \u0995\u09B0\u09C1\u09A8"],
1319
1640
  copyResponse: ["\u0989\u09A4\u09CD\u09A4\u09B0 \u0995\u09AA\u09BF \u0995\u09B0\u09C1\u09A8"],
1320
1641
  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"],
1642
+ modeOptions: {
1643
+ instant: ["\u09A4\u09BE\u09CE\u0995\u09CD\u09B7\u09A3\u09BF\u0995"],
1644
+ medium: ["\u09AE\u09BE\u099D\u09BE\u09B0\u09BF"],
1645
+ high: ["\u0989\u099A\u09CD\u099A"],
1646
+ extraHigh: ["\u0985\u09A4\u09BF \u0989\u099A\u09CD\u099A"],
1647
+ pro: ["\u09AA\u09CD\u09B0\u09CB"]
1648
+ },
1321
1649
  modeOpenerExtra: ["\u0995\u09A8\u09AB\u09BF\u0997\u09BE\u09B0 \u0995\u09B0\u09C1\u09A8..."],
1322
1650
  tools: {
1323
1651
  web_search: ["\u0993\u09AF\u09BC\u09C7\u09AC \u09B8\u09A8\u09CD\u09A7\u09BE\u09A8"],
@@ -1340,6 +1668,12 @@ var ms = {
1340
1668
  addPhotosFilesMenuItem: ["Muat naik foto & fail"],
1341
1669
  copyResponse: ["Salin tindak balas"],
1342
1670
  modeLabels: ["Segera", "Sederhana", "Tinggi", "Sangat Tinggi"],
1671
+ modeOptions: {
1672
+ instant: ["Segera"],
1673
+ medium: ["Sederhana"],
1674
+ high: ["Tinggi"],
1675
+ extraHigh: ["Sangat Tinggi"]
1676
+ },
1343
1677
  modeOpenerExtra: ["Konfigurasikan\u2026"],
1344
1678
  tools: {
1345
1679
  web_search: ["Carian web"],
@@ -1362,6 +1696,12 @@ var so = {
1362
1696
  addPhotosFilesMenuItem: ["Soo geli sawirada & faylasha"],
1363
1697
  copyResponse: ["Koobiyee jawaabta"],
1364
1698
  modeLabels: ["Degdeg", "Dhexdhexaad", "Sare", "Aad u sarreeya"],
1699
+ modeOptions: {
1700
+ instant: ["Degdeg"],
1701
+ medium: ["Dhexdhexaad"],
1702
+ high: ["Sare"],
1703
+ extraHigh: ["Aad u sarreeya"]
1704
+ },
1365
1705
  modeOpenerExtra: ["Ku xidh..."],
1366
1706
  tools: {
1367
1707
  web_search: ["Raadi shakabada"],
@@ -1384,6 +1724,12 @@ var nl = {
1384
1724
  addPhotosFilesMenuItem: ["Foto's en bestanden uploaden"],
1385
1725
  copyResponse: ["Reactie kopi\xEBren"],
1386
1726
  modeLabels: ["Direct", "Gemiddeld", "Hoog", "Extra hoog"],
1727
+ modeOptions: {
1728
+ instant: ["Direct"],
1729
+ medium: ["Gemiddeld"],
1730
+ high: ["Hoog"],
1731
+ extraHigh: ["Extra hoog"]
1732
+ },
1387
1733
  modeOpenerExtra: ["Configureren..."],
1388
1734
  tools: {
1389
1735
  web_search: ["Zoeken op internet"],
@@ -1406,6 +1752,12 @@ var sv = {
1406
1752
  addPhotosFilesMenuItem: ["Ladda upp foton och filer"],
1407
1753
  copyResponse: ["Kopiera svar"],
1408
1754
  modeLabels: ["Direkt", "Balanserad", "H\xF6g", "Extra h\xF6g"],
1755
+ modeOptions: {
1756
+ instant: ["Direkt"],
1757
+ medium: ["Balanserad"],
1758
+ high: ["H\xF6g"],
1759
+ extraHigh: ["Extra h\xF6g"]
1760
+ },
1409
1761
  modeOpenerExtra: ["Konfigurera \u2026"],
1410
1762
  tools: {
1411
1763
  web_search: ["Webbs\xF6kning"],
@@ -1428,6 +1780,12 @@ var lv = {
1428
1780
  addPhotosFilesMenuItem: ["Aug\u0161upiel\u0101d\u0113t foto un failus"],
1429
1781
  copyResponse: ["Kop\u0113t atbildi"],
1430
1782
  modeLabels: ["T\u016Bl\u012Bt\u0113js", "Vid\u0113js", "Augsts", "\u013Boti augsts"],
1783
+ modeOptions: {
1784
+ instant: ["T\u016Bl\u012Bt\u0113js"],
1785
+ medium: ["Vid\u0113js"],
1786
+ high: ["Augsts"],
1787
+ extraHigh: ["\u013Boti augsts"]
1788
+ },
1431
1789
  modeOpenerExtra: ["Konfigur\u0113t..."],
1432
1790
  tools: {
1433
1791
  web_search: ["Mekl\u0113\u0161ana t\u012Bmekl\u012B"],
@@ -1450,6 +1808,11 @@ var mk = {
1450
1808
  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"],
1451
1809
  copyResponse: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0458 \u043E\u0434\u0433\u043E\u0432\u043E\u0440"],
1452
1810
  modeLabels: ["\u0421\u0440\u0435\u0434\u043D\u043E", "\u0412\u0438\u0441\u043E\u043A\u043E", "\u041C\u043D\u043E\u0433\u0443 \u0432\u0438\u0441\u043E\u043A\u043E"],
1811
+ modeOptions: {
1812
+ medium: ["\u0421\u0440\u0435\u0434\u043D\u043E"],
1813
+ high: ["\u0412\u0438\u0441\u043E\u043A\u043E"],
1814
+ extraHigh: ["\u041C\u043D\u043E\u0433\u0443 \u0432\u0438\u0441\u043E\u043A\u043E"]
1815
+ },
1453
1816
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0458..."],
1454
1817
  tools: {
1455
1818
  web_search: ["\u041F\u0440\u0435\u0431\u0430\u0440\u0443\u0432\u0430\u045A\u0435 \u043D\u0430 \u0438\u043D\u0442\u0435\u0440\u043D\u0435\u0442"],
@@ -1472,6 +1835,12 @@ var sq = {
1472
1835
  addPhotosFilesMenuItem: ["Ngarko foto dhe skedar\xEB"],
1473
1836
  copyResponse: ["Kopjo p\xEBrgjigjen"],
1474
1837
  modeLabels: ["I menj\xEBhersh\xEBm", "Mesatar", "Lart\xEB", "Shum\xEB i lart\xEB"],
1838
+ modeOptions: {
1839
+ instant: ["I menj\xEBhersh\xEBm"],
1840
+ medium: ["Mesatar"],
1841
+ high: ["Lart\xEB"],
1842
+ extraHigh: ["Shum\xEB i lart\xEB"]
1843
+ },
1475
1844
  modeOpenerExtra: ["Konfiguro..."],
1476
1845
  tools: {
1477
1846
  web_search: ["K\xEBrkim n\xEB ueb"],
@@ -1494,6 +1863,12 @@ var sl = {
1494
1863
  addPhotosFilesMenuItem: ["Nalo\u017Ei fotografije in datoteke"],
1495
1864
  copyResponse: ["Kopiraj odgovor"],
1496
1865
  modeLabels: ["Takoj", "Srednja", "Visoka", "Zelo visoko"],
1866
+ modeOptions: {
1867
+ instant: ["Takoj"],
1868
+ medium: ["Srednja"],
1869
+ high: ["Visoka"],
1870
+ extraHigh: ["Zelo visoko"]
1871
+ },
1497
1872
  modeOpenerExtra: ["Konfiguracija \u2026"],
1498
1873
  tools: {
1499
1874
  web_search: ["Iskanje po spletu"],
@@ -1516,6 +1891,9 @@ var sr = {
1516
1891
  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"],
1517
1892
  copyResponse: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0458 \u043E\u0434\u0433\u043E\u0432\u043E\u0440"],
1518
1893
  modeLabels: ["\u0412\u0435\u043E\u043C\u0430 \u0432\u0438\u0441\u043E\u043A\u043E"],
1894
+ modeOptions: {
1895
+ extraHigh: ["\u0412\u0435\u043E\u043C\u0430 \u0432\u0438\u0441\u043E\u043A\u043E"]
1896
+ },
1519
1897
  modeOpenerExtra: ["\u041A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0448\u0438..."],
1520
1898
  tools: {
1521
1899
  web_search: ["\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u0432\u0435\u0431\u0430"],
@@ -1538,6 +1916,13 @@ var mn = {
1538
1916
  addPhotosFilesMenuItem: ["\u0417\u0443\u0440\u0430\u0433 \u0431\u0430 \u0444\u0430\u0439\u043B \u0431\u0430\u0439\u0440\u0448\u0443\u0443\u043B\u0430\u0445"],
1539
1917
  copyResponse: ["\u0425\u0430\u0440\u0438\u0443\u043B\u0442 \u0445\u0443\u0443\u043B\u0430\u0445"],
1540
1918
  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"],
1919
+ modeOptions: {
1920
+ instant: ["\u0428\u0443\u0443\u0440\u0445\u0430\u0439"],
1921
+ medium: ["\u0414\u0443\u043D\u0434"],
1922
+ high: ["\u04E8\u043D\u0434\u04E9\u0440"],
1923
+ extraHigh: ["\u041C\u0430\u0448 \u04E9\u043D\u0434\u04E9\u0440"],
1924
+ pro: ["\u041F\u0440\u043E"]
1925
+ },
1541
1926
  modeOpenerExtra: ["\u0422\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0445..."],
1542
1927
  tools: {
1543
1928
  web_search: ["\u0412\u0435\u0431 \u0445\u0430\u0439\u043B\u0442"],
@@ -1560,6 +1945,12 @@ var my = {
1560
1945
  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"],
1561
1946
  copyResponse: ["\u1010\u102F\u1036\u1037\u1015\u103C\u1014\u103A\u1019\u103E\u102F \u1000\u1030\u1038\u101A\u1030\u101B\u1014\u103A"],
1562
1947
  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"],
1948
+ modeOptions: {
1949
+ instant: ["\u1001\u103B\u1000\u103A\u1001\u103B\u1004\u103A\u1038"],
1950
+ medium: ["\u1021\u101C\u101A\u103A\u1021\u101C\u1010\u103A"],
1951
+ high: ["\u1019\u103C\u1004\u1037\u103A"],
1952
+ extraHigh: ["\u1021\u101C\u103D\u1014\u103A\u1019\u103C\u1004\u1037\u103A"]
1953
+ },
1563
1954
  modeOpenerExtra: ["\u1015\u103C\u102F\u1015\u103C\u1004\u103A\u1019\u103D\u1019\u103A\u1038\u1019\u1036\u101B\u1014\u103A"],
1564
1955
  tools: {
1565
1956
  web_search: ["\u101D\u1018\u103A\u101B\u103E\u102C\u1016\u103D\u1031\u101B\u1014\u103A"],
@@ -1582,6 +1973,13 @@ var ta = {
1582
1973
  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"],
1583
1974
  copyResponse: ["\u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0BA8\u0B95\u0BB2\u0BC6\u0B9F\u0BC1\u0B95\u0BCD\u0B95\u0BB2\u0BBE\u0BAE\u0BCD"],
1584
1975
  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"],
1976
+ modeOptions: {
1977
+ instant: ["\u0B89\u0B9F\u0BA9\u0B9F\u0BBF"],
1978
+ medium: ["\u0BA8\u0B9F\u0BC1\u0BA4\u0BCD\u0BA4\u0BB0"],
1979
+ high: ["\u0B89\u0BAF\u0BB0\u0BCD"],
1980
+ extraHigh: ["\u0BAE\u0BBF\u0B95 \u0B89\u0BAF\u0BB0\u0BCD\u0BB5\u0BC1"],
1981
+ pro: ["\u0BAA\u0BCD\u0BB0\u0BCB"]
1982
+ },
1585
1983
  modeOpenerExtra: ["\u0B95\u0B9F\u0BCD\u0B9F\u0BAE\u0BC8\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD..."],
1586
1984
  tools: {
1587
1985
  web_search: ["\u0B87\u0BA3\u0BC8\u0BAF \u0BA4\u0BC7\u0B9F\u0BB2\u0BCD"],
@@ -1595,6 +1993,16 @@ var ta = {
1595
1993
  // src/dom/locale/index.ts
1596
1994
  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];
1597
1995
  var TOOL_IDS = ["web_search", "deep_research", "create_image"];
1996
+ var MODE_OPTION_IDS = [
1997
+ "latest",
1998
+ "instant",
1999
+ "thinking",
2000
+ "extended",
2001
+ "medium",
2002
+ "high",
2003
+ "extraHigh",
2004
+ "pro"
2005
+ ];
1598
2006
  function flattenKey(localeList, key) {
1599
2007
  const seen = /* @__PURE__ */ new Set();
1600
2008
  const result = [];
@@ -1629,6 +2037,24 @@ function flattenTool(localeList, toolId) {
1629
2037
  }
1630
2038
  return result;
1631
2039
  }
2040
+ function flattenModeOption(localeList, optionId) {
2041
+ const seen = /* @__PURE__ */ new Set();
2042
+ const result = [];
2043
+ for (const locale of localeList) {
2044
+ const modeOptions = locale["modeOptions"];
2045
+ if (modeOptions === void 0 || modeOptions === null) continue;
2046
+ const value = modeOptions[optionId];
2047
+ if (value === void 0 || value === null) continue;
2048
+ const candidates = typeof value === "string" ? [value] : value;
2049
+ for (const candidate of candidates) {
2050
+ if (candidate.length > 0 && !seen.has(candidate)) {
2051
+ seen.add(candidate);
2052
+ result.push(candidate);
2053
+ }
2054
+ }
2055
+ }
2056
+ return result;
2057
+ }
1632
2058
  var nonToolKeys = [
1633
2059
  "composerTextbox",
1634
2060
  "sendButton",
@@ -1647,6 +2073,8 @@ var nonToolKeys = [
1647
2073
  "imageContainerHint",
1648
2074
  "modeLabels",
1649
2075
  "modeOpenerExtra",
2076
+ "threadActionMenuItems",
2077
+ "threadActionPrefixes",
1650
2078
  "signedInMarkers",
1651
2079
  "transientAssistant",
1652
2080
  "stopControl",
@@ -1662,8 +2090,12 @@ var builtLabels = Object.fromEntries(
1662
2090
  var builtTools = Object.fromEntries(
1663
2091
  TOOL_IDS.map((id2) => [id2, flattenTool(locales, id2)])
1664
2092
  );
2093
+ var builtModeOptions = Object.fromEntries(
2094
+ MODE_OPTION_IDS.map((id2) => [id2, flattenModeOption(locales, id2)])
2095
+ );
1665
2096
  var localeLabels = {
1666
2097
  ...builtLabels,
2098
+ modeOptions: builtModeOptions,
1667
2099
  tools: builtTools
1668
2100
  };
1669
2101
  function escapeRegExp(value) {
@@ -1675,8 +2107,17 @@ function anyLabelPattern(candidates) {
1675
2107
 
1676
2108
  // src/browser/page-state.ts
1677
2109
  function parseConversationId(url) {
1678
- const match = /\/c\/([A-Za-z0-9-]+)/.exec(url);
1679
- return match?.[1];
2110
+ let parsed;
2111
+ try {
2112
+ parsed = new URL(url, "https://chatgpt.com");
2113
+ } catch {
2114
+ return void 0;
2115
+ }
2116
+ const segments = parsed.pathname.split("/").filter(Boolean);
2117
+ if (segments[0] !== "c" || segments[1] === void 0 || segments[1].length === 0) {
2118
+ return void 0;
2119
+ }
2120
+ return segments[1];
1680
2121
  }
1681
2122
  async function readPageState(page) {
1682
2123
  const rawUrl = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
@@ -2780,7 +3221,7 @@ async function contextFromPage(page, partial = {}) {
2780
3221
  return { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...partial };
2781
3222
  }
2782
3223
  const url = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => partial.url) : partial.url;
2783
- const title = typeof page.title === "function" ? await page.title().catch(() => void 0) : partial.title;
3224
+ const title = typeof page.title === "function" ? await withTimeout(page.title(), 1e3, "Timed out while reading page title.").catch(() => partial.title) : partial.title;
2784
3225
  const [turnCount, assistantTurnCount] = await Promise.all([
2785
3226
  withTimeout(countPageMessages(page), 1e3, "Timed out while counting page messages.").catch(() => partial.turnCount),
2786
3227
  withTimeout(countPageMessages(page, "assistant"), 1e3, "Timed out while counting assistant messages.").catch(() => partial.assistantTurnCount)
@@ -3761,6 +4202,7 @@ async function sleep(page, ms2) {
3761
4202
  // src/commands/files.ts
3762
4203
  import { access, readFile, stat as stat3 } from "node:fs/promises";
3763
4204
  import { constants } from "node:fs";
4205
+ import { createHash } from "node:crypto";
3764
4206
  import path2 from "node:path";
3765
4207
 
3766
4208
  // src/platform/local-paths.ts
@@ -3864,7 +4306,17 @@ async function preflightFiles(env, args) {
3864
4306
  message: `File attachment exceeds the configured per-file preflight limit: ${absolute} (${fileStat.size}/${maxBytesPerFile} bytes)`
3865
4307
  });
3866
4308
  }
3867
- const metadata = fileMetadata(absolute, fileStat.size);
4309
+ if (fileStat.size === 0) {
4310
+ return filePreflightBlocker({
4311
+ env,
4312
+ status: "blocked",
4313
+ kind: "upload_failed",
4314
+ code: "file_empty",
4315
+ fieldPath,
4316
+ message: `File attachment path is zero bytes and ChatGPT rejects empty attachments: ${absolute}`
4317
+ });
4318
+ }
4319
+ const metadata = await fileMetadata(absolute, fileStat.size, args.includeHashes === true);
3868
4320
  files.push(metadata);
3869
4321
  }
3870
4322
  const totalBytes = files.reduce((sum, file) => sum + file.bytes, 0);
@@ -3882,7 +4334,11 @@ async function preflightFiles(env, args) {
3882
4334
  return resultOk({ files, totalBytes }, filePreflightContext(env), warnings);
3883
4335
  }
3884
4336
  async function attachFiles(env, args) {
3885
- const preflight = await preflightFiles(env, { paths: args.paths });
4337
+ const preflightArgs = { paths: args.paths };
4338
+ if (args.includeDiagnostics === true && args.includeHashes !== void 0) {
4339
+ preflightArgs.includeHashes = args.includeHashes;
4340
+ }
4341
+ const preflight = await preflightFiles(env, preflightArgs);
3886
4342
  if (!preflight.ok || preflight.data === void 0) {
3887
4343
  return preflight;
3888
4344
  }
@@ -3898,6 +4354,7 @@ async function attachFiles(env, args) {
3898
4354
  bytes: file.bytes
3899
4355
  }));
3900
4356
  await uploadFiles(page, files, args.timeoutMs ?? 3e4);
4357
+ const browserInput = args.includeDiagnostics === true ? await readBrowserInputDiagnostic(page).catch(() => void 0) : void 0;
3901
4358
  await page.waitForTimeout?.(args.timeoutMs === void 0 ? 1e3 : Math.min(args.timeoutMs, 3e3));
3902
4359
  const readiness = await waitForAttachedFilesReady(page, files, args.timeoutMs ?? 3e4);
3903
4360
  if (!readiness.ready) {
@@ -3930,7 +4387,14 @@ async function attachFiles(env, args) {
3930
4387
  context: await contextFromPage(page)
3931
4388
  };
3932
4389
  }
3933
- return resultOk({ files }, await contextFromPage(page), preflight.warnings);
4390
+ const data = { files };
4391
+ if (args.includeDiagnostics === true) {
4392
+ data.diagnostics = { preflight: preflight.data };
4393
+ if (browserInput !== void 0) {
4394
+ data.diagnostics.browserInput = browserInput;
4395
+ }
4396
+ }
4397
+ return resultOk(data, await contextFromPage(page), preflight.warnings);
3934
4398
  } catch (error) {
3935
4399
  if (isUploadBridgeBlocker(error)) {
3936
4400
  return {
@@ -3969,10 +4433,10 @@ function filePreflightBlocker(args) {
3969
4433
  function filePreflightContext(env) {
3970
4434
  return { timestamp: (env.now?.() ?? /* @__PURE__ */ new Date()).toISOString() };
3971
4435
  }
3972
- function fileMetadata(absolute, bytes) {
4436
+ async function fileMetadata(absolute, bytes, includeHash = false) {
3973
4437
  const extension = extensionForHostPath(absolute);
3974
4438
  const { mimeType, category } = guessFileType(extension);
3975
- return {
4439
+ const metadata = {
3976
4440
  path: absolute,
3977
4441
  name: basenameForHostPath(absolute),
3978
4442
  bytes,
@@ -3980,6 +4444,10 @@ function fileMetadata(absolute, bytes) {
3980
4444
  mimeType,
3981
4445
  category
3982
4446
  };
4447
+ if (includeHash) {
4448
+ metadata.sha256 = createHash("sha256").update(await readFile(absolute)).digest("hex");
4449
+ }
4450
+ return metadata;
3983
4451
  }
3984
4452
  function extensionForHostPath(value) {
3985
4453
  return process.platform === "win32" ? path2.win32.extname(value).toLowerCase() : path2.posix.extname(value).toLowerCase();
@@ -3988,9 +4456,6 @@ function collectFilePreflightWarnings(files, warnings) {
3988
4456
  const byPath = /* @__PURE__ */ new Map();
3989
4457
  const byName = /* @__PURE__ */ new Map();
3990
4458
  for (const file of files) {
3991
- if (file.bytes === 0) {
3992
- warnings.push(`Zero-byte file will be attached if ChatGPT accepts it: ${file.name}`);
3993
- }
3994
4459
  const pathCount = (byPath.get(file.path) ?? 0) + 1;
3995
4460
  byPath.set(file.path, pathCount);
3996
4461
  if (pathCount === 2) {
@@ -4309,6 +4774,32 @@ async function setHiddenFileInput(page, files) {
4309
4774
  }
4310
4775
  await input.setInputFiles(files.map((file) => file.path));
4311
4776
  }
4777
+ async function readBrowserInputDiagnostic(page) {
4778
+ if (typeof page.evaluate !== "function") {
4779
+ return void 0;
4780
+ }
4781
+ return page.evaluate(() => {
4782
+ const input = document.querySelector("#upload-files") || document.querySelector("input[type='file']:not([accept='image/*'])") || document.querySelector("input[type='file']");
4783
+ if (!input) {
4784
+ return { files: [] };
4785
+ }
4786
+ return {
4787
+ files: Array.from(input.files ?? []).map((file) => {
4788
+ const diagnostic2 = {
4789
+ name: file.name,
4790
+ size: file.size
4791
+ };
4792
+ if (file.type.length > 0) {
4793
+ diagnostic2.type = file.type;
4794
+ }
4795
+ if (file.lastModified !== 0) {
4796
+ diagnostic2.lastModified = file.lastModified;
4797
+ }
4798
+ return diagnostic2;
4799
+ })
4800
+ };
4801
+ });
4802
+ }
4312
4803
  async function ensurePage2(env) {
4313
4804
  if (env.page !== void 0) {
4314
4805
  return resultOk({}, await contextFromPage(env.page));
@@ -4987,16 +5478,36 @@ import { access as access2, stat as stat4 } from "node:fs/promises";
4987
5478
  import { execFile } from "node:child_process";
4988
5479
  import { promisify } from "node:util";
4989
5480
  var execFileAsync = promisify(execFile);
5481
+ function clipboardReadCommandsForPlatform(platform, env = {}) {
5482
+ if (platform === "darwin") {
5483
+ return [{ command: "pbpaste", args: [] }];
5484
+ }
5485
+ if (platform === "win32") {
5486
+ return [{ command: "powershell.exe", args: ["-NoProfile", "-Command", "Get-Clipboard -Raw"] }];
5487
+ }
5488
+ if (platform === "linux") {
5489
+ const waylandCommand = { command: "wl-paste", args: ["--no-newline"] };
5490
+ const x11Commands = [
5491
+ { command: "xclip", args: ["-selection", "clipboard", "-o"] },
5492
+ { command: "xsel", args: ["--clipboard", "--output"] }
5493
+ ];
5494
+ const isWayland = typeof env.WAYLAND_DISPLAY === "string" && env.WAYLAND_DISPLAY.length > 0;
5495
+ return isWayland ? [waylandCommand, ...x11Commands] : [...x11Commands, waylandCommand];
5496
+ }
5497
+ return [];
5498
+ }
4990
5499
  async function readSystemClipboard() {
4991
- if (typeof process === "undefined" || process.platform !== "darwin") {
5500
+ if (typeof process === "undefined") {
4992
5501
  return void 0;
4993
5502
  }
4994
- try {
4995
- const { stdout } = await execFileAsync("pbpaste", [], { timeout: 2e3, maxBuffer: 10 * 1024 * 1024 });
4996
- return stdout;
4997
- } catch {
4998
- return void 0;
5503
+ for (const { command, args } of clipboardReadCommandsForPlatform(process.platform, process.env)) {
5504
+ try {
5505
+ const { stdout } = await execFileAsync(command, args, { timeout: 2e3, maxBuffer: 10 * 1024 * 1024 });
5506
+ return stdout;
5507
+ } catch {
5508
+ }
4999
5509
  }
5510
+ return void 0;
5000
5511
  }
5001
5512
  async function waitForClipboardChange(before, timeoutMs, pollMs = 150) {
5002
5513
  const started = Date.now();
@@ -5335,6 +5846,7 @@ var REQUIRED_LOCALE_KEYS = [
5335
5846
  "rateLimitBlocker"
5336
5847
  ];
5337
5848
  var REQUIRED_TOOL_IDS = ["web_search", "deep_research", "create_image"];
5849
+ var REQUIRED_MODE_OPTION_IDS = ["latest", "instant", "thinking", "extended", "medium", "high", "extraHigh", "pro"];
5338
5850
  async function doctor(env, args = {}) {
5339
5851
  const wanted = args.check ?? DEFAULT_CHECKS;
5340
5852
  const checks = {};
@@ -5534,19 +6046,23 @@ async function filePreflightCheck(env, args) {
5534
6046
  function localizationCheck(env) {
5535
6047
  const requiredKeysMissing = REQUIRED_LOCALE_KEYS.filter((key) => localeLabels[key].length === 0);
5536
6048
  const missingToolIds = REQUIRED_TOOL_IDS.filter((id2) => (localeLabels.tools[id2]?.length ?? 0) === 0);
6049
+ const missingModeOptionIds = REQUIRED_MODE_OPTION_IDS.filter((id2) => (localeLabels.modeOptions[id2]?.length ?? 0) === 0);
5537
6050
  const toolIds = Object.keys(localeLabels.tools);
5538
- const englishCanonicalPresent = localeLabels.composerTextbox[0] === "Chat with ChatGPT" && localeLabels.sendButton[0] === "Send prompt" && localeLabels.modeLabels.includes("Thinking") && localeLabels.tools.web_search?.[0] === "Web search";
5539
- const labelCandidateCount = REQUIRED_LOCALE_KEYS.reduce((total, key) => total + localeLabels[key].length, 0) + Object.values(localeLabels.tools).reduce((total, values) => total + values.length, 0);
6051
+ const modeOptionIds = Object.keys(localeLabels.modeOptions);
6052
+ 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";
6053
+ 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);
5540
6054
  const details = {
5541
6055
  englishCanonicalPresent,
5542
6056
  requiredKeysMissing,
5543
6057
  missingToolIds,
6058
+ missingModeOptionIds,
5544
6059
  toolIds,
6060
+ modeOptionIds,
5545
6061
  labelCandidateCount,
5546
6062
  pageAvailable: env.page !== void 0,
5547
6063
  runtimeSelectorCoverage: "registry_only_stage_2"
5548
6064
  };
5549
- if (englishCanonicalPresent && requiredKeysMissing.length === 0 && missingToolIds.length === 0) {
6065
+ if (englishCanonicalPresent && requiredKeysMissing.length === 0 && missingToolIds.length === 0 && missingModeOptionIds.length === 0) {
5550
6066
  return unknown("The locale registry is loaded; localized runtime selector coverage is registry-only in Stage 2 and not fully proven.", void 0, details);
5551
6067
  }
5552
6068
  return blocked(
@@ -5646,6 +6162,9 @@ function isNodeError2(error) {
5646
6162
  return error instanceof Error && "code" in error;
5647
6163
  }
5648
6164
 
6165
+ // src/commands/messages.ts
6166
+ import { createHash as createHash2 } from "node:crypto";
6167
+
5649
6168
  // src/dom/generation-state.ts
5650
6169
  var EMPTY_GENERATION_STATE = {
5651
6170
  active: false,
@@ -5737,6 +6256,121 @@ function generationStateFromText(text) {
5737
6256
  };
5738
6257
  }
5739
6258
 
6259
+ // src/dom/wait-snapshot.ts
6260
+ function waitTextMetadata(rawText) {
6261
+ const normalized = normalizeWhitespace(rawText ?? "");
6262
+ return {
6263
+ length: normalized.length,
6264
+ hash: fnv1a32Hex(normalized),
6265
+ transient: isTransientAssistantText(normalized)
6266
+ };
6267
+ }
6268
+ function fnv1a32Hex(text) {
6269
+ let hash = 2166136261;
6270
+ for (let index = 0; index < text.length; index += 1) {
6271
+ hash ^= text.charCodeAt(index);
6272
+ hash = Math.imul(hash, 16777619);
6273
+ }
6274
+ return (hash >>> 0).toString(16).padStart(8, "0");
6275
+ }
6276
+ async function readWaitDomSnapshot(page) {
6277
+ if (typeof page.evaluate !== "function") {
6278
+ return void 0;
6279
+ }
6280
+ return page.evaluate((args) => {
6281
+ const __combinedWaitSnapshot = true;
6282
+ void __combinedWaitSnapshot;
6283
+ const normalizeWs = (value) => value.replace(/\s+/g, " ").trim();
6284
+ const normalizeLower = (value) => (value ?? "").trim().toLowerCase();
6285
+ const nodes = Array.from(document.querySelectorAll("[data-message-author-role]"));
6286
+ const assistantNodes = nodes.filter((node) => node.getAttribute("data-message-author-role") === "assistant");
6287
+ const latestAssistant = assistantNodes.at(-1);
6288
+ const latestAssistantTurnIndex = latestAssistant === void 0 ? void 0 : nodes.indexOf(latestAssistant) + 1;
6289
+ const normalizedText = normalizeWs(latestAssistant?.innerText ?? latestAssistant?.textContent ?? "");
6290
+ let hash = 2166136261;
6291
+ for (let index = 0; index < normalizedText.length; index += 1) {
6292
+ hash ^= normalizedText.charCodeAt(index);
6293
+ hash = Math.imul(hash, 16777619);
6294
+ }
6295
+ const textHash = (hash >>> 0).toString(16).padStart(8, "0");
6296
+ const trimmedForTransient = normalizedText.replace(/[.。…]+$/g, "").trim().toLowerCase();
6297
+ const transient = args.transient.some((phrase) => trimmedForTransient === phrase.toLowerCase()) || /^analyzing (?:the )?images?$/.test(trimmedForTransient) || /^processing (?:the )?images?$/.test(trimmedForTransient) || /^reading (?:the )?images?$/.test(trimmedForTransient);
6298
+ const isVisible = (element) => {
6299
+ const style = window.getComputedStyle(element);
6300
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && element.getAttribute("aria-hidden") !== "true";
6301
+ };
6302
+ const visibleButtons = Array.from(document.querySelectorAll("button")).filter((button) => isVisible(button) && button.disabled !== true && button.getAttribute("aria-disabled") !== "true");
6303
+ const buttonTexts = visibleButtons.map((button) => [
6304
+ button.innerText,
6305
+ button.textContent,
6306
+ button.getAttribute("aria-label"),
6307
+ button.getAttribute("title")
6308
+ ].map(normalizeLower).filter(Boolean).join(" ")).filter(Boolean);
6309
+ const bodyText = normalizeLower(document.body?.innerText);
6310
+ const haystacks = [bodyText, ...buttonTexts];
6311
+ const matchingSignals = (phrases) => haystacks.flatMap(
6312
+ (text) => phrases.map((phrase) => phrase.toLowerCase()).filter((phrase) => text.includes(phrase))
6313
+ );
6314
+ const activeSignals = matchingSignals(args.stop);
6315
+ const stoppedSignals = matchingSignals(args.stopped);
6316
+ const generation = {
6317
+ active: activeSignals.length > 0,
6318
+ stopped: stoppedSignals.length > 0,
6319
+ signals: [.../* @__PURE__ */ new Set([...activeSignals, ...stoppedSignals, ...buttonTexts.filter((text) => /stop|cancel|stopped|answering|thinking/i.test(text))])].slice(0, 5)
6320
+ };
6321
+ const turns = Array.from(document.querySelectorAll("[data-testid^='conversation-turn']"));
6322
+ let hasResponseActions;
6323
+ if (turns.length === 0) {
6324
+ hasResponseActions = void 0;
6325
+ } else {
6326
+ const latestTurn = [...turns].reverse().find(
6327
+ (turn) => turn.querySelector("[data-message-author-role='assistant']") !== null
6328
+ );
6329
+ if (latestTurn === void 0) {
6330
+ hasResponseActions = false;
6331
+ } else {
6332
+ const actionText = Array.from(latestTurn.querySelectorAll("button")).map((button) => [
6333
+ button.innerText,
6334
+ button.textContent,
6335
+ button.getAttribute("aria-label"),
6336
+ button.getAttribute("title")
6337
+ ].filter(Boolean).join(" ")).join(" ").toLowerCase();
6338
+ hasResponseActions = args.actions.some((phrase) => actionText.includes(phrase.toLowerCase()));
6339
+ }
6340
+ }
6341
+ const snapshot = {
6342
+ turnCount: nodes.length,
6343
+ assistantTurnCount: assistantNodes.length,
6344
+ text: { length: normalizedText.length, hash: textHash, transient },
6345
+ generation
6346
+ };
6347
+ if (latestAssistantTurnIndex !== void 0) snapshot.latestAssistantTurnIndex = latestAssistantTurnIndex;
6348
+ if (hasResponseActions !== void 0) snapshot.hasResponseActions = hasResponseActions;
6349
+ return snapshot;
6350
+ }, {
6351
+ transient: [...localeLabels.transientAssistant],
6352
+ stop: [...localeLabels.stopControl],
6353
+ stopped: [...localeLabels.stoppedAssistant],
6354
+ actions: [...localeLabels.responseActions]
6355
+ });
6356
+ }
6357
+
6358
+ // src/commands/deadline.ts
6359
+ function createDeadline(timeoutMs, startedAtMs = Date.now()) {
6360
+ const safeTimeoutMs = Math.max(0, timeoutMs);
6361
+ return {
6362
+ startedAtMs,
6363
+ timeoutMs: safeTimeoutMs,
6364
+ expiresAtMs: startedAtMs + safeTimeoutMs
6365
+ };
6366
+ }
6367
+ function remainingMs(deadline, nowMs = Date.now()) {
6368
+ return Math.max(0, deadline.expiresAtMs - nowMs);
6369
+ }
6370
+ function childTimeoutMs(deadline, capMs, nowMs = Date.now()) {
6371
+ return Math.max(0, Math.min(Math.max(0, capMs), remainingMs(deadline, nowMs)));
6372
+ }
6373
+
5740
6374
  // src/commands/output.ts
5741
6375
  function commandOutputText(data) {
5742
6376
  if (!isRecord2(data)) return void 0;
@@ -5763,6 +6397,69 @@ function isRecord2(value) {
5763
6397
  return typeof value === "object" && value !== null && !Array.isArray(value);
5764
6398
  }
5765
6399
 
6400
+ // src/commands/probes.ts
6401
+ function createSingleFlightProbe(name, probe) {
6402
+ let inFlight;
6403
+ return async (arg, deadline, options) => {
6404
+ if (inFlight !== void 0) {
6405
+ return {
6406
+ ok: false,
6407
+ skipped: true,
6408
+ warnings: [`Skipped ${name} DOM probe because previous browser-side work is still in flight.`]
6409
+ };
6410
+ }
6411
+ const timeoutMs = childTimeoutMs(deadline, options.timeoutMs);
6412
+ if (timeoutMs <= 0) {
6413
+ return {
6414
+ ok: false,
6415
+ timedOut: true,
6416
+ warnings: [`Skipped ${name} DOM probe because no deadline budget remained.`]
6417
+ };
6418
+ }
6419
+ const current = probe(arg);
6420
+ inFlight = current;
6421
+ current.finally(() => {
6422
+ if (inFlight === current) {
6423
+ inFlight = void 0;
6424
+ }
6425
+ }).catch(() => void 0);
6426
+ let timeout;
6427
+ try {
6428
+ const value = await Promise.race([
6429
+ current,
6430
+ new Promise((_resolve, reject) => {
6431
+ timeout = setTimeout(() => reject(new ProbeTimeoutError(timeoutMs)), timeoutMs);
6432
+ })
6433
+ ]);
6434
+ return { ok: true, value, warnings: [] };
6435
+ } catch (error) {
6436
+ if (error instanceof ProbeTimeoutError) {
6437
+ return {
6438
+ ok: false,
6439
+ timedOut: true,
6440
+ warnings: [`Timed out waiting ${timeoutMs}ms for ${name} DOM probe; this stopped SDK waiting but did not cancel browser-side work.`]
6441
+ };
6442
+ }
6443
+ return {
6444
+ ok: false,
6445
+ warnings: [`${name} DOM probe failed: ${error instanceof Error ? error.message : String(error)}`]
6446
+ };
6447
+ } finally {
6448
+ if (timeout !== void 0) {
6449
+ clearTimeout(timeout);
6450
+ }
6451
+ }
6452
+ };
6453
+ }
6454
+ var ProbeTimeoutError = class extends Error {
6455
+ constructor(timeoutMs) {
6456
+ super(`Probe timed out after ${timeoutMs}ms.`);
6457
+ this.timeoutMs = timeoutMs;
6458
+ this.name = "ProbeTimeoutError";
6459
+ }
6460
+ timeoutMs;
6461
+ };
6462
+
5766
6463
  // src/commands/messages.ts
5767
6464
  function isResponseComplete(snapshot) {
5768
6465
  return snapshot.latestText.trim().length > 0 && !isTransientAssistantText(snapshot.latestText) && snapshot.textStableForMs >= snapshot.stableMs && !snapshot.generation.active && !snapshot.generation.stopped && snapshot.hasResponseActions;
@@ -5970,7 +6667,14 @@ async function readVisibleTextForSubmit(page) {
5970
6667
  if (typeof page.evaluate !== "function") {
5971
6668
  return void 0;
5972
6669
  }
5973
- return page.evaluate(() => document.body?.innerText ?? "");
6670
+ return page.evaluate(() => {
6671
+ const composerForm = document.querySelector("main form") ?? document.querySelector("form");
6672
+ const scopedText = composerForm?.innerText;
6673
+ if (scopedText !== void 0 && scopedText.trim().length > 0) {
6674
+ return scopedText;
6675
+ }
6676
+ return document.body?.innerText ?? "";
6677
+ });
5974
6678
  }
5975
6679
  async function sendTimeoutWarnings(page) {
5976
6680
  const state = await readSendButtonState(page).catch(() => void 0);
@@ -6000,78 +6704,109 @@ async function waitForMessage(env, args = {}) {
6000
6704
  const stableMs = args.stableMs ?? (args.mode === "deep_research" ? 1e4 : 2e3);
6001
6705
  const pollMs = args.pollMs ?? 750;
6002
6706
  const started = Date.now();
6003
- let lastTargetText = "";
6707
+ const deadline = createDeadline(timeoutMs, started);
6708
+ const probeTimeoutMs = Math.max(50, Math.min(1e3, Math.max(pollMs, Math.floor(timeoutMs / 4))));
6709
+ const waitWarnings = /* @__PURE__ */ new Set();
6710
+ const waitSnapshotProbe = createSingleFlightProbe("wait snapshot", readWaitDomSnapshot);
6711
+ const pageStateProbe = createSingleFlightProbe("page state", readPageState);
6712
+ const PAGE_STATE_POLL_STRIDE = 4;
6713
+ let pollIndex = 0;
6714
+ let lastTargetKey = "";
6004
6715
  let lastChangedAt = Date.now();
6716
+ let lastObservedTextLength = 0;
6005
6717
  let latestAssistantCount = await countPageMessages(page, "assistant").catch(() => 0);
6006
6718
  while (Date.now() - started < timeoutMs) {
6007
- const state = await readPageState(page).catch(() => void 0);
6008
- if (state?.blocker !== void 0 && state.blocker.kind !== "modal") {
6009
- return {
6010
- ok: false,
6011
- status: "blocked",
6012
- warnings: [],
6013
- blocker: state.blocker,
6014
- context: await contextFromPage(page)
6015
- };
6016
- }
6017
- const progress = await readAssistantProgressSnapshot(page).catch(() => fallbackAssistantProgressSnapshot(page, latestAssistantCount));
6018
- latestAssistantCount = progress.assistantTurnCount;
6019
- const targetReached = waitTargetReached(args, progress);
6020
- const latestText = targetReached ? normalizeWhitespace(progress.latestText ?? "") : "";
6021
- if (latestText !== lastTargetText) {
6022
- lastTargetText = latestText;
6719
+ const probeResult = await waitSnapshotProbe(page, deadline, { timeoutMs: probeTimeoutMs });
6720
+ addWarnings(waitWarnings, probeResult.warnings);
6721
+ const snapshot = await waitSnapshotFromProbeResult(page, probeResult, latestAssistantCount);
6722
+ latestAssistantCount = snapshot.assistantTurnCount;
6723
+ const targetReached = waitTargetReached(args, snapshot);
6724
+ const targetKey = targetReached && snapshot.text.length > 0 ? `${snapshot.text.length}:${snapshot.text.hash}` : "";
6725
+ if (targetKey !== lastTargetKey) {
6726
+ lastTargetKey = targetKey;
6023
6727
  lastChangedAt = Date.now();
6024
6728
  }
6025
- const snapshot = {
6026
- latestText,
6027
- stableMs,
6028
- textStableForMs: Date.now() - lastChangedAt,
6029
- generation: await readAssistantGenerationState(page),
6030
- hasResponseActions: await latestAssistantTurnHasResponseActions(page)
6031
- };
6032
- if (targetReached && snapshot.generation.stopped && latestText.length > 0) {
6729
+ if (targetReached && snapshot.text.length > 0) {
6730
+ lastObservedTextLength = snapshot.text.length;
6731
+ }
6732
+ if (pollIndex % PAGE_STATE_POLL_STRIDE === 0) {
6733
+ const state = await pageStateFromProbe(pageStateProbe(page, deadline, { timeoutMs: probeTimeoutMs }), waitWarnings);
6734
+ if (state?.blocker !== void 0 && state.blocker.kind !== "modal") {
6735
+ return {
6736
+ ok: false,
6737
+ status: "blocked",
6738
+ warnings: [...waitWarnings],
6739
+ blocker: state.blocker,
6740
+ context: await contextFromPage(page)
6741
+ };
6742
+ }
6743
+ }
6744
+ pollIndex += 1;
6745
+ const hasResponseActions = await resolveResponseActions(page, snapshot);
6746
+ if (targetReached && snapshot.generation.stopped && snapshot.text.length > 0) {
6747
+ const stoppedText = normalizeWhitespace(await fetchLatestAssistantText(page) ?? "");
6748
+ const data = stoppedText.length > 0 ? waitDataFromText(args, false, stoppedText, latestAssistantCount, Date.now() - started) : waitDataWithoutText(latestAssistantCount, Date.now() - started);
6749
+ if (stoppedText.length === 0) {
6750
+ 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.`);
6751
+ }
6033
6752
  return withCommandOutputText({
6034
6753
  ok: false,
6035
6754
  status: "partial",
6036
- data: {
6037
- complete: false,
6038
- responseText: latestText,
6039
- assistantTurnCount: latestAssistantCount,
6040
- elapsedMs: Date.now() - started
6041
- },
6755
+ data,
6042
6756
  warnings: [
6757
+ ...waitWarnings,
6758
+ ...stoppedText.length > 0 ? responseContentWarnings(args, false) : [],
6043
6759
  "ChatGPT generation appears to have been stopped or interrupted before completion.",
6044
6760
  ...snapshot.generation.signals.map((signal) => `Generation state signal: ${signal}`)
6045
6761
  ],
6046
6762
  context: await contextFromPage(page)
6047
6763
  });
6048
6764
  }
6049
- if (targetReached && isResponseComplete(snapshot)) {
6050
- return withCommandOutputText(resultOk(
6051
- { complete: true, responseText: latestText, assistantTurnCount: latestAssistantCount, elapsedMs: Date.now() - started },
6052
- await contextFromPage(page)
6053
- ));
6765
+ const metadataComplete = targetReached && snapshot.text.length > 0 && !snapshot.text.transient && Date.now() - lastChangedAt >= stableMs && !snapshot.generation.active && !snapshot.generation.stopped && hasResponseActions;
6766
+ if (metadataComplete) {
6767
+ const latestText = normalizeWhitespace(await fetchLatestAssistantText(page) ?? "");
6768
+ const fetchedMetadata = waitTextMetadata(latestText);
6769
+ const completionSnapshot = {
6770
+ latestText,
6771
+ stableMs,
6772
+ textStableForMs: Date.now() - lastChangedAt,
6773
+ generation: snapshot.generation,
6774
+ hasResponseActions
6775
+ };
6776
+ if (fetchedMetadata.hash === snapshot.text.hash && isResponseComplete(completionSnapshot)) {
6777
+ const data = waitDataFromText(args, true, latestText, latestAssistantCount, Date.now() - started);
6778
+ return withCommandOutputText(resultOk(
6779
+ data,
6780
+ await contextFromPage(page),
6781
+ [...waitWarnings, ...responseContentWarnings(args, true)]
6782
+ ));
6783
+ }
6784
+ if (latestText.length > 0) {
6785
+ lastTargetKey = `${fetchedMetadata.length}:${fetchedMetadata.hash}`;
6786
+ lastChangedAt = Date.now();
6787
+ lastObservedTextLength = fetchedMetadata.length;
6788
+ }
6054
6789
  }
6055
6790
  await sleep2(page, pollMs);
6056
6791
  }
6057
- if (lastTargetText.length > 0) {
6058
- return withCommandOutputText({
6059
- ok: false,
6060
- status: "partial",
6061
- data: {
6062
- complete: false,
6063
- responseText: lastTargetText,
6064
- assistantTurnCount: latestAssistantCount,
6065
- elapsedMs: Date.now() - started
6066
- },
6067
- warnings: ["Timed out after receiving partial assistant text."],
6068
- context: await contextFromPage(page)
6069
- });
6792
+ if (lastObservedTextLength > 0) {
6793
+ const partialText = await fetchLatestAssistantText(page);
6794
+ if (partialText !== void 0 && normalizeWhitespace(partialText).length > 0) {
6795
+ const data = waitDataFromText(args, false, normalizeWhitespace(partialText), latestAssistantCount, Date.now() - started);
6796
+ return withCommandOutputText({
6797
+ ok: false,
6798
+ status: "partial",
6799
+ data,
6800
+ warnings: [...waitWarnings, ...responseContentWarnings(args, false), "Timed out after receiving partial assistant text."],
6801
+ context: await contextFromPage(page)
6802
+ });
6803
+ }
6804
+ waitWarnings.add(`Partial assistant text (${lastObservedTextLength} chars) was observed during polling but could not be re-read at wait exit.`);
6070
6805
  }
6071
6806
  return {
6072
6807
  ok: false,
6073
6808
  status: "timeout",
6074
- warnings: [],
6809
+ warnings: [...waitWarnings],
6075
6810
  error: {
6076
6811
  name: "WaitTimeout",
6077
6812
  message: "No assistant response appeared before the timeout.",
@@ -6080,6 +6815,94 @@ async function waitForMessage(env, args = {}) {
6080
6815
  context: await contextFromPage(page)
6081
6816
  };
6082
6817
  }
6818
+ async function fetchLatestAssistantText(page) {
6819
+ const first = await readLatestMessageText(page, "assistant").catch(() => void 0);
6820
+ if (first !== void 0) {
6821
+ return first;
6822
+ }
6823
+ await sleep2(page, 150);
6824
+ return readLatestMessageText(page, "assistant").catch(() => void 0);
6825
+ }
6826
+ function waitDataWithoutText(assistantTurnCount, elapsedMs) {
6827
+ return { complete: false, assistantTurnCount, elapsedMs };
6828
+ }
6829
+ async function resolveResponseActions(page, snapshot) {
6830
+ if (snapshot.hasResponseActions !== void 0) {
6831
+ return snapshot.hasResponseActions;
6832
+ }
6833
+ try {
6834
+ const copyButtons = copyResponseButtons(page);
6835
+ const count = await copyButtons.count?.();
6836
+ if (count !== void 0) {
6837
+ return count > 0;
6838
+ }
6839
+ return await copyButtons.isVisible?.() === true;
6840
+ } catch {
6841
+ return false;
6842
+ }
6843
+ }
6844
+ async function waitSnapshotFromProbeResult(page, result, previousAssistantTurnCount) {
6845
+ if (result.ok && result.value !== void 0) {
6846
+ return result.value;
6847
+ }
6848
+ if (!result.ok && (result.timedOut === true || result.skipped === true)) {
6849
+ return {
6850
+ turnCount: 0,
6851
+ assistantTurnCount: previousAssistantTurnCount,
6852
+ text: waitTextMetadata(""),
6853
+ generation: EMPTY_GENERATION_STATE,
6854
+ hasResponseActions: false
6855
+ };
6856
+ }
6857
+ return fallbackWaitSnapshot(page, previousAssistantTurnCount);
6858
+ }
6859
+ async function fallbackWaitSnapshot(page, previousAssistantTurnCount) {
6860
+ const progress = await fallbackAssistantProgressSnapshot(page, previousAssistantTurnCount);
6861
+ const generation = await readAssistantGenerationState(page).catch(() => EMPTY_GENERATION_STATE);
6862
+ const hasResponseActions = await latestAssistantTurnHasResponseActions(page).catch(() => false);
6863
+ const snapshot = {
6864
+ turnCount: progress.turnCount ?? 0,
6865
+ assistantTurnCount: progress.assistantTurnCount,
6866
+ text: waitTextMetadata(progress.latestText),
6867
+ generation,
6868
+ hasResponseActions
6869
+ };
6870
+ if (progress.latestAssistantTurnIndex !== void 0) {
6871
+ snapshot.latestAssistantTurnIndex = progress.latestAssistantTurnIndex;
6872
+ }
6873
+ return snapshot;
6874
+ }
6875
+ function waitDataFromText(args, complete, responseText, assistantTurnCount, elapsedMs) {
6876
+ const data = {
6877
+ complete,
6878
+ assistantTurnCount,
6879
+ elapsedMs
6880
+ };
6881
+ if (args.responseContent === "metadata") {
6882
+ data.responseContent = "metadata";
6883
+ data.responseChars = responseText.length;
6884
+ data.responseSha256 = createHash2("sha256").update(responseText).digest("hex");
6885
+ return data;
6886
+ }
6887
+ data.responseText = responseText;
6888
+ return data;
6889
+ }
6890
+ function responseContentWarnings(args, complete) {
6891
+ if (args.responseContent !== "metadata") return [];
6892
+ return [
6893
+ 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."
6894
+ ];
6895
+ }
6896
+ async function pageStateFromProbe(probe, warnings) {
6897
+ const result = await probe;
6898
+ addWarnings(warnings, result.warnings);
6899
+ return result.ok ? result.value : void 0;
6900
+ }
6901
+ function addWarnings(target, warnings) {
6902
+ for (const warning of warnings) {
6903
+ target.add(warning);
6904
+ }
6905
+ }
6083
6906
  async function readLatest(env, args = {}) {
6084
6907
  const boot = await ensurePage3(env);
6085
6908
  if (!boot.ok) {
@@ -6322,25 +7145,6 @@ ${language}
6322
7145
  ${language}
6323
7146
  ` : "\n").replace(/`([^`]+)`/g, "$1").replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/__([^_]+)__/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/_([^_]+)_/g, "$1");
6324
7147
  }
6325
- async function readAssistantProgressSnapshot(page) {
6326
- if (typeof page.evaluate === "function") {
6327
- return page.evaluate(() => {
6328
- const nodes = Array.from(document.querySelectorAll("[data-message-author-role]"));
6329
- const assistantNodes = nodes.filter((node) => node.getAttribute("data-message-author-role") === "assistant");
6330
- const latestAssistant = assistantNodes.at(-1);
6331
- const latestAssistantTurnIndex = latestAssistant === void 0 ? void 0 : nodes.indexOf(latestAssistant) + 1;
6332
- const snapshot = {
6333
- turnCount: nodes.length,
6334
- assistantTurnCount: assistantNodes.length
6335
- };
6336
- const latestText = latestAssistant?.innerText ?? latestAssistant?.textContent ?? void 0;
6337
- if (latestText !== void 0) snapshot.latestText = latestText;
6338
- if (latestAssistantTurnIndex !== void 0) snapshot.latestAssistantTurnIndex = latestAssistantTurnIndex;
6339
- return snapshot;
6340
- });
6341
- }
6342
- return fallbackAssistantProgressSnapshot(page, 0);
6343
- }
6344
7148
  async function fallbackAssistantProgressSnapshot(page, previousAssistantTurnCount) {
6345
7149
  const messages = await readMessages(page, { format: "normalized_text" }).catch(() => void 0);
6346
7150
  if (messages !== void 0) {
@@ -6438,6 +7242,31 @@ function forwardFailure(result) {
6438
7242
  return forwarded;
6439
7243
  }
6440
7244
 
7245
+ // src/dom/label-match.ts
7246
+ function normalizeForLabelMatch(text) {
7247
+ return normalizeWhitespace(text.normalize("NFKC")).toLocaleLowerCase();
7248
+ }
7249
+ function visibleLabelMatches(label, wanted) {
7250
+ const normalizedLabel = normalizeForLabelMatch(label);
7251
+ const normalizedWanted = normalizeForLabelMatch(wanted);
7252
+ if (normalizedWanted.length === 0) {
7253
+ return false;
7254
+ }
7255
+ if (normalizedLabel === normalizedWanted) {
7256
+ return true;
7257
+ }
7258
+ if (isShortLatinToken(normalizedWanted)) {
7259
+ return new RegExp(`(^|[^\\p{L}\\p{N}])${escapeRegExp2(normalizedWanted)}([^\\p{L}\\p{N}]|$)`, "iu").test(normalizedLabel);
7260
+ }
7261
+ return normalizedLabel.includes(normalizedWanted);
7262
+ }
7263
+ function isShortLatinToken(value) {
7264
+ return value.length <= 3 && /^[a-z0-9]+$/i.test(value);
7265
+ }
7266
+ function escapeRegExp2(value) {
7267
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7268
+ }
7269
+
6441
7270
  // src/dom/menus.ts
6442
7271
  function extractMenuItemsFromText(text) {
6443
7272
  return text.split(/\n| {2,}| • /).map((label) => normalizeWhitespace(label)).filter(Boolean).map((label) => ({ label, normalized: normalizeLabel(label) }));
@@ -6464,7 +7293,10 @@ async function enumerateVisibleMenuItems(page) {
6464
7293
  if (ariaLabel !== null) item.ariaLabel = ariaLabel;
6465
7294
  return item;
6466
7295
  };
6467
- const roleItems = Array.from(document.querySelectorAll("[role='menuitem'], [role='menuitemradio'], [role='option']")).map(toItem).filter((item) => item.label.length > 0);
7296
+ const allRoleNodes = Array.from(document.querySelectorAll("[role='menuitem'], [role='menuitemradio'], [role='option']"));
7297
+ const containers = Array.from(document.querySelectorAll("[role='menu'], [role='listbox'], [data-radix-popper-content-wrapper]")).filter((container) => typeof container.contains === "function");
7298
+ const scopedRoleNodes = containers.length > 0 ? allRoleNodes.filter((node) => containers.some((container) => container.contains(node))) : allRoleNodes;
7299
+ const roleItems = (scopedRoleNodes.length > 0 ? scopedRoleNodes : allRoleNodes).map(toItem).filter((item) => item.label.length > 0);
6468
7300
  if (roleItems.length > 0) {
6469
7301
  return { items: roleItems, labels: [], split: false };
6470
7302
  }
@@ -6481,13 +7313,16 @@ function findUniqueMenuItem(items, wanted) {
6481
7313
  if (exact.length === 1) {
6482
7314
  return exact[0];
6483
7315
  }
6484
- const fuzzy = items.filter((item) => item.normalized.includes(normalized));
7316
+ const fuzzy = items.filter((item) => visibleLabelMatches(item.label, wanted));
6485
7317
  return fuzzy.length === 1 ? fuzzy[0] : void 0;
6486
7318
  }
6487
7319
 
6488
7320
  // src/commands/modes.ts
6489
7321
  var DEFAULT_MODE_EFFORT = "Thinking";
6490
- var CURRENT_MODE_LABELS = [...localeLabels.modeLabels];
7322
+ var CURRENT_MODE_LABELS = dedupeLabels([
7323
+ ...localeLabels.modeLabels,
7324
+ ...Object.values(localeLabels.modeOptions).flat()
7325
+ ]);
6491
7326
  var MODE_OPENER_LABELS = [...CURRENT_MODE_LABELS.filter((label) => label !== "Pro"), ...localeLabels.modeOpenerExtra];
6492
7327
  var MODEL_VERSION_FAMILY_PATTERN = /^gpt[\s-]/i;
6493
7328
  var MODEL_VERSION_LABEL_PATTERN = /^(?:o\d+|\d+(?:\.\d+)?)$/i;
@@ -6495,9 +7330,31 @@ var CANONICAL_INTELLIGENCE_ORDER = /* @__PURE__ */ new Map([
6495
7330
  ["instant", 0],
6496
7331
  ["medium", 1],
6497
7332
  ["high", 2],
6498
- ["extra high", 3],
7333
+ ["extraHigh", 3],
6499
7334
  ["pro", 4]
6500
7335
  ]);
7336
+ var MODE_OPTION_IDS2 = [
7337
+ "latest",
7338
+ "instant",
7339
+ "thinking",
7340
+ "extended",
7341
+ "medium",
7342
+ "high",
7343
+ "extraHigh",
7344
+ "pro"
7345
+ ];
7346
+ var MODE_ID_ALIASES = {
7347
+ latest: ["latest"],
7348
+ instant: ["instant"],
7349
+ thinking: ["thinking"],
7350
+ extended: ["extended"],
7351
+ medium: ["medium"],
7352
+ high: ["high"],
7353
+ extraHigh: ["extra high", "extra-high", "extra_high", "extrahigh"],
7354
+ pro: ["pro"]
7355
+ };
7356
+ var THREAD_ACTION_MENU_LABELS = new Set(localeLabels.threadActionMenuItems.map(normalizeForLabelMatch));
7357
+ var THREAD_ACTION_PREFIXES = localeLabels.threadActionPrefixes.map(normalizeForLabelMatch).filter((prefix) => prefix.length > 0);
6501
7358
  async function setMode(env, args) {
6502
7359
  const boot = await ensurePage4(env);
6503
7360
  if (!boot.ok) {
@@ -6505,9 +7362,9 @@ async function setMode(env, args) {
6505
7362
  }
6506
7363
  const page = env.page;
6507
7364
  try {
6508
- const requested = requestedModeLabels(args);
7365
+ const requested = requestedModeSelections(args);
6509
7366
  const requestedVersion = requestedModelVersion(args);
6510
- const requestedForOpening = requestedVersion === void 0 ? requested : [...requested, requestedVersion];
7367
+ const requestedForOpening = requestedVersion === void 0 ? requested : [...requested, requestedModeSelection(requestedVersion)];
6511
7368
  const opened = await waitForModeMenu(page, requestedForOpening, args.timeoutMs ?? 3e4);
6512
7369
  if (requestedVersion === void 0 && opened.alreadySelected.length === requested.length) {
6513
7370
  return resultOk({ selected: opened.alreadySelected, candidates: opened.modeButtons }, await contextFromPage(page));
@@ -6518,15 +7375,25 @@ async function setMode(env, args) {
6518
7375
  await page.waitForTimeout?.(250);
6519
7376
  const candidates = await enumerateVisibleMenuItems(page);
6520
7377
  const selected = [];
6521
- for (const item of requested) {
6522
- const match = findModeMenuItem(candidates, item);
7378
+ if (requested.length > 0 && shouldRejectAsWrongModeMenu(candidates)) {
7379
+ const candidateLabels2 = candidates.map((candidate) => candidate.label);
7380
+ return {
7381
+ ok: false,
7382
+ status: "unsupported",
7383
+ warnings: [],
7384
+ blocker: selectorDriftBlocker("Visible menu appears to be a thread/action menu, not the ChatGPT mode menu.", candidateLabels2),
7385
+ context: await contextFromPage(page)
7386
+ };
7387
+ }
7388
+ for (const request of requested) {
7389
+ const match = findModeMenuItem(candidates, request);
6523
7390
  if (match === void 0) {
6524
7391
  const candidateLabels2 = candidates.map((candidate) => candidate.label);
6525
7392
  return {
6526
7393
  ok: false,
6527
7394
  status: "unsupported",
6528
7395
  warnings: [],
6529
- blocker: selectorDriftBlocker(`Mode option "${item}" was not found or was ambiguous.`, candidateLabels2),
7396
+ blocker: selectorDriftBlocker(`Mode option "${request.requested}" was not found or was ambiguous.`, candidateLabels2),
6530
7397
  context: await contextFromPage(page)
6531
7398
  };
6532
7399
  }
@@ -6550,7 +7417,42 @@ async function setMode(env, args) {
6550
7417
  }
6551
7418
  selected.push(versionResult.selected);
6552
7419
  }
6553
- return resultOk({ selected, candidates: candidateLabels }, await contextFromPage(page));
7420
+ const verificationWarnings = await modeVerificationWarnings(page, requested, selected);
7421
+ return resultOk({ selected, candidates: candidateLabels }, await contextFromPage(page), verificationWarnings);
7422
+ } catch (error) {
7423
+ return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
7424
+ }
7425
+ }
7426
+ async function modeVerificationWarnings(page, requested, selected) {
7427
+ if (requested.length === 0) {
7428
+ return [];
7429
+ }
7430
+ await page.waitForTimeout?.(250);
7431
+ const visibleButtons = await visibleModeButtonLabelList(page);
7432
+ if (visibleButtons.length === 0) {
7433
+ return [
7434
+ `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.`
7435
+ ];
7436
+ }
7437
+ const unverified = requested.filter((request) => findUniqueVisibleLabelForRequest(visibleButtons, request) === void 0);
7438
+ if (unverified.length === 0) {
7439
+ return [];
7440
+ }
7441
+ return [
7442
+ `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.`
7443
+ ];
7444
+ }
7445
+ async function getMode(env, args = {}) {
7446
+ void args;
7447
+ const boot = await ensurePage4(env);
7448
+ if (!boot.ok) {
7449
+ return boot;
7450
+ }
7451
+ const page = env.page;
7452
+ try {
7453
+ const modes = await visibleModeButtonLabelList(page);
7454
+ const warnings = modes.length === 0 ? ["No mode-labelled composer control is currently visible, so the active ChatGPT mode could not be read."] : [];
7455
+ return resultOk({ modes }, await contextFromPage(page), warnings);
6554
7456
  } catch (error) {
6555
7457
  return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
6556
7458
  }
@@ -6565,7 +7467,7 @@ async function waitForModeMenu(page, requested, timeoutMs) {
6565
7467
  return { opened: false, alreadySelected, modeButtons };
6566
7468
  }
6567
7469
  const openMenuItems = await enumerateVisibleMenuItems(page);
6568
- if (looksLikeModeMenu(openMenuItems.map((item) => item.label))) {
7470
+ if (looksLikeModeMenu(openMenuItems)) {
6569
7471
  return { opened: true, alreadySelected: [], modeButtons };
6570
7472
  }
6571
7473
  if (await clickModeOpener(page, modeButtons)) {
@@ -6645,12 +7547,47 @@ async function clickModeOpener(page, modeButtons) {
6645
7547
  }
6646
7548
  return clickFirstUniqueButton(page, MODE_OPENER_LABELS);
6647
7549
  }
6648
- function looksLikeModeMenu(labels) {
6649
- return labels.some((label) => {
6650
- const normalized = normalizeLabel(label);
6651
- return CURRENT_MODE_LABELS.some((modeLabel) => visibleLabelMatches(normalized, normalizeLabel(modeLabel)));
7550
+ function isThreadActionLabel(label) {
7551
+ const normalized = normalizeForLabelMatch(label);
7552
+ if (THREAD_ACTION_MENU_LABELS.has(normalized)) {
7553
+ return true;
7554
+ }
7555
+ return THREAD_ACTION_PREFIXES.some((prefix) => normalized.startsWith(`${prefix} `));
7556
+ }
7557
+ function hasStructuralModeEvidence(item) {
7558
+ if (item.testId?.startsWith("model-switcher-") === true) {
7559
+ return true;
7560
+ }
7561
+ return MODEL_VERSION_FAMILY_PATTERN.test(item.label) || MODEL_VERSION_LABEL_PATTERN.test(item.label);
7562
+ }
7563
+ function isModeMenuEvidence(item) {
7564
+ if (hasStructuralModeEvidence(item)) {
7565
+ return true;
7566
+ }
7567
+ if (isThreadActionLabel(item.label)) {
7568
+ return false;
7569
+ }
7570
+ const normalized = normalizeForLabelMatch(item.label);
7571
+ return CURRENT_MODE_LABELS.some((modeLabel) => {
7572
+ const normalizedMode = normalizeForLabelMatch(modeLabel);
7573
+ if (normalized === normalizedMode) {
7574
+ return true;
7575
+ }
7576
+ return !isShortLatinToken(normalizedMode) && visibleLabelMatches(normalized, normalizedMode);
6652
7577
  });
6653
7578
  }
7579
+ function looksLikeModeMenu(items) {
7580
+ return items.some((item) => isModeMenuEvidence(item));
7581
+ }
7582
+ function shouldRejectAsWrongModeMenu(items) {
7583
+ if (items.length === 0) {
7584
+ return false;
7585
+ }
7586
+ if (items.some((item) => isModeMenuEvidence(item))) {
7587
+ return false;
7588
+ }
7589
+ return items.some((item) => isThreadActionLabel(item.label));
7590
+ }
6654
7591
  async function clickMenuItem(page, label) {
6655
7592
  if (await clickModelSwitcherMenuItem(page, label)) {
6656
7593
  return true;
@@ -6737,26 +7674,72 @@ function toolLabels(tool) {
6737
7674
  const known = localeLabels.tools[tool];
6738
7675
  return known !== void 0 ? [...known] : [tool];
6739
7676
  }
6740
- function findModeMenuItem(candidates, wanted) {
6741
- const exact = findUniqueMenuItem(candidates, wanted);
6742
- if (exact !== void 0) {
6743
- return exact;
7677
+ function findModeMenuItem(candidates, request) {
7678
+ const selectable = candidates.filter((candidate) => !isThreadActionLabel(candidate.label));
7679
+ for (const wanted of request.labels) {
7680
+ const match = findUniqueModeMenuItem(selectable, wanted);
7681
+ if (match !== void 0) {
7682
+ return match;
7683
+ }
6744
7684
  }
6745
- const wantedIndex = CANONICAL_INTELLIGENCE_ORDER.get(normalizeLabel(wanted));
7685
+ const wantedIndex = request.modeId === void 0 ? void 0 : CANONICAL_INTELLIGENCE_ORDER.get(request.modeId);
6746
7686
  if (wantedIndex === void 0) {
6747
7687
  return void 0;
6748
7688
  }
6749
- const intelligenceItems = candidates.filter(
7689
+ const intelligenceItems = selectable.filter(
6750
7690
  (candidate) => candidate.role === "menuitemradio" && !MODEL_VERSION_LABEL_PATTERN.test(candidate.label) && !MODEL_VERSION_FAMILY_PATTERN.test(candidate.label)
6751
7691
  );
6752
7692
  return intelligenceItems.length >= CANONICAL_INTELLIGENCE_ORDER.size ? intelligenceItems[wantedIndex] : void 0;
6753
7693
  }
6754
- function requestedModeLabels(args) {
7694
+ function findUniqueModeMenuItem(items, wanted) {
7695
+ const normalizedWanted = normalizeForLabelMatch(wanted);
7696
+ const exact = items.filter((item) => normalizeForLabelMatch(item.label) === normalizedWanted);
7697
+ if (exact.length === 1) {
7698
+ return exact[0];
7699
+ }
7700
+ const fuzzy = items.filter((item) => visibleLabelMatches(item.label, wanted));
7701
+ if (fuzzy.length !== 1) {
7702
+ return void 0;
7703
+ }
7704
+ const match = fuzzy[0];
7705
+ if (!isShortLatinToken(normalizedWanted)) {
7706
+ return match;
7707
+ }
7708
+ return hasStructuralModeEvidence(match) || match.role === "menuitemradio" ? match : void 0;
7709
+ }
7710
+ function requestedModeSelections(args) {
6755
7711
  const requested = [args.model, args.intelligence, args.effort].filter((value) => value !== void 0);
6756
7712
  if (requestedModelVersion(args) !== void 0 && requested.length === 0) {
6757
7713
  return [];
6758
7714
  }
6759
- return requested.length > 0 ? requested : [DEFAULT_MODE_EFFORT];
7715
+ return (requested.length > 0 ? requested : [DEFAULT_MODE_EFFORT]).map(requestedModeSelection);
7716
+ }
7717
+ function requestedModeSelection(requested) {
7718
+ const modeId = modeOptionIdFor(requested);
7719
+ const labels = modeId === void 0 ? [requested] : localeLabels.modeOptions[modeId];
7720
+ const request = {
7721
+ requested,
7722
+ labels: labels.length > 0 ? [...labels] : [requested]
7723
+ };
7724
+ if (modeId !== void 0) {
7725
+ request.modeId = modeId;
7726
+ }
7727
+ return request;
7728
+ }
7729
+ function modeOptionIdFor(value) {
7730
+ const normalized = normalizeModeLookupKey(value);
7731
+ for (const id2 of MODE_OPTION_IDS2) {
7732
+ if (MODE_ID_ALIASES[id2].some((alias) => normalizeModeLookupKey(alias) === normalized)) {
7733
+ return id2;
7734
+ }
7735
+ if (localeLabels.modeOptions[id2].some((label) => normalizeModeLookupKey(label) === normalized)) {
7736
+ return id2;
7737
+ }
7738
+ }
7739
+ return void 0;
7740
+ }
7741
+ function normalizeModeLookupKey(value) {
7742
+ return normalizeForLabelMatch(value).replace(/[_-]+/g, " ");
6760
7743
  }
6761
7744
  function requestedModelVersion(args) {
6762
7745
  return args.modelVersion ?? args.version;
@@ -6770,25 +7753,25 @@ function findUniqueVisibleLabel(labels, wanted) {
6770
7753
  const fuzzy = labels.filter((label) => visibleLabelMatches(normalizeLabel(label), normalized));
6771
7754
  return fuzzy.length === 1 ? fuzzy[0] : void 0;
6772
7755
  }
6773
- function visibleLabelMatches(label, wanted) {
6774
- if (wanted.length <= 3) {
6775
- return new RegExp(`(^|[^a-z0-9])${escapeRegExp2(wanted)}([^a-z0-9]|$)`, "i").test(label);
6776
- }
6777
- return label.includes(wanted);
6778
- }
6779
- function escapeRegExp2(value) {
6780
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6781
- }
6782
7756
  function escapeAttributeValue(value) {
6783
7757
  return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
6784
7758
  }
6785
7759
  function findAlreadySelectedModes(visibleButtons, requested) {
6786
- return requested.map((label) => findUniqueVisibleLabel(visibleButtons, label)).filter((label) => label !== void 0);
7760
+ return requested.map((request) => findUniqueVisibleLabelForRequest(visibleButtons, request)).filter((label) => label !== void 0);
7761
+ }
7762
+ function findUniqueVisibleLabelForRequest(labels, request) {
7763
+ for (const label of request.labels) {
7764
+ const found = findUniqueVisibleLabel(labels, label);
7765
+ if (found !== void 0) {
7766
+ return found;
7767
+ }
7768
+ }
7769
+ return void 0;
6787
7770
  }
6788
7771
  async function selectModelVersion(page, requestedVersion, currentCandidates, timeoutMs) {
6789
7772
  let candidates = await enumerateVisibleMenuItems(page);
6790
- if (!looksLikeModeMenu(candidates.map((candidate) => candidate.label))) {
6791
- const opened2 = await waitForModeMenu(page, [requestedVersion], timeoutMs);
7773
+ if (!looksLikeModeMenu(candidates)) {
7774
+ const opened2 = await waitForModeMenu(page, [{ requested: requestedVersion, labels: [requestedVersion] }], timeoutMs);
6792
7775
  if (opened2.opened) {
6793
7776
  await page.waitForTimeout?.(250);
6794
7777
  candidates = await enumerateVisibleMenuItems(page);
@@ -7023,7 +8006,7 @@ function isSafeControlStringKey(key) {
7023
8006
  }
7024
8007
 
7025
8008
  // src/safety/untrusted-output.ts
7026
- import { createHash, randomUUID } from "node:crypto";
8009
+ import { createHash as createHash3, randomUUID } from "node:crypto";
7027
8010
  import { createReadStream } from "node:fs";
7028
8011
  import { link, mkdir as mkdir3, readFile as readFile2, stat as stat5, unlink, writeFile as writeFile2 } from "node:fs/promises";
7029
8012
  import { dirname } from "node:path";
@@ -7096,10 +8079,10 @@ function normalizePromptForIntegrity(prompt) {
7096
8079
  return prompt.replace(/\r\n?/g, "\n").split("\n").map((line) => line.replace(/[ \t]+$/g, "")).filter((line) => line.trim().length > 0).join("\n");
7097
8080
  }
7098
8081
  function sha256Text(text) {
7099
- return createHash("sha256").update(text).digest("hex");
8082
+ return createHash3("sha256").update(text).digest("hex");
7100
8083
  }
7101
8084
  async function sha256File(path3) {
7102
- const hash = createHash("sha256");
8085
+ const hash = createHash3("sha256");
7103
8086
  let bytes = 0;
7104
8087
  await new Promise((resolve3, reject) => {
7105
8088
  const stream = createReadStream(path3);
@@ -7216,7 +8199,7 @@ async function createRunReport(env, result, options = {}) {
7216
8199
  }, options);
7217
8200
  const report2 = {
7218
8201
  schemaVersion: 1,
7219
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
8202
+ createdAt,
7220
8203
  includeContent,
7221
8204
  summary,
7222
8205
  steps: result.steps?.map((step) => ({
@@ -7470,6 +8453,7 @@ var commandRisk = {
7470
8453
  "projects.sources.add": "medium",
7471
8454
  "response.copy": "medium",
7472
8455
  "modes.set": "medium",
8456
+ "modes.get": "low",
7473
8457
  "tools.select": "medium",
7474
8458
  "threads.delete": "high",
7475
8459
  "threads.archive": "high",
@@ -7566,6 +8550,7 @@ var descriptors = [
7566
8550
  primitive("projects.sources.add", "Append explicit local files to a visible ChatGPT Project Sources list after confirmMutation: true.", 18e4),
7567
8551
  primitive("response.copy", "Click Copy response and return clipboard Markdown, with DOM fallback.", 5e3),
7568
8552
  primitive("modes.set", "Select a visible model, intelligence, effort, or nested model-version candidate when unambiguous.", 3e4),
8553
+ primitive("modes.get", "Read the mode labels shown on the visible composer controls without changing them.", 3e4),
7569
8554
  primitive("tools.select", "Select a visible ChatGPT tool when unambiguous.", 3e4)
7570
8555
  ];
7571
8556
  function commandDescriptors() {
@@ -7702,13 +8687,30 @@ function reportArgs(name) {
7702
8687
  return { result: "CommandResult to persist", destDir: "optional report directory" };
7703
8688
  }
7704
8689
  function primitiveArgs(name) {
8690
+ if (name === "messages.wait") return {
8691
+ timeoutMs: "optional wait timeout",
8692
+ stableMs: "optional stability window before completion",
8693
+ pollMs: "optional polling interval",
8694
+ mode: "normal or deep_research",
8695
+ responseContent: "include for current behavior, metadata to omit assistant text and return chars/hash only"
8696
+ };
7705
8697
  if (name === "messages.readLatest") return { role: "assistant or user", format: "markdown, normalized_text, visible_text, html, blocks, or all" };
7706
8698
  if (name === "artifacts.listLatest") return { kind: "artifact kind; currently image", max: "maximum artifacts to return" };
7707
8699
  if (name === "artifacts.wait") return { kind: "artifact kind; currently image", afterArtifactCount: "baseline artifact count", requireDownload: "wait until a download affordance is visible" };
7708
8700
  if (name === "artifacts.downloadLatest") return { destDir: "download destination directory", prefer: "download_control or visible_image_source" };
7709
8701
  if (name === "response.copy") return { prefer: "clipboard or dom", format: "markdown, normalized_text, visible_text, html, blocks, or all" };
7710
8702
  if (name.startsWith("threads.search")) return { query: "history search query" };
7711
- if (name === "files.preflight") return { paths: "absolute local file paths", maxBytesPerFile: "optional local per-file byte limit", maxTotalBytes: "optional local total byte limit" };
8703
+ if (name === "files.preflight") return {
8704
+ paths: "absolute local file paths",
8705
+ maxBytesPerFile: "optional local per-file byte limit",
8706
+ maxTotalBytes: "optional local total byte limit",
8707
+ includeHashes: "optional SHA-256 metadata for diagnostics; file contents are not returned"
8708
+ };
8709
+ if (name === "files.attach") return {
8710
+ paths: "absolute local file paths",
8711
+ includeDiagnostics: "optional preflight and browser input file-size metadata",
8712
+ includeHashes: "optional SHA-256 metadata inside diagnostics; file contents are not returned"
8713
+ };
7712
8714
  if (name.startsWith("files.attach")) return { paths: "absolute local file paths" };
7713
8715
  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" };
7714
8716
  if (name === "projects.sources.planAdd") return { projectUrl: "ChatGPT Project URL", files: "explicit absolute local file paths", batchSize: "optional upload batch size" };
@@ -7723,6 +8725,11 @@ function primitiveArgs(name) {
7723
8725
  timeoutMs: "optional timeout for opening and selecting the visible mode menu"
7724
8726
  };
7725
8727
  }
8728
+ if (name === "modes.get") {
8729
+ return {
8730
+ timeoutMs: "optional timeout for attaching to the ChatGPT page"
8731
+ };
8732
+ }
7726
8733
  return {};
7727
8734
  }
7728
8735
  function primitiveExamples(name) {
@@ -7734,9 +8741,16 @@ function primitiveExamples(name) {
7734
8741
  `await chatgpt.askWithFiles({ mode: { model: "Pro" }, files: ["/absolute/host/path.jpg"], prompt: "Describe this image.", wait: true });`
7735
8742
  ];
7736
8743
  }
8744
+ if (name === "modes.get") {
8745
+ return [
8746
+ `await chatgpt.modes.get();`,
8747
+ `// Verify an expensive Pro consult before submitting: const current = await chatgpt.modes.get();`
8748
+ ];
8749
+ }
7737
8750
  if (name === "files.preflight") {
7738
8751
  return [
7739
- `await chatgpt.files.preflight({ paths: ["/absolute/host/path.md"] });`
8752
+ `await chatgpt.files.preflight({ paths: ["/absolute/host/path.md"] });`,
8753
+ `await chatgpt.files.preflight({ paths: ["/absolute/host/path.md"], includeHashes: true });`
7740
8754
  ];
7741
8755
  }
7742
8756
  if (name === "files.attach") {
@@ -7788,8 +8802,51 @@ function cloneDescriptor(descriptor) {
7788
8802
  };
7789
8803
  }
7790
8804
 
7791
- // src/commands/threads.ts
8805
+ // src/commands/conversation.ts
7792
8806
  var CHATGPT_HOME2 = "https://chatgpt.com/";
8807
+ async function ensureConversationTarget(page, target, options) {
8808
+ const targetUrl = absoluteConversationUrl(target);
8809
+ const expectedConversationId = parseConversationId(targetUrl);
8810
+ const currentUrl = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
8811
+ if (expectedConversationId !== void 0 && parseConversationId(typeof currentUrl === "string" ? currentUrl : "") === expectedConversationId) {
8812
+ await waitForConversationHydrated(page, options.timeoutMs, expectedConversationId);
8813
+ return ensureResult(false, targetUrl, expectedConversationId);
8814
+ }
8815
+ await page.goto?.(targetUrl, { waitUntil: "domcontentloaded", timeout: options.timeoutMs });
8816
+ await waitForConversationHydrated(page, options.timeoutMs, expectedConversationId);
8817
+ return ensureResult(true, targetUrl, expectedConversationId);
8818
+ }
8819
+ async function waitForConversationHydrated(page, timeoutMs, expectedConversationId) {
8820
+ const started = Date.now();
8821
+ do {
8822
+ const url = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
8823
+ const urlMatches2 = expectedConversationId === void 0 || parseConversationId(typeof url === "string" ? url : "") === expectedConversationId;
8824
+ const count = await countPageMessages(page).catch(() => 0);
8825
+ const latestAssistantText = await readLatestMessageText(page, "assistant").catch(() => void 0);
8826
+ const title = typeof page.title === "function" ? await page.title().catch(() => "") : "";
8827
+ if (urlMatches2 && ((latestAssistantText?.trim().length ?? 0) > 0 || count > 0 && title.length > 0 && title !== "ChatGPT")) {
8828
+ await page.waitForTimeout?.(250);
8829
+ return;
8830
+ }
8831
+ await page.waitForTimeout?.(500);
8832
+ } while (Date.now() - started < timeoutMs);
8833
+ }
8834
+ function absoluteConversationUrl(target) {
8835
+ if (target.href !== void 0 && target.href.startsWith("/")) {
8836
+ return new URL(target.href, CHATGPT_HOME2).toString();
8837
+ }
8838
+ return target.href ?? target.url;
8839
+ }
8840
+ function ensureResult(navigated, targetUrl, expectedConversationId) {
8841
+ const result = { navigated, targetUrl };
8842
+ if (expectedConversationId !== void 0) {
8843
+ result.expectedConversationId = expectedConversationId;
8844
+ }
8845
+ return result;
8846
+ }
8847
+
8848
+ // src/commands/threads.ts
8849
+ var CHATGPT_HOME3 = "https://chatgpt.com/";
7793
8850
  function extractThreadSearchResultsFromHtml(html) {
7794
8851
  const anchors = html.matchAll(/<a\b(?<attrs>[^>]*\bhref=["'](?<href>\/c\/[^"']+)["'][^>]*)>(?<body>[\s\S]*?)<\/a>/gi);
7795
8852
  const results = [];
@@ -7850,7 +8907,7 @@ async function newThread(env, args = {}) {
7850
8907
  try {
7851
8908
  await newChatButton(page).click?.();
7852
8909
  } catch {
7853
- await page.goto?.(CHATGPT_HOME2, { waitUntil: "domcontentloaded", timeout: args.timeoutMs ?? 3e4 });
8910
+ await page.goto?.(CHATGPT_HOME3, { waitUntil: "domcontentloaded", timeout: args.timeoutMs ?? 3e4 });
7854
8911
  }
7855
8912
  await page.waitForTimeout?.(500);
7856
8913
  const state = await readPageState(page);
@@ -7879,12 +8936,7 @@ async function openThread(env, args, previousResults) {
7879
8936
  context: await contextFromPage(page)
7880
8937
  };
7881
8938
  }
7882
- if (target.href !== void 0 && target.href.startsWith("/")) {
7883
- await page.goto?.(new URL(target.href, CHATGPT_HOME2).toString(), { waitUntil: "domcontentloaded", timeout: args.timeoutMs ?? 3e4 });
7884
- } else {
7885
- await page.goto?.(target.href ?? target.url, { waitUntil: "domcontentloaded", timeout: args.timeoutMs ?? 3e4 });
7886
- }
7887
- await waitForThreadHydrated(page, args.timeoutMs ?? 3e4, parseConversationId(target.url));
8939
+ await ensureConversationTarget(page, target, { timeoutMs: args.timeoutMs ?? 3e4 });
7888
8940
  const state = await readPageState(page);
7889
8941
  return resultOk(
7890
8942
  openThreadData(state.url, state.conversationId, state.title ?? target.title),
@@ -7905,21 +8957,21 @@ async function resolveOpenTarget(env, args, previousResults) {
7905
8957
  return { url: args.url };
7906
8958
  }
7907
8959
  if (args.conversationId !== void 0) {
7908
- return { url: new URL(`/c/${args.conversationId}`, CHATGPT_HOME2).toString() };
8960
+ return { url: new URL(`/c/${args.conversationId}`, CHATGPT_HOME3).toString() };
7909
8961
  }
7910
8962
  if (args.fromStep !== void 0 && previousResults !== void 0) {
7911
8963
  const previous = previousResults.get(args.fromStep);
7912
8964
  const data = previous?.data;
7913
8965
  const selected = selectSearchResult(data?.results ?? [], args.select ?? "first");
7914
8966
  if (selected !== void 0) {
7915
- return { href: selected.href, url: new URL(selected.href, CHATGPT_HOME2).toString(), title: selected.title };
8967
+ return { href: selected.href, url: new URL(selected.href, CHATGPT_HOME3).toString(), title: selected.title };
7916
8968
  }
7917
8969
  }
7918
8970
  if (args.title !== void 0) {
7919
8971
  const search = await searchThreads(env, { query: args.title, limit: 10 });
7920
8972
  const selected = selectSearchResult(search.data?.results ?? [], { title: args.title }) ?? search.data?.results[0];
7921
8973
  if (selected !== void 0) {
7922
- return { href: selected.href, url: new URL(selected.href, CHATGPT_HOME2).toString(), title: selected.title };
8974
+ return { href: selected.href, url: new URL(selected.href, CHATGPT_HOME3).toString(), title: selected.title };
7923
8975
  }
7924
8976
  }
7925
8977
  return void 0;
@@ -8052,22 +9104,6 @@ function filterResultsByQuery(results, query) {
8052
9104
  return haystack.includes(wanted) || wanted.includes(normalizeForMatch(result.title));
8053
9105
  });
8054
9106
  }
8055
- async function waitForThreadHydrated(page, timeoutMs, expectedConversationId) {
8056
- const started = Date.now();
8057
- await page.waitForTimeout?.(1e3);
8058
- while (Date.now() - started < timeoutMs) {
8059
- const url = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
8060
- const urlMatches2 = expectedConversationId === void 0 || url.includes(expectedConversationId);
8061
- const count = await countPageMessages(page).catch(() => 0);
8062
- const latestAssistantText = await readLatestMessageText(page, "assistant").catch(() => void 0);
8063
- const title = typeof page.title === "function" ? await page.title().catch(() => "") : "";
8064
- if (urlMatches2 && ((latestAssistantText?.trim().length ?? 0) > 0 || count > 0 && title.length > 0 && title !== "ChatGPT")) {
8065
- await page.waitForTimeout?.(250);
8066
- return;
8067
- }
8068
- await page.waitForTimeout?.(500);
8069
- }
8070
- }
8071
9107
 
8072
9108
  // src/commands/sequence.ts
8073
9109
  var defaultSequencePolicy = {
@@ -8837,7 +9873,8 @@ function createChatGPT(options = {}) {
8837
9873
  downloadLatest: (args) => downloadLatestArtifact(env, args)
8838
9874
  },
8839
9875
  modes: {
8840
- set: (args) => setMode(env, args)
9876
+ set: (args) => setMode(env, args),
9877
+ get: (args) => getMode(env, args)
8841
9878
  },
8842
9879
  tools: {
8843
9880
  select: (args) => selectTool(env, args)
@@ -9514,6 +10551,7 @@ var backendCommands = [
9514
10551
  "projects.sources.planAdd",
9515
10552
  "projects.sources.add",
9516
10553
  "modes.set",
10554
+ "modes.get",
9517
10555
  "tools.select",
9518
10556
  "response.copy"
9519
10557
  ];
@@ -9770,6 +10808,8 @@ async function dispatchBackendCommand(client, request) {
9770
10808
  return client.projects.sources.add(payload);
9771
10809
  case "modes.set":
9772
10810
  return client.modes.set(payload);
10811
+ case "modes.get":
10812
+ return client.modes.get(emptyToUndefined(payload));
9773
10813
  case "tools.select":
9774
10814
  return client.tools.select(payload);
9775
10815
  case "response.copy":