codex-chatgpt-control 0.3.0-alpha.1 → 0.5.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 (214) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +42 -2
  3. package/contracts/v1/fixtures/backend-capabilities.json +10 -0
  4. package/contracts/v1/fixtures/command-descriptors.json +257 -6
  5. package/contracts/v1/fixtures/describe-runner-run.json +5 -2
  6. package/contracts/v1/fixtures/doctor-scenario-preflight.json +34 -2
  7. package/contracts/v1/fixtures/help-root.json +1 -1
  8. package/contracts/v1/fixtures/output-json-parse-success.json +9 -0
  9. package/contracts/v1/fixtures/run-timeout-partial.json +15 -4
  10. package/contracts/v1/fixtures/stream-in-progress.ndjson +3 -0
  11. package/contracts/v1/fixtures/stream-submitted-completed.ndjson +1 -1
  12. package/contracts/v1/fixtures/surface-chat-legacy.json +35 -0
  13. package/contracts/v1/fixtures/surface-chat-simplified.json +37 -0
  14. package/contracts/v1/fixtures/surface-sidebar-false-positive.json +29 -0
  15. package/contracts/v1/fixtures/surface-work-advanced.json +45 -0
  16. package/contracts/v1/fixtures/surface-work-basic.json +38 -0
  17. package/contracts/v1/fixtures/workflow-ask-success.json +8 -0
  18. package/contracts/v1/manifest.json +32 -1
  19. package/contracts/v1/parity-suite.json +113 -0
  20. package/contracts/v1/schemas/backend-request.schema.json +15 -0
  21. package/contracts/v1/schemas/manifest.schema.json +6 -3
  22. package/contracts/v1/schemas/surface-profile.schema.json +166 -0
  23. package/dist/codex-chatgpt-control-backend.mjs +2045 -227
  24. package/dist/codex-chatgpt-control.bundle.mjs +3817 -1960
  25. package/dist/src/backend/client.d.ts +26 -1
  26. package/dist/src/backend/client.js +23 -1
  27. package/dist/src/backend/protocol.d.ts +1 -1
  28. package/dist/src/backend/protocol.js +10 -0
  29. package/dist/src/backend/session.js +20 -0
  30. package/dist/src/browser/attach.d.ts +1 -0
  31. package/dist/src/browser/attach.js +3 -3
  32. package/dist/src/browser/page-state.js +5 -2
  33. package/dist/src/client.d.ts +31 -1
  34. package/dist/src/client.js +69 -14
  35. package/dist/src/commands/artifacts.js +1 -7
  36. package/dist/src/commands/configuration.d.ts +15 -0
  37. package/dist/src/commands/configuration.js +674 -0
  38. package/dist/src/commands/doctor.js +38 -1
  39. package/dist/src/commands/experience.d.ts +12 -0
  40. package/dist/src/commands/experience.js +288 -0
  41. package/dist/src/commands/files.js +1 -7
  42. package/dist/src/commands/messages.d.ts +2 -1
  43. package/dist/src/commands/messages.js +138 -16
  44. package/dist/src/commands/modes.js +28 -14
  45. package/dist/src/commands/registry.js +69 -7
  46. package/dist/src/commands/response-actions.js +1 -7
  47. package/dist/src/commands/sequence.js +24 -1
  48. package/dist/src/commands/session.d.ts +2 -0
  49. package/dist/src/commands/session.js +50 -1
  50. package/dist/src/commands/threads.js +1 -7
  51. package/dist/src/commands/work.d.ts +6 -0
  52. package/dist/src/commands/work.js +338 -0
  53. package/dist/src/dom/locale/am.d.ts +2 -1
  54. package/dist/src/dom/locale/am.js +2 -1
  55. package/dist/src/dom/locale/ar.d.ts +2 -1
  56. package/dist/src/dom/locale/ar.js +2 -1
  57. package/dist/src/dom/locale/bg.d.ts +2 -1
  58. package/dist/src/dom/locale/bg.js +2 -1
  59. package/dist/src/dom/locale/bn.d.ts +2 -1
  60. package/dist/src/dom/locale/bn.js +2 -1
  61. package/dist/src/dom/locale/bs.d.ts +2 -1
  62. package/dist/src/dom/locale/bs.js +2 -1
  63. package/dist/src/dom/locale/ca.d.ts +2 -1
  64. package/dist/src/dom/locale/ca.js +2 -1
  65. package/dist/src/dom/locale/cs.d.ts +2 -1
  66. package/dist/src/dom/locale/cs.js +2 -1
  67. package/dist/src/dom/locale/da.d.ts +2 -1
  68. package/dist/src/dom/locale/da.js +2 -1
  69. package/dist/src/dom/locale/de.d.ts +4 -3
  70. package/dist/src/dom/locale/de.js +4 -3
  71. package/dist/src/dom/locale/el.d.ts +2 -1
  72. package/dist/src/dom/locale/el.js +2 -1
  73. package/dist/src/dom/locale/en.d.ts +27 -2
  74. package/dist/src/dom/locale/en.js +28 -2
  75. package/dist/src/dom/locale/es-419.d.ts +2 -1
  76. package/dist/src/dom/locale/es-419.js +2 -1
  77. package/dist/src/dom/locale/es-ES.d.ts +2 -1
  78. package/dist/src/dom/locale/es-ES.js +2 -1
  79. package/dist/src/dom/locale/et.d.ts +2 -1
  80. package/dist/src/dom/locale/et.js +2 -1
  81. package/dist/src/dom/locale/fa.d.ts +2 -1
  82. package/dist/src/dom/locale/fa.js +2 -1
  83. package/dist/src/dom/locale/fi.d.ts +2 -1
  84. package/dist/src/dom/locale/fi.js +2 -1
  85. package/dist/src/dom/locale/fr-CA.d.ts +2 -1
  86. package/dist/src/dom/locale/fr-CA.js +2 -1
  87. package/dist/src/dom/locale/fr-FR.d.ts +3 -3
  88. package/dist/src/dom/locale/fr-FR.js +3 -3
  89. package/dist/src/dom/locale/gu.d.ts +2 -1
  90. package/dist/src/dom/locale/gu.js +2 -1
  91. package/dist/src/dom/locale/hi.d.ts +2 -1
  92. package/dist/src/dom/locale/hi.js +2 -1
  93. package/dist/src/dom/locale/hr.d.ts +2 -1
  94. package/dist/src/dom/locale/hr.js +2 -1
  95. package/dist/src/dom/locale/hu.d.ts +2 -1
  96. package/dist/src/dom/locale/hu.js +2 -1
  97. package/dist/src/dom/locale/hy.d.ts +2 -1
  98. package/dist/src/dom/locale/hy.js +2 -1
  99. package/dist/src/dom/locale/id.d.ts +2 -1
  100. package/dist/src/dom/locale/id.js +2 -1
  101. package/dist/src/dom/locale/index.d.ts +17 -2
  102. package/dist/src/dom/locale/index.js +65 -0
  103. package/dist/src/dom/locale/is.d.ts +2 -1
  104. package/dist/src/dom/locale/is.js +2 -1
  105. package/dist/src/dom/locale/it.d.ts +2 -1
  106. package/dist/src/dom/locale/it.js +2 -1
  107. package/dist/src/dom/locale/ja.d.ts +2 -1
  108. package/dist/src/dom/locale/ja.js +2 -1
  109. package/dist/src/dom/locale/ka.d.ts +2 -1
  110. package/dist/src/dom/locale/ka.js +2 -1
  111. package/dist/src/dom/locale/kk.d.ts +2 -1
  112. package/dist/src/dom/locale/kk.js +2 -1
  113. package/dist/src/dom/locale/kn.d.ts +2 -1
  114. package/dist/src/dom/locale/kn.js +2 -1
  115. package/dist/src/dom/locale/ko.d.ts +2 -1
  116. package/dist/src/dom/locale/ko.js +2 -1
  117. package/dist/src/dom/locale/lt.d.ts +2 -1
  118. package/dist/src/dom/locale/lt.js +2 -1
  119. package/dist/src/dom/locale/lv.d.ts +2 -1
  120. package/dist/src/dom/locale/lv.js +2 -1
  121. package/dist/src/dom/locale/mk.d.ts +2 -1
  122. package/dist/src/dom/locale/mk.js +2 -1
  123. package/dist/src/dom/locale/ml.d.ts +2 -1
  124. package/dist/src/dom/locale/ml.js +2 -1
  125. package/dist/src/dom/locale/mn.d.ts +2 -1
  126. package/dist/src/dom/locale/mn.js +2 -1
  127. package/dist/src/dom/locale/mr.d.ts +2 -1
  128. package/dist/src/dom/locale/mr.js +2 -1
  129. package/dist/src/dom/locale/ms.d.ts +2 -1
  130. package/dist/src/dom/locale/ms.js +2 -1
  131. package/dist/src/dom/locale/my.d.ts +2 -1
  132. package/dist/src/dom/locale/my.js +2 -1
  133. package/dist/src/dom/locale/nb.d.ts +2 -1
  134. package/dist/src/dom/locale/nb.js +2 -1
  135. package/dist/src/dom/locale/nl.d.ts +2 -1
  136. package/dist/src/dom/locale/nl.js +2 -1
  137. package/dist/src/dom/locale/pa.d.ts +2 -1
  138. package/dist/src/dom/locale/pa.js +2 -1
  139. package/dist/src/dom/locale/pl.d.ts +2 -1
  140. package/dist/src/dom/locale/pl.js +2 -1
  141. package/dist/src/dom/locale/pt-BR.d.ts +2 -1
  142. package/dist/src/dom/locale/pt-BR.js +2 -1
  143. package/dist/src/dom/locale/pt-PT.d.ts +2 -1
  144. package/dist/src/dom/locale/pt-PT.js +2 -1
  145. package/dist/src/dom/locale/ro.d.ts +2 -1
  146. package/dist/src/dom/locale/ro.js +2 -1
  147. package/dist/src/dom/locale/ru.d.ts +2 -1
  148. package/dist/src/dom/locale/ru.js +2 -1
  149. package/dist/src/dom/locale/sk.d.ts +2 -1
  150. package/dist/src/dom/locale/sk.js +2 -1
  151. package/dist/src/dom/locale/sl.d.ts +2 -1
  152. package/dist/src/dom/locale/sl.js +2 -1
  153. package/dist/src/dom/locale/so.d.ts +2 -1
  154. package/dist/src/dom/locale/so.js +2 -1
  155. package/dist/src/dom/locale/sq.d.ts +2 -1
  156. package/dist/src/dom/locale/sq.js +2 -1
  157. package/dist/src/dom/locale/sr.d.ts +2 -1
  158. package/dist/src/dom/locale/sr.js +2 -1
  159. package/dist/src/dom/locale/sv.d.ts +2 -1
  160. package/dist/src/dom/locale/sv.js +2 -1
  161. package/dist/src/dom/locale/sw.d.ts +2 -1
  162. package/dist/src/dom/locale/sw.js +2 -1
  163. package/dist/src/dom/locale/ta.d.ts +2 -1
  164. package/dist/src/dom/locale/ta.js +2 -1
  165. package/dist/src/dom/locale/te.d.ts +2 -1
  166. package/dist/src/dom/locale/te.js +2 -1
  167. package/dist/src/dom/locale/th.d.ts +2 -1
  168. package/dist/src/dom/locale/th.js +2 -1
  169. package/dist/src/dom/locale/tl.d.ts +4 -5
  170. package/dist/src/dom/locale/tl.js +4 -5
  171. package/dist/src/dom/locale/tr.d.ts +2 -1
  172. package/dist/src/dom/locale/tr.js +2 -1
  173. package/dist/src/dom/locale/types.d.ts +18 -1
  174. package/dist/src/dom/locale/uk.d.ts +2 -1
  175. package/dist/src/dom/locale/uk.js +2 -1
  176. package/dist/src/dom/locale/ur.d.ts +2 -1
  177. package/dist/src/dom/locale/ur.js +2 -1
  178. package/dist/src/dom/locale/vi.d.ts +2 -1
  179. package/dist/src/dom/locale/vi.js +2 -1
  180. package/dist/src/dom/locale/zh-HK.d.ts +2 -1
  181. package/dist/src/dom/locale/zh-HK.js +4 -3
  182. package/dist/src/dom/locale/zh-Hans.d.ts +2 -1
  183. package/dist/src/dom/locale/zh-Hans.js +2 -1
  184. package/dist/src/dom/locale/zh-TW.d.ts +2 -1
  185. package/dist/src/dom/locale/zh-TW.js +2 -1
  186. package/dist/src/dom/selectors.js +6 -1
  187. package/dist/src/index.d.ts +3 -0
  188. package/dist/src/index.js +3 -0
  189. package/dist/src/runner/responses.d.ts +3 -1
  190. package/dist/src/runner/responses.js +16 -1
  191. package/dist/src/runner/result.js +129 -4
  192. package/dist/src/runner/stream.d.ts +1 -1
  193. package/dist/src/runner/stream.js +6 -0
  194. package/dist/src/runner/types.d.ts +35 -1
  195. package/dist/src/safety/risk.d.ts +10 -0
  196. package/dist/src/safety/risk.js +10 -0
  197. package/dist/src/scripts/apply-intelligence-locale-captures.d.ts +6 -0
  198. package/dist/src/scripts/apply-intelligence-locale-captures.js +53 -7
  199. package/dist/src/scripts/capture-intelligence-locales.d.ts +3 -0
  200. package/dist/src/scripts/capture-intelligence-locales.js +372 -3
  201. package/dist/src/scripts/capture-surface-profile.d.ts +23 -0
  202. package/dist/src/scripts/capture-surface-profile.js +304 -0
  203. package/dist/src/scripts/live-smoke/scenarios.js +34 -1
  204. package/dist/src/scripts/live-smoke.js +1 -0
  205. package/dist/src/types.d.ts +245 -2
  206. package/package.json +3 -2
  207. package/references/2026-07-16-chat-work-surfaces.md +87 -0
  208. package/references/agents-runner.md +13 -2
  209. package/references/backend-protocol.md +15 -5
  210. package/references/language-coverage.md +40 -3
  211. package/references/localization.md +34 -6
  212. package/references/python-parity.md +11 -1
  213. package/references/responses-adapter.md +12 -1
  214. package/references/troubleshooting.md +22 -2
@@ -141,7 +141,9 @@ function classifyVisibleText(text) {
141
141
  // src/dom/locale/en.ts
142
142
  var en = {
143
143
  // --- Primary interaction path (accessible names) ---
144
- composerTextbox: ["Chat with ChatGPT"],
144
+ composerTextbox: ["Chat with ChatGPT", "Ask ChatGPT"],
145
+ workComposerTextbox: ["Work on anything", "Work on something"],
146
+ newWork: ["Work on something else", "New work", "New task"],
145
147
  sendButton: ["Send prompt"],
146
148
  searchChatsButton: ["Search chats"],
147
149
  searchChatsPlaceholder: ["Search chats..."],
@@ -169,10 +171,34 @@ var en = {
169
171
  medium: ["Medium"],
170
172
  high: ["High"],
171
173
  extraHigh: ["Extra High"],
172
- pro: ["Pro", "Pro Extended", "Extended Pro"]
174
+ pro: ["Pro", "Pro Extended", "Pro \u2022 Extended", "Extended Pro"]
173
175
  },
174
176
  /** Extra openers that surface the mode menu but are not selectable modes themselves. */
175
177
  modeOpenerExtra: ["Configure"],
178
+ // --- Chat / Work surfaces and capability-driven configuration ---
179
+ experienceOptions: {
180
+ chat: ["Chat", "Quick chat"],
181
+ work: ["Work"]
182
+ },
183
+ configurationAxes: {
184
+ model: ["Model"],
185
+ intelligence: ["Intelligence"],
186
+ effort: ["Effort"],
187
+ speed: ["Speed"],
188
+ advanced: ["Advanced"]
189
+ },
190
+ configurationOptions: {
191
+ instant: ["Instant"],
192
+ light: ["Light"],
193
+ medium: ["Medium"],
194
+ high: ["High"],
195
+ extraHigh: ["Extra High"],
196
+ max: ["Max"],
197
+ ultra: ["Ultra"],
198
+ pro: ["Pro"],
199
+ standard: ["Standard"],
200
+ fast: ["Fast"]
201
+ },
176
202
  // --- Thread/action menu rejection (wrong-menu veto for mode selection) ---
177
203
  /** Exact thread/conversation action menu items; a menu containing these is not the mode menu. */
178
204
  threadActionMenuItems: ["Archive", "Copy link", "Delete", "Move to project", "Rename", "Share"],
@@ -228,7 +254,8 @@ var de = {
228
254
  create_image: ["Bild erstellen"]
229
255
  },
230
256
  signedInMarkers: ["Neuer Chat", "Chats durchsuchen", "Letzte", "Bibliothek", "Projekte", "Mit ChatGPT chatten"],
231
- responseActions: ["Antwort kopieren"]
257
+ responseActions: ["Antwort kopieren"],
258
+ stopControl: ["Antwort stoppen"]
232
259
  };
233
260
 
234
261
  // src/dom/locale/es-ES.ts
@@ -256,7 +283,8 @@ var esES = {
256
283
  create_image: ["Crea una imagen"]
257
284
  },
258
285
  signedInMarkers: ["Nuevo chat", "Buscar chats", "Recientes", "Biblioteca", "Proyectos", "Chatear con ChatGPT"],
259
- responseActions: ["Copiar respuesta"]
286
+ responseActions: ["Copiar respuesta"],
287
+ stopControl: ["Detener respuesta"]
260
288
  };
261
289
 
262
290
  // src/dom/locale/fr-FR.ts
@@ -283,7 +311,8 @@ var frFR = {
283
311
  create_image: ["Cr\xE9er une image"]
284
312
  },
285
313
  signedInMarkers: ["Nouveau chat", "Rechercher dans les chats", "R\xE9cents", "Biblioth\xE8que", "Projets", "Discuter avec ChatGPT"],
286
- responseActions: ["Copier la r\xE9ponse"]
314
+ responseActions: ["Copier la r\xE9ponse"],
315
+ stopControl: ["Interrompre la r\xE9ponse"]
287
316
  };
288
317
 
289
318
  // src/dom/locale/zh-HK.ts
@@ -297,10 +326,10 @@ var zhHK = {
297
326
  addFilesOpenerCandidates: ["\u4E0A\u8F09\u6A94\u6848\u548C\u5176\u4ED6\u5185\u5BB9"],
298
327
  addPhotosFilesMenuItem: ["\u52A0\u5165\u76F8\u7247\u548C\u6A94\u6848"],
299
328
  copyResponse: ["\u8907\u88FD\u56DE\u8986"],
300
- modeLabels: ["\u5373\u6642", "\u5747\u8861", "\u9AD8", "\u6975\u9AD8", "\u5C08\u696D"],
329
+ modeLabels: ["\u5373\u6642", "\u5747\u8861", "\u9AD8", "\u6975\u9AD8", "\u5C08\u696D", "\u4E2D\u7B49"],
301
330
  modeOptions: {
302
331
  instant: ["\u5373\u6642"],
303
- medium: ["\u5747\u8861"],
332
+ medium: ["\u5747\u8861", "\u4E2D\u7B49"],
304
333
  high: ["\u9AD8"],
305
334
  extraHigh: ["\u6975\u9AD8"],
306
335
  pro: ["\u5C08\u696D"]
@@ -312,7 +341,8 @@ var zhHK = {
312
341
  create_image: ["\u5275\u4F5C\u5716\u50CF"]
313
342
  },
314
343
  signedInMarkers: ["\u65B0\u5C0D\u8A71", "\u641C\u5C0B\u5C0D\u8A71", "\u6700\u8FD1\u5C0D\u8A71", "\u5716\u5EAB", "\u9805\u76EE", "\u8207 ChatGPT \u5C0D\u8A71"],
315
- responseActions: ["\u8907\u88FD\u56DE\u8986"]
344
+ responseActions: ["\u8907\u88FD\u56DE\u8986"],
345
+ stopControl: ["\u505C\u6B62\u56DE\u61C9"]
316
346
  };
317
347
 
318
348
  // src/dom/locale/zh-TW.ts
@@ -341,7 +371,8 @@ var zhTW = {
341
371
  create_image: ["\u5275\u4F5C\u5716\u50CF"]
342
372
  },
343
373
  signedInMarkers: ["\u65B0\u5C0D\u8A71", "\u641C\u5C0B\u5C0D\u8A71", "\u6700\u8FD1\u7684\u5C0D\u8A71", "\u5716\u5EAB", "\u5C08\u6848", "\u8207 ChatGPT \u5C0D\u8A71"],
344
- responseActions: ["\u8907\u88FD\u56DE\u61C9"]
374
+ responseActions: ["\u8907\u88FD\u56DE\u61C9"],
375
+ stopControl: ["\u505C\u6B62\u56DE\u61C9"]
345
376
  };
346
377
 
347
378
  // src/dom/locale/ja.ts
@@ -368,7 +399,8 @@ var ja = {
368
399
  create_image: ["\u753B\u50CF\u3092\u4F5C\u6210\u3059\u308B"]
369
400
  },
370
401
  signedInMarkers: ["\u65B0\u3057\u3044\u30C1\u30E3\u30C3\u30C8", "\u30C1\u30E3\u30C3\u30C8\u3092\u691C\u7D22", "\u6700\u8FD1\u306E\u30C1\u30E3\u30C3\u30C8", "\u30E9\u30A4\u30D6\u30E9\u30EA", "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8", "ChatGPT \u3068\u30C1\u30E3\u30C3\u30C8\u3059\u308B"],
371
- responseActions: ["\u56DE\u7B54\u3092\u30B3\u30D4\u30FC\u3059\u308B"]
402
+ responseActions: ["\u56DE\u7B54\u3092\u30B3\u30D4\u30FC\u3059\u308B"],
403
+ stopControl: ["\u56DE\u7B54\u3092\u505C\u6B62"]
372
404
  };
373
405
 
374
406
  // src/dom/locale/it.ts
@@ -395,7 +427,8 @@ var it = {
395
427
  create_image: ["Crea immagine"]
396
428
  },
397
429
  signedInMarkers: ["Nuova chat", "Cerca chat", "Chat recenti", "Libreria", "Progetti", "Chatta con ChatGPT"],
398
- responseActions: ["Copia risposta"]
430
+ responseActions: ["Copia risposta"],
431
+ stopControl: ["Interrompi risposta"]
399
432
  };
400
433
 
401
434
  // src/dom/locale/vi.ts
@@ -423,7 +456,8 @@ var vi = {
423
456
  create_image: ["T\u1EA1o h\xECnh \u1EA3nh"]
424
457
  },
425
458
  signedInMarkers: ["\u0110o\u1EA1n chat m\u1EDBi", "T\xECm ki\u1EBFm \u0111o\u1EA1n chat", "G\u1EA7n \u0111\xE2y", "Th\u01B0 vi\u1EC7n", "D\u1EF1 \xE1n", "Tr\xF2 chuy\u1EC7n v\u1EDBi ChatGPT"],
426
- responseActions: ["Sao ch\xE9p ph\u1EA3n h\u1ED3i"]
459
+ responseActions: ["Sao ch\xE9p ph\u1EA3n h\u1ED3i"],
460
+ stopControl: ["D\u1EEBng tr\u1EA3 l\u1EDDi"]
427
461
  };
428
462
 
429
463
  // src/dom/locale/am.ts
@@ -451,7 +485,8 @@ var am = {
451
485
  create_image: ["\u121D\u1235\u120D \u134D\u1320\u122D"]
452
486
  },
453
487
  signedInMarkers: ["\u12A0\u12F2\u1235 \u12CD\u12ED\u12ED\u1275", "\u12CD\u12ED\u12ED\u1276\u127D\u1295 \u1348\u120D\u130D", "\u12E8\u1245\u122D\u1265 \u130A\u12DC\u12CE\u127D", "\u120B\u12ED\u1265\u1228\u122A", "\u1355\u122E\u1300\u12AD\u1276\u127D", "\u12A8ChatGPT \u130B\u122D \u12ED\u12C8\u12EB\u12E9"],
454
- responseActions: ["\u121D\u120B\u1239\u1295 \u12ED\u1245\u12F1"]
488
+ responseActions: ["\u121D\u120B\u1239\u1295 \u12ED\u1245\u12F1"],
489
+ stopControl: ["\u1218\u120D\u1235 \u1218\u1235\u1320\u1275 \u12A0\u1241\u121D"]
455
490
  };
456
491
 
457
492
  // src/dom/locale/ar.ts
@@ -480,7 +515,8 @@ var ar = {
480
515
  create_image: ["\u0625\u0646\u0634\u0627\u0621 \u0635\u0648\u0631\u0629"]
481
516
  },
482
517
  signedInMarkers: ["\u062F\u0631\u062F\u0634\u0629 \u062C\u062F\u064A\u062F\u0629", "\u0627\u0644\u0628\u062D\u062B \u0641\u064A \u0627\u0644\u062F\u0631\u062F\u0634\u0627\u062A", "\u0627\u0644\u0645\u062D\u0627\u062F\u062B\u0627\u062A \u0627\u0644\u0623\u062E\u064A\u0631\u0629", "\u0627\u0644\u0645\u0643\u062A\u0628\u0629", "\u0627\u0644\u0645\u0634\u0631\u0648\u0639\u0627\u062A", "\u0627\u0644\u062F\u0631\u062F\u0634\u0629 \u0645\u0639 ChatGPT"],
483
- responseActions: ["\u0646\u0633\u062E \u0625\u062C\u0627\u0628\u0629"]
518
+ responseActions: ["\u0646\u0633\u062E \u0625\u062C\u0627\u0628\u0629"],
519
+ stopControl: ["\u0625\u064A\u0642\u0627\u0641 \u0627\u0644\u0631\u062F"]
484
520
  };
485
521
 
486
522
  // src/dom/locale/bg.ts
@@ -509,7 +545,8 @@ var bg = {
509
545
  create_image: ["\u0421\u044A\u0437\u0434\u0430\u0432\u0430\u043D\u0435 \u043D\u0430 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435"]
510
546
  },
511
547
  signedInMarkers: ["\u041D\u043E\u0432 \u0447\u0430\u0442", "\u0422\u044A\u0440\u0441\u0435\u043D\u0435 \u043D\u0430 \u0447\u0430\u0442\u043E\u0432\u0435", "\u0421\u043A\u043E\u0440\u043E\u0448\u043D\u0438 \u0447\u0430\u0442\u043E\u0432\u0435", "\u041A\u0430\u0442\u0430\u043B\u043E\u0433", "\u041F\u0440\u043E\u0435\u043A\u0442\u0438", "\u0427\u0430\u0442 \u0441 ChatGPT"],
512
- responseActions: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0439\u0442\u0435 \u043E\u0442\u0433\u043E\u0432\u043E\u0440\u0430"]
548
+ responseActions: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0439\u0442\u0435 \u043E\u0442\u0433\u043E\u0432\u043E\u0440\u0430"],
549
+ stopControl: ["\u0421\u043F\u0440\u0438 \u043E\u0442\u0433\u043E\u0432\u043E\u0440\u0430"]
513
550
  };
514
551
 
515
552
  // src/dom/locale/bs.ts
@@ -537,7 +574,8 @@ var bs = {
537
574
  create_image: ["Kreirajte sliku"]
538
575
  },
539
576
  signedInMarkers: ["Novi razgovor", "Pretra\u017Ei razgovore", "Nedavno", "Biblioteka", "Projekti", "Razgovarajte pomo\u0107u ChatGPT-a"],
540
- responseActions: ["Kopiraj odgovor"]
577
+ responseActions: ["Kopiraj odgovor"],
578
+ stopControl: ["Zaustavi odgovaranje"]
541
579
  };
542
580
 
543
581
  // src/dom/locale/ca.ts
@@ -565,7 +603,8 @@ var ca = {
565
603
  create_image: ["Crea una imatge"]
566
604
  },
567
605
  signedInMarkers: ["Xat nou", "Cerca xats", "Recents", "Hist\xF2ria de xats", "Projectes", "Xateja amb el ChatGPT"],
568
- responseActions: ["Copia la resposta"]
606
+ responseActions: ["Copia la resposta"],
607
+ stopControl: ["Atura la resposta"]
569
608
  };
570
609
 
571
610
  // src/dom/locale/cs.ts
@@ -593,7 +632,8 @@ var cs = {
593
632
  create_image: ["Vytvo\u0159 obr\xE1zek"]
594
633
  },
595
634
  signedInMarkers: ["Nov\xFD chat", "Hledat chaty", "Ned\xE1vn\xE9", "Historie chatu", "Projekty", "Chatovat s ChatGPT"],
596
- responseActions: ["Zkop\xEDrovat odpov\u011B\u010F"]
635
+ responseActions: ["Zkop\xEDrovat odpov\u011B\u010F"],
636
+ stopControl: ["Zastavit odpov\xEDd\xE1n\xED"]
597
637
  };
598
638
 
599
639
  // src/dom/locale/da.ts
@@ -620,7 +660,8 @@ var da = {
620
660
  create_image: ["Lav et billede"]
621
661
  },
622
662
  signedInMarkers: ["Ny chat", "S\xF8g i chats", "Seneste", "Chathistorik", "Projekter", "Chat med ChatGPT"],
623
- responseActions: ["Kopi\xE9r svar"]
663
+ responseActions: ["Kopi\xE9r svar"],
664
+ stopControl: ["Afbryd svar"]
624
665
  };
625
666
 
626
667
  // src/dom/locale/el.ts
@@ -648,7 +689,8 @@ var el = {
648
689
  create_image: ["\u0394\u03B7\u03BC\u03B9\u03BF\u03C5\u03C1\u03B3\u03AF\u03B1 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B1\u03C2"]
649
690
  },
650
691
  signedInMarkers: ["\u039D\u03AD\u03B1 \u03C3\u03C5\u03BD\u03BF\u03BC\u03B9\u03BB\u03AF\u03B1", "\u0391\u03BD\u03B1\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7 \u03C3\u03C5\u03BD\u03BF\u03BC\u03B9\u03BB\u03B9\u03CE\u03BD", "\u03A0\u03C1\u03CC\u03C3\u03C6\u03B1\u03C4\u03B5\u03C2", "\u0399\u03C3\u03C4\u03BF\u03C1\u03B9\u03BA\u03CC \u03C3\u03C5\u03BD\u03BF\u03BC\u03B9\u03BB\u03B9\u03CE\u03BD", "\u0388\u03C1\u03B3\u03B1", "\u03A3\u03C5\u03BD\u03BF\u03BC\u03B9\u03BB\u03AF\u03B1 \u03BC\u03B5 \u03C4\u03BF ChatGPT"],
651
- responseActions: ["\u0391\u03BD\u03C4\u03B9\u03B3\u03C1\u03B1\u03C6\u03AE \u03B1\u03C0\u03AC\u03BD\u03C4\u03B7\u03C3\u03B7\u03C2"]
692
+ responseActions: ["\u0391\u03BD\u03C4\u03B9\u03B3\u03C1\u03B1\u03C6\u03AE \u03B1\u03C0\u03AC\u03BD\u03C4\u03B7\u03C3\u03B7\u03C2"],
693
+ stopControl: ["\u0394\u03B9\u03B1\u03BA\u03BF\u03C0\u03AE \u03B1\u03C0\u03AC\u03BD\u03C4\u03B7\u03C3\u03B7\u03C2"]
652
694
  };
653
695
 
654
696
  // src/dom/locale/es-419.ts
@@ -676,7 +718,8 @@ var es419 = {
676
718
  create_image: ["Crea una imagen"]
677
719
  },
678
720
  signedInMarkers: ["Nuevo chat", "Buscar chats", "Recientes", "Historial del chat", "Proyectos", "Chatear con ChatGPT"],
679
- responseActions: ["Copiar respuesta"]
721
+ responseActions: ["Copiar respuesta"],
722
+ stopControl: ["Detener respuesta"]
680
723
  };
681
724
 
682
725
  // src/dom/locale/et.ts
@@ -704,7 +747,8 @@ var et = {
704
747
  create_image: ["Loo pilt"]
705
748
  },
706
749
  signedInMarkers: ["Uus vestlus", "Otsi vestlusi", "Hiljutised", "Vestlusajalugu", "Projektid", "Vestle ChatGPT-ga"],
707
- responseActions: ["Kopeeri vastus"]
750
+ responseActions: ["Kopeeri vastus"],
751
+ stopControl: ["Peata vastamine"]
708
752
  };
709
753
 
710
754
  // src/dom/locale/fa.ts
@@ -733,7 +777,8 @@ var fa = {
733
777
  create_image: ["\u0627\u06CC\u062C\u0627\u062F \u062A\u0635\u0648\u06CC\u0631"]
734
778
  },
735
779
  signedInMarkers: ["\u06AF\u0641\u062A\u06AF\u0648\u06CC \u062C\u062F\u06CC\u062F", "\u062C\u0633\u062A\u200C\u0648\u062C\u0648\u06CC \u0686\u062A\u200C\u0647\u0627", "\u0645\u0648\u0627\u0631\u062F \u0627\u062E\u06CC\u0631", "\u062A\u0627\u0631\u06CC\u062E\u0686\u0647 \u06AF\u0641\u062A\u06AF\u0648", "\u067E\u0631\u0648\u0698\u0647\u200C\u0647\u0627", "\u06AF\u0641\u062A\u06AF\u0648 \u0628\u0627 ChatGPT"],
736
- responseActions: ["\u06A9\u067E\u06CC \u06A9\u0631\u062F\u0646 \u067E\u0627\u0633\u062E"]
780
+ responseActions: ["\u06A9\u067E\u06CC \u06A9\u0631\u062F\u0646 \u067E\u0627\u0633\u062E"],
781
+ stopControl: ["\u062A\u0648\u0642\u0641 \u067E\u0627\u0633\u062E \u06AF\u0648\u06CC\u06CC"]
737
782
  };
738
783
 
739
784
  // src/dom/locale/fi.ts
@@ -761,7 +806,8 @@ var fi = {
761
806
  create_image: ["Luo kuva"]
762
807
  },
763
808
  signedInMarkers: ["Uusi keskustelu", "Hae keskusteluista", "\xC4skett\xE4iset", "Keskusteluhistoria", "Projektit", "Keskustele ChatGPT:n kanssa"],
764
- responseActions: ["Kopioi vastaus"]
809
+ responseActions: ["Kopioi vastaus"],
810
+ stopControl: ["Lopeta vastaaminen"]
765
811
  };
766
812
 
767
813
  // src/dom/locale/fr-CA.ts
@@ -789,7 +835,8 @@ var frCA = {
789
835
  create_image: ["Cr\xE9er une image"]
790
836
  },
791
837
  signedInMarkers: ["Nouvelle session de clavardage", "Rechercher les clavardages", "R\xE9centes", "Historique des clavardages", "Projets", "Converser avec ChatGPT"],
792
- responseActions: ["Copier la r\xE9ponse"]
838
+ responseActions: ["Copier la r\xE9ponse"],
839
+ stopControl: ["Arr\xEAter de r\xE9pondre"]
793
840
  };
794
841
 
795
842
  // src/dom/locale/gu.ts
@@ -817,7 +864,8 @@ var gu = {
817
864
  create_image: ["\u0A9B\u0AAC\u0AC0 \u0AAC\u0AA8\u0ABE\u0AB5\u0ACB"]
818
865
  },
819
866
  signedInMarkers: ["\u0AA8\u0AB5\u0AC0 \u0A9A\u0AC7\u0A9F", "\u0A9A\u0AC7\u0A9F \u0AB6\u0ACB\u0AA7\u0ACB", "\u0AA4\u0ABE\u0A9C\u0AC7\u0AA4\u0AB0", "\u0A9A\u0AC7\u0A9F \u0A87\u0AA4\u0ABF\u0AB9\u0ABE\u0AB8", "\u0AAA\u0ACD\u0AB0\u0ACB\u0A9C\u0AC7\u0A95\u0ACD\u0A9F", "ChatGPT \u0AB8\u0ABE\u0AA5\u0AC7 \u0A9A\u0AC5\u0A9F"],
820
- responseActions: ["\u0AAA\u0ACD\u0AB0\u0AA4\u0ABF\u0AAD\u0ABE\u0AB5 \u0A95\u0AC9\u0AAA\u0ABF \u0A95\u0AB0\u0ACB"]
867
+ responseActions: ["\u0AAA\u0ACD\u0AB0\u0AA4\u0ABF\u0AAD\u0ABE\u0AB5 \u0A95\u0AC9\u0AAA\u0ABF \u0A95\u0AB0\u0ACB"],
868
+ stopControl: ["\u0A9C\u0AB5\u0ABE\u0AAC \u0A86\u0AAA\u0AB5\u0ABE\u0AA8\u0AC1\u0A82 \u0AAC\u0A82\u0AA7 \u0A95\u0AB0\u0ACB"]
821
869
  };
822
870
 
823
871
  // src/dom/locale/hi.ts
@@ -845,7 +893,8 @@ var hi = {
845
893
  create_image: ["\u0907\u092E\u0947\u091C \u092C\u0928\u093E\u090F\u0901"]
846
894
  },
847
895
  signedInMarkers: ["\u0928\u0908 \u091A\u0948\u091F", "\u091A\u0948\u091F \u0916\u094B\u091C\u0947\u0902", "\u0939\u093E\u0932\u093F\u092F\u093E", "\u091A\u0948\u091F \u0939\u093F\u0938\u094D\u091F\u0930\u0940", "\u092A\u094D\u0930\u094B\u091C\u0947\u0915\u094D\u091F\u094D\u0938", "ChatGPT \u0915\u0947 \u0938\u093E\u0925 \u091A\u0948\u091F \u0915\u0930\u0947\u0902"],
848
- responseActions: ["\u091C\u0935\u093E\u092C \u0915\u094B \u0915\u0949\u092A\u0940 \u0915\u0930\u0947\u0902"]
896
+ responseActions: ["\u091C\u0935\u093E\u092C \u0915\u094B \u0915\u0949\u092A\u0940 \u0915\u0930\u0947\u0902"],
897
+ stopControl: ["\u0909\u0924\u094D\u0924\u0930 \u0930\u094B\u0915\u0947\u0902"]
849
898
  };
850
899
 
851
900
  // src/dom/locale/hr.ts
@@ -872,7 +921,8 @@ var hr = {
872
921
  create_image: ["Stvaranje slike"]
873
922
  },
874
923
  signedInMarkers: ["Novi razgovor", "Pretra\u017Ei razgovore", "Nedavni sadr\u017Eaj", "Povijest razgovora", "Projekti", "Razgovor s ChatGPT-om"],
875
- responseActions: ["Kopiraj odgovor"]
924
+ responseActions: ["Kopiraj odgovor"],
925
+ stopControl: ["Zaustavi odgovaranje"]
876
926
  };
877
927
 
878
928
  // src/dom/locale/hu.ts
@@ -900,7 +950,8 @@ var hu = {
900
950
  create_image: ["K\xE9p l\xE9trehoz\xE1sa"]
901
951
  },
902
952
  signedInMarkers: ["\xDAj cseveg\xE9s", "Besz\xE9lget\xE9sek keres\xE9se", "Legut\xF3bbiak", "Cseveg\xE9si el\u0151zm\xE9nyek", "Projektek", "Cseveg\xE9s a ChatGPT-vel"],
903
- responseActions: ["V\xE1lasz m\xE1sol\xE1sa"]
953
+ responseActions: ["V\xE1lasz m\xE1sol\xE1sa"],
954
+ stopControl: ["V\xE1lasz le\xE1ll\xEDt\xE1sa"]
904
955
  };
905
956
 
906
957
  // src/dom/locale/hy.ts
@@ -929,7 +980,8 @@ var hy = {
929
980
  create_image: ["\u054D\u057F\u0565\u0572\u056E\u0565\u056C \u057A\u0561\u057F\u056F\u0565\u0580"]
930
981
  },
931
982
  signedInMarkers: ["\u0546\u0578\u0580 \u0566\u0580\u0578\u0582\u0575\u0581", "\u0548\u0580\u0578\u0576\u0565\u056C \u0566\u0580\u0578\u0582\u0575\u0581\u0576\u0565\u0580\u0568", "\u0539\u0561\u0580\u0574", "\u0536\u0580\u0578\u0582\u0575\u0581\u0576\u0565\u0580\u056B \u057A\u0561\u057F\u0574\u0578\u0582\u0569\u0575\u0578\u0582\u0576", "\u0546\u0561\u056D\u0561\u0563\u056E\u0565\u0580", "\u0536\u0580\u0578\u0582\u0575\u0581 ChatGPT-\u056B \u0570\u0565\u057F"],
932
- responseActions: ["\u054A\u0561\u057F\u0573\u0565\u0576\u0565\u056C \u057A\u0561\u057F\u0561\u057D\u056D\u0561\u0576\u0568"]
983
+ responseActions: ["\u054A\u0561\u057F\u0573\u0565\u0576\u0565\u056C \u057A\u0561\u057F\u0561\u057D\u056D\u0561\u0576\u0568"],
984
+ stopControl: ["\u0534\u0561\u0564\u0561\u0580\u0565\u0581\u0576\u0565\u056C \u057A\u0561\u057F\u0561\u057D\u056D\u0561\u0576\u0565\u056C\u0568"]
933
985
  };
934
986
 
935
987
  // src/dom/locale/id.ts
@@ -957,7 +1009,8 @@ var id = {
957
1009
  create_image: ["Buat gambar"]
958
1010
  },
959
1011
  signedInMarkers: ["Obrolan baru", "Cari obrolan", "Terkini", "Riwayat obrolan", "Proyek", "Obrolan dengan ChatGPT"],
960
- responseActions: ["Salin respons"]
1012
+ responseActions: ["Salin respons"],
1013
+ stopControl: ["Hentikan jawaban"]
961
1014
  };
962
1015
 
963
1016
  // src/dom/locale/is.ts
@@ -985,7 +1038,8 @@ var is = {
985
1038
  create_image: ["B\xFAa til mynd"]
986
1039
  },
987
1040
  signedInMarkers: ["N\xFDtt spjall", "Leita \xED spj\xF6llum", "N\xFDlegt", "Spjallferill", "Verkefni", "Spjalla\xF0u vi\xF0 ChatGPT"],
988
- responseActions: ["Afrita svar"]
1041
+ responseActions: ["Afrita svar"],
1042
+ stopControl: ["H\xE6tta a\xF0 svara"]
989
1043
  };
990
1044
 
991
1045
  // src/dom/locale/ka.ts
@@ -1013,7 +1067,8 @@ var ka = {
1013
1067
  create_image: ["\u10E8\u10D4\u10E5\u10DB\u10D4\u10DC\u10D8 \u10E1\u10E3\u10E0\u10D0\u10D7\u10D8"]
1014
1068
  },
1015
1069
  signedInMarkers: ["\u10D0\u10EE\u10D0\u10DA\u10D8 \u10E9\u10D0\u10E2\u10D8", "\u10E9\u10D0\u10E2\u10D4\u10D1\u10D8\u10E1 \u10EB\u10D8\u10D4\u10D1\u10D0", "\u10D1\u10DD\u10DA\u10DD\u10D3\u10E0\u10DD\u10D8\u10DC\u10D3\u10D4\u10DA\u10D8", "\u10E9\u10D0\u10E2\u10D8\u10E1 \u10D8\u10E1\u10E2\u10DD\u10E0\u10D8\u10D0", "\u10DE\u10E0\u10DD\u10D4\u10E5\u10E2\u10D4\u10D1\u10D8", "\u10E1\u10D0\u10E3\u10D1\u10D0\u10E0\u10D8 ChatGPT-\u10E1\u10D7\u10D0\u10DC"],
1016
- responseActions: ["\u10DE\u10D0\u10E1\u10E3\u10EE\u10D8\u10E1 \u10D9\u10DD\u10DE\u10D8\u10E0\u10D4\u10D1\u10D0"]
1070
+ responseActions: ["\u10DE\u10D0\u10E1\u10E3\u10EE\u10D8\u10E1 \u10D9\u10DD\u10DE\u10D8\u10E0\u10D4\u10D1\u10D0"],
1071
+ stopControl: ["\u10DE\u10D0\u10E1\u10E3\u10EE\u10D8\u10E1 \u10E8\u10D4\u10EC\u10E7\u10D5\u10D4\u10E2\u10D0"]
1017
1072
  };
1018
1073
 
1019
1074
  // src/dom/locale/kk.ts
@@ -1041,7 +1096,8 @@ var kk = {
1041
1096
  create_image: ["\u0421\u0443\u0440\u0435\u0442 \u0436\u0430\u0441\u0430"]
1042
1097
  },
1043
1098
  signedInMarkers: ["\u0416\u0430\u04A3\u0430 \u0447\u0430\u0442", "\u0427\u0430\u0442\u0442\u0430\u0440\u0434\u044B \u0456\u0437\u0434\u0435\u0443", "\u0421\u043E\u04A3\u0493\u044B\u043B\u0430\u0440\u044B", "\u0427\u0430\u0442 \u0442\u0430\u0440\u0438\u0445\u044B", "\u0416\u043E\u0431\u0430\u043B\u0430\u0440", "ChatGPT-\u043C\u0435\u043D \u0447\u0430\u0442"],
1044
- responseActions: ["\u0416\u0430\u0443\u0430\u043F\u0442\u044B \u043A\u04E9\u0448\u0456\u0440\u0443"]
1099
+ responseActions: ["\u0416\u0430\u0443\u0430\u043F\u0442\u044B \u043A\u04E9\u0448\u0456\u0440\u0443"],
1100
+ stopControl: ["\u0416\u0430\u0443\u0430\u043F \u0431\u0435\u0440\u0443\u0434\u0456 \u0442\u043E\u049B\u0442\u0430\u0442\u0443"]
1045
1101
  };
1046
1102
 
1047
1103
  // src/dom/locale/kn.ts
@@ -1070,7 +1126,8 @@ var kn = {
1070
1126
  create_image: ["\u0C87\u0CAE\u0CC7\u0C9C\u0CCD \u0CB0\u0C9A\u0CBF\u0CB8\u0CBF"]
1071
1127
  },
1072
1128
  signedInMarkers: ["\u0CB9\u0CCA\u0CB8 \u0C9A\u0CBE\u0C9F\u0CCD", "\u0C9A\u0CBE\u0C9F\u0CCD\u200C\u0C97\u0CB3\u0CA8\u0CCD\u0CA8\u0CC1 \u0CB9\u0CC1\u0CA1\u0CC1\u0C95\u0CBF", "\u0C87\u0CA4\u0CCD\u0CA4\u0CC0\u0C9A\u0CBF\u0CA8\u0CA6\u0CC1", "\u0C9A\u0CBE\u0C9F\u0CCD \u0C87\u0CA4\u0CBF\u0CB9\u0CBE\u0CB8", "\u0CAA\u0CCD\u0CB0\u0CBE\u0C9C\u0CC6\u0C95\u0CCD\u0C9F\u0CCD\u200C\u0C97\u0CB3\u0CC1", "ChatGPT \u0C9C\u0CCA\u0CA4\u0CC6\u0C97\u0CC6 \u0C9A\u0CBE\u0C9F\u0CCD \u0CAE\u0CBE\u0CA1\u0CBF"],
1073
- responseActions: ["\u0CAA\u0CCD\u0CB0\u0CA4\u0CBF\u0C95\u0CCD\u0CB0\u0CBF\u0CAF\u0CC6\u0CAF\u0CA8\u0CCD\u0CA8\u0CC1 \u0CA8\u0C95\u0CB2\u0CBF\u0CB8\u0CBF"]
1129
+ responseActions: ["\u0CAA\u0CCD\u0CB0\u0CA4\u0CBF\u0C95\u0CCD\u0CB0\u0CBF\u0CAF\u0CC6\u0CAF\u0CA8\u0CCD\u0CA8\u0CC1 \u0CA8\u0C95\u0CB2\u0CBF\u0CB8\u0CBF"],
1130
+ stopControl: ["\u0C89\u0CA4\u0CCD\u0CA4\u0CB0\u0CBF\u0CB8\u0CC1\u0CB5\u0CC1\u0CA6\u0CA8\u0CCD\u0CA8\u0CC1 \u0CA8\u0CBF\u0CB2\u0CCD\u0CB2\u0CBF\u0CB8\u0CBF"]
1074
1131
  };
1075
1132
 
1076
1133
  // src/dom/locale/ko.ts
@@ -1098,7 +1155,8 @@ var ko = {
1098
1155
  create_image: ["\uC774\uBBF8\uC9C0 \uB9CC\uB4E4\uAE30"]
1099
1156
  },
1100
1157
  signedInMarkers: ["\uC0C8 \uCC44\uD305", "\uCC44\uD305 \uAC80\uC0C9", "\uCD5C\uADFC", "\uCC44\uD305 \uAE30\uB85D", "\uD504\uB85C\uC81D\uD2B8", "ChatGPT\uC640 \uCC44\uD305"],
1101
- responseActions: ["\uC751\uB2F5 \uBCF5\uC0AC"]
1158
+ responseActions: ["\uC751\uB2F5 \uBCF5\uC0AC"],
1159
+ stopControl: ["\uB2F5\uBCC0 \uC911\uC9C0"]
1102
1160
  };
1103
1161
 
1104
1162
  // src/dom/locale/lt.ts
@@ -1127,7 +1185,8 @@ var lt = {
1127
1185
  create_image: ["Sukurti vaizd\u0105"]
1128
1186
  },
1129
1187
  signedInMarkers: ["Naujas pokalbis", "Ie\u0161koti pokalbiuose", "V\u0117liausieji", "Pokalbi\u0173 istorija", "Projektai", 'Pokalbis su \u201EChatGPT"'],
1130
- responseActions: ["Kopijuoti atsakym\u0105"]
1188
+ responseActions: ["Kopijuoti atsakym\u0105"],
1189
+ stopControl: ["Stabdyti atsakym\u0105"]
1131
1190
  };
1132
1191
 
1133
1192
  // src/dom/locale/zh-Hans.ts
@@ -1156,7 +1215,8 @@ var zhHans = {
1156
1215
  create_image: ["\u521B\u5EFA\u56FE\u7247"]
1157
1216
  },
1158
1217
  signedInMarkers: ["\u65B0\u804A\u5929", "\u641C\u7D22\u804A\u5929", "\u6700\u8FD1", "\u5386\u53F2\u804A\u5929\u8BB0\u5F55", "\u9879\u76EE", "\u6709\u95EE\u9898\uFF0C\u5C3D\u7BA1\u95EE"],
1159
- responseActions: ["\u590D\u5236\u56DE\u590D"]
1218
+ responseActions: ["\u590D\u5236\u56DE\u590D"],
1219
+ stopControl: ["\u505C\u6B62\u56DE\u7B54"]
1160
1220
  };
1161
1221
 
1162
1222
  // src/dom/locale/ur.ts
@@ -1184,7 +1244,8 @@ var ur = {
1184
1244
  create_image: ["\u062A\u0635\u0648\u06CC\u0631 \u0628\u0646\u0627\u0626\u06CC\u06BA"]
1185
1245
  },
1186
1246
  signedInMarkers: ["\u0646\u0626\u06CC \u0686\u06CC\u0679", "\u0686\u06CC\u0679\u0633 \u062A\u0644\u0627\u0634 \u06A9\u0631\u06CC\u06BA", "\u062D\u0627\u0644\u06CC\u06C1", "\u0686\u06CC\u0679 \u06C1\u0633\u0679\u0631\u06CC", "\u067E\u0631\u0627\u062C\u06CC\u06A9\u0679\u0633", "\u06A9\u0648\u0626\u06CC \u0628\u06BE\u06CC \u0686\u06CC\u0632 \u067E\u0648\u0686\u06BE\u06CC\u06BA\u06D4\u06D4\u06D4"],
1187
- responseActions: ["\u062C\u0648\u0627\u0628 \u06A9\u0627\u067E\u06CC \u06A9\u0631\u06CC\u06BA"]
1247
+ responseActions: ["\u062C\u0648\u0627\u0628 \u06A9\u0627\u067E\u06CC \u06A9\u0631\u06CC\u06BA"],
1248
+ stopControl: ["\u062C\u0648\u0627\u0628 \u0631\u0648\u06A9\u06CC\u06BA"]
1188
1249
  };
1189
1250
 
1190
1251
  // src/dom/locale/uk.ts
@@ -1212,7 +1273,8 @@ var uk = {
1212
1273
  create_image: ["\u0421\u0442\u0432\u043E\u0440\u0438\u0442\u0438 \u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u043D\u044F"]
1213
1274
  },
1214
1275
  signedInMarkers: ["\u041D\u043E\u0432\u0438\u0439 \u0447\u0430\u0442", "\u041F\u043E\u0448\u0443\u043A \u0447\u0430\u0442\u0456\u0432", "\u041D\u0435\u0449\u043E\u0434\u0430\u0432\u043D\u0456", "\u0406\u0441\u0442\u043E\u0440\u0456\u044F \u0447\u0430\u0442\u0456\u0432", "\u041F\u0440\u043E\u0454\u043A\u0442\u0438", "\u0417\u0430\u043F\u0438\u0442\u0430\u0439\u0442\u0435 \u0431\u0443\u0434\u044C-\u0449\u043E"],
1215
- responseActions: ["\u041A\u043E\u043F\u0456\u044E\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u044C"]
1276
+ responseActions: ["\u041A\u043E\u043F\u0456\u044E\u0432\u0430\u0442\u0438 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u044C"],
1277
+ stopControl: ["\u0417\u0443\u043F\u0438\u043D\u0438\u0442\u0438 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u044C"]
1216
1278
  };
1217
1279
 
1218
1280
  // src/dom/locale/pt-BR.ts
@@ -1240,7 +1302,8 @@ var ptBR = {
1240
1302
  create_image: ["Criar imagem"]
1241
1303
  },
1242
1304
  signedInMarkers: ["Novo chat", "Buscar chats", "Recentes", "Hist\xF3rico de chats", "Projetos", "Pergunte alguma coisa"],
1243
- responseActions: ["Copiar resposta"]
1305
+ responseActions: ["Copiar resposta"],
1306
+ stopControl: ["Parar de responder"]
1244
1307
  };
1245
1308
 
1246
1309
  // src/dom/locale/pt-PT.ts
@@ -1268,7 +1331,8 @@ var ptPT = {
1268
1331
  create_image: ["Criar imagem"]
1269
1332
  },
1270
1333
  signedInMarkers: ["Novo chat", "Pesquisar chats", "Recentes", "Hist\xF3rico de chat", "Projetos", "Pergunte qualquer coisa"],
1271
- responseActions: ["Copiar resposta"]
1334
+ responseActions: ["Copiar resposta"],
1335
+ stopControl: ["Parar resposta"]
1272
1336
  };
1273
1337
 
1274
1338
  // src/dom/locale/pl.ts
@@ -1296,7 +1360,8 @@ var pl = {
1296
1360
  create_image: ["Stw\xF3rz obraz"]
1297
1361
  },
1298
1362
  signedInMarkers: ["Nowy czat", "Szukaj czat\xF3w", "Ostatnie", "Historia czatu", "Projekty", "Zapytaj o cokolwiek"],
1299
- responseActions: ["Kopiuj odpowied\u017A"]
1363
+ responseActions: ["Kopiuj odpowied\u017A"],
1364
+ stopControl: ["Przerwij odpowied\u017A"]
1300
1365
  };
1301
1366
 
1302
1367
  // src/dom/locale/sk.ts
@@ -1324,7 +1389,8 @@ var sk = {
1324
1389
  create_image: ["Vytvor obr\xE1zok"]
1325
1390
  },
1326
1391
  signedInMarkers: ["Nov\xFD \u010Det", "H\u013Eada\u0165 v \u010Detoch", "Ned\xE1vne", "Hist\xF3ria \u010Detov", "Projekty", "Sp\xFDtaj sa hoci\u010Do\u2026"],
1327
- responseActions: ["Kop\xEDrova\u0165 odpove\u010F"]
1392
+ responseActions: ["Kop\xEDrova\u0165 odpove\u010F"],
1393
+ stopControl: ["Zastavi\u0165 odpove\u010F"]
1328
1394
  };
1329
1395
 
1330
1396
  // src/dom/locale/ro.ts
@@ -1351,7 +1417,8 @@ var ro = {
1351
1417
  create_image: ["Creeaz\u0103 o imagine"]
1352
1418
  },
1353
1419
  signedInMarkers: ["Discu\u021Bie nou\u0103", "Caut\u0103 discu\u021Bii", "Recente", "Istoricul discu\u021Biilor", "Proiecte", "\xCEntreab\u0103 orice"],
1354
- responseActions: ["Copiaz\u0103 r\u0103spunsul"]
1420
+ responseActions: ["Copiaz\u0103 r\u0103spunsul"],
1421
+ stopControl: ["Opre\u0219te r\u0103spunsul"]
1355
1422
  };
1356
1423
 
1357
1424
  // src/dom/locale/nb.ts
@@ -1379,7 +1446,8 @@ var nb = {
1379
1446
  create_image: ["Lag et bilde"]
1380
1447
  },
1381
1448
  signedInMarkers: ["Ny chat", "S\xF8k i samtaler", "Nylige", "Chattehistorikk", "Prosjekter", "Sp\xF8r om hva som helst"],
1382
- responseActions: ["Kopier svar"]
1449
+ responseActions: ["Kopier svar"],
1450
+ stopControl: ["Avbryt svar"]
1383
1451
  };
1384
1452
 
1385
1453
  // src/dom/locale/ml.ts
@@ -1408,7 +1476,8 @@ var ml = {
1408
1476
  create_image: ["\u0D1A\u0D3F\u0D24\u0D4D\u0D30\u0D02 \u0D38\u0D43\u0D37\u0D4D\u0D1F\u0D3F\u0D15\u0D4D\u0D15\u0D41\u0D15"]
1409
1477
  },
1410
1478
  signedInMarkers: ["\u0D2A\u0D41\u0D24\u0D3F\u0D2F \u0D1A\u0D3E\u0D31\u0D4D\u0D31\u0D4D", "\u0D1A\u0D3E\u0D31\u0D4D\u0D31\u0D41\u0D15\u0D7E \u0D24\u0D3F\u0D30\u0D2F\u0D41\u0D15", "\u0D38\u0D2E\u0D40\u0D2A\u0D15\u0D3E\u0D32\u0D24\u0D4D\u0D24\u0D41\u0D33\u0D4D\u0D33", "\u0D1A\u0D3E\u0D31\u0D4D\u0D31\u0D4D \u0D1A\u0D30\u0D3F\u0D24\u0D4D\u0D30\u0D02", "\u0D2A\u0D4D\u0D30\u0D4B\u0D1C\u0D15\u0D4D\u0D31\u0D4D\u0D31\u0D41\u0D15\u0D7E", "\u0D0E\u0D28\u0D4D\u0D24\u0D41\u0D02 \u0D1A\u0D4B\u0D26\u0D3F\u0D15\u0D4D\u0D15\u0D41\u0D15"],
1411
- responseActions: ["\u0D2E\u0D31\u0D41\u0D2A\u0D1F\u0D3F \u0D15\u0D4B\u0D2A\u0D4D\u0D2A\u0D3F \u0D1A\u0D46\u0D2F\u0D4D\u0D2F\u0D41\u0D15"]
1479
+ responseActions: ["\u0D2E\u0D31\u0D41\u0D2A\u0D1F\u0D3F \u0D15\u0D4B\u0D2A\u0D4D\u0D2A\u0D3F \u0D1A\u0D46\u0D2F\u0D4D\u0D2F\u0D41\u0D15"],
1480
+ stopControl: ["\u0D2E\u0D31\u0D41\u0D2A\u0D1F\u0D3F \u0D28\u0D3F\u0D7C\u0D24\u0D4D\u0D24\u0D41\u0D15"]
1412
1481
  };
1413
1482
 
1414
1483
  // src/dom/locale/ru.ts
@@ -1433,7 +1502,8 @@ var ru = {
1433
1502
  create_image: ["\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435"]
1434
1503
  },
1435
1504
  signedInMarkers: ["\u041D\u043E\u0432\u044B\u0439 \u0447\u0430\u0442", "\u0418\u0441\u043A\u0430\u0442\u044C \u0447\u0430\u0442\u044B", "\u041D\u0435\u0434\u0430\u0432\u043D\u0435\u0435", "\u0418\u0441\u0442\u043E\u0440\u0438\u044F \u0447\u0430\u0442\u0430", "\u041F\u0440\u043E\u0435\u043A\u0442\u044B", "\u0421\u043F\u0440\u043E\u0441\u0438\u0442\u0435 ChatGPT"],
1436
- responseActions: ["\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043E\u0442\u0432\u0435\u0442"]
1505
+ responseActions: ["\u041A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043E\u0442\u0432\u0435\u0442"],
1506
+ stopControl: ["\u041E\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u043E\u0442\u0432\u0435\u0442"]
1437
1507
  };
1438
1508
 
1439
1509
  // src/dom/locale/pa.ts
@@ -1462,7 +1532,8 @@ var pa = {
1462
1532
  create_image: ["\u0A24\u0A38\u0A35\u0A40\u0A30 \u0A2C\u0A23\u0A3E\u0A09"]
1463
1533
  },
1464
1534
  signedInMarkers: ["\u0A28\u0A35\u0A40\u0A02 \u0A1A\u0A48\u0A1F", "\u0A1A\u0A48\u0A1F\u0A3E\u0A02 \u0A16\u0A4B\u0A1C\u0A4B", "\u0A39\u0A3E\u0A32\u0A40\u0A06", "\u0A1A\u0A48\u0A1F \u0A39\u0A3F\u0A38\u0A1F\u0A30\u0A40", "\u0A2A\u0A4D\u0A30\u0A4B\u0A1C\u0A48\u0A15\u0A1F", "\u0A15\u0A41\u0A1D \u0A35\u0A40 \u0A2A\u0A41\u0A71\u0A1B\u0A4B"],
1465
- responseActions: ["\u0A1C\u0A35\u0A3E\u0A2C \u0A15\u0A3E\u0A2A\u0A40 \u0A15\u0A30\u0A4B"]
1535
+ responseActions: ["\u0A1C\u0A35\u0A3E\u0A2C \u0A15\u0A3E\u0A2A\u0A40 \u0A15\u0A30\u0A4B"],
1536
+ stopControl: ["\u0A1C\u0A35\u0A3E\u0A2C \u0A26\u0A47\u0A23\u0A3E \u0A2C\u0A70\u0A26 \u0A15\u0A30\u0A4B"]
1466
1537
  };
1467
1538
 
1468
1539
  // src/dom/locale/mr.ts
@@ -1491,7 +1562,8 @@ var mr = {
1491
1562
  create_image: ["\u092A\u094D\u0930\u0924\u093F\u092E\u093E \u0924\u092F\u093E\u0930 \u0915\u0930\u093E"]
1492
1563
  },
1493
1564
  signedInMarkers: ["\u0928\u0935\u0940\u0928 \u091A\u0945\u091F", "\u091A\u0945\u091F\u094D\u0938 \u0936\u094B\u0927\u093E", "\u0905\u0932\u0940\u0915\u0921\u0940\u0932", "\u091A\u0945\u091F \u0907\u0924\u093F\u0939\u093E\u0938", "\u092A\u094D\u0930\u094B\u091C\u0947\u0915\u094D\u091F\u094D\u0938", "\u0915\u093E\u0939\u0940\u0939\u0940 \u0935\u093F\u091A\u093E\u0930\u093E"],
1494
- responseActions: ["\u092A\u094D\u0930\u0924\u093F\u0938\u093E\u0926 \u0915\u0949\u092A\u0940 \u0915\u0930\u093E"]
1565
+ responseActions: ["\u092A\u094D\u0930\u0924\u093F\u0938\u093E\u0926 \u0915\u0949\u092A\u0940 \u0915\u0930\u093E"],
1566
+ stopControl: ["\u0909\u0924\u094D\u0924\u0930 \u0925\u093E\u0902\u092C\u0935\u093E"]
1495
1567
  };
1496
1568
 
1497
1569
  // src/dom/locale/tr.ts
@@ -1519,7 +1591,8 @@ var tr = {
1519
1591
  create_image: ["G\xF6rsel olu\u015Ftur"]
1520
1592
  },
1521
1593
  signedInMarkers: ["Yeni sohbet", "Sohbetlerde ara", "Yak\u0131n zamandakiler", "Sohbet ge\xE7mi\u015Fi", "Projeler", "Herhangi bir \u015Fey sor"],
1522
- responseActions: ["Yan\u0131t\u0131 kopyala"]
1594
+ responseActions: ["Yan\u0131t\u0131 kopyala"],
1595
+ stopControl: ["Yan\u0131tlamay\u0131 durdur"]
1523
1596
  };
1524
1597
 
1525
1598
  // src/dom/locale/sw.ts
@@ -1547,7 +1620,8 @@ var sw = {
1547
1620
  create_image: ["Unda picha"]
1548
1621
  },
1549
1622
  signedInMarkers: ["Chati mpya", "Tafuta mazungumzo", "Hivi karibuni", "Historia ya chati", "Miradi", "Uliza chochote"],
1550
- responseActions: ["Nakili jibu"]
1623
+ responseActions: ["Nakili jibu"],
1624
+ stopControl: ["Sitisha kujibu"]
1551
1625
  };
1552
1626
 
1553
1627
  // src/dom/locale/te.ts
@@ -1576,7 +1650,8 @@ var te = {
1576
1650
  create_image: ["\u0C1A\u0C3F\u0C24\u0C4D\u0C30\u0C3E\u0C28\u0C4D\u0C28\u0C3F \u0C38\u0C43\u0C37\u0C4D\u0C1F\u0C3F\u0C02\u0C1A\u0C41"]
1577
1651
  },
1578
1652
  signedInMarkers: ["\u0C15\u0C4A\u0C24\u0C4D\u0C24 \u0C1A\u0C3E\u0C1F\u0C4D", "\u0C1A\u0C3E\u0C1F\u0C4D\u200C\u0C32\u0C28\u0C41 \u0C36\u0C4B\u0C27\u0C3F\u0C02\u0C1A\u0C02\u0C21\u0C3F", "\u0C07\u0C1F\u0C40\u0C35\u0C32\u0C3F\u0C35\u0C3F", "\u0C1A\u0C3E\u0C1F\u0C4D \u0C1A\u0C30\u0C3F\u0C24\u0C4D\u0C30", "\u0C2A\u0C4D\u0C30\u0C3E\u0C1C\u0C46\u0C15\u0C4D\u0C1F\u0C4D\u200C\u0C32\u0C41", "\u0C0F\u0C26\u0C48\u0C28\u0C3E \u0C05\u0C21\u0C17\u0C02\u0C21\u0C3F"],
1579
- responseActions: ["\u0C2A\u0C4D\u0C30\u0C24\u0C3F\u0C38\u0C4D\u0C2A\u0C02\u0C26\u0C28\u0C28\u0C41 \u0C15\u0C3E\u0C2A\u0C40 \u0C1A\u0C47\u0C2F\u0C02\u0C21\u0C3F"]
1653
+ responseActions: ["\u0C2A\u0C4D\u0C30\u0C24\u0C3F\u0C38\u0C4D\u0C2A\u0C02\u0C26\u0C28\u0C28\u0C41 \u0C15\u0C3E\u0C2A\u0C40 \u0C1A\u0C47\u0C2F\u0C02\u0C21\u0C3F"],
1654
+ stopControl: ["\u0C38\u0C2E\u0C3E\u0C27\u0C3E\u0C28\u0C02 \u0C07\u0C35\u0C4D\u0C35\u0C21\u0C02 \u0C06\u0C2A\u0C41"]
1580
1655
  };
1581
1656
 
1582
1657
  // src/dom/locale/tl.ts
@@ -1596,7 +1671,8 @@ var tl = {
1596
1671
  create_image: ["Gumawa ng larawan"]
1597
1672
  },
1598
1673
  signedInMarkers: ["Bagong chat", "Maghanap sa mga chat", "Mga kamakailan", "History ng chat", "Mga proyekto", "Mag-chat sa ChatGPT"],
1599
- responseActions: ["Kopyahin ang sagot"]
1674
+ responseActions: ["Kopyahin ang sagot"],
1675
+ stopControl: ["Itigil ang pagsagot"]
1600
1676
  };
1601
1677
 
1602
1678
  // src/dom/locale/th.ts
@@ -1624,7 +1700,8 @@ var th = {
1624
1700
  create_image: ["\u0E2A\u0E23\u0E49\u0E32\u0E07\u0E23\u0E39\u0E1B\u0E20\u0E32\u0E1E"]
1625
1701
  },
1626
1702
  signedInMarkers: ["\u0E41\u0E0A\u0E15\u0E43\u0E2B\u0E21\u0E48", "\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E41\u0E0A\u0E15", "\u0E40\u0E21\u0E37\u0E48\u0E2D\u0E40\u0E23\u0E47\u0E27\u0E46 \u0E19\u0E35\u0E49", "\u0E1B\u0E23\u0E30\u0E27\u0E31\u0E15\u0E34\u0E01\u0E32\u0E23\u0E41\u0E0A\u0E15", "\u0E42\u0E04\u0E23\u0E07\u0E01\u0E32\u0E23", "\u0E16\u0E32\u0E21\u0E2D\u0E30\u0E44\u0E23\u0E01\u0E47\u0E44\u0E14\u0E49"],
1627
- responseActions: ["\u0E04\u0E31\u0E14\u0E25\u0E2D\u0E01\u0E04\u0E33\u0E15\u0E2D\u0E1A"]
1703
+ responseActions: ["\u0E04\u0E31\u0E14\u0E25\u0E2D\u0E01\u0E04\u0E33\u0E15\u0E2D\u0E1A"],
1704
+ stopControl: ["\u0E2B\u0E22\u0E38\u0E14\u0E15\u0E2D\u0E1A"]
1628
1705
  };
1629
1706
 
1630
1707
  // src/dom/locale/bn.ts
@@ -1653,7 +1730,8 @@ var bn = {
1653
1730
  create_image: ["\u099B\u09AC\u09BF \u09A4\u09C8\u09B0\u09BF \u0995\u09B0\u09C1\u09A8"]
1654
1731
  },
1655
1732
  signedInMarkers: ["\u09A8\u09A4\u09C1\u09A8 \u099A\u09CD\u09AF\u09BE\u099F", "\u099A\u09CD\u09AF\u09BE\u099F \u0996\u09C1\u0981\u099C\u09C1\u09A8", "\u09B8\u09BE\u09AE\u09CD\u09AA\u09CD\u09B0\u09A4\u09BF\u0995", "\u099A\u09CD\u09AF\u09BE\u099F\u09C7\u09B0 \u0987\u09A4\u09BF\u09B9\u09BE\u09B8", "\u09AA\u09CD\u09B0\u09CB\u099C\u09C7\u0995\u09CD\u099F", "\u09AF\u09C7 \u0995\u09CB\u09A8 \u0995\u09BF\u099B\u09C1 \u099C\u09BF\u099C\u09CD\u099E\u09C7\u09B8 \u0995\u09B0\u09C1\u09A8\u2026"],
1656
- responseActions: ["\u0989\u09A4\u09CD\u09A4\u09B0 \u0995\u09AA\u09BF \u0995\u09B0\u09C1\u09A8"]
1733
+ responseActions: ["\u0989\u09A4\u09CD\u09A4\u09B0 \u0995\u09AA\u09BF \u0995\u09B0\u09C1\u09A8"],
1734
+ stopControl: ["\u0989\u09A4\u09CD\u09A4\u09B0 \u09A5\u09BE\u09AE\u09BE\u09A8"]
1657
1735
  };
1658
1736
 
1659
1737
  // src/dom/locale/ms.ts
@@ -1681,7 +1759,8 @@ var ms = {
1681
1759
  create_image: ["Cipta imej"]
1682
1760
  },
1683
1761
  signedInMarkers: ["Sembang baharu", "Cari sembang", "Terbaharu", "Sejarah sembang", "Projek", "Tanya apa-apa sahaja..."],
1684
- responseActions: ["Salin tindak balas"]
1762
+ responseActions: ["Salin tindak balas"],
1763
+ stopControl: ["Hentikan jawapan"]
1685
1764
  };
1686
1765
 
1687
1766
  // src/dom/locale/so.ts
@@ -1709,7 +1788,8 @@ var so = {
1709
1788
  create_image: ["Abuur sawir"]
1710
1789
  },
1711
1790
  signedInMarkers: ["Wada Sheekeysi cusub", "Raadi wada-sheekaysiyada", "Waxyaabihii dhawaa", "Taariikhda sheekeysiga", "Mashruucyada", "Waydii waxkasta"],
1712
- responseActions: ["Koobiyee jawaabta"]
1791
+ responseActions: ["Koobiyee jawaabta"],
1792
+ stopControl: ["Jooji jawaabista"]
1713
1793
  };
1714
1794
 
1715
1795
  // src/dom/locale/nl.ts
@@ -1737,7 +1817,8 @@ var nl = {
1737
1817
  create_image: ["Maak een afbeelding"]
1738
1818
  },
1739
1819
  signedInMarkers: ["Nieuwe chat", "Chats doorzoeken", "Recente items", "Chatgeschiedenis", "Projecten", "Stel een vraag"],
1740
- responseActions: ["Reactie kopi\xEBren"]
1820
+ responseActions: ["Reactie kopi\xEBren"],
1821
+ stopControl: ["Prompt versturen"]
1741
1822
  };
1742
1823
 
1743
1824
  // src/dom/locale/sv.ts
@@ -1765,7 +1846,8 @@ var sv = {
1765
1846
  create_image: ["Skapa en bild"]
1766
1847
  },
1767
1848
  signedInMarkers: ["Ny chatt", "S\xF6k i chattar", "Senaste", "Chatthistorik", "Projekt", "Fr\xE5ga vad som helst"],
1768
- responseActions: ["Kopiera svar"]
1849
+ responseActions: ["Kopiera svar"],
1850
+ stopControl: ["Sluta svara"]
1769
1851
  };
1770
1852
 
1771
1853
  // src/dom/locale/lv.ts
@@ -1793,7 +1875,8 @@ var lv = {
1793
1875
  create_image: ["Izveido att\u0113lu"]
1794
1876
  },
1795
1877
  signedInMarkers: ["Jauna t\u0113rz\u0113tava", "Mekl\u0113t t\u0113rz\u0113\u0161anas", "Nesen\u0101s sarunas", "T\u0113rz\u0113\u0161anas v\u0113sture", "Projekti", "Jaut\u0101 jebko"],
1796
- responseActions: ["Kop\u0113t atbildi"]
1878
+ responseActions: ["Kop\u0113t atbildi"],
1879
+ stopControl: ["P\u0101rtraukt atbildi"]
1797
1880
  };
1798
1881
 
1799
1882
  // src/dom/locale/mk.ts
@@ -1820,7 +1903,8 @@ var mk = {
1820
1903
  create_image: ["\u041A\u0440\u0435\u0438\u0440\u0430\u0458 \u0441\u043B\u0438\u043A\u0430"]
1821
1904
  },
1822
1905
  signedInMarkers: ["\u041D\u043E\u0432 \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440", "\u041F\u0440\u0435\u0431\u0430\u0440\u0430\u0458 \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440\u0438", "\u041D\u0435\u043E\u0434\u0430\u043C\u043D\u0435\u0448\u043D\u0438", "\u0418\u0441\u0442\u043E\u0440\u0438\u0458\u0430 \u043D\u0430 \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440\u0438", "\u041F\u0440\u043E\u0435\u043A\u0442\u0438", "\u041F\u0440\u0430\u0448\u0430\u0458 \u0448\u0442\u043E \u0431\u0438\u043B\u043E"],
1823
- responseActions: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0458 \u043E\u0434\u0433\u043E\u0432\u043E\u0440"]
1906
+ responseActions: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0458 \u043E\u0434\u0433\u043E\u0432\u043E\u0440"],
1907
+ stopControl: ["\u0421\u043E\u043F\u0440\u0438 \u043E\u0434\u0433\u043E\u0432\u0430\u0440\u0430\u045A\u0435"]
1824
1908
  };
1825
1909
 
1826
1910
  // src/dom/locale/sq.ts
@@ -1848,7 +1932,8 @@ var sq = {
1848
1932
  create_image: ["Krijo nj\xEB imazh"]
1849
1933
  },
1850
1934
  signedInMarkers: ["Bised\xEB e re", "K\xEBrko bisedat", "M\xEB t\xEB fundit", "Historia e bised\xEBs", "Projektet", "Pyet p\xEBr \xE7do gj\xEB"],
1851
- responseActions: ["Kopjo p\xEBrgjigjen"]
1935
+ responseActions: ["Kopjo p\xEBrgjigjen"],
1936
+ stopControl: ["Ndalo p\xEBrgjigjen"]
1852
1937
  };
1853
1938
 
1854
1939
  // src/dom/locale/sl.ts
@@ -1876,7 +1961,8 @@ var sl = {
1876
1961
  create_image: ["Ustvari sliko"]
1877
1962
  },
1878
1963
  signedInMarkers: ["Nov klepet", "I\u0161\u010Di po klepetih", "Nedavno", "Zgodovina klepetov", "Projekti", "Vpra\u0161ajte kar koli"],
1879
- responseActions: ["Kopiraj odgovor"]
1964
+ responseActions: ["Kopiraj odgovor"],
1965
+ stopControl: ["Ustavi odgovarjanje"]
1880
1966
  };
1881
1967
 
1882
1968
  // src/dom/locale/sr.ts
@@ -1901,7 +1987,8 @@ var sr = {
1901
1987
  create_image: ["\u041D\u0430\u043F\u0440\u0430\u0432\u0438 \u0441\u043B\u0438\u043A\u0443"]
1902
1988
  },
1903
1989
  signedInMarkers: ["\u041D\u043E\u0432\u043E \u045B\u0430\u0441\u043A\u0430\u045A\u0435", "\u041F\u0440\u0435\u0442\u0440\u0430\u0436\u0438 \u045B\u0430\u0441\u043A\u0430\u045A\u0430", "\u0421\u043A\u043E\u0440\u0430\u0448\u045A\u0438", "\u0418\u0441\u0442\u043E\u0440\u0438\u0458\u0430 \u045B\u0430\u0441\u043A\u0430\u045A\u0430", "\u041F\u0440\u043E\u0458\u0435\u043A\u0442\u0438", "\u041F\u0438\u0442\u0430\u0458 \u0431\u0438\u043B\u043E \u0448\u0442\u0430"],
1904
- responseActions: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0458 \u043E\u0434\u0433\u043E\u0432\u043E\u0440"]
1990
+ responseActions: ["\u041A\u043E\u043F\u0438\u0440\u0430\u0458 \u043E\u0434\u0433\u043E\u0432\u043E\u0440"],
1991
+ stopControl: ["\u0417\u0430\u0443\u0441\u0442\u0430\u0432\u0438 \u043E\u0434\u0433\u043E\u0432\u0430\u0440\u0430\u045A\u0435"]
1905
1992
  };
1906
1993
 
1907
1994
  // src/dom/locale/mn.ts
@@ -1930,7 +2017,8 @@ var mn = {
1930
2017
  create_image: ["\u0417\u0443\u0440\u0430\u0433 \u04AF\u04AF\u0441\u0433\u044D\u0445"]
1931
2018
  },
1932
2019
  signedInMarkers: ["\u0428\u0438\u043D\u044D \u0447\u0430\u0442", "\u0427\u0430\u0442 \u0445\u0430\u0439\u0445", "\u0421\u0430\u044F\u0445\u043D\u044B \u0437\u04AF\u0439\u043B\u0441", "\u0427\u0430\u0442\u044B\u043D \u0442\u04AF\u04AF\u0445", "\u0422\u04E9\u0441\u043B\u04AF\u04AF\u0434", "\u0414\u0443\u0440\u044B\u043D \u0437\u04AF\u0439\u043B \u0430\u0441\u0443\u0443\u0433\u0430\u0430\u0440\u0430\u0439..."],
1933
- responseActions: ["\u0425\u0430\u0440\u0438\u0443\u043B\u0442 \u0445\u0443\u0443\u043B\u0430\u0445"]
2020
+ responseActions: ["\u0425\u0430\u0440\u0438\u0443\u043B\u0442 \u0445\u0443\u0443\u043B\u0430\u0445"],
2021
+ stopControl: ["\u0425\u0430\u0440\u0438\u0443\u043B\u0442\u044B\u0433 \u0437\u043E\u0433\u0441\u043E\u043E\u0445"]
1934
2022
  };
1935
2023
 
1936
2024
  // src/dom/locale/my.ts
@@ -1958,7 +2046,8 @@ var my = {
1958
2046
  create_image: ["\u101B\u102F\u1015\u103A\u1015\u102F\u1036\u1016\u1014\u103A\u1010\u102E\u1038\u1015\u102B"]
1959
2047
  },
1960
2048
  signedInMarkers: ["\u1001\u103B\u1010\u103A\u1021\u101E\u1005\u103A", "\u1001\u103B\u1010\u103A\u1019\u103B\u102C\u1038 \u101B\u103E\u102C\u101B\u1014\u103A", "\u101C\u1010\u103A\u1010\u101C\u1031\u102C", "\u1001\u103B\u1010\u103A \u1019\u103E\u1010\u103A\u1010\u1019\u103A\u1038", "\u1005\u102E\u1019\u1036\u1000\u102D\u1014\u103A\u1038\u1019\u103B\u102C\u1038", "\u1010\u1005\u103A\u1001\u102F\u1001\u102F \u1019\u1031\u1038\u1015\u102B\u2026"],
1961
- responseActions: ["\u1010\u102F\u1036\u1037\u1015\u103C\u1014\u103A\u1019\u103E\u102F \u1000\u1030\u1038\u101A\u1030\u101B\u1014\u103A"]
2049
+ responseActions: ["\u1010\u102F\u1036\u1037\u1015\u103C\u1014\u103A\u1019\u103E\u102F \u1000\u1030\u1038\u101A\u1030\u101B\u1014\u103A"],
2050
+ stopControl: ["\u1016\u103C\u1031\u1006\u102D\u102F\u1001\u103C\u1004\u103A\u1038 \u101B\u1015\u103A\u101B\u1014\u103A"]
1962
2051
  };
1963
2052
 
1964
2053
  // src/dom/locale/ta.ts
@@ -1987,11 +2076,30 @@ var ta = {
1987
2076
  create_image: ["\u0BAA\u0B9F\u0BA4\u0BCD\u0BA4\u0BC8 \u0B89\u0BB0\u0BC1\u0BB5\u0BBE\u0B95\u0BCD\u0B95\u0BB5\u0BC1\u0BAE\u0BCD"]
1988
2077
  },
1989
2078
  signedInMarkers: ["\u0BAA\u0BC1\u0BA4\u0BBF\u0BAF \u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8", "\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8\u0B95\u0BB3\u0BC8\u0BA4\u0BCD \u0BA4\u0BC7\u0B9F\u0BC1", "\u0B9A\u0BAE\u0BC0\u0BAA\u0BA4\u0BCD\u0BA4\u0BBF\u0BAF\u0BA4\u0BC1", "\u0B85\u0BB0\u0B9F\u0BCD\u0B9F\u0BC8 \u0BB5\u0BB0\u0BB2\u0BBE\u0BB1\u0BC1", "\u0BA4\u0BBF\u0B9F\u0BCD\u0B9F\u0B99\u0BCD\u0B95\u0BB3\u0BCD", "\u0B8E\u0BA4\u0BC8\u0BAF\u0BC1\u0BAE\u0BCD \u0B95\u0BC7\u0BB3\u0BC1\u0B99\u0BCD\u0B95\u0BB3\u0BCD"],
1990
- responseActions: ["\u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0BA8\u0B95\u0BB2\u0BC6\u0B9F\u0BC1\u0B95\u0BCD\u0B95\u0BB2\u0BBE\u0BAE\u0BCD"]
2079
+ responseActions: ["\u0BAA\u0BA4\u0BBF\u0BB2\u0BC8 \u0BA8\u0B95\u0BB2\u0BC6\u0B9F\u0BC1\u0B95\u0BCD\u0B95\u0BB2\u0BBE\u0BAE\u0BCD"],
2080
+ stopControl: ["\u0BAA\u0BA4\u0BBF\u0BB2\u0BB3\u0BBF\u0BAA\u0BCD\u0BAA\u0BA4\u0BC8 \u0BA8\u0BBF\u0BB1\u0BC1\u0BA4\u0BCD\u0BA4\u0BC1"]
1991
2081
  };
1992
2082
 
1993
2083
  // src/dom/locale/index.ts
1994
2084
  var locales = [en, de, esES, frFR, zhHK, zhTW, ja, it, vi, am, ar, bg, bs, ca, cs, da, el, es419, et, fa, fi, frCA, gu, hi, hr, hu, hy, id, is, ka, kk, kn, ko, lt, zhHans, ur, uk, ptBR, ptPT, pl, sk, ro, nb, ml, ru, pa, mr, tr, sw, te, tl, th, bn, ms, so, nl, sv, lv, mk, sq, sl, sr, mn, my, ta];
2085
+ function hasLocaleKey(locale, key) {
2086
+ const value = locale[key];
2087
+ if (typeof value === "string") return value.trim().length > 0;
2088
+ return Array.isArray(value) && value.some((candidate) => typeof candidate === "string" && candidate.trim().length > 0);
2089
+ }
2090
+ function countLocalesWithKey(localeList, key) {
2091
+ return localeList.filter((locale) => hasLocaleKey(locale, key)).length;
2092
+ }
2093
+ var localeCoverageSummary = {
2094
+ registeredLocaleCount: locales.length,
2095
+ nonEnglishLocaleCount: Math.max(0, locales.length - 1),
2096
+ runningState: {
2097
+ stopControlLocaleCount: countLocalesWithKey(locales, "stopControl"),
2098
+ stoppedAssistantLocaleCount: countLocalesWithKey(locales, "stoppedAssistant"),
2099
+ nonEnglishStopControlLocaleCount: countLocalesWithKey(locales.slice(1), "stopControl"),
2100
+ nonEnglishStoppedAssistantLocaleCount: countLocalesWithKey(locales.slice(1), "stoppedAssistant")
2101
+ }
2102
+ };
1995
2103
  var TOOL_IDS = ["web_search", "deep_research", "create_image"];
1996
2104
  var MODE_OPTION_IDS = [
1997
2105
  "latest",
@@ -2003,6 +2111,26 @@ var MODE_OPTION_IDS = [
2003
2111
  "extraHigh",
2004
2112
  "pro"
2005
2113
  ];
2114
+ var EXPERIENCE_OPTION_IDS = ["chat", "work"];
2115
+ var CONFIGURATION_AXIS_IDS = [
2116
+ "model",
2117
+ "intelligence",
2118
+ "effort",
2119
+ "speed",
2120
+ "advanced"
2121
+ ];
2122
+ var CONFIGURATION_OPTION_IDS = [
2123
+ "instant",
2124
+ "light",
2125
+ "medium",
2126
+ "high",
2127
+ "extraHigh",
2128
+ "max",
2129
+ "ultra",
2130
+ "pro",
2131
+ "standard",
2132
+ "fast"
2133
+ ];
2006
2134
  function flattenKey(localeList, key) {
2007
2135
  const seen = /* @__PURE__ */ new Set();
2008
2136
  const result = [];
@@ -2055,8 +2183,27 @@ function flattenModeOption(localeList, optionId) {
2055
2183
  }
2056
2184
  return result;
2057
2185
  }
2186
+ function flattenNestedLabel(localeList, group, id2) {
2187
+ const seen = /* @__PURE__ */ new Set();
2188
+ const result = [];
2189
+ for (const locale of localeList) {
2190
+ const contribution = locale[group];
2191
+ const value = contribution?.[id2];
2192
+ if (value === void 0) continue;
2193
+ const candidates = typeof value === "string" ? [value] : value;
2194
+ for (const candidate of candidates) {
2195
+ if (candidate.length > 0 && !seen.has(candidate)) {
2196
+ seen.add(candidate);
2197
+ result.push(candidate);
2198
+ }
2199
+ }
2200
+ }
2201
+ return result;
2202
+ }
2058
2203
  var nonToolKeys = [
2059
2204
  "composerTextbox",
2205
+ "workComposerTextbox",
2206
+ "newWork",
2060
2207
  "sendButton",
2061
2208
  "searchChatsButton",
2062
2209
  "searchChatsPlaceholder",
@@ -2093,9 +2240,21 @@ var builtTools = Object.fromEntries(
2093
2240
  var builtModeOptions = Object.fromEntries(
2094
2241
  MODE_OPTION_IDS.map((id2) => [id2, flattenModeOption(locales, id2)])
2095
2242
  );
2243
+ var builtExperienceOptions = Object.fromEntries(
2244
+ EXPERIENCE_OPTION_IDS.map((id2) => [id2, flattenNestedLabel(locales, "experienceOptions", id2)])
2245
+ );
2246
+ var builtConfigurationAxes = Object.fromEntries(
2247
+ CONFIGURATION_AXIS_IDS.map((id2) => [id2, flattenNestedLabel(locales, "configurationAxes", id2)])
2248
+ );
2249
+ var builtConfigurationOptions = Object.fromEntries(
2250
+ CONFIGURATION_OPTION_IDS.map((id2) => [id2, flattenNestedLabel(locales, "configurationOptions", id2)])
2251
+ );
2096
2252
  var localeLabels = {
2097
2253
  ...builtLabels,
2098
2254
  modeOptions: builtModeOptions,
2255
+ experienceOptions: builtExperienceOptions,
2256
+ configurationAxes: builtConfigurationAxes,
2257
+ configurationOptions: builtConfigurationOptions,
2099
2258
  tools: builtTools
2100
2259
  };
2101
2260
  function escapeRegExp(value) {
@@ -2125,8 +2284,9 @@ async function readPageState(page) {
2125
2284
  const rawTitle = typeof page.title === "function" ? await page.title().catch(() => void 0) : void 0;
2126
2285
  const title = typeof rawTitle === "string" ? rawTitle : void 0;
2127
2286
  const visibleText = await readVisibleText(page);
2128
- const blocker = classifyVisibleText(visibleText);
2129
- const signedIn = isLikelySignedIn(visibleText) && blocker?.kind !== "login_required";
2287
+ const signedIn = isLikelySignedIn(visibleText);
2288
+ const classifiedBlocker = classifyVisibleText(visibleText);
2289
+ const blocker = classifiedBlocker?.kind === "login_required" && signedIn ? void 0 : classifiedBlocker;
2130
2290
  const conversationId = parseConversationId(url);
2131
2291
  const state = {
2132
2292
  url,
@@ -2385,7 +2545,12 @@ function composerTextbox(page) {
2385
2545
  if (typeof page.getByRole !== "function") {
2386
2546
  return requiredLocator(page, "[contenteditable='true'], textarea");
2387
2547
  }
2388
- return page.getByRole("textbox", { name: anyLabelPattern(localeLabels.composerTextbox) });
2548
+ return page.getByRole("textbox", {
2549
+ name: anyLabelPattern([
2550
+ ...localeLabels.composerTextbox,
2551
+ ...localeLabels.workComposerTextbox
2552
+ ])
2553
+ });
2389
2554
  }
2390
2555
  function sendButton(page) {
2391
2556
  if (typeof page.getByRole !== "function") {
@@ -3266,7 +3431,7 @@ async function attachChatGPTBrowser(env, args = {}) {
3266
3431
  page,
3267
3432
  browserName: browser.name ?? "chrome"
3268
3433
  };
3269
- const tabId = getTabId(page);
3434
+ const tabId = tabIdFromPage(page);
3270
3435
  if (tabId !== void 0) {
3271
3436
  attached.tabId = tabId;
3272
3437
  }
@@ -3551,7 +3716,7 @@ function mismatchReasonForNoMatches(policy, tabs, chatgptTabs) {
3551
3716
  async function pageMatchesExistingTarget(page, policy) {
3552
3717
  const url = await Promise.resolve(page.url?.()).catch(() => void 0);
3553
3718
  const title = await Promise.resolve(page.title?.()).catch(() => void 0);
3554
- const tab = { id: getTabId(page) ?? "" };
3719
+ const tab = { id: tabIdFromPage(page) ?? "" };
3555
3720
  if (url !== void 0) tab.url = url;
3556
3721
  if (title !== void 0) tab.title = title;
3557
3722
  return userTabMatchesTarget(tab, policy);
@@ -3764,7 +3929,7 @@ function normalizePage(pageOrTab) {
3764
3929
  }
3765
3930
  return pageOrTab;
3766
3931
  }
3767
- function getTabId(page) {
3932
+ function tabIdFromPage(page) {
3768
3933
  const maybe = page;
3769
3934
  const id2 = maybe.id ?? maybe.tabId;
3770
3935
  return typeof id2 === "string" ? id2 : void 0;
@@ -3776,6 +3941,9 @@ async function bootstrap(env, args = {}) {
3776
3941
  const attached = await attachChatGPTBrowser(env, args);
3777
3942
  env.browser = attached.browser;
3778
3943
  env.page = attached.page;
3944
+ if (attached.tabId !== void 0) {
3945
+ env.expectedTabId = attached.tabId;
3946
+ }
3779
3947
  const state = await readPageState(attached.page);
3780
3948
  const data = {
3781
3949
  browserName: attached.browserName,
@@ -3789,6 +3957,50 @@ async function bootstrap(env, args = {}) {
3789
3957
  return resultError(error instanceof Error ? error : new Error(String(error)));
3790
3958
  }
3791
3959
  }
3960
+ async function ensurePage(env) {
3961
+ if (env.page === void 0) {
3962
+ return bootstrap(env, { preferExistingTab: true });
3963
+ }
3964
+ const affinity = await verifyTabAffinity(env);
3965
+ if (affinity !== void 0) {
3966
+ return affinity;
3967
+ }
3968
+ return resultOk({}, await contextFromPage(env.page, tabContext(env)));
3969
+ }
3970
+ async function verifyTabAffinity(env) {
3971
+ if (env.expectedTabId === void 0 || env.page === void 0) {
3972
+ return void 0;
3973
+ }
3974
+ const actualTabId = tabIdFromPage(env.page);
3975
+ if (actualTabId === env.expectedTabId) {
3976
+ return void 0;
3977
+ }
3978
+ const code = actualTabId === void 0 ? "tab_affinity_unverifiable" : "tab_affinity_lost";
3979
+ const message = actualTabId === void 0 ? `ChatGPT command cannot verify it is still attached to expected tab ${env.expectedTabId}.` : `ChatGPT command would run on tab ${actualTabId}, but the workflow expected tab ${env.expectedTabId}.`;
3980
+ return {
3981
+ ok: false,
3982
+ status: "blocked",
3983
+ warnings: [],
3984
+ blocker: {
3985
+ kind: "selector_drift",
3986
+ code,
3987
+ message,
3988
+ remediation: [
3989
+ {
3990
+ label: "Reclaim the intended tab",
3991
+ instruction: "Run session.bootstrap again with an exact existingTab target, or pass the correct page/tab to createChatGPT before retrying.",
3992
+ userActionRequired: false
3993
+ }
3994
+ ],
3995
+ resumable: false
3996
+ },
3997
+ context: await contextFromPage(env.page, tabContext(env, actualTabId))
3998
+ };
3999
+ }
4000
+ function tabContext(env, actualTabId = tabIdFromPage(env.page)) {
4001
+ const tabId = actualTabId ?? env.expectedTabId;
4002
+ return tabId === void 0 ? {} : { tabId };
4003
+ }
3792
4004
 
3793
4005
  // src/commands/artifacts.ts
3794
4006
  async function listLatestArtifacts(env, args = {}) {
@@ -4173,12 +4385,6 @@ function artifactDownloadBlocker(error, context) {
4173
4385
  context
4174
4386
  };
4175
4387
  }
4176
- async function ensurePage(env) {
4177
- if (env.page !== void 0) {
4178
- return resultOk({}, await contextFromPage(env.page));
4179
- }
4180
- return bootstrap(env, { preferExistingTab: true });
4181
- }
4182
4388
  async function hasStopControl(page, timeoutMs) {
4183
4389
  if (typeof page.evaluate !== "function") return false;
4184
4390
  return withTimeout(
@@ -4342,7 +4548,7 @@ async function attachFiles(env, args) {
4342
4548
  if (!preflight.ok || preflight.data === void 0) {
4343
4549
  return preflight;
4344
4550
  }
4345
- const boot = await ensurePage2(env);
4551
+ const boot = await ensurePage(env);
4346
4552
  if (!boot.ok) {
4347
4553
  return boot;
4348
4554
  }
@@ -4709,7 +4915,7 @@ async function locatorCount(locator) {
4709
4915
  return locator.count();
4710
4916
  }
4711
4917
  async function downloadLatestFile(env, args) {
4712
- const boot = await ensurePage2(env);
4918
+ const boot = await ensurePage(env);
4713
4919
  if (!boot.ok) {
4714
4920
  return boot;
4715
4921
  }
@@ -4800,12 +5006,6 @@ async function readBrowserInputDiagnostic(page) {
4800
5006
  };
4801
5007
  });
4802
5008
  }
4803
- async function ensurePage2(env) {
4804
- if (env.page !== void 0) {
4805
- return resultOk({}, await contextFromPage(env.page));
4806
- }
4807
- return bootstrap(env, { preferExistingTab: true });
4808
- }
4809
5009
  async function setFilesViaDomDataTransfer(page, files) {
4810
5010
  const totalBytes = files.reduce((sum, file) => sum + file.bytes, 0);
4811
5011
  const maxInlineBytes = 25 * 1024 * 1024;
@@ -6049,6 +6249,17 @@ function localizationCheck(env) {
6049
6249
  const missingModeOptionIds = REQUIRED_MODE_OPTION_IDS.filter((id2) => (localeLabels.modeOptions[id2]?.length ?? 0) === 0);
6050
6250
  const toolIds = Object.keys(localeLabels.tools);
6051
6251
  const modeOptionIds = Object.keys(localeLabels.modeOptions);
6252
+ const proAliases = [...localeLabels.modeOptions.pro];
6253
+ const supportsProExtendedAlias = proAliases.some((alias) => /pro\s*(?:•\s*)?extended/i.test(alias)) && proAliases.some((alias) => /extended\s+pro/i.test(alias));
6254
+ const runningStateLocalizationSupport = runningStateSupport();
6255
+ const runningStateLabelCoverage = {
6256
+ support: runningStateLocalizationSupport,
6257
+ stopControlCandidateCount: localeLabels.stopControl.length,
6258
+ stoppedAssistantCandidateCount: localeLabels.stoppedAssistant.length,
6259
+ ...localeCoverageSummary.runningState,
6260
+ registeredLocaleCount: localeCoverageSummary.registeredLocaleCount,
6261
+ nonEnglishLocaleCount: localeCoverageSummary.nonEnglishLocaleCount
6262
+ };
6052
6263
  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
6264
  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);
6054
6265
  const details = {
@@ -6058,12 +6269,16 @@ function localizationCheck(env) {
6058
6269
  missingModeOptionIds,
6059
6270
  toolIds,
6060
6271
  modeOptionIds,
6272
+ proAliases,
6273
+ supportsProExtendedAlias,
6274
+ runningStateLabelCoverage,
6061
6275
  labelCandidateCount,
6062
6276
  pageAvailable: env.page !== void 0,
6063
6277
  runtimeSelectorCoverage: "registry_only_stage_2"
6064
6278
  };
6065
6279
  if (englishCanonicalPresent && requiredKeysMissing.length === 0 && missingToolIds.length === 0 && missingModeOptionIds.length === 0) {
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);
6280
+ const runningStateMessage = runningStateLocalizationSupport === "complete" ? "running-state labels are present for every registered non-English locale" : runningStateLocalizationSupport === "partial" ? "running-state labels are partially localized" : runningStateLocalizationSupport === "english_only" ? "running-state labels are English-only" : "running-state labels are missing";
6281
+ return unknown(`The locale registry is loaded; localized runtime selector coverage is registry-only in Stage 2 and ${runningStateMessage}.`, void 0, details);
6067
6282
  }
6068
6283
  return blocked(
6069
6284
  "The locale registry is missing canonical labels required for selector fallback.",
@@ -6072,6 +6287,16 @@ function localizationCheck(env) {
6072
6287
  "selector_drift"
6073
6288
  );
6074
6289
  }
6290
+ function runningStateSupport() {
6291
+ const coverage = localeCoverageSummary.runningState;
6292
+ const hasEnglishStop = coverage.stopControlLocaleCount > coverage.nonEnglishStopControlLocaleCount;
6293
+ const hasEnglishStopped = coverage.stoppedAssistantLocaleCount > coverage.nonEnglishStoppedAssistantLocaleCount;
6294
+ const hasEnglishFallback = hasEnglishStop && hasEnglishStopped;
6295
+ const allNonEnglishCovered = localeCoverageSummary.nonEnglishLocaleCount > 0 && coverage.nonEnglishStopControlLocaleCount >= localeCoverageSummary.nonEnglishLocaleCount && coverage.nonEnglishStoppedAssistantLocaleCount >= localeCoverageSummary.nonEnglishLocaleCount;
6296
+ if (allNonEnglishCovered) return "complete";
6297
+ if (coverage.nonEnglishStopControlLocaleCount > 0 || coverage.nonEnglishStoppedAssistantLocaleCount > 0) return "partial";
6298
+ return hasEnglishFallback ? "english_only" : "missing";
6299
+ }
6075
6300
  async function reportsCheck(options) {
6076
6301
  const destDir = options?.destDir ?? "reports/runs";
6077
6302
  const includeContent = options?.includeContent === true;
@@ -6465,7 +6690,7 @@ function isResponseComplete(snapshot) {
6465
6690
  return snapshot.latestText.trim().length > 0 && !isTransientAssistantText(snapshot.latestText) && snapshot.textStableForMs >= snapshot.stableMs && !snapshot.generation.active && !snapshot.generation.stopped && snapshot.hasResponseActions;
6466
6691
  }
6467
6692
  async function composeMessage(env, args) {
6468
- const boot = await ensurePage3(env);
6693
+ const boot = await ensurePage(env);
6469
6694
  if (!boot.ok) {
6470
6695
  return boot;
6471
6696
  }
@@ -6496,7 +6721,7 @@ async function composeMessage(env, args) {
6496
6721
  }
6497
6722
  }
6498
6723
  async function submitMessage(env, args = {}) {
6499
- const boot = await ensurePage3(env);
6724
+ const boot = await ensurePage(env);
6500
6725
  if (!boot.ok) {
6501
6726
  return boot;
6502
6727
  }
@@ -6550,12 +6775,22 @@ async function submitMessage(env, args = {}) {
6550
6775
  }
6551
6776
  if (userTurn === void 0) {
6552
6777
  const latestUser = await readLatestMessage(page, "user", "normalized_text");
6778
+ const generation = await readAssistantGenerationState(page).catch(() => EMPTY_GENERATION_STATE);
6779
+ const turnCount = await countPageMessages(page).catch(() => void 0);
6553
6780
  if (submittedUserTurnMatches(latestUser?.text, args.text)) {
6554
6781
  return resultOk(
6555
- submitData(latestUser?.text, await countPageMessages(page).catch(() => void 0)),
6782
+ submitData(latestUser?.text, turnCount, generation.active ? "submitted_generating" : "submitted", generation),
6556
6783
  await contextFromPage(page)
6557
6784
  );
6558
6785
  }
6786
+ const turnAdvanced = previousTurnCount !== void 0 && turnCount !== void 0 && turnCount > previousTurnCount;
6787
+ if (turnAdvanced || generation.active) {
6788
+ return resultOk(
6789
+ submitData(void 0, turnCount, generation.active ? "submitted_generating" : "submitted_unconfirmed", generation),
6790
+ await contextFromPage(page),
6791
+ ["Submitted prompt could not be matched to a rendered user turn yet, but ChatGPT page state indicates progress."]
6792
+ );
6793
+ }
6559
6794
  return {
6560
6795
  ok: false,
6561
6796
  status: "timeout",
@@ -6569,7 +6804,12 @@ async function submitMessage(env, args = {}) {
6569
6804
  };
6570
6805
  }
6571
6806
  return resultOk(
6572
- submitData(userTurn, await countPageMessages(page).catch(() => void 0)),
6807
+ submitData(
6808
+ userTurn,
6809
+ await countPageMessages(page).catch(() => void 0),
6810
+ "submitted",
6811
+ await readAssistantGenerationState(page).catch(() => EMPTY_GENERATION_STATE)
6812
+ ),
6573
6813
  await contextFromPage(page)
6574
6814
  );
6575
6815
  } catch (error) {
@@ -6695,7 +6935,7 @@ function describeSendState(state) {
6695
6935
  return parts.length > 0 ? ` ${parts.join(" ")}` : "";
6696
6936
  }
6697
6937
  async function waitForMessage(env, args = {}) {
6698
- const boot = await ensurePage3(env);
6938
+ const boot = await ensurePage(env);
6699
6939
  if (!boot.ok) {
6700
6940
  return boot;
6701
6941
  }
@@ -6715,6 +6955,7 @@ async function waitForMessage(env, args = {}) {
6715
6955
  let lastChangedAt = Date.now();
6716
6956
  let lastObservedTextLength = 0;
6717
6957
  let latestAssistantCount = await countPageMessages(page, "assistant").catch(() => 0);
6958
+ let lastGeneration = EMPTY_GENERATION_STATE;
6718
6959
  while (Date.now() - started < timeoutMs) {
6719
6960
  const probeResult = await waitSnapshotProbe(page, deadline, { timeoutMs: probeTimeoutMs });
6720
6961
  addWarnings(waitWarnings, probeResult.warnings);
@@ -6743,9 +6984,13 @@ async function waitForMessage(env, args = {}) {
6743
6984
  }
6744
6985
  pollIndex += 1;
6745
6986
  const hasResponseActions = await resolveResponseActions(page, snapshot);
6987
+ lastGeneration = snapshot.generation;
6746
6988
  if (targetReached && snapshot.generation.stopped && snapshot.text.length > 0) {
6747
6989
  const stoppedText = normalizeWhitespace(await fetchLatestAssistantText(page) ?? "");
6748
6990
  const data = stoppedText.length > 0 ? waitDataFromText(args, false, stoppedText, latestAssistantCount, Date.now() - started) : waitDataWithoutText(latestAssistantCount, Date.now() - started);
6991
+ data.completionState = "stopped";
6992
+ data.generationActive = snapshot.generation.active;
6993
+ data.generationSignals = snapshot.generation.signals;
6749
6994
  if (stoppedText.length === 0) {
6750
6995
  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
6996
  }
@@ -6775,6 +7020,9 @@ async function waitForMessage(env, args = {}) {
6775
7020
  };
6776
7021
  if (fetchedMetadata.hash === snapshot.text.hash && isResponseComplete(completionSnapshot)) {
6777
7022
  const data = waitDataFromText(args, true, latestText, latestAssistantCount, Date.now() - started);
7023
+ data.completionState = "complete";
7024
+ data.generationActive = false;
7025
+ data.generationSignals = snapshot.generation.signals;
6778
7026
  return withCommandOutputText(resultOk(
6779
7027
  data,
6780
7028
  await contextFromPage(page),
@@ -6792,7 +7040,11 @@ async function waitForMessage(env, args = {}) {
6792
7040
  if (lastObservedTextLength > 0) {
6793
7041
  const partialText = await fetchLatestAssistantText(page);
6794
7042
  if (partialText !== void 0 && normalizeWhitespace(partialText).length > 0) {
6795
- const data = waitDataFromText(args, false, normalizeWhitespace(partialText), latestAssistantCount, Date.now() - started);
7043
+ const normalizedPartialText = normalizeWhitespace(partialText);
7044
+ const data = waitDataFromText(args, false, normalizedPartialText, latestAssistantCount, Date.now() - started);
7045
+ data.completionState = completionStateFromGeneration(lastGeneration, false, normalizedPartialText.length > 0);
7046
+ data.generationActive = lastGeneration.active;
7047
+ data.generationSignals = lastGeneration.signals;
6796
7048
  return withCommandOutputText({
6797
7049
  ok: false,
6798
7050
  status: "partial",
@@ -6904,7 +7156,7 @@ function addWarnings(target, warnings) {
6904
7156
  }
6905
7157
  }
6906
7158
  async function readLatest(env, args = {}) {
6907
- const boot = await ensurePage3(env);
7159
+ const boot = await ensurePage(env);
6908
7160
  if (!boot.ok) {
6909
7161
  return boot;
6910
7162
  }
@@ -6941,17 +7193,51 @@ async function readLatest(env, args = {}) {
6941
7193
  if (latest.actions !== void 0) data.actions = latest.actions;
6942
7194
  if (latest.thoughtDurationText !== void 0) data.thoughtDurationText = latest.thoughtDurationText;
6943
7195
  if (latest.sourcesAvailable !== void 0) data.sourcesAvailable = latest.sourcesAvailable;
7196
+ if (role === "assistant") {
7197
+ const generation = await readAssistantGenerationState(page).catch(() => EMPTY_GENERATION_STATE);
7198
+ data.completionState = completionStateFromGeneration(generation, void 0, latest.text.trim().length > 0);
7199
+ data.generationActive = generation.active;
7200
+ data.generationSignals = generation.signals;
7201
+ }
6944
7202
  return withCommandOutputText(resultOk(data, await contextFromPage(page), data.warnings ?? []));
6945
7203
  }
7204
+ async function messageStatus(env, args = {}) {
7205
+ const boot = await ensurePage(env);
7206
+ if (!boot.ok) {
7207
+ return boot;
7208
+ }
7209
+ const page = env.page;
7210
+ const snapshot = await readWaitDomSnapshot(page).catch(() => void 0) ?? await fallbackWaitSnapshot(page, 0);
7211
+ const maxPreviewChars = Math.max(0, args.maxPreviewChars ?? 240);
7212
+ const latestText = snapshot.text.length > 0 ? normalizeWhitespace(await fetchLatestAssistantText(page) ?? "") : "";
7213
+ const data = {
7214
+ turnCount: snapshot.turnCount,
7215
+ assistantTurnCount: snapshot.assistantTurnCount,
7216
+ completionState: completionStateFromGeneration(snapshot.generation, void 0, latestText.length > 0),
7217
+ generationActive: snapshot.generation.active,
7218
+ generationSignals: snapshot.generation.signals
7219
+ };
7220
+ if (snapshot.latestAssistantTurnIndex !== void 0) data.latestAssistantTurnIndex = snapshot.latestAssistantTurnIndex;
7221
+ if (latestText.length > 0) {
7222
+ data.latestAssistantTextLength = latestText.length;
7223
+ data.latestAssistantPreview = latestText.length > maxPreviewChars ? `${latestText.slice(0, Math.max(0, maxPreviewChars - 1))}...` : latestText;
7224
+ }
7225
+ return resultOk(data, await contextFromPage(page));
7226
+ }
6946
7227
  async function askMessage(env, args) {
6947
- const boot = await ensurePage3(env);
7228
+ const normalizedPrompt = normalizeAskPrompt(args);
7229
+ if (!normalizedPrompt.ok) {
7230
+ return normalizedPrompt.result;
7231
+ }
7232
+ const prompt = normalizedPrompt.text;
7233
+ const boot = await ensurePage(env);
6948
7234
  if (!boot.ok) {
6949
7235
  return boot;
6950
7236
  }
6951
7237
  const page = env.page;
6952
7238
  const beforeTurnCount = await countPageMessages(page).catch(() => void 0);
6953
7239
  const beforeAssistantTurnCount = await countPageMessages(page, "assistant").catch(() => void 0);
6954
- const composeArgs = { text: args.text, mode: "replace" };
7240
+ const composeArgs = { text: prompt, mode: "replace" };
6955
7241
  if (args.timeoutMs !== void 0) {
6956
7242
  composeArgs.timeoutMs = args.timeoutMs;
6957
7243
  }
@@ -6959,7 +7245,7 @@ async function askMessage(env, args) {
6959
7245
  if (!compose.ok) {
6960
7246
  return forwardFailure(compose);
6961
7247
  }
6962
- const submitArgs = { text: args.text };
7248
+ const submitArgs = { text: prompt };
6963
7249
  if (beforeTurnCount !== void 0) {
6964
7250
  submitArgs.previousTurnCount = beforeTurnCount;
6965
7251
  }
@@ -7017,7 +7303,7 @@ async function askMessage(env, args) {
7017
7303
  return forwardFailure(waitFailure);
7018
7304
  }
7019
7305
  const state = await readPageState(page).catch(() => void 0);
7020
- const data = { prompt: args.text };
7306
+ const data = { prompt };
7021
7307
  const complete = waitResult?.data?.complete ?? (waitResult === void 0 ? void 0 : false);
7022
7308
  if (complete !== void 0) {
7023
7309
  data.complete = complete;
@@ -7031,6 +7317,7 @@ async function askMessage(env, args) {
7031
7317
  if (state?.title !== void 0) {
7032
7318
  data.title = state.title;
7033
7319
  }
7320
+ applyMessageState(data, submit.data, waitResult?.data);
7034
7321
  if (waitFailure !== void 0) {
7035
7322
  data.complete = false;
7036
7323
  return withCommandOutputText({
@@ -7068,7 +7355,7 @@ async function waitAndRead(env, args = {}) {
7068
7355
  }
7069
7356
  return forwardFailure(read);
7070
7357
  }
7071
- const data = askReadData("", read.data?.text, wait.data?.complete);
7358
+ const data = askReadData("", read.data?.text, wait.data?.complete, wait.data, read.data);
7072
7359
  const warnings = [...read.warnings, ...wait.warnings];
7073
7360
  if (!wait.ok && wait.status === "partial") {
7074
7361
  data.complete = false;
@@ -7085,12 +7372,6 @@ async function waitAndRead(env, args = {}) {
7085
7372
  }
7086
7373
  return withCommandOutputText(resultOk(data, read.context, warnings));
7087
7374
  }
7088
- async function ensurePage3(env) {
7089
- if (env.page !== void 0) {
7090
- return resultOk({}, await contextFromPage(env.page));
7091
- }
7092
- return bootstrap(env, { preferExistingTab: true });
7093
- }
7094
7375
  async function waitForSubmittedUserTurn(page, text, previousTurnCount, timeoutMs) {
7095
7376
  const started = Date.now();
7096
7377
  const wanted = text === void 0 ? void 0 : normalizeWhitespace(text);
@@ -7195,7 +7476,7 @@ async function sleep2(page, ms2) {
7195
7476
  }
7196
7477
  await new Promise((resolve3) => setTimeout(resolve3, ms2));
7197
7478
  }
7198
- function submitData(userTurnText, turnCount) {
7479
+ function submitData(userTurnText, turnCount, submissionState, generation) {
7199
7480
  const data = { submitted: true };
7200
7481
  if (userTurnText !== void 0) {
7201
7482
  data.userTurnText = userTurnText;
@@ -7203,9 +7484,13 @@ function submitData(userTurnText, turnCount) {
7203
7484
  if (turnCount !== void 0) {
7204
7485
  data.turnCount = turnCount;
7205
7486
  }
7487
+ data.submissionState = submissionState;
7488
+ data.completionState = completionStateFromGeneration(generation);
7489
+ data.generationActive = generation.active;
7490
+ data.generationSignals = generation.signals;
7206
7491
  return data;
7207
7492
  }
7208
- function askReadData(prompt, responseText, complete) {
7493
+ function askReadData(prompt, responseText, complete, wait, read) {
7209
7494
  const data = { prompt };
7210
7495
  if (responseText !== void 0) {
7211
7496
  data.responseText = responseText;
@@ -7213,8 +7498,63 @@ function askReadData(prompt, responseText, complete) {
7213
7498
  if (complete !== void 0) {
7214
7499
  data.complete = complete;
7215
7500
  }
7501
+ applyMessageState(data, void 0, wait, read);
7216
7502
  return data;
7217
7503
  }
7504
+ function applyMessageState(data, submit, wait, read) {
7505
+ if (submit?.submissionState !== void 0) data.submissionState = submit.submissionState;
7506
+ const completionState = wait?.completionState ?? read?.completionState ?? submit?.completionState;
7507
+ if (completionState !== void 0) data.completionState = completionState;
7508
+ const generationActive = wait?.generationActive ?? read?.generationActive ?? submit?.generationActive;
7509
+ if (generationActive !== void 0) data.generationActive = generationActive;
7510
+ const generationSignals = wait?.generationSignals ?? read?.generationSignals ?? submit?.generationSignals;
7511
+ if (generationSignals !== void 0) data.generationSignals = generationSignals;
7512
+ }
7513
+ function completionStateFromGeneration(generation, complete, hasPartialText = false) {
7514
+ if (complete === true) return "complete";
7515
+ if (generation.active) return "generating";
7516
+ if (generation.stopped) return "stopped";
7517
+ if (complete === false || hasPartialText) return "partial";
7518
+ return "unknown";
7519
+ }
7520
+ function normalizeAskPrompt(args) {
7521
+ const text = args.text;
7522
+ const prompt = args.prompt;
7523
+ if (text !== void 0 && prompt !== void 0 && text !== prompt) {
7524
+ return {
7525
+ ok: false,
7526
+ result: {
7527
+ ok: false,
7528
+ status: "error",
7529
+ warnings: [],
7530
+ error: {
7531
+ name: "InvalidAskArgs",
7532
+ message: "messages.ask received both text and prompt with different values.",
7533
+ recoverable: false
7534
+ },
7535
+ context: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
7536
+ }
7537
+ };
7538
+ }
7539
+ const normalized = text ?? prompt;
7540
+ if (normalized === void 0 || normalized.trim().length === 0) {
7541
+ return {
7542
+ ok: false,
7543
+ result: {
7544
+ ok: false,
7545
+ status: "error",
7546
+ warnings: [],
7547
+ error: {
7548
+ name: "InvalidAskArgs",
7549
+ message: "messages.ask requires a non-empty text or prompt argument.",
7550
+ recoverable: false
7551
+ },
7552
+ context: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
7553
+ }
7554
+ };
7555
+ }
7556
+ return { ok: true, text: normalized };
7557
+ }
7218
7558
  function readRole(read) {
7219
7559
  return typeof read === "object" ? read.role : void 0;
7220
7560
  }
@@ -7321,7 +7661,8 @@ function findUniqueMenuItem(items, wanted) {
7321
7661
  var DEFAULT_MODE_EFFORT = "Thinking";
7322
7662
  var CURRENT_MODE_LABELS = dedupeLabels([
7323
7663
  ...localeLabels.modeLabels,
7324
- ...Object.values(localeLabels.modeOptions).flat()
7664
+ ...Object.values(localeLabels.modeOptions).flat(),
7665
+ ...Object.values(localeLabels.configurationOptions).flat()
7325
7666
  ]);
7326
7667
  var MODE_OPENER_LABELS = [...CURRENT_MODE_LABELS.filter((label) => label !== "Pro"), ...localeLabels.modeOpenerExtra];
7327
7668
  var MODEL_VERSION_FAMILY_PATTERN = /^gpt[\s-]/i;
@@ -7356,7 +7697,7 @@ var MODE_ID_ALIASES = {
7356
7697
  var THREAD_ACTION_MENU_LABELS = new Set(localeLabels.threadActionMenuItems.map(normalizeForLabelMatch));
7357
7698
  var THREAD_ACTION_PREFIXES = localeLabels.threadActionPrefixes.map(normalizeForLabelMatch).filter((prefix) => prefix.length > 0);
7358
7699
  async function setMode(env, args) {
7359
- const boot = await ensurePage4(env);
7700
+ const boot = await ensurePage(env);
7360
7701
  if (!boot.ok) {
7361
7702
  return boot;
7362
7703
  }
@@ -7444,7 +7785,7 @@ async function modeVerificationWarnings(page, requested, selected) {
7444
7785
  }
7445
7786
  async function getMode(env, args = {}) {
7446
7787
  void args;
7447
- const boot = await ensurePage4(env);
7788
+ const boot = await ensurePage(env);
7448
7789
  if (!boot.ok) {
7449
7790
  return boot;
7450
7791
  }
@@ -7481,7 +7822,7 @@ async function waitForModeMenu(page, requested, timeoutMs) {
7481
7822
  return { opened: false, alreadySelected: [], modeButtons };
7482
7823
  }
7483
7824
  async function selectTool(env, args) {
7484
- const boot = await ensurePage4(env);
7825
+ const boot = await ensurePage(env);
7485
7826
  if (!boot.ok) {
7486
7827
  return boot;
7487
7828
  }
@@ -7522,12 +7863,6 @@ async function selectTool(env, args) {
7522
7863
  return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
7523
7864
  }
7524
7865
  }
7525
- async function ensurePage4(env) {
7526
- if (env.page !== void 0) {
7527
- return resultOk({}, await contextFromPage(env.page));
7528
- }
7529
- return bootstrap(env, { preferExistingTab: true });
7530
- }
7531
7866
  async function clickFirstUniqueButton(page, labels) {
7532
7867
  for (const label of labels) {
7533
7868
  const roleLocator = page.getByRole?.("button", { name: label, exact: true });
@@ -7777,17 +8112,33 @@ async function selectModelVersion(page, requestedVersion, currentCandidates, tim
7777
8112
  candidates = await enumerateVisibleMenuItems(page);
7778
8113
  }
7779
8114
  }
7780
- let exact = findExactMenuItem(candidates, requestedVersion);
8115
+ let exact = findExactSelectableMenuItem(candidates, requestedVersion);
7781
8116
  if (exact !== void 0) {
7782
- return await clickMenuItem(page, exact.label) ? { selected: exact.label, candidates: candidates.map((candidate) => candidate.label) } : { candidates: candidates.map((candidate) => candidate.label) };
8117
+ return await clickResolvedMenuItem(page, exact) ? { selected: exact.label, candidates: candidates.map((candidate) => candidate.label) } : { candidates: candidates.map((candidate) => candidate.label) };
7783
8118
  }
7784
8119
  const opened = await openModelVersionSubmenu(page, currentCandidates);
7785
8120
  candidates = await enumerateVisibleMenuItems(page);
7786
- exact = findExactMenuItem(candidates, requestedVersion);
8121
+ exact = findExactSelectableMenuItem(candidates, requestedVersion);
7787
8122
  if (!opened || exact === void 0) {
7788
8123
  return { candidates: candidates.map((candidate) => candidate.label) };
7789
8124
  }
7790
- return await clickMenuItem(page, exact.label) ? { selected: exact.label, candidates: candidates.map((candidate) => candidate.label) } : { candidates: candidates.map((candidate) => candidate.label) };
8125
+ return await clickResolvedMenuItem(page, exact) ? { selected: exact.label, candidates: candidates.map((candidate) => candidate.label) } : { candidates: candidates.map((candidate) => candidate.label) };
8126
+ }
8127
+ function isModelVersionSubmenuOpener(item) {
8128
+ return item.hasPopup === true || item.role !== "menuitemradio" && MODEL_VERSION_FAMILY_PATTERN.test(item.label);
8129
+ }
8130
+ async function clickResolvedMenuItem(page, item) {
8131
+ if (item.testId !== void 0 && await clickIfUnique(
8132
+ page.locator?.(`[data-testid="${escapeAttributeValue(item.testId)}"]`)
8133
+ )) {
8134
+ return true;
8135
+ }
8136
+ if (item.role !== void 0 && await clickIfUnique(
8137
+ page.getByRole?.(item.role, { name: item.label, exact: true })
8138
+ )) {
8139
+ return true;
8140
+ }
8141
+ return clickMenuItem(page, item.label);
7791
8142
  }
7792
8143
  async function openModelVersionSubmenu(page, candidates) {
7793
8144
  const submenuOpeners = candidates.filter((item) => item.hasPopup === true || MODEL_VERSION_FAMILY_PATTERN.test(item.label));
@@ -7862,9 +8213,11 @@ async function menuItemCenter(page, item, roles = ["menuitem", "menuitemradio",
7862
8213
  async function modelVersionMenuItemsAreVisible(page) {
7863
8214
  return (await enumerateVisibleMenuItems(page)).some((candidate) => candidate.role === "menuitemradio" && MODEL_VERSION_LABEL_PATTERN.test(candidate.label));
7864
8215
  }
7865
- function findExactMenuItem(items, wanted) {
8216
+ function findExactSelectableMenuItem(items, wanted) {
7866
8217
  const normalized = normalizeLabel(wanted);
7867
- const matches = items.filter((item) => item.normalized === normalized);
8218
+ const matches = items.filter(
8219
+ (item) => item.normalized === normalized && !isModelVersionSubmenuOpener(item)
8220
+ );
7868
8221
  return matches.length === 1 ? matches[0] : void 0;
7869
8222
  }
7870
8223
  function dedupeLabels(labels) {
@@ -7920,8 +8273,12 @@ async function visibleModeButtonLabelList(page) {
7920
8273
  }
7921
8274
  return text.includes(token);
7922
8275
  };
8276
+ const scopedRoots = Array.from(document.querySelectorAll(
8277
+ "main form, main [data-testid*='composer' i], main [class*='composer' i]"
8278
+ ));
7923
8279
  return Array.from(document.querySelectorAll("button, [role='button']")).map((node) => {
7924
8280
  const element = node;
8281
+ if (scopedRoots.length > 0 && !scopedRoots.some((root) => root.contains(node))) return "";
7925
8282
  const visibleText = (element.innerText ?? element.textContent ?? "").replace(/\s+/g, " ").trim();
7926
8283
  const ariaLabel = (element.getAttribute("aria-label") ?? "").replace(/\s+/g, " ").trim();
7927
8284
  const label = visibleText.length > 0 ? visibleText : ariaLabel;
@@ -7930,86 +8287,976 @@ async function visibleModeButtonLabelList(page) {
7930
8287
  if (/open profile menu/i.test(label)) return "";
7931
8288
  if (visibleText.length === 0 && /feedback|conversation options|dismiss/i.test(ariaLabel)) return "";
7932
8289
  const normalized = label.toLowerCase();
7933
- if (!normalizedModeLabels.some((modeLabel) => tokenMatches(normalized, modeLabel))) return "";
8290
+ const structuralModelControl = /model-switcher|model-selector|mode-selector/i.test(testId) || /\b(?:gpt|sol|luna|terra)\b/i.test(label);
8291
+ if (!structuralModelControl && !normalizedModeLabels.some((modeLabel) => tokenMatches(normalized, modeLabel))) return "";
7934
8292
  return label;
7935
8293
  }).filter(Boolean).slice(0, 30);
7936
8294
  }, CURRENT_MODE_LABELS).then((labels) => labels.map(normalizeWhitespace)).catch(() => []);
7937
8295
  }
7938
8296
 
7939
- // src/commands/reports.ts
7940
- import { join as join3 } from "node:path";
7941
-
7942
- // src/safety/report-redaction.ts
7943
- var DEFAULT_MAX_PREVIEW_CHARS = 240;
7944
- var DEFAULT_MAX_DEPTH = 8;
7945
- var DEFAULT_MAX_ARRAY_ITEMS = 40;
7946
- var DEFAULT_MAX_OBJECT_ENTRIES = 80;
7947
- function redactReportValue(value, options = {}) {
7948
- return redactValue(value, normalizeOptions(options), 0, /* @__PURE__ */ new WeakSet(), void 0);
7949
- }
7950
- function redactValue(value, options, depth, seen, key) {
7951
- if (value === void 0 || value === null) return value;
7952
- if (typeof value === "string") {
7953
- if (!options.includeContent && key !== void 0 && isSafeControlStringKey(key)) {
7954
- return value;
7955
- }
7956
- if (!options.includeContent) return `[redacted:${value.length} chars]`;
7957
- return compactVisibleText(redactSensitiveText(value), options.maxPreviewChars);
8297
+ // src/commands/experience.ts
8298
+ async function detectExperience(env, args = {}) {
8299
+ void args;
8300
+ const boot = await ensurePage(env);
8301
+ if (!boot.ok) {
8302
+ return boot;
7958
8303
  }
7959
- if (typeof value === "number" || typeof value === "boolean") return value;
7960
- if (typeof value !== "object") return redactSensitiveText(String(value));
7961
- if (seen.has(value)) return "[redacted:cycle]";
7962
- if (depth >= options.maxDepth) return "[redacted:max-depth]";
7963
- if (!options.includeContent && key !== void 0 && isHeavyContentKey(key)) {
7964
- return summarizeHeavyValue(value);
8304
+ const page = env.page;
8305
+ try {
8306
+ const data = detectExperienceFromSnapshot(await readSurfaceSnapshot(page));
8307
+ return resultOk(data, await contextFromPage(page, {
8308
+ experience: data.experience,
8309
+ selectorProfile: data.selectorProfile
8310
+ }), data.experience === "unknown" ? ["The current ChatGPT surface could not be classified as Chat or Work from scoped composer evidence."] : []);
8311
+ } catch (error) {
8312
+ return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
7965
8313
  }
7966
- seen.add(value);
8314
+ }
8315
+ async function openExperience(env, args) {
8316
+ const boot = await ensurePage(env);
8317
+ if (!boot.ok) {
8318
+ return boot;
8319
+ }
8320
+ const page = env.page;
7967
8321
  try {
7968
- if (Array.isArray(value)) {
7969
- const items = value.slice(0, options.maxArrayItems).map((item) => redactValue(item, options, depth + 1, seen, key));
7970
- if (value.length > options.maxArrayItems) {
7971
- items.push(`[redacted:${value.length - options.maxArrayItems} more items]`);
8322
+ const before = detectExperienceFromSnapshot(await readSurfaceSnapshot(page));
8323
+ if (before.experience === args.experience) {
8324
+ return resultOk({
8325
+ experience: args.experience,
8326
+ previousExperience: before.experience,
8327
+ changed: false,
8328
+ selectorProfile: before.selectorProfile
8329
+ }, await contextFromPage(page, {
8330
+ experience: before.experience,
8331
+ selectorProfile: before.selectorProfile
8332
+ }));
8333
+ }
8334
+ const labels = localeLabels.experienceOptions[args.experience];
8335
+ if (!await clickUniqueExperienceControl(page, labels)) {
8336
+ return experienceSelectorDrift(
8337
+ page,
8338
+ `No unique visible ChatGPT ${args.experience === "work" ? "Work" : "Chat"} surface control was found.`,
8339
+ before
8340
+ );
8341
+ }
8342
+ const timeoutMs = args.timeoutMs ?? 3e4;
8343
+ const started = Date.now();
8344
+ let after = before;
8345
+ while (Date.now() - started < timeoutMs) {
8346
+ await page.waitForTimeout?.(250);
8347
+ after = detectExperienceFromSnapshot(await readSurfaceSnapshot(page));
8348
+ if (after.experience === args.experience) {
8349
+ return resultOk({
8350
+ experience: args.experience,
8351
+ previousExperience: before.experience,
8352
+ changed: true,
8353
+ selectorProfile: after.selectorProfile
8354
+ }, await contextFromPage(page, {
8355
+ experience: after.experience,
8356
+ selectorProfile: after.selectorProfile
8357
+ }));
7972
8358
  }
7973
- return items;
7974
8359
  }
7975
- const entries = Object.entries(value);
7976
- const kept = entries.slice(0, options.maxObjectEntries).map(([childKey, child]) => [
7977
- childKey,
7978
- redactValue(child, options, depth + 1, seen, childKey)
8360
+ return {
8361
+ ok: false,
8362
+ status: "blocked",
8363
+ warnings: [],
8364
+ blocker: {
8365
+ kind: "selector_drift",
8366
+ code: "experience_postcondition_unverified",
8367
+ fieldPath: "experience",
8368
+ message: `The ${args.experience} surface control was clicked, but the composer did not verify that ChatGPT switched to ${args.experience}.`,
8369
+ candidates: labels.map((label) => ({ label })),
8370
+ resumable: true
8371
+ },
8372
+ context: await contextFromPage(page, {
8373
+ experience: after.experience,
8374
+ selectorProfile: after.selectorProfile
8375
+ })
8376
+ };
8377
+ } catch (error) {
8378
+ return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
8379
+ }
8380
+ }
8381
+ function detectExperienceFromSnapshot(snapshot) {
8382
+ const evidence = [];
8383
+ const composerLabels = snapshot.composerLabels.map(normalizeForLabelMatch);
8384
+ const controls = snapshot.mainControls.map(normalizeForLabelMatch);
8385
+ const mainText = normalizeForLabelMatch(snapshot.mainText);
8386
+ const url = snapshot.url.toLowerCase();
8387
+ const workComposer = matchingLabels(composerLabels, localeLabels.workComposerTextbox);
8388
+ for (const label of workComposer) {
8389
+ evidence.push({ source: "composer", label });
8390
+ }
8391
+ const chatComposer = matchingLabels(composerLabels, localeLabels.composerTextbox);
8392
+ for (const label of chatComposer) {
8393
+ evidence.push({ source: "composer", label });
8394
+ }
8395
+ const workAxisCount = ["model", "effort", "speed"].filter((axis) => hasAnyLabel(controls, localeLabels.configurationAxes[axis])).length;
8396
+ if (workAxisCount >= 2) {
8397
+ evidence.push({ source: "control", label: `Work configuration axes (${workAxisCount}/3)` });
8398
+ }
8399
+ if (/\/work(?:\/|$|\?)/.test(url)) {
8400
+ evidence.push({ source: "url", label: snapshot.url });
8401
+ }
8402
+ if (containsAny(mainText, ["work on something else", "work on anything"])) {
8403
+ evidence.push({ source: "heading", label: "Work composer copy" });
8404
+ }
8405
+ const workScore = workComposer.length * 4 + (workAxisCount >= 2 ? 4 : 0) + (/\/work(?:\/|$|\?)/.test(url) ? 3 : 0) + (containsAny(mainText, ["work on something else", "work on anything"]) ? 2 : 0);
8406
+ const chatScore = chatComposer.length * 4;
8407
+ let experience = "unknown";
8408
+ let confidence = "low";
8409
+ if (workScore > chatScore && workScore >= 4) {
8410
+ experience = "work";
8411
+ confidence = workScore >= 7 ? "high" : "medium";
8412
+ } else if (chatScore > workScore && chatScore >= 4) {
8413
+ experience = "chat";
8414
+ confidence = "high";
8415
+ }
8416
+ const selectorProfile = profileFromSnapshot(snapshot, experience);
8417
+ return { experience, selectorProfile, confidence, evidence };
8418
+ }
8419
+ async function readSurfaceSnapshot(page) {
8420
+ const url = typeof page.url === "function" ? await Promise.resolve(page.url()).catch(() => "") : "";
8421
+ if (typeof page.evaluate !== "function") {
8422
+ return { url, composerLabels: [], mainControls: [], mainText: "" };
8423
+ }
8424
+ const snapshot = await page.evaluate(() => {
8425
+ const visible = (element) => {
8426
+ const html = element;
8427
+ const rect = html.getBoundingClientRect?.();
8428
+ const style = typeof window !== "undefined" ? window.getComputedStyle?.(html) : void 0;
8429
+ return (rect === void 0 || rect.width > 0 && rect.height > 0) && style?.display !== "none" && style?.visibility !== "hidden" && style?.opacity !== "0";
8430
+ };
8431
+ const labelFor = (element) => {
8432
+ const html = element;
8433
+ return element.getAttribute("aria-label") ?? element.getAttribute("placeholder") ?? html.innerText ?? element.textContent ?? "";
8434
+ };
8435
+ const normalize = (value) => value.replace(/\s+/g, " ").trim();
8436
+ const composerRoots = Array.from(document.querySelectorAll(
8437
+ "main form, main [data-testid*='composer' i], main [class*='composer' i]"
8438
+ ));
8439
+ const composerNodes = composerRoots.flatMap((root) => [
8440
+ root,
8441
+ ...Array.from(root.querySelectorAll("textarea, [contenteditable='true'], [role='textbox'], input"))
7979
8442
  ]);
7980
- if (entries.length > options.maxObjectEntries) {
7981
- kept.push(["__redactedMoreEntries", entries.length - options.maxObjectEntries]);
8443
+ const composerLabels = Array.from(new Set(composerNodes.filter(visible).map(labelFor).map(normalize).filter(Boolean))).slice(0, 16);
8444
+ const main = document.querySelector("main");
8445
+ const overlayRoots = Array.from(document.querySelectorAll(
8446
+ "[role='menu'], [role='listbox'], [data-radix-popper-content-wrapper], [data-radix-menu-content]"
8447
+ )).filter(visible);
8448
+ const controlRoots = Array.from(/* @__PURE__ */ new Set([...composerRoots, ...overlayRoots]));
8449
+ const effectiveControlRoots = controlRoots.length > 0 ? controlRoots : main === null ? [] : [main];
8450
+ const mainControls = Array.from(new Set(effectiveControlRoots.flatMap((root) => Array.from(root.querySelectorAll(
8451
+ "button, [role='button'], [role='menuitem'], [role='menuitemradio'], [role='option']"
8452
+ ))).filter(visible).map(labelFor).map(normalize).filter(Boolean))).slice(0, 120);
8453
+ const surfaceTextNodes = main === null ? [] : Array.from(main.querySelectorAll(
8454
+ "h1, h2, h3, form, [data-testid*='composer' i], [class*='composer' i]"
8455
+ )).filter(visible).slice(0, 32);
8456
+ const mainText = normalize(surfaceTextNodes.map(labelFor).join(" ")).slice(0, 2e3);
8457
+ return { composerLabels, mainControls, mainText };
8458
+ }).catch(() => ({ composerLabels: [], mainControls: [], mainText: "" }));
8459
+ return { url, ...snapshot };
8460
+ }
8461
+ function profileFromSnapshot(snapshot, experience) {
8462
+ const controls = snapshot.mainControls.map(normalizeForLabelMatch);
8463
+ const mainText = normalizeForLabelMatch(snapshot.mainText);
8464
+ if (experience === "work") {
8465
+ return hasAnyLabel(controls, localeLabels.configurationAxes.advanced) || containsAny(mainText, localeLabels.configurationAxes.advanced) ? "work_advanced_v1" : "work_basic_v1";
8466
+ }
8467
+ if (experience !== "chat") {
8468
+ return "unknown";
8469
+ }
8470
+ const simplifiedOptions = [
8471
+ ...localeLabels.configurationOptions.instant,
8472
+ ...localeLabels.configurationOptions.medium,
8473
+ ...localeLabels.configurationOptions.high,
8474
+ ...localeLabels.configurationOptions.extraHigh,
8475
+ ...localeLabels.configurationOptions.pro
8476
+ ];
8477
+ if (hasAnyLabel(controls, simplifiedOptions)) {
8478
+ return "chat_simplified_v1";
8479
+ }
8480
+ const legacyOptions = [
8481
+ ...localeLabels.modeOptions.latest,
8482
+ ...localeLabels.modeOptions.thinking,
8483
+ ...localeLabels.modeOptions.extended
8484
+ ];
8485
+ return hasAnyLabel(controls, legacyOptions) ? "chat_legacy_v1" : "chat_simplified_v1";
8486
+ }
8487
+ async function clickUniqueExperienceControl(page, labels) {
8488
+ for (const label of labels) {
8489
+ for (const role of ["button", "menuitem", "tab", "link"]) {
8490
+ if (await clickIfUnique2(page.getByRole?.(role, { name: label, exact: true }))) {
8491
+ return true;
8492
+ }
7982
8493
  }
7983
- return Object.fromEntries(kept);
7984
- } finally {
7985
- seen.delete(value);
7986
8494
  }
8495
+ if (typeof page.evaluate !== "function") {
8496
+ return false;
8497
+ }
8498
+ return page.evaluate((wantedLabels) => {
8499
+ const normalize = (value) => value.replace(/\s+/g, " ").trim().toLocaleLowerCase();
8500
+ const wanted = new Set(wantedLabels.map(normalize));
8501
+ const nodes = Array.from(document.querySelectorAll(
8502
+ "header button, header [role='button'], header [role='tab'], main [role='menuitem'], main [role='option']"
8503
+ ));
8504
+ const matches = nodes.filter((node) => {
8505
+ const html = node;
8506
+ const label = node.getAttribute("aria-label") ?? html.innerText ?? node.textContent ?? "";
8507
+ return wanted.has(normalize(label));
8508
+ });
8509
+ if (matches.length !== 1) return false;
8510
+ matches[0].click();
8511
+ return true;
8512
+ }, labels).catch(() => false);
7987
8513
  }
7988
- function normalizeOptions(options) {
7989
- return {
7990
- includeContent: options.includeContent === true,
7991
- maxPreviewChars: options.maxPreviewChars ?? DEFAULT_MAX_PREVIEW_CHARS,
7992
- maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH,
7993
- maxArrayItems: options.maxArrayItems ?? DEFAULT_MAX_ARRAY_ITEMS,
7994
- maxObjectEntries: options.maxObjectEntries ?? DEFAULT_MAX_OBJECT_ENTRIES
7995
- };
8514
+ async function clickIfUnique2(locator) {
8515
+ if (locator?.count === void 0 || locator.click === void 0) {
8516
+ return false;
8517
+ }
8518
+ if (await locator.count().catch(() => 0) !== 1) {
8519
+ return false;
8520
+ }
8521
+ await locator.click();
8522
+ return true;
7996
8523
  }
7997
- function isHeavyContentKey(key) {
7998
- return /^(text|markdown|html|visibleText|normalizedText|responseText|output_text|outputText|finalOutput|prompt|blocks|tables|codeBlocks|dataPreview)$/i.test(key);
8524
+ function matchingLabels(normalizedHaystack, candidates) {
8525
+ const normalizedCandidates = candidates.map(normalizeForLabelMatch);
8526
+ return normalizedHaystack.filter((label) => normalizedCandidates.some(
8527
+ (candidate) => label === candidate || visibleLabelMatches(label, candidate)
8528
+ )).slice(0, 4);
8529
+ }
8530
+ function hasAnyLabel(normalizedHaystack, candidates) {
8531
+ const normalizedCandidates = candidates.map(normalizeForLabelMatch);
8532
+ return normalizedHaystack.some(
8533
+ (label) => normalizedCandidates.some(
8534
+ (candidate) => label === candidate || visibleLabelMatches(label, candidate)
8535
+ )
8536
+ );
7999
8537
  }
8000
- function summarizeHeavyValue(value) {
8001
- if (Array.isArray(value)) return `[redacted-array:${value.length} items]`;
8002
- return "[redacted-object]";
8538
+ function containsAny(normalizedText, candidates) {
8539
+ return candidates.map(normalizeForLabelMatch).some((candidate) => normalizedText.includes(candidate));
8003
8540
  }
8004
- function isSafeControlStringKey(key) {
8005
- return /^(schemaVersion|status|startedAt|endedAt|createdAt|timestamp|requiredFailures)$/i.test(key);
8541
+ async function experienceSelectorDrift(page, message, detected) {
8542
+ return {
8543
+ ok: false,
8544
+ status: "unsupported",
8545
+ warnings: [],
8546
+ blocker: {
8547
+ kind: "selector_drift",
8548
+ code: "experience_control_not_found",
8549
+ fieldPath: "experience",
8550
+ message,
8551
+ candidates: detected.evidence.map((item) => ({ label: `${item.source}: ${item.label}` })),
8552
+ resumable: true
8553
+ },
8554
+ context: await contextFromPage(page, {
8555
+ experience: detected.experience,
8556
+ selectorProfile: detected.selectorProfile
8557
+ })
8558
+ };
8006
8559
  }
8007
8560
 
8008
- // src/safety/untrusted-output.ts
8009
- import { createHash as createHash3, randomUUID } from "node:crypto";
8010
- import { createReadStream } from "node:fs";
8011
- import { link, mkdir as mkdir3, readFile as readFile2, stat as stat5, unlink, writeFile as writeFile2 } from "node:fs/promises";
8012
- import { dirname } from "node:path";
8561
+ // src/commands/configuration.ts
8562
+ var WORK_AXES = ["model", "effort", "speed"];
8563
+ var CONFIGURATION_AXIS_ORDER = [
8564
+ "model",
8565
+ "intelligence",
8566
+ "effort",
8567
+ "speed",
8568
+ "modelVersion"
8569
+ ];
8570
+ async function inspectConfiguration(env, args = {}) {
8571
+ const boot = await ensurePage(env);
8572
+ if (!boot.ok) {
8573
+ return boot;
8574
+ }
8575
+ const page = env.page;
8576
+ try {
8577
+ const detected = await detectExperience(
8578
+ env,
8579
+ args.timeoutMs === void 0 ? {} : { timeoutMs: args.timeoutMs }
8580
+ );
8581
+ if (!detected.ok || detected.data === void 0) {
8582
+ return forwardFailure2(detected);
8583
+ }
8584
+ if (args.experience !== void 0 && detected.data.experience !== args.experience) {
8585
+ return {
8586
+ ok: false,
8587
+ status: "unsupported",
8588
+ warnings: [],
8589
+ blocker: {
8590
+ kind: "selector_drift",
8591
+ code: "experience_mismatch",
8592
+ fieldPath: "experience",
8593
+ message: `Configuration inspection expected ${args.experience}, but the visible composer is ${detected.data.experience}. Call experience.open first or omit the expected experience.`,
8594
+ resumable: true
8595
+ },
8596
+ context: await contextFromPage(page, {
8597
+ experience: detected.data.experience,
8598
+ selectorProfile: detected.data.selectorProfile
8599
+ })
8600
+ };
8601
+ }
8602
+ const experience = detected.data.experience;
8603
+ const rootOpened = experience !== "unknown" && await openConfigurationRoot(page, experience);
8604
+ if (rootOpened) {
8605
+ await page.waitForTimeout?.(150);
8606
+ }
8607
+ const panel = await readConfigurationPanel(page);
8608
+ const rootItems = rootOpened ? await enumerateVisibleMenuItems(page) : [];
8609
+ const data = configurationInspectionFromSurface(
8610
+ experience,
8611
+ detected.data.selectorProfile,
8612
+ detected.data.evidence,
8613
+ panel,
8614
+ rootItems
8615
+ );
8616
+ if (args.includeOptions !== false && experience === "work" && panel.axisRows.length > 0) {
8617
+ for (const axis of WORK_AXES) {
8618
+ if (!data.availableAxes.includes(axis)) continue;
8619
+ const options = await inspectWorkAxisOptions(page, axis);
8620
+ if (options.length > 0) {
8621
+ data.options[axis] = options;
8622
+ }
8623
+ }
8624
+ await closeConfigurationMenus(page);
8625
+ }
8626
+ const warnings = [];
8627
+ if (!rootOpened) {
8628
+ warnings.push("No scoped configuration opener was available; inspection is limited to controls already visible in the composer.");
8629
+ }
8630
+ if (!data.verified) {
8631
+ warnings.push("The visible configuration could not be verified from a recognized Chat or Work selector profile.");
8632
+ }
8633
+ return resultOk(data, await contextFromPage(page, {
8634
+ experience: data.experience,
8635
+ selectorProfile: data.selectorProfile
8636
+ }), warnings);
8637
+ } catch (error) {
8638
+ return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
8639
+ }
8640
+ }
8641
+ async function applyConfiguration(env, args) {
8642
+ const boot = await ensurePage(env);
8643
+ if (!boot.ok) {
8644
+ return boot;
8645
+ }
8646
+ const page = env.page;
8647
+ const strict = args.strict ?? true;
8648
+ try {
8649
+ const desired = normalizeDesiredSelection(args.desired);
8650
+ if (selectionEntries(desired).length === 0) {
8651
+ return {
8652
+ ok: false,
8653
+ status: "unsupported",
8654
+ warnings: [],
8655
+ blocker: {
8656
+ kind: "selector_drift",
8657
+ code: "configuration_empty",
8658
+ fieldPath: "desired",
8659
+ message: "configuration.apply requires at least one desired model, intelligence, effort, speed, or modelVersion value.",
8660
+ resumable: false
8661
+ },
8662
+ context: await contextFromPage(page)
8663
+ };
8664
+ }
8665
+ if (args.experience !== void 0) {
8666
+ const opened = await openExperience(env, {
8667
+ experience: args.experience,
8668
+ ...args.timeoutMs === void 0 ? {} : { timeoutMs: args.timeoutMs }
8669
+ });
8670
+ if (!opened.ok) {
8671
+ return forwardFailure2(opened);
8672
+ }
8673
+ }
8674
+ const beforeResult = await inspectConfiguration(env, {
8675
+ ...args.experience === void 0 ? {} : { experience: args.experience },
8676
+ includeOptions: true,
8677
+ ...args.timeoutMs === void 0 ? {} : { timeoutMs: args.timeoutMs }
8678
+ });
8679
+ if (!beforeResult.ok || beforeResult.data === void 0) {
8680
+ return forwardFailure2(beforeResult);
8681
+ }
8682
+ const before = beforeResult.data;
8683
+ if (before.experience === "unknown") {
8684
+ return configurationFailure(page, before, desired, [], "The visible surface is not recognizable as Chat or Work.", "experience_unknown");
8685
+ }
8686
+ const selected = [];
8687
+ for (const [axis, requested] of selectionEntries(desired)) {
8688
+ const active = activeConfigurationValue(before, axis);
8689
+ if (active !== void 0 && configurationValueMatches(active, requested)) {
8690
+ selected.push({ axis, requested, selected: active });
8691
+ continue;
8692
+ }
8693
+ const selection = before.experience === "work" ? await selectWorkAxis(page, axis, requested) : await selectChatAxis(env, axis, requested, args.timeoutMs);
8694
+ if (selection === void 0) {
8695
+ return configurationFailure(
8696
+ page,
8697
+ before,
8698
+ desired,
8699
+ selected,
8700
+ `Configuration option "${requested}" for ${axis} was not found or was ambiguous on the ${before.experience} surface.`,
8701
+ "configuration_option_not_found",
8702
+ before.options[axis]?.map((option) => option.label)
8703
+ );
8704
+ }
8705
+ selected.push({ axis, requested, selected: selection });
8706
+ }
8707
+ const afterResult = await inspectConfiguration(env, {
8708
+ ...args.experience === void 0 ? {} : { experience: args.experience },
8709
+ includeOptions: false,
8710
+ ...args.timeoutMs === void 0 ? {} : { timeoutMs: args.timeoutMs }
8711
+ });
8712
+ if (!afterResult.ok || afterResult.data === void 0) {
8713
+ return forwardFailure2(afterResult);
8714
+ }
8715
+ const after = afterResult.data;
8716
+ const verified = configurationMatchesSelection(after, desired);
8717
+ const data = { requested: desired, selected, before, after, verified };
8718
+ if (!verified && strict) {
8719
+ return {
8720
+ ok: false,
8721
+ status: "blocked",
8722
+ data,
8723
+ warnings: [],
8724
+ blocker: {
8725
+ kind: "selector_drift",
8726
+ code: "configuration_postcondition_unverified",
8727
+ fieldPath: "desired",
8728
+ message: `ChatGPT accepted configuration clicks, but the visible ${after.experience} controls do not verify every requested value.`,
8729
+ candidates: Object.entries(after.active).map(([axis, label]) => ({ label: `${axis}: ${label}` })),
8730
+ resumable: true
8731
+ },
8732
+ context: await contextFromPage(page, {
8733
+ experience: after.experience,
8734
+ selectorProfile: after.selectorProfile
8735
+ })
8736
+ };
8737
+ }
8738
+ const warnings = verified ? [] : ["Configuration clicks completed, but strict verification was disabled and the visible postcondition remains unverified."];
8739
+ return resultOk(data, await contextFromPage(page, {
8740
+ experience: after.experience,
8741
+ selectorProfile: after.selectorProfile
8742
+ }), warnings);
8743
+ } catch (error) {
8744
+ return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
8745
+ }
8746
+ }
8747
+ function configurationInspectionFromSurface(experience, detectedProfile, evidence, panel, menuItems) {
8748
+ const active = {};
8749
+ const options = {};
8750
+ const availableAxes = [];
8751
+ let selectorProfile = detectedProfile;
8752
+ if (experience === "work") {
8753
+ for (const row of panel.axisRows) {
8754
+ if (!availableAxes.includes(row.axis)) availableAxes.push(row.axis);
8755
+ if (row.value !== void 0 && row.value.length > 0) active[row.axis] = row.value;
8756
+ }
8757
+ selectorProfile = panel.advancedVisible ? "work_advanced_v1" : "work_basic_v1";
8758
+ } else if (experience === "chat") {
8759
+ const simplified = chatMenuLooksSimplified(menuItems);
8760
+ selectorProfile = simplified ? "chat_simplified_v1" : detectedProfile;
8761
+ const axis = simplified ? "intelligence" : "effort";
8762
+ if (menuItems.length > 0 || panel.openerLabel !== void 0) {
8763
+ availableAxes.push(axis);
8764
+ }
8765
+ if (panel.openerLabel !== void 0) {
8766
+ active[axis] = panel.openerLabel;
8767
+ }
8768
+ const chatOptions = menuItems.filter((item) => !isConfigurationAxisRow(item.label)).map(menuItemToOption);
8769
+ if (chatOptions.length > 0) {
8770
+ options[axis] = chatOptions;
8771
+ }
8772
+ const modelRows = menuItems.filter((item) => /^gpt[\s-]/i.test(item.label) || item.hasPopup === true);
8773
+ if (modelRows.length > 0) {
8774
+ availableAxes.push("modelVersion");
8775
+ options.modelVersion = modelRows.map(menuItemToOption);
8776
+ }
8777
+ }
8778
+ return {
8779
+ experience,
8780
+ selectorProfile,
8781
+ availableAxes,
8782
+ active,
8783
+ options,
8784
+ verified: experience !== "unknown" && (availableAxes.length > 0 || Object.keys(active).length > 0),
8785
+ evidence
8786
+ };
8787
+ }
8788
+ async function inspectWorkAxisOptions(page, axis) {
8789
+ await ensureWorkConfigurationRoot(page);
8790
+ if (!await clickWorkAxisRow(page, axis)) {
8791
+ return [];
8792
+ }
8793
+ await page.waitForTimeout?.(120);
8794
+ const items = await enumerateVisibleMenuItems(page);
8795
+ const options = items.filter((item) => !isConfigurationAxisRow(item.label)).map(menuItemToOption);
8796
+ await page.keyboard?.press?.("Escape");
8797
+ await page.waitForTimeout?.(80);
8798
+ return dedupeOptions(options);
8799
+ }
8800
+ async function selectWorkAxis(page, axis, requested) {
8801
+ if (!WORK_AXES.includes(axis)) {
8802
+ return void 0;
8803
+ }
8804
+ await ensureWorkConfigurationRoot(page);
8805
+ if (!await clickWorkAxisRow(page, axis)) {
8806
+ return void 0;
8807
+ }
8808
+ await page.waitForTimeout?.(120);
8809
+ const candidates = await enumerateVisibleMenuItems(page);
8810
+ const match = findConfigurationOption(candidates, requested);
8811
+ if (match === void 0 || !await clickVisibleMenuItem(page, match)) {
8812
+ return void 0;
8813
+ }
8814
+ await page.waitForTimeout?.(150);
8815
+ return match.label;
8816
+ }
8817
+ async function selectChatAxis(env, axis, requested, timeoutMs) {
8818
+ const legacyArgs = axis === "modelVersion" ? { modelVersion: requested } : axis === "intelligence" ? { intelligence: requested } : axis === "effort" ? { effort: requested } : axis === "model" ? { model: requested } : void 0;
8819
+ if (legacyArgs === void 0) {
8820
+ return void 0;
8821
+ }
8822
+ const result = await setMode(env, {
8823
+ ...legacyArgs,
8824
+ ...timeoutMs === void 0 ? {} : { timeoutMs }
8825
+ });
8826
+ return result.ok ? result.data?.selected.at(-1) : void 0;
8827
+ }
8828
+ async function openConfigurationRoot(page, experience) {
8829
+ const existing = await readConfigurationPanel(page);
8830
+ if (existing.axisRows.length > 0) {
8831
+ return true;
8832
+ }
8833
+ const existingItems = await enumerateVisibleMenuItems(page).catch(() => []);
8834
+ if (configurationMenuLooksRecognized(existingItems, experience, existing.openerLabel)) {
8835
+ return true;
8836
+ }
8837
+ if (typeof page.evaluate === "function") {
8838
+ const clicked = await page.evaluate((surface) => {
8839
+ const normalize = (value) => value.replace(/\s+/g, " ").trim();
8840
+ const visible = (element) => {
8841
+ const html = element;
8842
+ const rect = html.getBoundingClientRect?.();
8843
+ const style = typeof window !== "undefined" ? window.getComputedStyle?.(html) : void 0;
8844
+ return (rect === void 0 || rect.width > 0 && rect.height > 0) && style?.display !== "none" && style?.visibility !== "hidden" && style?.opacity !== "0";
8845
+ };
8846
+ const forms = Array.from(document.querySelectorAll("main form, main [data-testid*='composer' i]"));
8847
+ const controls = forms.flatMap((form) => Array.from(form.querySelectorAll("button, [role='button']"))).filter(visible);
8848
+ const matches = controls.filter((control) => {
8849
+ const html = control;
8850
+ const label = normalize(control.getAttribute("aria-label") ?? html.innerText ?? control.textContent ?? "");
8851
+ const testId = control.getAttribute("data-testid") ?? "";
8852
+ if (/send|voice|microphone|attach|upload|add files|plus/i.test(`${label} ${testId}`)) return false;
8853
+ if (/model-switcher|model-selector|mode-selector/i.test(testId)) return true;
8854
+ return surface === "work" ? /\b(?:gpt|sol|luna|terra|light|medium|high|max|ultra|standard|fast)\b/i.test(label) : /\b(?:instant|medium|high|extra high|pro|thinking|extended|gpt)\b/i.test(label);
8855
+ });
8856
+ if (matches.length !== 1) return false;
8857
+ matches[0].click();
8858
+ return true;
8859
+ }, experience).catch(() => false);
8860
+ if (clicked) return true;
8861
+ }
8862
+ const labels = experience === "work" ? [
8863
+ ...localeLabels.configurationOptions.light,
8864
+ ...localeLabels.configurationOptions.medium,
8865
+ ...localeLabels.configurationOptions.high,
8866
+ ...localeLabels.configurationOptions.standard
8867
+ ] : [
8868
+ ...localeLabels.configurationOptions.instant,
8869
+ ...localeLabels.configurationOptions.medium,
8870
+ ...localeLabels.configurationOptions.high,
8871
+ ...localeLabels.configurationOptions.extraHigh,
8872
+ ...localeLabels.configurationOptions.pro,
8873
+ ...localeLabels.modeOptions.thinking
8874
+ ];
8875
+ for (const label of labels) {
8876
+ if (await clickIfUnique3(page.getByRole?.("button", { name: label, exact: true }))) {
8877
+ return true;
8878
+ }
8879
+ }
8880
+ return false;
8881
+ }
8882
+ function configurationMenuLooksRecognized(items, experience, openerLabel) {
8883
+ if (items.some((item) => /(?:model|mode|effort|speed)-(?:switcher|selector)|model-switcher/i.test(item.testId ?? ""))) {
8884
+ return true;
8885
+ }
8886
+ if (openerLabel === void 0 || items.length === 0) {
8887
+ return false;
8888
+ }
8889
+ const semanticLabels = experience === "work" ? [
8890
+ ...localeLabels.configurationOptions.light,
8891
+ ...localeLabels.configurationOptions.medium,
8892
+ ...localeLabels.configurationOptions.high,
8893
+ ...localeLabels.configurationOptions.max,
8894
+ ...localeLabels.configurationOptions.ultra,
8895
+ ...localeLabels.configurationOptions.standard,
8896
+ ...localeLabels.configurationOptions.fast
8897
+ ] : [
8898
+ ...localeLabels.configurationOptions.instant,
8899
+ ...localeLabels.configurationOptions.medium,
8900
+ ...localeLabels.configurationOptions.high,
8901
+ ...localeLabels.configurationOptions.extraHigh,
8902
+ ...localeLabels.configurationOptions.pro,
8903
+ ...localeLabels.modeOptions.thinking,
8904
+ ...localeLabels.modeOptions.extended
8905
+ ];
8906
+ const matched = new Set(
8907
+ items.filter((item) => semanticLabels.some((label) => visibleLabelMatches(item.label, label))).map((item) => normalizeConfigurationId(item.label))
8908
+ );
8909
+ return matched.size >= 2;
8910
+ }
8911
+ async function ensureWorkConfigurationRoot(page) {
8912
+ const panel = await readConfigurationPanel(page);
8913
+ if (panel.axisRows.length > 0) return true;
8914
+ await page.keyboard?.press?.("Escape");
8915
+ await page.waitForTimeout?.(50);
8916
+ return openConfigurationRoot(page, "work");
8917
+ }
8918
+ async function readConfigurationPanel(page) {
8919
+ if (typeof page.evaluate !== "function") {
8920
+ return { axisRows: [], advancedVisible: false };
8921
+ }
8922
+ return page.evaluate((axisLabels) => {
8923
+ const normalize = (value) => value.replace(/\s+/g, " ").trim();
8924
+ const normalizedAxes = Object.fromEntries(
8925
+ Object.entries(axisLabels).map(([axis, labels]) => [
8926
+ axis,
8927
+ labels.map((label) => normalize(label).toLocaleLowerCase())
8928
+ ])
8929
+ );
8930
+ const visible = (element) => {
8931
+ const html = element;
8932
+ const rect = html.getBoundingClientRect?.();
8933
+ const style = typeof window !== "undefined" ? window.getComputedStyle?.(html) : void 0;
8934
+ return (rect === void 0 || rect.width > 0 && rect.height > 0) && style?.display !== "none" && style?.visibility !== "hidden" && style?.opacity !== "0";
8935
+ };
8936
+ const overlays = Array.from(document.querySelectorAll(
8937
+ "[role='menu'], [role='listbox'], [data-radix-popper-content-wrapper], [data-radix-menu-content]"
8938
+ )).filter(visible);
8939
+ const roots = overlays.length > 0 ? overlays : Array.from(document.querySelectorAll("main")).filter(visible);
8940
+ const rows = roots.flatMap((root) => Array.from(root.querySelectorAll(
8941
+ "button, [role='button'], [role='menuitem'], [role='menuitemradio'], [role='option']"
8942
+ ))).filter(visible);
8943
+ const axisRows = [];
8944
+ let advancedVisible = false;
8945
+ for (const row of rows) {
8946
+ const html = row;
8947
+ const label = normalize(row.getAttribute("aria-label") ?? html.innerText ?? row.textContent ?? "");
8948
+ const normalized = label.toLocaleLowerCase();
8949
+ if (normalizedAxes.advanced?.some((candidate) => normalized === candidate || normalized.startsWith(`${candidate} `))) {
8950
+ advancedVisible = true;
8951
+ }
8952
+ for (const axis of ["model", "intelligence", "effort", "speed"]) {
8953
+ const candidates = normalizedAxes[axis] ?? [];
8954
+ const prefix = candidates.find((candidate) => normalized === candidate || normalized.startsWith(`${candidate} `));
8955
+ if (prefix === void 0) continue;
8956
+ const value = normalize(label.slice(prefix.length));
8957
+ const item = { axis, label };
8958
+ if (value.length > 0) item.value = value;
8959
+ axisRows.push(item);
8960
+ break;
8961
+ }
8962
+ }
8963
+ const forms = Array.from(document.querySelectorAll("main form, main [data-testid*='composer' i]"));
8964
+ const openerCandidates = forms.flatMap((form) => Array.from(form.querySelectorAll("button, [role='button']"))).filter(visible).map((control) => {
8965
+ const html = control;
8966
+ return {
8967
+ label: normalize(control.getAttribute("aria-label") ?? html.innerText ?? control.textContent ?? ""),
8968
+ testId: control.getAttribute("data-testid") ?? ""
8969
+ };
8970
+ }).filter((item) => !/send|voice|microphone|attach|upload|add files|plus/i.test(`${item.label} ${item.testId}`)).filter((item) => /model-switcher|model-selector|mode-selector/i.test(item.testId) || /\b(?:gpt|sol|luna|terra|instant|medium|high|extra high|pro|thinking|extended|light|standard|fast)\b/i.test(item.label));
8971
+ const result = {
8972
+ axisRows,
8973
+ advancedVisible
8974
+ };
8975
+ if (openerCandidates.length === 1 && openerCandidates[0]?.label.length) {
8976
+ result.openerLabel = openerCandidates[0].label;
8977
+ }
8978
+ return result;
8979
+ }, localeLabels.configurationAxes).catch(() => ({ axisRows: [], advancedVisible: false }));
8980
+ }
8981
+ async function clickWorkAxisRow(page, axis) {
8982
+ const labels = axis === "modelVersion" ? [] : localeLabels.configurationAxes[axis] ?? [];
8983
+ for (const label of labels) {
8984
+ const pattern = new RegExp(`^${escapeRegExp3(label)}(?:\\s|$)`, "i");
8985
+ for (const role of ["button", "menuitem"]) {
8986
+ if (await clickIfUnique3(page.getByRole?.(role, { name: pattern }))) {
8987
+ return true;
8988
+ }
8989
+ }
8990
+ }
8991
+ if (typeof page.evaluate !== "function") return false;
8992
+ return page.evaluate((wantedLabels) => {
8993
+ const normalize = (value) => value.replace(/\s+/g, " ").trim().toLocaleLowerCase();
8994
+ const wanted = wantedLabels.map(normalize);
8995
+ const overlays = Array.from(document.querySelectorAll(
8996
+ "[role='menu'], [data-radix-popper-content-wrapper], [data-radix-menu-content]"
8997
+ ));
8998
+ const nodes = overlays.flatMap((root) => Array.from(root.querySelectorAll("button, [role='button'], [role='menuitem']")));
8999
+ const matches = nodes.filter((node) => {
9000
+ const html = node;
9001
+ const label = normalize(node.getAttribute("aria-label") ?? html.innerText ?? node.textContent ?? "");
9002
+ return wanted.some((prefix) => label === prefix || label.startsWith(`${prefix} `));
9003
+ });
9004
+ if (matches.length !== 1) return false;
9005
+ matches[0].click();
9006
+ return true;
9007
+ }, labels).catch(() => false);
9008
+ }
9009
+ async function clickVisibleMenuItem(page, item) {
9010
+ if (item.testId !== void 0 && await clickIfUnique3(page.locator?.(`[data-testid="${escapeAttributeValue2(item.testId)}"]`))) {
9011
+ return true;
9012
+ }
9013
+ for (const role of ["menuitemradio", "menuitem", "option"]) {
9014
+ if (await clickIfUnique3(page.getByRole?.(role, { name: item.label, exact: true }))) {
9015
+ return true;
9016
+ }
9017
+ }
9018
+ return clickIfUnique3(page.getByText?.(item.label, { exact: true }));
9019
+ }
9020
+ function findConfigurationOption(items, requested) {
9021
+ const normalizedRequested = normalizeConfigurationId(requested);
9022
+ const exact = items.filter((item) => normalizeConfigurationId(item.label) === normalizedRequested);
9023
+ if (exact.length === 1) return exact[0];
9024
+ const semanticLabels = configurationSemanticLabels(requested);
9025
+ for (const wanted of semanticLabels) {
9026
+ const matches = items.filter(
9027
+ (item) => normalizeForLabelMatch(item.label) === normalizeForLabelMatch(wanted) || visibleLabelMatches(item.label, wanted)
9028
+ );
9029
+ if (matches.length === 1) return matches[0];
9030
+ }
9031
+ return void 0;
9032
+ }
9033
+ function configurationSemanticLabels(requested) {
9034
+ const normalized = normalizeConfigurationId(requested);
9035
+ for (const labels of Object.values(localeLabels.configurationOptions)) {
9036
+ if (labels.some((label) => normalizeConfigurationId(label) === normalized)) {
9037
+ return labels;
9038
+ }
9039
+ }
9040
+ for (const labels of Object.values(localeLabels.modeOptions)) {
9041
+ if (labels.some((label) => normalizeConfigurationId(label) === normalized)) {
9042
+ return labels;
9043
+ }
9044
+ }
9045
+ return [requested];
9046
+ }
9047
+ function configurationMatchesSelection(inspection, desired) {
9048
+ return selectionEntries(desired).every(([axis, requested]) => {
9049
+ const active = activeConfigurationValue(inspection, axis);
9050
+ return active !== void 0 && configurationValueMatches(active, requested);
9051
+ });
9052
+ }
9053
+ function activeConfigurationValue(inspection, axis) {
9054
+ const direct = inspection.active[axis];
9055
+ if (direct !== void 0 || inspection.experience !== "chat") {
9056
+ return direct;
9057
+ }
9058
+ if (axis === "model" || axis === "intelligence") {
9059
+ return inspection.active.intelligence ?? inspection.active.effort;
9060
+ }
9061
+ if (axis === "effort") {
9062
+ return inspection.active.effort ?? inspection.active.intelligence;
9063
+ }
9064
+ return void 0;
9065
+ }
9066
+ function configurationValueMatches(actual, requested) {
9067
+ const normalizedActual = normalizeConfigurationId(actual);
9068
+ const normalizedRequested = normalizeConfigurationId(requested);
9069
+ if (normalizedActual === normalizedRequested) return true;
9070
+ return configurationSemanticLabels(requested).some((label) => normalizeConfigurationId(label) === normalizedActual);
9071
+ }
9072
+ function selectionEntries(selection) {
9073
+ const entries = [];
9074
+ for (const axis of CONFIGURATION_AXIS_ORDER) {
9075
+ const value = selection[axis];
9076
+ if (typeof value === "string" && value.trim().length > 0) {
9077
+ entries.push([axis, value.trim()]);
9078
+ }
9079
+ }
9080
+ return entries;
9081
+ }
9082
+ function normalizeDesiredSelection(selection) {
9083
+ const normalized = {};
9084
+ for (const axis of ["model", "intelligence", "effort", "speed"]) {
9085
+ const value = selection[axis]?.trim();
9086
+ if (value !== void 0 && value.length > 0) normalized[axis] = value;
9087
+ }
9088
+ const modelVersion = (selection.modelVersion ?? selection.version)?.trim();
9089
+ if (modelVersion !== void 0 && modelVersion.length > 0) {
9090
+ normalized.modelVersion = modelVersion;
9091
+ }
9092
+ return normalized;
9093
+ }
9094
+ function menuItemToOption(item) {
9095
+ const option = {
9096
+ id: normalizeConfigurationId(item.label),
9097
+ label: item.label,
9098
+ selected: item.checked === true
9099
+ };
9100
+ if (item.hasPopup !== void 0) option.hasSubmenu = item.hasPopup;
9101
+ return option;
9102
+ }
9103
+ function dedupeOptions(options) {
9104
+ const seen = /* @__PURE__ */ new Set();
9105
+ return options.filter((option) => {
9106
+ const key = `${option.id}\0${option.label}`;
9107
+ if (seen.has(key)) return false;
9108
+ seen.add(key);
9109
+ return true;
9110
+ });
9111
+ }
9112
+ function chatMenuLooksSimplified(items) {
9113
+ const normalized = items.map((item) => normalizeConfigurationId(item.label));
9114
+ const simplified = ["instant", "medium", "high", "extra high", "pro"];
9115
+ return simplified.filter((label) => normalized.includes(label)).length >= 3;
9116
+ }
9117
+ function isConfigurationAxisRow(label) {
9118
+ const normalized = normalizeForLabelMatch(label);
9119
+ return Object.values(localeLabels.configurationAxes).flat().some((axis) => {
9120
+ const prefix = normalizeForLabelMatch(axis);
9121
+ return normalized === prefix || normalized.startsWith(`${prefix} `);
9122
+ });
9123
+ }
9124
+ function normalizeConfigurationId(value) {
9125
+ return normalizeForLabelMatch(value).replace(/^gpt[\s-]*/i, "gpt ").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
9126
+ }
9127
+ async function closeConfigurationMenus(page) {
9128
+ await page.keyboard?.press?.("Escape");
9129
+ await page.waitForTimeout?.(50);
9130
+ await page.keyboard?.press?.("Escape");
9131
+ }
9132
+ async function clickIfUnique3(locator) {
9133
+ if (locator?.count === void 0 || locator.click === void 0) return false;
9134
+ if (await locator.count().catch(() => 0) !== 1) return false;
9135
+ await locator.click();
9136
+ return true;
9137
+ }
9138
+ async function configurationFailure(page, before, desired, selected, message, code, candidates = []) {
9139
+ const data = {
9140
+ requested: desired,
9141
+ selected,
9142
+ before,
9143
+ after: before,
9144
+ verified: false
9145
+ };
9146
+ return {
9147
+ ok: false,
9148
+ status: "unsupported",
9149
+ data,
9150
+ warnings: [],
9151
+ blocker: {
9152
+ kind: "selector_drift",
9153
+ code,
9154
+ fieldPath: "desired",
9155
+ message,
9156
+ candidates: candidates.map((label) => ({ label })),
9157
+ resumable: true
9158
+ },
9159
+ context: await contextFromPage(page, {
9160
+ experience: before.experience,
9161
+ selectorProfile: before.selectorProfile
9162
+ })
9163
+ };
9164
+ }
9165
+ function escapeRegExp3(value) {
9166
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9167
+ }
9168
+ function escapeAttributeValue2(value) {
9169
+ return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
9170
+ }
9171
+ function forwardFailure2(result) {
9172
+ const forwarded = {
9173
+ ok: false,
9174
+ status: result.status,
9175
+ warnings: result.warnings,
9176
+ context: result.context
9177
+ };
9178
+ if (result.output_text !== void 0) forwarded.output_text = result.output_text;
9179
+ if (result.reportPath !== void 0) forwarded.reportPath = result.reportPath;
9180
+ if (result.error !== void 0) forwarded.error = result.error;
9181
+ if (result.blocker !== void 0) forwarded.blocker = result.blocker;
9182
+ if (result.steps !== void 0) forwarded.steps = result.steps;
9183
+ return forwarded;
9184
+ }
9185
+
9186
+ // src/commands/reports.ts
9187
+ import { join as join3 } from "node:path";
9188
+
9189
+ // src/safety/report-redaction.ts
9190
+ var DEFAULT_MAX_PREVIEW_CHARS = 240;
9191
+ var DEFAULT_MAX_DEPTH = 8;
9192
+ var DEFAULT_MAX_ARRAY_ITEMS = 40;
9193
+ var DEFAULT_MAX_OBJECT_ENTRIES = 80;
9194
+ function redactReportValue(value, options = {}) {
9195
+ return redactValue(value, normalizeOptions(options), 0, /* @__PURE__ */ new WeakSet(), void 0);
9196
+ }
9197
+ function redactValue(value, options, depth, seen, key) {
9198
+ if (value === void 0 || value === null) return value;
9199
+ if (typeof value === "string") {
9200
+ if (!options.includeContent && key !== void 0 && isSafeControlStringKey(key)) {
9201
+ return value;
9202
+ }
9203
+ if (!options.includeContent) return `[redacted:${value.length} chars]`;
9204
+ return compactVisibleText(redactSensitiveText(value), options.maxPreviewChars);
9205
+ }
9206
+ if (typeof value === "number" || typeof value === "boolean") return value;
9207
+ if (typeof value !== "object") return redactSensitiveText(String(value));
9208
+ if (seen.has(value)) return "[redacted:cycle]";
9209
+ if (depth >= options.maxDepth) return "[redacted:max-depth]";
9210
+ if (!options.includeContent && key !== void 0 && isHeavyContentKey(key)) {
9211
+ return summarizeHeavyValue(value);
9212
+ }
9213
+ seen.add(value);
9214
+ try {
9215
+ if (Array.isArray(value)) {
9216
+ const items = value.slice(0, options.maxArrayItems).map((item) => redactValue(item, options, depth + 1, seen, key));
9217
+ if (value.length > options.maxArrayItems) {
9218
+ items.push(`[redacted:${value.length - options.maxArrayItems} more items]`);
9219
+ }
9220
+ return items;
9221
+ }
9222
+ const entries = Object.entries(value);
9223
+ const kept = entries.slice(0, options.maxObjectEntries).map(([childKey, child]) => [
9224
+ childKey,
9225
+ redactValue(child, options, depth + 1, seen, childKey)
9226
+ ]);
9227
+ if (entries.length > options.maxObjectEntries) {
9228
+ kept.push(["__redactedMoreEntries", entries.length - options.maxObjectEntries]);
9229
+ }
9230
+ return Object.fromEntries(kept);
9231
+ } finally {
9232
+ seen.delete(value);
9233
+ }
9234
+ }
9235
+ function normalizeOptions(options) {
9236
+ return {
9237
+ includeContent: options.includeContent === true,
9238
+ maxPreviewChars: options.maxPreviewChars ?? DEFAULT_MAX_PREVIEW_CHARS,
9239
+ maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH,
9240
+ maxArrayItems: options.maxArrayItems ?? DEFAULT_MAX_ARRAY_ITEMS,
9241
+ maxObjectEntries: options.maxObjectEntries ?? DEFAULT_MAX_OBJECT_ENTRIES
9242
+ };
9243
+ }
9244
+ function isHeavyContentKey(key) {
9245
+ return /^(text|markdown|html|visibleText|normalizedText|responseText|output_text|outputText|finalOutput|prompt|blocks|tables|codeBlocks|dataPreview)$/i.test(key);
9246
+ }
9247
+ function summarizeHeavyValue(value) {
9248
+ if (Array.isArray(value)) return `[redacted-array:${value.length} items]`;
9249
+ return "[redacted-object]";
9250
+ }
9251
+ function isSafeControlStringKey(key) {
9252
+ return /^(schemaVersion|status|startedAt|endedAt|createdAt|timestamp|requiredFailures)$/i.test(key);
9253
+ }
9254
+
9255
+ // src/safety/untrusted-output.ts
9256
+ import { createHash as createHash3, randomUUID } from "node:crypto";
9257
+ import { createReadStream } from "node:fs";
9258
+ import { link, mkdir as mkdir3, readFile as readFile2, stat as stat5, unlink, writeFile as writeFile2 } from "node:fs/promises";
9259
+ import { dirname } from "node:path";
8013
9260
  var UNTRUSTED_OUTPUT_INLINE_LIMIT_BYTES = 12e3;
8014
9261
  var UNTRUSTED_OUTPUT_SCHEMA_VERSION = "chatgpt.browser_control.untrusted_output_return.v1";
8015
9262
  var INTEGRITY_SCHEMA_VERSION = "chatgpt.browser_control.integrity.v1";
@@ -8285,7 +9532,7 @@ function isRecord3(value) {
8285
9532
 
8286
9533
  // src/commands/response-actions.ts
8287
9534
  async function copyResponse(env, args = {}) {
8288
- const boot = await ensurePage5(env);
9535
+ const boot = await ensurePage(env);
8289
9536
  if (!boot.ok) {
8290
9537
  return boot;
8291
9538
  }
@@ -8423,16 +9670,19 @@ function mergeResponseMetadata(data, latest) {
8423
9670
  if (latest.thoughtDurationText !== void 0) data.thoughtDurationText = latest.thoughtDurationText;
8424
9671
  if (latest.sourcesAvailable !== void 0) data.sourcesAvailable = latest.sourcesAvailable;
8425
9672
  }
8426
- async function ensurePage5(env) {
8427
- if (env.page !== void 0) {
8428
- return resultOk({}, await contextFromPage(env.page));
8429
- }
8430
- return bootstrap(env, { preferExistingTab: true });
8431
- }
8432
9673
 
8433
9674
  // src/safety/risk.ts
8434
9675
  var commandRisk = {
8435
9676
  "session.bootstrap": "low",
9677
+ "experience.detect": "low",
9678
+ "experience.open": "medium",
9679
+ "configuration.inspect": "low",
9680
+ "configuration.apply": "medium",
9681
+ "work.start": "medium",
9682
+ "work.status": "medium",
9683
+ "work.wait": "low",
9684
+ "work.steer": "medium",
9685
+ "work.readLatest": "medium",
8436
9686
  "threads.search": "medium",
8437
9687
  "threads.open": "medium",
8438
9688
  "threads.new": "low",
@@ -8441,6 +9691,7 @@ var commandRisk = {
8441
9691
  "messages.ask": "medium",
8442
9692
  "messages.wait": "low",
8443
9693
  "messages.readLatest": "medium",
9694
+ "messages.status": "medium",
8444
9695
  "messages.waitAndRead": "medium",
8445
9696
  "artifacts.listLatest": "medium",
8446
9697
  "artifacts.wait": "low",
@@ -8474,8 +9725,9 @@ var descriptors = [
8474
9725
  `await chatgpt.askInThread({ thread: { type: "search", query: "Naming macOS Utility" }, prompt: "Continue." });`,
8475
9726
  `await chatgpt.askInThread({ thread: { type: "url", url: "https://chatgpt.com/c/<conversation-id>" }, existingTab: true, prompt: "Continue." });`
8476
9727
  ]),
8477
- workflow("askWithFiles", "Attach absolute local file paths, optionally set mode, ask, wait, and read.", [
8478
- `await chatgpt.askWithFiles({ thread: { type: "url", url: "https://chatgpt.com/c/<conversation-id>" }, existingTab: true, mode: { model: "Pro" }, files: ["/absolute/host/path/brief.md"], prompt: "Summarize this.", wait: true, read: { format: "markdown" } });`
9728
+ workflow("askWithFiles", "Attach absolute local file paths, optionally open/configure Chat or Work, ask, wait, and read.", [
9729
+ `await chatgpt.askWithFiles({ thread: { type: "url", url: "https://chatgpt.com/c/<conversation-id>" }, existingTab: true, experience: "chat", configuration: { intelligence: "Pro" }, files: ["/absolute/host/path/brief.md"], prompt: "Summarize this.", wait: true, read: { format: "markdown" } });`,
9730
+ `await chatgpt.askWithFiles({ mode: { model: "Pro" }, files: ["/absolute/host/path/image.jpg"], prompt: "Describe this image.", wait: true });`
8479
9731
  ]),
8480
9732
  workflow("askAndDownload", "Ask ChatGPT to produce a visible downloadable output and save the latest exposed file.", [
8481
9733
  `await chatgpt.askAndDownload({ prompt: "Create a CSV.", download: { destDir: "/absolute/host/output" }, wait: true });`
@@ -8483,13 +9735,16 @@ var descriptors = [
8483
9735
  workflow("runMessages", "Run sequential prompts where later prompts can use earlier step data.", [
8484
9736
  `await chatgpt.runMessages({ messages: [{ id: "first", prompt: "alpha" }, { id: "second", prompt: "beta" }] });`
8485
9737
  ]),
8486
- workflow("runner.run", "Agents-style facade: run a visible ChatGPT browser-control agent against input, files, thread, existing-tab, mode, and response options.", [
8487
- `const agent = chatgpt.agent({ name: "reviewer", instructions: "Review deeply." }); await chatgpt.runner.run(agent, { input: "Review this.", thread: { type: "new" } });`,
9738
+ workflow("runner.run", "Agents-style facade: run a visible ChatGPT agent against input, files, thread, existing-tab, experience, configuration, legacy mode, and response options.", [
9739
+ `const agent = chatgpt.agent({ name: "reviewer", instructions: "Review deeply." }); await chatgpt.runner.run(agent, { input: "Review this.", thread: { type: "new" }, experience: "chat" });`,
8488
9740
  `await chatgpt.runner.run(agent, { input: "Continue.", thread: { type: "url", url: "https://chatgpt.com/c/<conversation-id>" }, existingTab: true });`
8489
9741
  ]),
8490
9742
  workflow("responses.create", "Narrow Responses-shaped adapter over the visible ChatGPT browser-control runner; rejects unsupported API-only fields before prompt submission.", [
8491
9743
  `await chatgpt.responses.create({ input: "Summarize.", thread: { type: "current" }, text: { format: "markdown" }, stream: false });`
8492
9744
  ]),
9745
+ workflow("work.start", "Open Work, optionally apply model/effort/speed configuration, submit one task, and optionally wait/read without blind resubmission.", [
9746
+ `await chatgpt.work.start({ prompt: "Analyze the attached package.", files: ["/absolute/path/package.tgz"], configuration: { model: "GPT-5.6 Sol", effort: "High", speed: "Fast" }, wait: true, read: { format: "markdown" } });`
9747
+ ]),
8493
9748
  workflow("copyLatest", "Copy or DOM-read the latest assistant response with Markdown-first fidelity.", [
8494
9749
  `await chatgpt.copyLatest({ prefer: "clipboard" });`
8495
9750
  ]),
@@ -8530,6 +9785,14 @@ var descriptors = [
8530
9785
  `await chatgpt.createReport(result, { destDir: "/absolute/host/reports" });`
8531
9786
  ]),
8532
9787
  primitive("session.bootstrap", "Attach to ChatGPT in Chrome and detect login/blocker state.", 3e4),
9788
+ primitive("experience.detect", "Detect whether the scoped visible composer is Chat, Work, or unknown and return its selector profile.", 3e4),
9789
+ primitive("experience.open", "Open Chat or Work and verify the target surface from scoped composer evidence.", 3e4),
9790
+ primitive("configuration.inspect", "Inspect the active Chat or Work selector profile, axes, options, and selected values.", 3e4),
9791
+ primitive("configuration.apply", "Apply model/intelligence/effort/speed configuration one axis at a time and verify the final visible state.", 3e4),
9792
+ primitive("work.status", "Read current Work task progress and optionally enumerate visible artifacts.", 5e3),
9793
+ primitive("work.wait", "Wait for the current Work task response to stabilize.", 12e4),
9794
+ primitive("work.steer", "Submit a visible steering message to the current Work task without opening a new task.", 12e4),
9795
+ primitive("work.readLatest", "Read the latest response from the current Work task.", 3e4),
8533
9796
  primitive("threads.new", "Open a new ChatGPT thread.", 3e4),
8534
9797
  primitive("threads.search", "Search visible ChatGPT history by query.", 3e4),
8535
9798
  primitive("threads.open", "Open a thread by URL, conversation id, title, or search result.", 3e4),
@@ -8538,6 +9801,7 @@ var descriptors = [
8538
9801
  primitive("messages.ask", "Compose, submit, optionally wait, and optionally read.", 12e4),
8539
9802
  primitive("messages.wait", "Wait for the latest assistant response to stabilize.", 12e4),
8540
9803
  primitive("messages.readLatest", "Read the latest message as Markdown, normalized text, blocks, or HTML.", 3e4),
9804
+ primitive("messages.status", "Read a compact latest-assistant progress snapshot without treating partial text as complete.", 5e3),
8541
9805
  primitive("messages.waitAndRead", "Wait for completion and read the latest message.", 12e4),
8542
9806
  primitive("artifacts.listLatest", "Detect the latest visible generated ChatGPT artifact, such as an image-only result.", 3e4),
8543
9807
  primitive("artifacts.wait", "Wait for a visible generated ChatGPT artifact to appear and stabilize.", 12e4),
@@ -8549,8 +9813,8 @@ var descriptors = [
8549
9813
  primitive("projects.sources.planAdd", "Dry-run an append-only Project Sources file add from explicit local files without opening ChatGPT.", 3e4),
8550
9814
  primitive("projects.sources.add", "Append explicit local files to a visible ChatGPT Project Sources list after confirmMutation: true.", 18e4),
8551
9815
  primitive("response.copy", "Click Copy response and return clipboard Markdown, with DOM fallback.", 5e3),
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),
9816
+ primitive("modes.set", "Legacy compatibility command: select a visible model/intelligence/effort/version candidate with historical warning-oriented verification.", 3e4),
9817
+ primitive("modes.get", "Legacy compatibility command: read mode labels shown on visible composer controls without changing them.", 3e4),
8554
9818
  primitive("tools.select", "Select a visible ChatGPT tool when unambiguous.", 3e4)
8555
9819
  ];
8556
9820
  function commandDescriptors() {
@@ -8649,12 +9913,24 @@ function workflowArgs(name) {
8649
9913
  if (name === "ask-and-download") return { prompt: "message to send", destDir: "download destination directory" };
8650
9914
  if (name === "two-turn") return { first: "first message", second: "second message" };
8651
9915
  if (name === "new-ask-read") return { prompt: "message to send" };
9916
+ if (name === "work.start") {
9917
+ return {
9918
+ prompt: "visible Work task prompt",
9919
+ newTask: "start from a blank Work task; defaults to true",
9920
+ files: "optional absolute local file paths",
9921
+ configuration: "optional Work model, effort, and speed values",
9922
+ wait: "optional wait behavior",
9923
+ read: "optional response capture behavior"
9924
+ };
9925
+ }
8652
9926
  if (name === "askWithFiles") {
8653
9927
  return {
8654
9928
  files: "absolute local file paths to attach before submitting",
8655
9929
  prompt: "message to send after files are attached",
8656
9930
  thread: "optional thread selector",
8657
9931
  existingTab: "true or explicit policy to claim a user-open Chrome tab instead of opening a replacement",
9932
+ experience: "optional chat or work surface",
9933
+ configuration: 'optional strict visible configuration such as { intelligence: "Pro" } or Work model/effort/speed',
8658
9934
  mode: 'optional visible mode selection, e.g. { model: "Pro" } or { intelligence: "Pro", modelVersion: "5.4" }',
8659
9935
  wait: "true or wait options; defaults to true",
8660
9936
  read: 'true or read options such as { format: "markdown" }; defaults to Markdown',
@@ -8665,6 +9941,9 @@ function workflowArgs(name) {
8665
9941
  prompt: "message to send or workflow-specific input",
8666
9942
  thread: "optional thread selector",
8667
9943
  existingTab: "true or explicit policy to claim a user-open Chrome tab instead of opening a replacement",
9944
+ experience: "optional chat or work surface",
9945
+ configuration: "optional surface-aware visible configuration",
9946
+ mode: "legacy visible mode preference",
8668
9947
  report: "optional redacted report settings"
8669
9948
  };
8670
9949
  }
@@ -8695,6 +9974,15 @@ function primitiveArgs(name) {
8695
9974
  responseContent: "include for current behavior, metadata to omit assistant text and return chars/hash only"
8696
9975
  };
8697
9976
  if (name === "messages.readLatest") return { role: "assistant or user", format: "markdown, normalized_text, visible_text, html, blocks, or all" };
9977
+ if (name === "messages.status") return { maxPreviewChars: "maximum latest-assistant preview characters to return; defaults to 240" };
9978
+ if (name === "experience.detect") return { timeoutMs: "optional timeout for attaching to the ChatGPT page" };
9979
+ if (name === "experience.open") return { experience: "chat or work", timeoutMs: "optional verified-switch timeout" };
9980
+ if (name === "configuration.inspect") return { experience: "optional expected chat or work surface", includeOptions: "open visible axis menus to enumerate options; defaults to true", timeoutMs: "optional inspection timeout" };
9981
+ if (name === "configuration.apply") return { experience: "optional target chat or work surface", desired: "model, intelligence, effort, speed, and/or modelVersion values", strict: "fail when visible postconditions are not verified; defaults to true", timeoutMs: "optional selection timeout" };
9982
+ if (name === "work.status") return { includeArtifacts: "include the latest visible artifact inventory; defaults to false for lightweight polling", maxPreviewChars: "maximum assistant preview characters" };
9983
+ if (name === "work.wait") return { timeoutMs: "optional Work wait timeout", stableMs: "required response stability window", pollMs: "polling interval" };
9984
+ if (name === "work.steer") return { prompt: "visible steering message for the current task", wait: "optional wait behavior", read: "optional response capture behavior" };
9985
+ if (name === "work.readLatest") return { format: "markdown, normalized_text, visible_text, html, blocks, or all", maxChars: "optional capture limit" };
8698
9986
  if (name === "artifacts.listLatest") return { kind: "artifact kind; currently image", max: "maximum artifacts to return" };
8699
9987
  if (name === "artifacts.wait") return { kind: "artifact kind; currently image", afterArtifactCount: "baseline artifact count", requireDownload: "wait until a download affordance is visible" };
8700
9988
  if (name === "artifacts.downloadLatest") return { destDir: "download destination directory", prefer: "download_control or visible_image_source" };
@@ -8747,6 +10035,14 @@ function primitiveExamples(name) {
8747
10035
  `// Verify an expensive Pro consult before submitting: const current = await chatgpt.modes.get();`
8748
10036
  ];
8749
10037
  }
10038
+ if (name === "experience.detect") return [`await chatgpt.experience.detect();`];
10039
+ if (name === "experience.open") return [`await chatgpt.experience.open({ experience: "work" });`];
10040
+ if (name === "configuration.inspect") return [`await chatgpt.configuration.inspect({ experience: "work" });`];
10041
+ if (name === "configuration.apply") return [`await chatgpt.configuration.apply({ experience: "work", desired: { model: "GPT-5.6 Sol", effort: "High", speed: "Fast" }, strict: true });`];
10042
+ if (name === "work.status") return [`await chatgpt.work.status();`];
10043
+ if (name === "work.wait") return [`await chatgpt.work.wait({ timeoutMs: 600000 });`];
10044
+ if (name === "work.steer") return [`await chatgpt.work.steer({ prompt: "Focus the comparison on deployment ergonomics." });`];
10045
+ if (name === "work.readLatest") return [`await chatgpt.work.readLatest({ format: "markdown" });`];
8750
10046
  if (name === "files.preflight") {
8751
10047
  return [
8752
10048
  `await chatgpt.files.preflight({ paths: ["/absolute/host/path.md"] });`,
@@ -8780,7 +10076,7 @@ function primitiveBlockers(name) {
8780
10076
  if (name === "projects.sources.planAdd") return ["not_found", "permission", "upload_failed"];
8781
10077
  if (name.startsWith("projects.sources.")) return ["browser_bridge_unavailable", "login_required", "selector_drift", "confirmation", "permission", "upload_failed"];
8782
10078
  if (name.startsWith("artifacts.")) return ["browser_bridge_unavailable", "login_required", "artifact_unavailable", "artifact_selector_drift", "artifact_download_unavailable"];
8783
- if (name.startsWith("modes.") || name.startsWith("tools.")) return ["browser_bridge_unavailable", "login_required", "selector_drift"];
10079
+ if (name.startsWith("modes.") || name.startsWith("tools.") || name.startsWith("experience.") || name.startsWith("configuration.") || name.startsWith("work.")) return ["browser_bridge_unavailable", "login_required", "selector_drift"];
8784
10080
  return commonBlockers();
8785
10081
  }
8786
10082
  function commonBlockers() {
@@ -8876,7 +10172,7 @@ function extractThreadSearchResultsFromHtml(html) {
8876
10172
  return dedupeResults(results);
8877
10173
  }
8878
10174
  async function searchThreads(env, args) {
8879
- const boot = await ensurePage6(env);
10175
+ const boot = await ensurePage(env);
8880
10176
  if (!boot.ok) {
8881
10177
  return boot;
8882
10178
  }
@@ -8898,7 +10194,7 @@ async function searchThreads(env, args) {
8898
10194
  }
8899
10195
  }
8900
10196
  async function newThread(env, args = {}) {
8901
- const boot = await ensurePage6(env);
10197
+ const boot = await ensurePage(env);
8902
10198
  if (!boot.ok) {
8903
10199
  return boot;
8904
10200
  }
@@ -8917,7 +10213,7 @@ async function newThread(env, args = {}) {
8917
10213
  }
8918
10214
  }
8919
10215
  async function openThread(env, args, previousResults) {
8920
- const boot = await ensurePage6(env);
10216
+ const boot = await ensurePage(env);
8921
10217
  if (!boot.ok) {
8922
10218
  return boot;
8923
10219
  }
@@ -8946,12 +10242,6 @@ async function openThread(env, args, previousResults) {
8946
10242
  return resultError(error instanceof Error ? error : new Error(String(error)), await contextFromPage(page));
8947
10243
  }
8948
10244
  }
8949
- async function ensurePage6(env) {
8950
- if (env.page !== void 0) {
8951
- return resultOk({}, await contextFromPage(env.page));
8952
- }
8953
- return bootstrap(env, { preferExistingTab: true });
8954
- }
8955
10245
  async function resolveOpenTarget(env, args, previousResults) {
8956
10246
  if (args.url !== void 0) {
8957
10247
  return { url: args.url };
@@ -9105,6 +10395,312 @@ function filterResultsByQuery(results, query) {
9105
10395
  });
9106
10396
  }
9107
10397
 
10398
+ // src/commands/work.ts
10399
+ var NEW_WORK_LABELS = localeLabels.newWork;
10400
+ async function startWork(env, args) {
10401
+ const prompt = args.prompt.trim();
10402
+ if (prompt.length === 0) {
10403
+ return {
10404
+ ok: false,
10405
+ status: "unsupported",
10406
+ warnings: [],
10407
+ blocker: {
10408
+ kind: "selector_drift",
10409
+ code: "empty_work_prompt",
10410
+ fieldPath: "prompt",
10411
+ message: "work.start requires a non-empty visible prompt.",
10412
+ resumable: false
10413
+ },
10414
+ context: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
10415
+ };
10416
+ }
10417
+ const boot = await ensurePage(env);
10418
+ if (!boot.ok) {
10419
+ return boot;
10420
+ }
10421
+ const page = env.page;
10422
+ try {
10423
+ const surface = await openExperience(env, {
10424
+ experience: "work",
10425
+ ...args.timeoutMs === void 0 ? {} : { timeoutMs: args.timeoutMs }
10426
+ });
10427
+ if (!surface.ok) {
10428
+ return forwardCommandFailure(surface);
10429
+ }
10430
+ if (args.newTask !== false) {
10431
+ const fresh = await ensureBlankWorkTask(env, args.timeoutMs);
10432
+ if (!fresh.ok) {
10433
+ return forwardCommandFailure(fresh);
10434
+ }
10435
+ }
10436
+ const baselineTurnCount = await countPageMessages(page).catch(() => void 0);
10437
+ const baselineAssistantTurnCount = await countPageMessages(page, "assistant").catch(() => void 0);
10438
+ let configuration;
10439
+ if (args.configuration !== void 0) {
10440
+ const applied = await applyConfiguration(env, {
10441
+ experience: "work",
10442
+ desired: args.configuration,
10443
+ strict: true,
10444
+ ...args.timeoutMs === void 0 ? {} : { timeoutMs: args.timeoutMs }
10445
+ });
10446
+ if (!applied.ok || applied.data === void 0) {
10447
+ return forwardCommandFailure(applied);
10448
+ }
10449
+ configuration = applied.data;
10450
+ }
10451
+ if ((args.files?.length ?? 0) > 0) {
10452
+ const attach = await attachFiles(env, {
10453
+ paths: args.files ?? [],
10454
+ ...args.timeoutMs === void 0 ? {} : { timeoutMs: args.timeoutMs }
10455
+ });
10456
+ if (!attach.ok) {
10457
+ return forwardCommandFailure(attach);
10458
+ }
10459
+ }
10460
+ const compose = await composeMessage(env, {
10461
+ text: prompt,
10462
+ mode: "replace",
10463
+ ...args.timeoutMs === void 0 ? {} : { timeoutMs: args.timeoutMs }
10464
+ });
10465
+ if (!compose.ok) {
10466
+ return forwardCommandFailure(compose);
10467
+ }
10468
+ const submitArgs = {
10469
+ text: prompt,
10470
+ ...baselineTurnCount === void 0 ? {} : { previousTurnCount: baselineTurnCount },
10471
+ ...args.timeoutMs === void 0 ? {} : { timeoutMs: args.timeoutMs }
10472
+ };
10473
+ const submit = await submitMessage(env, submitArgs);
10474
+ if (!submit.ok || submit.data === void 0) {
10475
+ return forwardCommandFailure(submit);
10476
+ }
10477
+ const task = await workTaskRef(env, baselineTurnCount, baselineAssistantTurnCount);
10478
+ const data = { task, submitted: submit.data };
10479
+ if (configuration !== void 0) data.configuration = configuration;
10480
+ let waitResult;
10481
+ if (args.wait === true || typeof args.wait === "object") {
10482
+ const waitArgs = typeof args.wait === "object" ? { ...args.wait } : {};
10483
+ if (baselineTurnCount !== void 0) waitArgs.afterTurnCount = baselineTurnCount;
10484
+ if (baselineAssistantTurnCount !== void 0) waitArgs.afterAssistantTurnCount = baselineAssistantTurnCount;
10485
+ waitResult = await waitForMessage(env, waitArgs);
10486
+ if (waitResult.data !== void 0) data.wait = waitResult.data;
10487
+ if (!waitResult.ok && waitResult.status !== "partial") {
10488
+ return forwardWorkFailure(waitResult, data);
10489
+ }
10490
+ }
10491
+ if (args.read === true || typeof args.read === "object") {
10492
+ const read = await readLatest(env, typeof args.read === "object" ? args.read : {});
10493
+ if (!read.ok || read.data === void 0) {
10494
+ return forwardWorkFailure(read, data);
10495
+ }
10496
+ data.response = read.data;
10497
+ }
10498
+ if (waitResult !== void 0 && !waitResult.ok) {
10499
+ const partial = {
10500
+ ok: false,
10501
+ status: "partial",
10502
+ data,
10503
+ warnings: [
10504
+ ...waitResult.warnings,
10505
+ "The Work task was submitted exactly once, but completion was not verified."
10506
+ ],
10507
+ context: await workContext(env)
10508
+ };
10509
+ const outputText = data.response?.text ?? waitResult.output_text;
10510
+ if (outputText !== void 0) partial.output_text = outputText;
10511
+ return partial;
10512
+ }
10513
+ return resultOk(
10514
+ data,
10515
+ await workContext(env, surface.data?.selectorProfile),
10516
+ ["Work task submission uses matching-turn recovery and will not blindly resubmit the prompt."]
10517
+ );
10518
+ } catch (error) {
10519
+ return resultError(error instanceof Error ? error : new Error(String(error)), await workContext(env));
10520
+ }
10521
+ }
10522
+ async function workStatus(env, args = {}) {
10523
+ const ready = await requireWork(env);
10524
+ if (!ready.ok) return forwardCommandFailure(ready);
10525
+ const message = await messageStatus(env, args);
10526
+ if (!message.ok || message.data === void 0) {
10527
+ return forwardCommandFailure(message);
10528
+ }
10529
+ const data = {
10530
+ experience: "work",
10531
+ task: await workTaskRef(env, void 0, void 0),
10532
+ message: message.data
10533
+ };
10534
+ const warnings = [...message.warnings];
10535
+ if (args.includeArtifacts === true) {
10536
+ const artifacts = await listLatestArtifacts(env, {});
10537
+ if (artifacts.ok && artifacts.data !== void 0) {
10538
+ data.artifacts = artifacts.data;
10539
+ warnings.push(...artifacts.warnings);
10540
+ } else {
10541
+ warnings.push(`Work artifact status was unavailable: ${artifacts.blocker?.message ?? artifacts.error?.message ?? artifacts.status}`);
10542
+ }
10543
+ }
10544
+ return resultOk(data, {
10545
+ ...message.context,
10546
+ experience: "work",
10547
+ ...ready.data?.selectorProfile === void 0 ? {} : { selectorProfile: ready.data.selectorProfile }
10548
+ }, warnings);
10549
+ }
10550
+ async function waitForWork(env, args = {}) {
10551
+ const ready = await requireWork(env);
10552
+ if (!ready.ok) return forwardCommandFailure(ready);
10553
+ return markWorkResult(await waitForMessage(env, args), ready.data?.selectorProfile);
10554
+ }
10555
+ async function steerWork(env, args) {
10556
+ const ready = await requireWork(env);
10557
+ if (!ready.ok) return forwardCommandFailure(ready);
10558
+ return markWorkResult(await askMessage(env, {
10559
+ text: args.prompt,
10560
+ wait: args.wait ?? false,
10561
+ read: args.read ?? false,
10562
+ ...args.timeoutMs === void 0 ? {} : { timeoutMs: args.timeoutMs }
10563
+ }), ready.data?.selectorProfile);
10564
+ }
10565
+ async function readLatestWork(env, args = {}) {
10566
+ const ready = await requireWork(env);
10567
+ if (!ready.ok) return forwardCommandFailure(ready);
10568
+ return markWorkResult(await readLatest(env, args), ready.data?.selectorProfile);
10569
+ }
10570
+ async function ensureBlankWorkTask(env, timeoutMs) {
10571
+ const page = env.page;
10572
+ const currentTurns = await countPageMessages(page).catch(() => 0);
10573
+ if (currentTurns === 0) {
10574
+ return resultOk({ fresh: true }, await workContext(env));
10575
+ }
10576
+ if (await clickNewWorkControl(page)) {
10577
+ const started = Date.now();
10578
+ const timeout = timeoutMs ?? 3e4;
10579
+ while (Date.now() - started < timeout) {
10580
+ await page.waitForTimeout?.(150);
10581
+ if (await countPageMessages(page).catch(() => currentTurns) === 0) {
10582
+ return resultOk({ fresh: true }, await workContext(env));
10583
+ }
10584
+ }
10585
+ return {
10586
+ ok: false,
10587
+ status: "blocked",
10588
+ warnings: [],
10589
+ blocker: {
10590
+ kind: "selector_drift",
10591
+ code: "work_new_task_unverified",
10592
+ message: "The new Work task control was clicked, but the visible conversation did not reset to a blank task.",
10593
+ resumable: true
10594
+ },
10595
+ context: await workContext(env)
10596
+ };
10597
+ }
10598
+ return {
10599
+ ok: false,
10600
+ status: "blocked",
10601
+ warnings: [],
10602
+ blocker: {
10603
+ kind: "selector_drift",
10604
+ code: "work_new_task_control_not_found",
10605
+ message: "A current Work task is loaded and no unique new-task control was found. Pass newTask: false only when intentionally steering the current task.",
10606
+ candidates: NEW_WORK_LABELS.map((label) => ({ label })),
10607
+ resumable: true
10608
+ },
10609
+ context: await workContext(env)
10610
+ };
10611
+ }
10612
+ async function clickNewWorkControl(page) {
10613
+ for (const label of NEW_WORK_LABELS) {
10614
+ for (const role of ["button", "link"]) {
10615
+ if (await clickIfUnique4(page.getByRole?.(role, { name: label, exact: true }))) {
10616
+ return true;
10617
+ }
10618
+ }
10619
+ }
10620
+ return false;
10621
+ }
10622
+ async function requireWork(env) {
10623
+ const detected = await detectExperience(env);
10624
+ if (detected.ok && detected.data?.experience === "work") {
10625
+ return resultOk({
10626
+ experience: "work",
10627
+ selectorProfile: detected.data.selectorProfile
10628
+ }, detected.context);
10629
+ }
10630
+ return {
10631
+ ok: false,
10632
+ status: "unsupported",
10633
+ warnings: detected.warnings,
10634
+ blocker: {
10635
+ kind: "selector_drift",
10636
+ code: "work_surface_required",
10637
+ fieldPath: "experience",
10638
+ message: `This command requires the visible Work surface; detected ${detected.data?.experience ?? "unknown"}.`,
10639
+ resumable: true
10640
+ },
10641
+ context: detected.context
10642
+ };
10643
+ }
10644
+ async function workTaskRef(env, baselineTurnCount, baselineAssistantTurnCount) {
10645
+ const context = await workContext(env);
10646
+ const task = {};
10647
+ if (context.url !== void 0) task.url = context.url;
10648
+ if (context.conversationId !== void 0) task.conversationId = context.conversationId;
10649
+ if (context.title !== void 0) task.title = context.title;
10650
+ if (baselineTurnCount !== void 0) task.baselineTurnCount = baselineTurnCount;
10651
+ if (baselineAssistantTurnCount !== void 0) task.baselineAssistantTurnCount = baselineAssistantTurnCount;
10652
+ return task;
10653
+ }
10654
+ async function workContext(env, selectorProfile) {
10655
+ return contextFromPage(env.page, {
10656
+ experience: "work",
10657
+ ...selectorProfile === void 0 ? {} : { selectorProfile }
10658
+ });
10659
+ }
10660
+ function markWorkResult(result, selectorProfile) {
10661
+ return {
10662
+ ...result,
10663
+ context: {
10664
+ ...result.context,
10665
+ experience: "work",
10666
+ ...selectorProfile === void 0 ? {} : { selectorProfile }
10667
+ }
10668
+ };
10669
+ }
10670
+ function forwardWorkFailure(result, data) {
10671
+ const forwarded = {
10672
+ ok: false,
10673
+ status: result.status,
10674
+ data,
10675
+ warnings: result.warnings,
10676
+ context: result.context
10677
+ };
10678
+ if (result.output_text !== void 0) forwarded.output_text = result.output_text;
10679
+ if (result.blocker !== void 0) forwarded.blocker = result.blocker;
10680
+ if (result.error !== void 0) forwarded.error = result.error;
10681
+ return forwarded;
10682
+ }
10683
+ function forwardCommandFailure(result) {
10684
+ const forwarded = {
10685
+ ok: false,
10686
+ status: result.status,
10687
+ warnings: result.warnings,
10688
+ context: result.context
10689
+ };
10690
+ if (result.output_text !== void 0) forwarded.output_text = result.output_text;
10691
+ if (result.reportPath !== void 0) forwarded.reportPath = result.reportPath;
10692
+ if (result.blocker !== void 0) forwarded.blocker = result.blocker;
10693
+ if (result.error !== void 0) forwarded.error = result.error;
10694
+ if (result.steps !== void 0) forwarded.steps = result.steps;
10695
+ return forwarded;
10696
+ }
10697
+ async function clickIfUnique4(locator) {
10698
+ if (locator?.count === void 0 || locator.click === void 0) return false;
10699
+ if (await locator.count().catch(() => 0) !== 1) return false;
10700
+ await locator.click();
10701
+ return true;
10702
+ }
10703
+
9108
10704
  // src/commands/sequence.ts
9109
10705
  var defaultSequencePolicy = {
9110
10706
  stopOnError: true,
@@ -9142,6 +10738,24 @@ async function executeStep(step, env, previousResults) {
9142
10738
  switch (step.command) {
9143
10739
  case "session.bootstrap":
9144
10740
  return bootstrap(env, step.args);
10741
+ case "experience.detect":
10742
+ return detectExperience(env, step.args);
10743
+ case "experience.open":
10744
+ return openExperience(env, step.args);
10745
+ case "configuration.inspect":
10746
+ return inspectConfiguration(env, step.args);
10747
+ case "configuration.apply":
10748
+ return applyConfiguration(env, step.args);
10749
+ case "work.start":
10750
+ return startWork(env, step.args);
10751
+ case "work.status":
10752
+ return workStatus(env, step.args);
10753
+ case "work.wait":
10754
+ return waitForWork(env, step.args);
10755
+ case "work.steer":
10756
+ return steerWork(env, step.args);
10757
+ case "work.readLatest":
10758
+ return readLatestWork(env, step.args);
9145
10759
  case "threads.search":
9146
10760
  return searchThreads(env, step.args);
9147
10761
  case "threads.open":
@@ -9158,6 +10772,8 @@ async function executeStep(step, env, previousResults) {
9158
10772
  return waitForMessage(env, step.args);
9159
10773
  case "messages.readLatest":
9160
10774
  return readLatest(env, step.args);
10775
+ case "messages.status":
10776
+ return messageStatus(env, step.args);
9161
10777
  case "messages.waitAndRead":
9162
10778
  return waitAndRead(env, step.args);
9163
10779
  case "artifacts.listLatest":
@@ -9438,6 +11054,12 @@ function toRunResult(agent, result) {
9438
11054
  const output = runItemsFromResult(result, outputText);
9439
11055
  const state = runStateFromResult(result, interruptions);
9440
11056
  const data = { outputText };
11057
+ const submissionState = readSubmissionState(result.data);
11058
+ const completionState = readCompletionState(result.data);
11059
+ const generationActive = readGenerationActive(result.data);
11060
+ if (submissionState !== void 0) data.submissionState = submissionState;
11061
+ if (completionState !== void 0) data.completionState = completionState;
11062
+ if (generationActive !== void 0) data.generationActive = generationActive;
9441
11063
  if (outputText.length > 0) {
9442
11064
  const envelopeArgs = {
9443
11065
  outputText,
@@ -9491,15 +11113,52 @@ function parseFinalOutput(agent, outputText) {
9491
11113
  return outputText;
9492
11114
  }
9493
11115
  function runItemsFromResult(result, outputText) {
9494
- const items = messageItemsFromData(result.data);
9495
- if (!items.some((item) => item.type === "message.completed") && outputText.length > 0) {
9496
- items.push({ type: "message.completed", role: "assistant", output_text: outputText, format: "markdown" });
11116
+ const items = lifecycleItemsFromSteps(result.steps);
11117
+ items.push(...messageItemsFromData(result.data));
11118
+ if (!items.some((item) => item.type === "message.completed" || item.type === "message.in_progress") && outputText.length > 0) {
11119
+ if (result.status === "partial" && readCompletionState(result.data) !== "complete") {
11120
+ items.push(inProgressItem(outputText, readCompletionState(result.data), readGenerationActive(result.data)));
11121
+ } else {
11122
+ items.push({ type: "message.completed", role: "assistant", output_text: outputText, format: "markdown" });
11123
+ }
9497
11124
  }
9498
11125
  if (result.blocker !== void 0) {
9499
11126
  items.push({ type: "run.blocked", blocker: augmentCommandBlocker(result.blocker) });
9500
11127
  }
9501
11128
  return items;
9502
11129
  }
11130
+ function lifecycleItemsFromSteps(steps) {
11131
+ if (steps === void 0) return [];
11132
+ const items = [];
11133
+ for (const step of steps) {
11134
+ if (!step.ok || !isRecord4(step.dataPreview)) continue;
11135
+ if (step.command === "experience.open") {
11136
+ const experience = step.dataPreview.experience;
11137
+ if (experience === "chat" || experience === "work") {
11138
+ const item = {
11139
+ type: "experience.opened",
11140
+ experience
11141
+ };
11142
+ if (typeof step.dataPreview.changed === "boolean") item.changed = step.dataPreview.changed;
11143
+ items.push(item);
11144
+ }
11145
+ continue;
11146
+ }
11147
+ if (step.command === "configuration.apply") {
11148
+ const item = {
11149
+ type: "configuration.applied"
11150
+ };
11151
+ if (isRecord4(step.dataPreview.requested)) {
11152
+ item.requested = step.dataPreview.requested;
11153
+ }
11154
+ if (typeof step.dataPreview.verified === "boolean") {
11155
+ item.verified = step.dataPreview.verified;
11156
+ }
11157
+ items.push(item);
11158
+ }
11159
+ }
11160
+ return items;
11161
+ }
9503
11162
  function messageItemsFromData(data) {
9504
11163
  if (!isRecord4(data)) return [];
9505
11164
  const items = [];
@@ -9512,7 +11171,11 @@ function messageItemsFromData(data) {
9512
11171
  });
9513
11172
  }
9514
11173
  if (typeof data.responseText === "string" && data.responseText.length > 0) {
9515
- items.push({ type: "message.completed", role: "assistant", output_text: data.responseText, format: "markdown" });
11174
+ if (readCompletionState(data) === "complete" || data.complete === true) {
11175
+ items.push({ type: "message.completed", role: "assistant", output_text: data.responseText, format: "markdown" });
11176
+ } else {
11177
+ items.push(inProgressItem(data.responseText, readCompletionState(data), readGenerationActive(data)));
11178
+ }
9516
11179
  }
9517
11180
  if (items.length > 0) return items;
9518
11181
  for (const value of Object.values(data)) {
@@ -9530,8 +11193,67 @@ function runStateFromResult(result, interruptions) {
9530
11193
  };
9531
11194
  const thread = threadRefFromContext(result.context);
9532
11195
  if (thread !== void 0) state.thread = thread;
11196
+ const submissionState = readSubmissionState(result.data);
11197
+ const completionState = readCompletionState(result.data);
11198
+ if (submissionState !== void 0) state.submissionState = submissionState;
11199
+ if (completionState !== void 0) state.completionState = completionState;
9533
11200
  return state;
9534
11201
  }
11202
+ function inProgressItem(outputText, completionState, generationActive) {
11203
+ const item = {
11204
+ type: "message.in_progress",
11205
+ role: "assistant",
11206
+ output_text: outputText,
11207
+ preview: outputText.length > 160 ? `${outputText.slice(0, 159)}...` : outputText,
11208
+ format: "markdown",
11209
+ textLength: outputText.length,
11210
+ textHash: hashText(outputText)
11211
+ };
11212
+ if (completionState !== void 0) item.completionState = completionState;
11213
+ if (generationActive !== void 0) item.generationActive = generationActive;
11214
+ return item;
11215
+ }
11216
+ function readCompletionState(data) {
11217
+ if (!isRecord4(data)) return void 0;
11218
+ const value = data.completionState;
11219
+ if (value === "complete" || value === "generating" || value === "stopped" || value === "partial" || value === "unknown") {
11220
+ return value;
11221
+ }
11222
+ for (const nested of Object.values(data)) {
11223
+ const nestedState = readCompletionState(nested);
11224
+ if (nestedState !== void 0) return nestedState;
11225
+ }
11226
+ return void 0;
11227
+ }
11228
+ function readSubmissionState(data) {
11229
+ if (!isRecord4(data)) return void 0;
11230
+ const value = data.submissionState;
11231
+ if (value === "not_submitted" || value === "submitted" || value === "submitted_unconfirmed" || value === "submitted_generating") {
11232
+ return value;
11233
+ }
11234
+ for (const nested of Object.values(data)) {
11235
+ const nestedState = readSubmissionState(nested);
11236
+ if (nestedState !== void 0) return nestedState;
11237
+ }
11238
+ return void 0;
11239
+ }
11240
+ function readGenerationActive(data) {
11241
+ if (!isRecord4(data)) return void 0;
11242
+ if (typeof data.generationActive === "boolean") return data.generationActive;
11243
+ for (const nested of Object.values(data)) {
11244
+ const value = readGenerationActive(nested);
11245
+ if (value !== void 0) return value;
11246
+ }
11247
+ return void 0;
11248
+ }
11249
+ function hashText(value) {
11250
+ let hash = 2166136261;
11251
+ for (let index = 0; index < value.length; index += 1) {
11252
+ hash ^= value.charCodeAt(index);
11253
+ hash = Math.imul(hash, 16777619);
11254
+ }
11255
+ return (hash >>> 0).toString(16).padStart(8, "0");
11256
+ }
9535
11257
  function threadRefFromContext(context) {
9536
11258
  const thread = {};
9537
11259
  if (context.url !== void 0) thread.url = context.url;
@@ -9557,6 +11279,8 @@ var acceptedTopLevelFields = /* @__PURE__ */ new Set([
9557
11279
  "thread",
9558
11280
  "existingTab",
9559
11281
  "preferExistingTab",
11282
+ "experience",
11283
+ "configuration",
9560
11284
  "attachments",
9561
11285
  "mode",
9562
11286
  "tools",
@@ -9567,7 +11291,7 @@ var acceptedTopLevelFields = /* @__PURE__ */ new Set([
9567
11291
  "instructionsMode"
9568
11292
  ]);
9569
11293
  var unsupportedAlternatives = {
9570
- model: "Use mode for visible ChatGPT UI mode preference. This does not select an API model.",
11294
+ model: "Use experience plus configuration for visible ChatGPT UI preferences. Legacy mode remains supported. These do not select an API model.",
9571
11295
  temperature: "No browser-control equivalent. ChatGPT web does not expose API temperature.",
9572
11296
  top_p: "No browser-control equivalent. ChatGPT web does not expose API nucleus sampling.",
9573
11297
  seed: "No browser-control equivalent. Visible ChatGPT web does not expose deterministic API seeds.",
@@ -9662,6 +11386,8 @@ function responsesCreateArgsToRunInput(args) {
9662
11386
  if (args.thread !== void 0) runInput2.thread = args.thread;
9663
11387
  if (args.existingTab !== void 0) runInput2.existingTab = args.existingTab;
9664
11388
  if (args.preferExistingTab !== void 0) runInput2.preferExistingTab = args.preferExistingTab;
11389
+ if (args.experience !== void 0) runInput2.experience = args.experience;
11390
+ if (args.configuration !== void 0) runInput2.configuration = args.configuration;
9665
11391
  if (args.attachments !== void 0) runInput2.attachments = args.attachments;
9666
11392
  if (args.mode !== void 0) runInput2.mode = args.mode;
9667
11393
  if (args.tools !== void 0) runInput2.tools = args.tools;
@@ -9677,6 +11403,12 @@ function responseFromRunResult(result, now = /* @__PURE__ */ new Date()) {
9677
11403
  if (result.data?.thread !== void 0) browserControl.thread = result.data.thread;
9678
11404
  const reportPath = result.data?.reportPath ?? result.reportPath;
9679
11405
  if (reportPath !== void 0) browserControl.reportPath = reportPath;
11406
+ const submissionState = result.state.submissionState ?? result.data?.submissionState;
11407
+ const completionState = result.state.completionState ?? result.data?.completionState;
11408
+ const generationActive = result.data?.generationActive;
11409
+ if (submissionState !== void 0) browserControl.submissionState = submissionState;
11410
+ if (completionState !== void 0) browserControl.completionState = completionState;
11411
+ if (generationActive !== void 0) browserControl.generationActive = generationActive;
9680
11412
  if (result.output_text.length > 0) {
9681
11413
  const envelopeArgs = {
9682
11414
  outputText: result.output_text,
@@ -9780,6 +11512,10 @@ function runItemEventName(item) {
9780
11512
  switch (item.type) {
9781
11513
  case "thread.opened":
9782
11514
  return "thread_opened";
11515
+ case "experience.opened":
11516
+ return "experience_opened";
11517
+ case "configuration.applied":
11518
+ return "configuration_applied";
9783
11519
  case "mode.selected":
9784
11520
  return "mode_selected";
9785
11521
  case "tool.selected":
@@ -9788,6 +11524,8 @@ function runItemEventName(item) {
9788
11524
  return "file_attached";
9789
11525
  case "message.submitted":
9790
11526
  return "message_submitted";
11527
+ case "message.in_progress":
11528
+ return "message_in_progress";
9791
11529
  case "message.completed":
9792
11530
  return "message_completed";
9793
11531
  case "file.downloaded":
@@ -9842,6 +11580,26 @@ function createChatGPT(options = {}) {
9842
11580
  session: {
9843
11581
  bootstrap: (args) => bootstrap(env, args)
9844
11582
  },
11583
+ experience: {
11584
+ detect: (args) => detectExperience(env, args),
11585
+ open: (args) => openExperience(env, args)
11586
+ },
11587
+ configuration: {
11588
+ inspect: (args) => inspectConfiguration(env, args),
11589
+ apply: (args) => applyConfiguration(env, args)
11590
+ },
11591
+ work: {
11592
+ start: (args) => startWork(env, args),
11593
+ status: (args) => workStatus(env, args),
11594
+ wait: (args) => waitForWork(env, args),
11595
+ steer: (args) => steerWork(env, args),
11596
+ readLatest: (args) => readLatestWork(env, args),
11597
+ artifacts: {
11598
+ listLatest: (args) => listLatestArtifacts(env, args),
11599
+ wait: (args) => waitForArtifact(env, args),
11600
+ downloadLatest: (args) => downloadLatestArtifact(env, args)
11601
+ }
11602
+ },
9845
11603
  threads: {
9846
11604
  new: (args) => newThread(env, args),
9847
11605
  search: (args) => searchThreads(env, args),
@@ -9853,6 +11611,7 @@ function createChatGPT(options = {}) {
9853
11611
  ask: (args) => askMessage(env, args),
9854
11612
  wait: (args) => waitForMessage(env, args),
9855
11613
  readLatest: (args) => readLatest(env, args),
11614
+ status: (args) => messageStatus(env, args),
9856
11615
  waitAndRead: (args) => waitAndRead(env, args)
9857
11616
  },
9858
11617
  files: {
@@ -9942,6 +11701,30 @@ function pathsFromAttachStep(step) {
9942
11701
  const paths = step.args.paths;
9943
11702
  return paths.every((item) => typeof item === "string") ? paths : [];
9944
11703
  }
11704
+ function appendSurfaceConfigurationSteps(steps, preferences) {
11705
+ if (preferences.experience !== void 0) {
11706
+ steps.push({
11707
+ id: "experience",
11708
+ command: "experience.open",
11709
+ args: { experience: preferences.experience }
11710
+ });
11711
+ }
11712
+ if (preferences.configuration !== void 0) {
11713
+ steps.push({
11714
+ id: "configuration",
11715
+ command: "configuration.apply",
11716
+ args: {
11717
+ ...preferences.experience === void 0 ? {} : { experience: preferences.experience },
11718
+ desired: preferences.configuration,
11719
+ strict: true
11720
+ }
11721
+ });
11722
+ return;
11723
+ }
11724
+ if (preferences.mode !== void 0) {
11725
+ steps.push({ id: "mode", command: "modes.set", args: preferences.mode });
11726
+ }
11727
+ }
9945
11728
  function normalizeLimits(limits) {
9946
11729
  return {
9947
11730
  maxPromptsPerRun: limits?.maxPromptsPerRun ?? 5,
@@ -9954,7 +11737,7 @@ function normalizeLimits(limits) {
9954
11737
  function checkRunBudget(plan, limits) {
9955
11738
  const prompts = plan.steps.filter((step) => step.command === "messages.ask" || step.command === "messages.submit").length;
9956
11739
  const threads = plan.steps.filter((step) => step.command === "threads.new" || step.command === "threads.open").length;
9957
- const reads = plan.steps.filter((step) => step.command === "messages.readLatest" || step.command === "messages.waitAndRead" || step.command === "response.copy").length + plan.steps.filter((step) => step.command === "messages.ask" && askStepReads(step.args)).length;
11740
+ const reads = plan.steps.filter((step) => step.command === "messages.readLatest" || step.command === "messages.status" || step.command === "messages.waitAndRead" || step.command === "response.copy").length + plan.steps.filter((step) => step.command === "messages.ask" && askStepReads(step.args)).length;
9958
11741
  const violations = [];
9959
11742
  if (prompts > limits.maxPromptsPerRun) violations.push(`prompts ${prompts}/${limits.maxPromptsPerRun}`);
9960
11743
  if (threads > limits.maxThreadsOpenedPerRun) violations.push(`threads ${threads}/${limits.maxThreadsOpenedPerRun}`);
@@ -10041,10 +11824,11 @@ function planAgentWorkflowFromNormalized(agent, input, defaults = {}) {
10041
11824
  ),
10042
11825
  ...threadSteps(thread)
10043
11826
  ];
10044
- const mode = input.mode ?? agent.defaults.mode ?? defaults.mode;
10045
- if (mode !== void 0) {
10046
- steps.push({ id: "mode", command: "modes.set", args: mode });
10047
- }
11827
+ appendSurfaceConfigurationSteps(steps, {
11828
+ experience: input.experience ?? agent.defaults.experience ?? defaults.experience,
11829
+ configuration: input.configuration ?? agent.defaults.configuration ?? defaults.configuration,
11830
+ mode: input.mode ?? agent.defaults.mode ?? defaults.mode
11831
+ });
10048
11832
  for (const [index, tool] of input.tools.entries()) {
10049
11833
  steps.push({ id: `tool${index + 1}`, command: "tools.select", args: tool });
10050
11834
  }
@@ -10106,6 +11890,8 @@ function normalizeRunnerInput(agent, input) {
10106
11890
  if (args.thread !== void 0) normalized.thread = args.thread;
10107
11891
  if (args.existingTab !== void 0) normalized.existingTab = args.existingTab;
10108
11892
  if (args.preferExistingTab !== void 0) normalized.preferExistingTab = args.preferExistingTab;
11893
+ if (args.experience !== void 0) normalized.experience = args.experience;
11894
+ if (args.configuration !== void 0) normalized.configuration = args.configuration;
10109
11895
  if (mode !== void 0) normalized.mode = mode;
10110
11896
  if (args.response !== void 0) normalized.read = args.response;
10111
11897
  if (args.download !== void 0) normalized.download = args.download;
@@ -10225,10 +12011,11 @@ function planAskWorkflow(args, defaults = {}) {
10225
12011
  ),
10226
12012
  ...threadSteps(thread)
10227
12013
  ];
10228
- const mode = args.mode ?? defaults.mode;
10229
- if (mode !== void 0) {
10230
- steps.push({ id: "mode", command: "modes.set", args: mode });
10231
- }
12014
+ appendSurfaceConfigurationSteps(steps, {
12015
+ experience: args.experience ?? defaults.experience,
12016
+ configuration: args.configuration ?? defaults.configuration,
12017
+ mode: args.mode ?? defaults.mode
12018
+ });
10232
12019
  for (const [index, tool] of (args.tools ?? []).entries()) {
10233
12020
  steps.push({ id: `tool${index + 1}`, command: "tools.select", args: tool });
10234
12021
  }
@@ -10297,10 +12084,11 @@ function planRunMessages(args, defaults = {}) {
10297
12084
  ),
10298
12085
  ...threadSteps(thread)
10299
12086
  ];
10300
- const mode = args.mode ?? defaults.mode;
10301
- if (mode !== void 0) {
10302
- steps.push({ id: "mode", command: "modes.set", args: mode });
10303
- }
12087
+ appendSurfaceConfigurationSteps(steps, {
12088
+ experience: args.experience ?? defaults.experience,
12089
+ configuration: args.configuration ?? defaults.configuration,
12090
+ mode: args.mode ?? defaults.mode
12091
+ });
10304
12092
  args.messages.forEach((message, index) => {
10305
12093
  steps.push({
10306
12094
  id: message.id ?? `message${index + 1}`,
@@ -10532,6 +12320,15 @@ var backendCommands = [
10532
12320
  "describe",
10533
12321
  "help",
10534
12322
  "session.bootstrap",
12323
+ "experience.detect",
12324
+ "experience.open",
12325
+ "configuration.inspect",
12326
+ "configuration.apply",
12327
+ "work.start",
12328
+ "work.status",
12329
+ "work.wait",
12330
+ "work.steer",
12331
+ "work.readLatest",
10535
12332
  "threads.new",
10536
12333
  "threads.search",
10537
12334
  "threads.open",
@@ -10540,6 +12337,7 @@ var backendCommands = [
10540
12337
  "messages.ask",
10541
12338
  "messages.wait",
10542
12339
  "messages.readLatest",
12340
+ "messages.status",
10543
12341
  "messages.waitAndRead",
10544
12342
  "artifacts.listLatest",
10545
12343
  "artifacts.wait",
@@ -10770,6 +12568,24 @@ async function dispatchBackendCommand(client, request) {
10770
12568
  );
10771
12569
  case "session.bootstrap":
10772
12570
  return client.session.bootstrap(emptyToUndefined(payload));
12571
+ case "experience.detect":
12572
+ return client.experience.detect(emptyToUndefined(payload));
12573
+ case "experience.open":
12574
+ return client.experience.open(payload);
12575
+ case "configuration.inspect":
12576
+ return client.configuration.inspect(emptyToUndefined(payload));
12577
+ case "configuration.apply":
12578
+ return client.configuration.apply(payload);
12579
+ case "work.start":
12580
+ return client.work.start(payload);
12581
+ case "work.status":
12582
+ return client.work.status(emptyToUndefined(payload));
12583
+ case "work.wait":
12584
+ return client.work.wait(emptyToUndefined(payload));
12585
+ case "work.steer":
12586
+ return client.work.steer(payload);
12587
+ case "work.readLatest":
12588
+ return client.work.readLatest(emptyToUndefined(payload));
10773
12589
  case "threads.new":
10774
12590
  return client.threads.new(emptyToUndefined(payload));
10775
12591
  case "threads.search":
@@ -10786,6 +12602,8 @@ async function dispatchBackendCommand(client, request) {
10786
12602
  return client.messages.wait(emptyToUndefined(payload));
10787
12603
  case "messages.readLatest":
10788
12604
  return client.messages.readLatest(emptyToUndefined(payload));
12605
+ case "messages.status":
12606
+ return client.messages.status(emptyToUndefined(payload));
10789
12607
  case "messages.waitAndRead":
10790
12608
  return client.messages.waitAndRead(payload);
10791
12609
  case "artifacts.listLatest":