openmausbot 0.1.97 → 0.1.99

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 (434) hide show
  1. package/dist/assets/ActivityPanel-CgUgtumZ.js +1 -0
  2. package/dist/assets/BotSettingsDialog-lJj6oiir.js +7 -0
  3. package/dist/assets/CloudBackendPicker-C5-_arUz.js +1 -0
  4. package/dist/assets/ComputerPanel-euJ2CSlH.js +1 -0
  5. package/dist/assets/DesktopViewer-XCln1Pn_.js +5 -0
  6. package/dist/assets/InspectorPanel-DKYyQZlo.js +5 -0
  7. package/dist/assets/KeyboardShortcutsModal-DkkZWZRI.js +1 -0
  8. package/dist/assets/LocalVmWorkspace-Cwt3_XSx.js +1 -0
  9. package/dist/assets/MacLocalControl-B28RbdCS.js +1 -0
  10. package/dist/assets/NewBotDialog-dMWDs5xm.js +2 -0
  11. package/dist/assets/RemoteAgentSettingsPanel-B5KWXnqH.js +1 -0
  12. package/dist/assets/RoutinesPage-DOosRYDK.js +1 -0
  13. package/dist/assets/RoutinesSection-uOfOTfkB.js +1 -0
  14. package/dist/assets/SettingsModal-BTGkFbj1.js +11 -0
  15. package/dist/assets/TeamMapPage-DqNdJn96.js +8 -0
  16. package/dist/assets/TriggersPanel-c6xkG9mi.js +1 -0
  17. package/dist/assets/VisibilitySection-DD4ffIR5.js +12 -0
  18. package/dist/assets/WebhooksPanel-Cz17K-_O.js +3 -0
  19. package/dist/assets/{abnfDiagram-O67JEVCF-k1UCNXb7.js → abnfDiagram-O67JEVCF-CX6tDpkg.js} +1 -1
  20. package/dist/assets/activity-BAVWO0Zj.js +1 -0
  21. package/dist/assets/{arc-BUWGa9UU.js → arc-h45-9NFk.js} +1 -1
  22. package/dist/assets/architectureDiagram-NJMV4G6O-CgLFXbg6.js +36 -0
  23. package/dist/assets/{blockDiagram-BEXU5L5S-Ag9nLW4H.js → blockDiagram-BEXU5L5S-DGDFFc9M.js} +1 -1
  24. package/dist/assets/brain-CeCdoTb2.js +1 -0
  25. package/dist/assets/{c4Diagram-YGBWAQC7-Bh0sjgUa.js → c4Diagram-YGBWAQC7-B9aklAUj.js} +1 -1
  26. package/dist/assets/channel-TsOXCiPg.js +1 -0
  27. package/dist/assets/{chunk-2Q5K7J3B-BFBcIIqu.js → chunk-2Q5K7J3B-BC0KmWsM.js} +1 -1
  28. package/dist/assets/{chunk-3FUC2YCW-Dvfpex-f.js → chunk-3FUC2YCW-BbDFHsJ1.js} +2 -2
  29. package/dist/assets/{chunk-5VM5RSS4-CMjP2YZW.js → chunk-5VM5RSS4-DtGbsjOM.js} +1 -1
  30. package/dist/assets/{chunk-GTNCS2PH-BryoeTc7.js → chunk-GTNCS2PH-VMghMcEl.js} +1 -1
  31. package/dist/assets/{chunk-GWA4HPMP-BhfvcchO.js → chunk-GWA4HPMP-BP_JyGWQ.js} +1 -1
  32. package/dist/assets/{chunk-JWPE2WC7-bcCVp8rp.js → chunk-JWPE2WC7-CYFyzgAU.js} +1 -1
  33. package/dist/assets/{chunk-NETBCI7D-yKIjIlkQ.js → chunk-NETBCI7D-DBNa_kqm.js} +1 -1
  34. package/dist/assets/{chunk-WEXAMYUT-D3Zqbmup.js → chunk-WEXAMYUT-BKEeM7CJ.js} +1 -1
  35. package/dist/assets/{chunk-XXDRQBXY-CjVoIMG6.js → chunk-XXDRQBXY-C__m3ZXl.js} +1 -1
  36. package/dist/assets/{classDiagram-v2-NBCMYWYE-mUCWdVyH.js → classDiagram-v2-NBCMYWYE-CBUrTSAX.js} +1 -1
  37. package/dist/assets/computer-control-NLov352p.js +1 -0
  38. package/dist/assets/core-6lvx-ypA.js +12 -0
  39. package/dist/assets/cose-bilkent-JH36ORCC-GRfL-1Vb.js +1 -0
  40. package/dist/assets/cpp-DddhVWhK.js +1 -0
  41. package/dist/assets/{cynefin-OW5HDTMX-BpRrxoO4.js → cynefin-OW5HDTMX-LopwGUjm.js} +1 -1
  42. package/dist/assets/{cynefinDiagram-VND7K2PF-D3VBWCPK.js → cynefinDiagram-VND7K2PF-DSB8ZRNS.js} +1 -1
  43. package/dist/assets/{dagre-6A5THRUB-DxEIACOO.js → dagre-6A5THRUB-DL3Kgdfk.js} +1 -1
  44. package/dist/assets/{diagram-22UHCM2B-BANgZEOS.js → diagram-22UHCM2B-DIxN34BM.js} +1 -1
  45. package/dist/assets/{diagram-3UASUU5V-Cnq7nJir.js → diagram-3UASUU5V-CJnSvXaI.js} +1 -1
  46. package/dist/assets/{diagram-ATOU4E4O-4TBDIWnz.js → diagram-ATOU4E4O-C-XF-lO8.js} +1 -1
  47. package/dist/assets/{diagram-CDSNMT55-CD_B39D4.js → diagram-CDSNMT55-Df2yZPi_.js} +1 -1
  48. package/dist/assets/{diagram-MLGK6HIB-CzvnFhEC.js → diagram-MLGK6HIB-BBs9oZFs.js} +1 -1
  49. package/dist/assets/{diagram-MPIPVDR6-C4w2SNml.js → diagram-MPIPVDR6-CEbK11mM.js} +1 -1
  50. package/dist/assets/{ebnfDiagram-ZINNZB2B-gkUEBm2s.js → ebnfDiagram-ZINNZB2B-BNq6Yv3C.js} +1 -1
  51. package/dist/assets/{elk-276RUBZZ-B_56X6mw.js → elk-276RUBZZ-CFbQ2bGm.js} +1 -1
  52. package/dist/assets/engine-javascript-D5Xfc425.js +141 -0
  53. package/dist/assets/{erDiagram-OPXOYQCR-C_oByoDS.js → erDiagram-OPXOYQCR-Bz8vmjN4.js} +1 -1
  54. package/dist/assets/{flowDiagram-KWPJA3E3-CR9xXJkC.js → flowDiagram-KWPJA3E3-cQUfEYrx.js} +1 -1
  55. package/dist/assets/ganttDiagram-FUAMR5RP-BY8n9tbI.js +292 -0
  56. package/dist/assets/{gitGraphDiagram-X574FWY7-VJ6-Tp_p.js → gitGraphDiagram-X574FWY7-KduSOMDN.js} +1 -1
  57. package/dist/assets/image-plus-DNIWU160.js +1 -0
  58. package/dist/assets/index-C8xb62XS.js +585 -0
  59. package/dist/assets/index-DbN_Hfjs.css +1 -0
  60. package/dist/assets/{infoDiagram-VRGFBTTK-2Lu9te4D.js → infoDiagram-VRGFBTTK-xBKgUkpL.js} +1 -1
  61. package/dist/assets/{ishikawaDiagram-OU5B5YK6-DR49XY-e.js → ishikawaDiagram-OU5B5YK6-_ei09tAJ.js} +1 -1
  62. package/dist/assets/{journeyDiagram-ZHPQQLJL-ZoR0M305.js → journeyDiagram-ZHPQQLJL-Fp49MkSp.js} +1 -1
  63. package/dist/assets/{kanban-definition-PNTS6WVX-DLKHxrO-.js → kanban-definition-PNTS6WVX-CY9lLm7V.js} +1 -1
  64. package/dist/assets/{linear-BASsfWly.js → linear-D2ai4eM2.js} +1 -1
  65. package/dist/assets/{mermaid.core-BVidiPkk.js → mermaid.core-DP6qPqu1.js} +5 -5
  66. package/dist/assets/{mindmap-definition-NLK3R4M7-g_Qx0U5C.js → mindmap-definition-NLK3R4M7-g1ynEw_d.js} +1 -1
  67. package/dist/assets/module-DCUsy2BQ.js +3 -0
  68. package/dist/assets/page-visible-BZn8304W.js +1 -0
  69. package/dist/assets/{pegDiagram-GJSIUBJH-DI9Cjs8w.js → pegDiagram-GJSIUBJH-Bt4ObsZj.js} +1 -1
  70. package/dist/assets/{pieDiagram-5QR66LMP-sRI0Uhr5.js → pieDiagram-5QR66LMP-CeLld8bY.js} +1 -1
  71. package/dist/assets/{quadrantDiagram-O4NWA36T-CamKTby3.js → quadrantDiagram-O4NWA36T-D4WWZw3x.js} +1 -1
  72. package/dist/assets/{railroadDiagram-XR7U4H2S-DOLlkbf3.js → railroadDiagram-XR7U4H2S-D95P5NqU.js} +1 -1
  73. package/dist/assets/remote-desktop-panel-DOIMmT4T.js +1 -0
  74. package/dist/assets/{requirementDiagram-PLB6GJNP-DrRQ5r97.js → requirementDiagram-PLB6GJNP-D12p3RhR.js} +1 -1
  75. package/dist/assets/ruby-Ct1eTYOr.js +1 -0
  76. package/dist/assets/{sankeyDiagram-IPEJSGJF-DGS_lXcX.js → sankeyDiagram-IPEJSGJF-Co26Dwcs.js} +1 -1
  77. package/dist/assets/{sequenceDiagram-PO4LG4MO-CkjWqwtf.js → sequenceDiagram-PO4LG4MO-y5YxaDKt.js} +1 -1
  78. package/dist/assets/{sizeCapture-INFHLROL-CepRgful.js → sizeCapture-INFHLROL-D49hZ8U5.js} +1 -1
  79. package/dist/assets/{stateDiagram-v2-GCMORJYK-hykr-9RS.js → stateDiagram-v2-GCMORJYK-C0sylr-r.js} +1 -1
  80. package/dist/assets/{swimlanes-2SLR337P-CKOHEZbI.js → swimlanes-2SLR337P-DmRWsDIs.js} +1 -1
  81. package/dist/assets/swimlanesDiagram-TC7HE7FX-DzhbBHtd.js +8 -0
  82. package/dist/assets/table-file.worker-KkMx-SNx.js +10 -0
  83. package/dist/assets/{timeline-definition-EJHVYXUP-CB8pJ6AC.js → timeline-definition-EJHVYXUP-DVmHYs3w.js} +1 -1
  84. package/dist/assets/{usecaseDiagram-POWQR4AR-DrclJHdl.js → usecaseDiagram-POWQR4AR-BQ1q0VV6.js} +1 -1
  85. package/dist/assets/user-B9lohN4n.js +1 -0
  86. package/dist/assets/{vennDiagram-UO4OBE2U-zS23qjv8.js → vennDiagram-UO4OBE2U-C_cnfST0.js} +1 -1
  87. package/dist/assets/{wardleyDiagram-VNRHLVJA-52jgeKxz.js → wardleyDiagram-VNRHLVJA-Bb3BSu12.js} +1 -1
  88. package/dist/assets/{xychartDiagram-PMCCYNJV-DSdl9rQ8.js → xychartDiagram-PMCCYNJV-CcwEuuEi.js} +1 -1
  89. package/dist/index.html +2 -2
  90. package/dist-server/cloud-home-start.js +19 -8
  91. package/dist-server/container-mcp.js +8 -0
  92. package/dist-server/desktop-entry.mjs +54 -0
  93. package/dist-server/drivers/agents-proxy.js +30 -12
  94. package/dist-server/index.js +2745 -1487
  95. package/dist-server/openmausbot.js +1004 -642
  96. package/dist-server/pair-cli.js +1004 -642
  97. package/dist-server/permission-proxy.js +2 -0
  98. package/dist-server/server/activity.js +2 -0
  99. package/dist-server/server/atomic.js +70 -2
  100. package/dist-server/server/checkpoints.js +55 -39
  101. package/dist-server/server/cloud-home-start.js +3 -3
  102. package/dist-server/server/config.js +22 -1
  103. package/dist-server/server/connector-card-text.js +15 -0
  104. package/dist-server/server/default-model-selection.js +7 -4
  105. package/dist-server/server/direct-apply.js +20 -0
  106. package/dist-server/server/drivers/acp/core.js +10 -0
  107. package/dist-server/server/drivers/acp/grok.js +47 -5
  108. package/dist-server/server/drivers/agents-call.js +1 -1
  109. package/dist-server/server/drivers/agents-catalog.js +34 -11
  110. package/dist-server/server/drivers/agents-proxy.js +1 -0
  111. package/dist-server/server/drivers/chat-mcp-tools.js +5 -3
  112. package/dist-server/server/drivers/claude-login-auth.js +1 -1
  113. package/dist-server/server/drivers/claude.js +35 -11
  114. package/dist-server/server/drivers/codex-device-auth.js +27 -319
  115. package/dist-server/server/drivers/codex.js +147 -24
  116. package/dist-server/server/drivers/device-auth.js +343 -0
  117. package/dist-server/server/drivers/openai-chat.js +17 -8
  118. package/dist-server/server/fleet-agent.js +18 -5
  119. package/dist-server/server/harness/http.js +5 -2
  120. package/dist-server/server/harness/registry.js +82 -45
  121. package/dist-server/server/harness-capabilities.js +7 -4
  122. package/dist-server/server/hosted-models.js +3 -1
  123. package/dist-server/server/index.js +471 -77
  124. package/dist-server/server/key-rejections.js +57 -0
  125. package/dist-server/server/mcp-oauth.js +125 -47
  126. package/dist-server/server/message-file.js +102 -7
  127. package/dist-server/server/model-requests.js +55 -4
  128. package/dist-server/server/permission-proxy.js +4 -0
  129. package/dist-server/server/profile-requests.js +80 -4
  130. package/dist-server/server/provider-key-check.js +5 -1
  131. package/dist-server/server/request-auth.js +2 -1
  132. package/dist-server/server/room-turn-timeout.js +28 -0
  133. package/dist-server/server/routes/thread-models.js +36 -0
  134. package/dist-server/server/routes/undo.js +17 -0
  135. package/dist-server/server/routine-requests.js +210 -6
  136. package/dist-server/server/routines.js +2 -2
  137. package/dist-server/server/setup-mode.js +1 -1
  138. package/dist-server/server/skill-learn.js +2 -2
  139. package/dist-server/server/skills.js +33 -2
  140. package/dist-server/server/store.js +148 -60
  141. package/dist-server/server/system-prompt.js +1 -1
  142. package/dist-server/server/team-backup.js +19 -4
  143. package/dist-server/server/thread-model.js +25 -0
  144. package/dist-server/server/turn-continuation.js +17 -16
  145. package/dist-server/server/webhook-ingress.js +8 -3
  146. package/dist-server/server/webhooks.js +40 -5
  147. package/dist-server/server/workspace-backup.js +6 -1
  148. package/dist-server/shared/device-sign-in.js +57 -0
  149. package/dist-server/shared/team-backup.js +2 -0
  150. package/dist-server/shared/thread-model.js +13 -0
  151. package/dist-server/vps-container-mcp.js +8 -0
  152. package/dist-server/workspace-backup.worker.js +42 -23
  153. package/package.json +1 -1
  154. package/skills/create-verification-skill/SKILL.md +9 -8
  155. package/skills/create-verification-skill/manifest.json +1 -1
  156. package/dist/assets/DesktopViewer-CPidMCtt.js +0 -5
  157. package/dist/assets/abap-BdImnpbu.js +0 -1
  158. package/dist/assets/actionscript-3-B3316cI-.js +0 -1
  159. package/dist/assets/ada-bCR0ucgS.js +0 -1
  160. package/dist/assets/ahk-CsyLZFj1.js +0 -1
  161. package/dist/assets/ahk2-8Zs4aa1G.js +0 -1
  162. package/dist/assets/andromeeda-C4gqWexZ.js +0 -1
  163. package/dist/assets/angular-html-DA-rfuFy.js +0 -1
  164. package/dist/assets/angular-ts-BrjP3tb8.js +0 -1
  165. package/dist/assets/apache-Pmp26Uib.js +0 -1
  166. package/dist/assets/apex-DhZFqWV2.js +0 -1
  167. package/dist/assets/apl-CORt7UWP.js +0 -1
  168. package/dist/assets/applescript-Co6uUVPk.js +0 -1
  169. package/dist/assets/ara-BRHolxvo.js +0 -1
  170. package/dist/assets/architectureDiagram-NJMV4G6O-DiPor3UT.js +0 -36
  171. package/dist/assets/asciidoc-CSVQ5wI8.js +0 -1
  172. package/dist/assets/asm-D_Q5rh1f.js +0 -1
  173. package/dist/assets/astro-HNnZUWAn.js +0 -1
  174. package/dist/assets/aurora-x-D-2ljcwZ.js +0 -1
  175. package/dist/assets/awk-DMzUqQB5.js +0 -1
  176. package/dist/assets/ayu-dark-DYE7WIF3.js +0 -1
  177. package/dist/assets/ayu-light-BA47KaF1.js +0 -1
  178. package/dist/assets/ayu-mirage-32ctXXKs.js +0 -1
  179. package/dist/assets/ballerina-BFfxhgS-.js +0 -1
  180. package/dist/assets/bat-CickPsom.js +0 -1
  181. package/dist/assets/beancount-k_qm7-4y.js +0 -1
  182. package/dist/assets/berry-uYugtg8r.js +0 -1
  183. package/dist/assets/bibtex-CHM0blh-.js +0 -1
  184. package/dist/assets/bicep-Bmn6On1c.js +0 -1
  185. package/dist/assets/bird2-Bx8U0n9b.js +0 -1
  186. package/dist/assets/blade-2xfisSek.js +0 -1
  187. package/dist/assets/bsl-DlhNcFeZ.js +0 -1
  188. package/dist/assets/c3-Dp5svz6Z.js +0 -1
  189. package/dist/assets/cadence-Bv_4Rxtq.js +0 -1
  190. package/dist/assets/cairo-KRGpt6FW.js +0 -1
  191. package/dist/assets/catppuccin-frappe-CZL1YF0i.js +0 -1
  192. package/dist/assets/catppuccin-latte-DH-8KZSZ.js +0 -1
  193. package/dist/assets/catppuccin-macchiato-B7yYVSCf.js +0 -1
  194. package/dist/assets/catppuccin-mocha-Ct7hS0mc.js +0 -1
  195. package/dist/assets/channel-DR8eD6QW.js +0 -1
  196. package/dist/assets/chapel-DTp_pixX.js +0 -1
  197. package/dist/assets/clarity-Dn5IMItf.js +0 -1
  198. package/dist/assets/clojure-P80f7IUj.js +0 -1
  199. package/dist/assets/cmake-D1j8_8rp.js +0 -1
  200. package/dist/assets/cobol-nBiQ_Alo.js +0 -1
  201. package/dist/assets/codeowners-Bp6g37R7.js +0 -1
  202. package/dist/assets/codeql-DsOJ9woJ.js +0 -1
  203. package/dist/assets/coffee-Ch7k5sss.js +0 -1
  204. package/dist/assets/common-lisp-Cg-RD9OK.js +0 -1
  205. package/dist/assets/coq-C7JzOVbR.js +0 -1
  206. package/dist/assets/cose-bilkent-JH36ORCC-BBmR1bbX.js +0 -1
  207. package/dist/assets/cpp-BMRokrvK.js +0 -1
  208. package/dist/assets/crystal-DGywbUpC.js +0 -1
  209. package/dist/assets/csv-fuZLfV_i.js +0 -1
  210. package/dist/assets/cue-D82EKSYY.js +0 -1
  211. package/dist/assets/cypher-COkxafJQ.js +0 -1
  212. package/dist/assets/d-85-TOEBH.js +0 -1
  213. package/dist/assets/dark-plus-C3mMm8J8.js +0 -1
  214. package/dist/assets/dax-CEL-wOlO.js +0 -1
  215. package/dist/assets/desktop-BmXAJ9_W.js +0 -1
  216. package/dist/assets/dotenv-Da5cRb03.js +0 -1
  217. package/dist/assets/dracula-BzJJZx-M.js +0 -1
  218. package/dist/assets/dracula-soft-BXkSAIEj.js +0 -1
  219. package/dist/assets/dream-maker-BtqSS_iP.js +0 -1
  220. package/dist/assets/edge-FbVlp4U3.js +0 -1
  221. package/dist/assets/elixir-CkH2-t6x.js +0 -1
  222. package/dist/assets/elm-DbKCFpqz.js +0 -1
  223. package/dist/assets/emacs-lisp-C_m_b--Z.js +0 -1
  224. package/dist/assets/erb-DXfck5VN.js +0 -1
  225. package/dist/assets/erlang-DsQrWhSR.js +0 -1
  226. package/dist/assets/everforest-dark-BgDCqdQA.js +0 -1
  227. package/dist/assets/everforest-light-C8M2exoo.js +0 -1
  228. package/dist/assets/fennel-BYunw83y.js +0 -1
  229. package/dist/assets/fluent-C4IJs8-o.js +0 -1
  230. package/dist/assets/fortran-fixed-form-CkoXwp7k.js +0 -1
  231. package/dist/assets/fortran-free-form-BxgE0vQu.js +0 -1
  232. package/dist/assets/fsharp-CXgrBDvD.js +0 -1
  233. package/dist/assets/ganttDiagram-FUAMR5RP-gtYBTu0B.js +0 -292
  234. package/dist/assets/gdresource-TyuKm33G.js +0 -1
  235. package/dist/assets/gdscript-DqcFQ5yU.js +0 -1
  236. package/dist/assets/gdshader-DkwncUOv.js +0 -1
  237. package/dist/assets/genie-D0YGMca9.js +0 -1
  238. package/dist/assets/gherkin-DyxjwDmM.js +0 -1
  239. package/dist/assets/git-commit-F4YmCXRG.js +0 -1
  240. package/dist/assets/git-rebase-r7XF79zn.js +0 -1
  241. package/dist/assets/github-dark-DHJKELXO.js +0 -1
  242. package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +0 -1
  243. package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +0 -1
  244. package/dist/assets/github-light-DAi9KRSo.js +0 -1
  245. package/dist/assets/github-light-high-contrast-BfjtVDDH.js +0 -1
  246. package/dist/assets/gleam-BspZqrRM.js +0 -1
  247. package/dist/assets/glimmer-js-ByusRIyA.js +0 -1
  248. package/dist/assets/glimmer-ts-BfAWNZQY.js +0 -1
  249. package/dist/assets/glsl-DplSGwfg.js +0 -1
  250. package/dist/assets/gn-n2N0HUVH.js +0 -1
  251. package/dist/assets/gnuplot-DdkO51Og.js +0 -1
  252. package/dist/assets/groovy-gcz8RCvz.js +0 -1
  253. package/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +0 -1
  254. package/dist/assets/gruvbox-dark-medium-GsRaNv29.js +0 -1
  255. package/dist/assets/gruvbox-dark-soft-CVdnzihN.js +0 -1
  256. package/dist/assets/gruvbox-light-hard-CH1njM8p.js +0 -1
  257. package/dist/assets/gruvbox-light-medium-DRw_LuNl.js +0 -1
  258. package/dist/assets/gruvbox-light-soft-hJgmCMqR.js +0 -1
  259. package/dist/assets/hack-BWmVpMyf.js +0 -1
  260. package/dist/assets/haml-D5jkg6IW.js +0 -1
  261. package/dist/assets/handlebars-BpdQsYii.js +0 -1
  262. package/dist/assets/haskell-Df6bDoY_.js +0 -1
  263. package/dist/assets/haxe-CfZj7gIn.js +0 -1
  264. package/dist/assets/hcl-BWvSN4gD.js +0 -1
  265. package/dist/assets/hjson-D5-asLiD.js +0 -1
  266. package/dist/assets/hlsl-D3lLCCz7.js +0 -1
  267. package/dist/assets/horizon-BUw7H-hv.js +0 -1
  268. package/dist/assets/horizon-bright-CUuTKBJd.js +0 -1
  269. package/dist/assets/houston-DnULxvSX.js +0 -1
  270. package/dist/assets/html-derivative-DlHx6ybY.js +0 -1
  271. package/dist/assets/http-jrhK8wxY.js +0 -1
  272. package/dist/assets/hurl-irOxFIW8.js +0 -1
  273. package/dist/assets/hxml-2-FPmUDs.js +0 -1
  274. package/dist/assets/hy-DFXneXwc.js +0 -1
  275. package/dist/assets/imba-DGztddWO.js +0 -1
  276. package/dist/assets/index-Cp4S4NOL.js +0 -153
  277. package/dist/assets/index-CpaIXRLp.js +0 -614
  278. package/dist/assets/index-Z81SMsgR.css +0 -1
  279. package/dist/assets/ini-BEwlwnbL.js +0 -1
  280. package/dist/assets/jinja-f2NsQr07.js +0 -1
  281. package/dist/assets/jison-wvAkD_A8.js +0 -1
  282. package/dist/assets/jsonl-DcaNXYhu.js +0 -1
  283. package/dist/assets/jsonnet-DFQXde-d.js +0 -1
  284. package/dist/assets/jssm-C2t-YnRu.js +0 -1
  285. package/dist/assets/julia-5Bft2YPA.js +0 -1
  286. package/dist/assets/just-Cwhn7H3k.js +0 -1
  287. package/dist/assets/kanagawa-dragon-BuwD2xS4.js +0 -1
  288. package/dist/assets/kanagawa-lotus-C3DzagqV.js +0 -1
  289. package/dist/assets/kanagawa-wave-DFGoQZhC.js +0 -1
  290. package/dist/assets/kdl-DV7GczEv.js +0 -1
  291. package/dist/assets/kusto-wEQ09or8.js +0 -1
  292. package/dist/assets/laserwave-DUszq2jm.js +0 -1
  293. package/dist/assets/latex-D5pSuvFb.js +0 -1
  294. package/dist/assets/lean-BZvkOJ9d.js +0 -1
  295. package/dist/assets/light-plus-B7mTdjB0.js +0 -1
  296. package/dist/assets/liquid-C0sCDyMI.js +0 -1
  297. package/dist/assets/llvm-BZoOZj88.js +0 -1
  298. package/dist/assets/log-2UxHyX5q.js +0 -1
  299. package/dist/assets/logo-BtOb2qkB.js +0 -1
  300. package/dist/assets/luau-BnpPk5vE.js +0 -1
  301. package/dist/assets/marko-DjSrsDqO.js +0 -1
  302. package/dist/assets/material-theme-D5KoaKCx.js +0 -1
  303. package/dist/assets/material-theme-darker-BfHTSMKl.js +0 -1
  304. package/dist/assets/material-theme-lighter-B0m2ddpp.js +0 -1
  305. package/dist/assets/material-theme-ocean-CyktbL80.js +0 -1
  306. package/dist/assets/material-theme-palenight-Csfq5Kiy.js +0 -1
  307. package/dist/assets/matlab-D7o27uSR.js +0 -1
  308. package/dist/assets/mdc-D1_yUvq7.js +0 -1
  309. package/dist/assets/mermaid-CQcHuHx7.js +0 -1
  310. package/dist/assets/min-dark-CafNBF8u.js +0 -1
  311. package/dist/assets/min-light-CTRr51gU.js +0 -1
  312. package/dist/assets/mipsasm-CKIfxQSi.js +0 -1
  313. package/dist/assets/mojo-DJz3ZmWd.js +0 -1
  314. package/dist/assets/monokai-BRVnQi9A.js +0 -1
  315. package/dist/assets/moonbit-CHtswR0a.js +0 -1
  316. package/dist/assets/move-el3G9tDJ.js +0 -1
  317. package/dist/assets/narrat-DRg8JJMk.js +0 -1
  318. package/dist/assets/nextflow-C-mBbutL.js +0 -1
  319. package/dist/assets/nextflow-groovy-vE_lwT2v.js +0 -1
  320. package/dist/assets/nginx-BpAMiNFr.js +0 -1
  321. package/dist/assets/night-owl-C39BiMTA.js +0 -1
  322. package/dist/assets/night-owl-light-CMTm3GFP.js +0 -1
  323. package/dist/assets/nim-BIad80T-.js +0 -1
  324. package/dist/assets/nix-CwoSXNpI.js +0 -1
  325. package/dist/assets/nord-Ddv68eIx.js +0 -1
  326. package/dist/assets/nsis-BlV79W_Q.js +0 -1
  327. package/dist/assets/nushell-D3jzshHO.js +0 -1
  328. package/dist/assets/objective-c-DXmwc3jG.js +0 -1
  329. package/dist/assets/objective-cpp-CLxacb5B.js +0 -1
  330. package/dist/assets/ocaml-C0hk2d4L.js +0 -1
  331. package/dist/assets/odin-BBf5iR-q.js +0 -1
  332. package/dist/assets/one-dark-pro-DVMEJ2y_.js +0 -1
  333. package/dist/assets/one-light-C3Wv6jpd.js +0 -1
  334. package/dist/assets/openscad-C4EeE6gA.js +0 -1
  335. package/dist/assets/org-DM6o9KBp.js +0 -1
  336. package/dist/assets/pascal-D93ZcfNL.js +0 -1
  337. package/dist/assets/perl-B9cMNwum.js +0 -1
  338. package/dist/assets/pkl-u5AG7uiY.js +0 -1
  339. package/dist/assets/plastic-3e1v2bzS.js +0 -1
  340. package/dist/assets/plsql-ChMvpjG-.js +0 -1
  341. package/dist/assets/po-BTJTHyun.js +0 -1
  342. package/dist/assets/poimandres-CS3Unz2-.js +0 -1
  343. package/dist/assets/polar-C0HS_06l.js +0 -1
  344. package/dist/assets/postcss-CXtECtnM.js +0 -1
  345. package/dist/assets/powerquery-CEu0bR-o.js +0 -1
  346. package/dist/assets/prisma-Vru482bI.js +0 -1
  347. package/dist/assets/prolog-CbFg5uaA.js +0 -1
  348. package/dist/assets/pug-DKIMFp6K.js +0 -1
  349. package/dist/assets/puppet-BMWR74SV.js +0 -1
  350. package/dist/assets/purescript-CklMAg4u.js +0 -1
  351. package/dist/assets/qml-3beO22l8.js +0 -1
  352. package/dist/assets/qmldir-C8lEn-DE.js +0 -1
  353. package/dist/assets/qss-IeuSbFQv.js +0 -1
  354. package/dist/assets/racket-BqYA7rlc.js +0 -1
  355. package/dist/assets/raku-DXvB9xmW.js +0 -1
  356. package/dist/assets/razor-BjBPvh-w.js +0 -1
  357. package/dist/assets/rbs-CpoqiR4B.js +0 -1
  358. package/dist/assets/red-hvxz__6c.js +0 -1
  359. package/dist/assets/reg-C-SQnVFl.js +0 -1
  360. package/dist/assets/regexp-CDVJQ6XC.js +0 -1
  361. package/dist/assets/rel-C3B-1QV4.js +0 -1
  362. package/dist/assets/riscv-BM1_JUlF.js +0 -1
  363. package/dist/assets/ron-D8l8udqQ.js +0 -1
  364. package/dist/assets/rose-pine-5qJOZa0Y.js +0 -1
  365. package/dist/assets/rose-pine-dawn-zx0QlTCp.js +0 -1
  366. package/dist/assets/rose-pine-moon-C9pEdX9L.js +0 -1
  367. package/dist/assets/rosmsg-BJDFO7_C.js +0 -1
  368. package/dist/assets/rst-bs7f0vWN.js +0 -1
  369. package/dist/assets/ruby-C0TQ7zu5.js +0 -1
  370. package/dist/assets/sas-DEy46yEz.js +0 -1
  371. package/dist/assets/scala-CqE71os6.js +0 -1
  372. package/dist/assets/scheme-C98Dy4si.js +0 -1
  373. package/dist/assets/sdbl-DVxCFoDh.js +0 -1
  374. package/dist/assets/shaderlab-Dg9Lc6iA.js +0 -1
  375. package/dist/assets/shellsession-BADoaaVG.js +0 -1
  376. package/dist/assets/slack-dark-BthQWCQV.js +0 -1
  377. package/dist/assets/slack-ochin-DqwNpetd.js +0 -1
  378. package/dist/assets/smalltalk-BOQMe2GC.js +0 -1
  379. package/dist/assets/smithy-cds9vsN8.js +0 -1
  380. package/dist/assets/snazzy-light-Bw305WKR.js +0 -1
  381. package/dist/assets/solarized-dark-CpvCGNkr.js +0 -1
  382. package/dist/assets/solarized-light-Dlz6yCKv.js +0 -1
  383. package/dist/assets/solidity-DijEV5ha.js +0 -1
  384. package/dist/assets/soy-8wufbnw4.js +0 -1
  385. package/dist/assets/sparql-rVzFXLq3.js +0 -1
  386. package/dist/assets/splunk-BtCnVYZw.js +0 -1
  387. package/dist/assets/ssh-config-_ykCGR6B.js +0 -1
  388. package/dist/assets/stata-DI20mbqo.js +0 -1
  389. package/dist/assets/stylus-BEDo0Tqx.js +0 -1
  390. package/dist/assets/surrealql-Cjom0U5J.js +0 -1
  391. package/dist/assets/svelte-Cy7k_4gC.js +0 -1
  392. package/dist/assets/swimlanesDiagram-TC7HE7FX-D-8vqZ4-.js +0 -8
  393. package/dist/assets/synthwave-84-CbfX1IO0.js +0 -1
  394. package/dist/assets/system-verilog-0hqHdDBg.js +0 -1
  395. package/dist/assets/systemd-4A_iFExJ.js +0 -1
  396. package/dist/assets/talonscript-CkByrt1z.js +0 -1
  397. package/dist/assets/tasl-QIJgUcNo.js +0 -1
  398. package/dist/assets/tcl-dwOrl1Do.js +0 -1
  399. package/dist/assets/templ-DhtptRzy.js +0 -1
  400. package/dist/assets/terraform-BETggiCN.js +0 -1
  401. package/dist/assets/tex-D96PA37w.js +0 -1
  402. package/dist/assets/tokyo-night-hegEt444.js +0 -1
  403. package/dist/assets/ts-tags-D351s5mN.js +0 -1
  404. package/dist/assets/tsv-B_m7g4N7.js +0 -1
  405. package/dist/assets/turtle-BsS91CYL.js +0 -1
  406. package/dist/assets/twig-27uCiNez.js +0 -1
  407. package/dist/assets/typespec-CAFt9gP4.js +0 -1
  408. package/dist/assets/typst-BUadGCkm.js +0 -1
  409. package/dist/assets/v-BGw2Nkan.js +0 -1
  410. package/dist/assets/vala-CsfeWuGM.js +0 -1
  411. package/dist/assets/vb-Cu-pLBUe.js +0 -1
  412. package/dist/assets/verilog-nZwndyjY.js +0 -1
  413. package/dist/assets/vesper-DRje8inN.js +0 -1
  414. package/dist/assets/vhdl-CeAyd5Ju.js +0 -1
  415. package/dist/assets/viml-CJc9bBzg.js +0 -1
  416. package/dist/assets/vitesse-black-Bkuqu6BP.js +0 -1
  417. package/dist/assets/vitesse-dark-D0r3Knsf.js +0 -1
  418. package/dist/assets/vitesse-light-CVO1_9PV.js +0 -1
  419. package/dist/assets/vue-BqiEGhQt.js +0 -1
  420. package/dist/assets/vue-html-AaS7Mt5G.js +0 -1
  421. package/dist/assets/vue-vine-BoDAl6tE.js +0 -1
  422. package/dist/assets/vyper-CDx5xZoG.js +0 -1
  423. package/dist/assets/wasm-CG6Dc4jp.js +0 -1
  424. package/dist/assets/wenyan-BV7otONQ.js +0 -1
  425. package/dist/assets/wgsl-Dx-B1_4e.js +0 -1
  426. package/dist/assets/wikitext-BhOHFoWU.js +0 -1
  427. package/dist/assets/wit-5i3qLPDT.js +0 -1
  428. package/dist/assets/wolfram-lXgVvXCa.js +0 -1
  429. package/dist/assets/xsl-CtQFsRM5.js +0 -1
  430. package/dist/assets/zenscript-DVFEvuxE.js +0 -1
  431. package/dist/assets/zig-VOosw3JB.js +0 -1
  432. /package/dist/assets/{shellscript-Yzrsuije.js → bash-Yzrsuije.js} +0 -0
  433. /package/dist/assets/{docker-BcOcwvcX.js → dockerfile-BcOcwvcX.js} +0 -0
  434. /package/dist/assets/{make-CHLpvVh8.js → makefile-CHLpvVh8.js} +0 -0
@@ -10,7 +10,7 @@ import { codexToolSurfaceArgs } from "./codex-tool-surface.js";
10
10
  //
11
11
  // resumeCursor is the codex thread id; a later turn tries thread/resume
12
12
  // and preserves that history or reports a failed resume.
13
- import { existsSync, mkdirSync } from "node:fs";
13
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
14
14
  import { createHash } from "node:crypto";
15
15
  import { join } from "node:path";
16
16
  import { homedir } from "node:os";
@@ -23,7 +23,7 @@ import { ChatGptPlanAuthController } from "./chatgpt-plan-auth.js";
23
23
  import { describeSpawnFailure, execCli, killCliTree, spawnCli } from "../procs.js";
24
24
  import { isHarnessOwnedMcpEnvName } from "../mcp-registry.js";
25
25
  import { newEventId, newId } from "../contracts.js";
26
- import { decodeCodexSelection, readCodexModelCatalog, STATIC_CODEX_MODELS } from "./codex-catalog.js";
26
+ import { decodeCodexSelection, OFFICIAL_CODEX_PROVIDER, readCodexModelCatalog, STATIC_CODEX_MODELS } from "./codex-catalog.js";
27
27
  import { codexLocalProviderArgs } from "./local-inject.js";
28
28
  import { augmentedPath, splitCliString } from "../env-path.js";
29
29
  import { classifyError, computeBackoff, interruptibleDelay, RETRY_MAX_ATTEMPTS } from "./retry.js";
@@ -33,7 +33,8 @@ import { commandSummary, toolDetailPreview } from "../tool-summary.js";
33
33
  import { codexDeveloperInstructions, syncCodexInstructions } from "./codex-instructions.js";
34
34
  import { volatileContextNote, withContextNote } from "./prompt-split.js";
35
35
  import { CodexDeviceAuthController } from "./codex-device-auth.js";
36
- import { codexAccountEmail } from "./codex-identity.js";
36
+ import { codexAccountEmail, codexHome } from "./codex-identity.js";
37
+ import { keyRejected, noteKeyAccepted, noteKeyRejected } from "../key-rejections.js";
37
38
  import { classifyResumeFailure, mayReplay, recoveryPromptFor } from "../resume-recovery.js";
38
39
  import { extractMcpImages } from "../mcp-tool-images.js";
39
40
  import { parseProtocolAskQuestions, questionAnswersById, questionChoices } from "../../shared/ask-question.js";
@@ -54,6 +55,30 @@ export function codexUserError(value, chatgptPlan) {
54
55
  }
55
56
  return value.slice(0, 400);
56
57
  }
58
+ // Codex's own words when OpenAI refuses its stored ChatGPT login (codex-cli
59
+ // 0.160 login/src/auth: workspace routing, token refresh, auth storage).
60
+ const CODEX_SIGN_IN_REFUSED = /workspace routing discovery unauthorized|access token could not be refreshed|authentication session could not be refreshed|ChatGPT login is required|auth data is not available|please (?:log out and )?sign in again/i;
61
+ /** A turn error (TurnError: message, codexErrorInfo) that says Codex's own
62
+ * sign-in was refused: `unauthorized`, a 401 from the model backend, or one
63
+ * of Codex's sign-in messages. A 401 from an MCP server or a tool reaches the
64
+ * model as a tool result, never as a turn error, so it cannot land here. */
65
+ export function codexSignInRefused(error) {
66
+ if (!error || typeof error !== "object")
67
+ return false;
68
+ const { message, codexErrorInfo: info } = error;
69
+ if (info === "unauthorized")
70
+ return true;
71
+ if (info && typeof info === "object" &&
72
+ Object.values(info).some((variant) => variant?.httpStatusCode === 401))
73
+ return true;
74
+ return typeof message === "string" && CODEX_SIGN_IN_REFUSED.test(message);
75
+ }
76
+ export const CODEX_SIGN_IN_EXPIRED = "Codex's ChatGPT sign-in has expired. Sign in again in Settings → Model providers → Codex.";
77
+ /** The plain sentence first, so a peer bot's one-line report keeps it;
78
+ * Codex's own words follow as the detail. */
79
+ export function codexSignInExpired(raw) {
80
+ return `${CODEX_SIGN_IN_EXPIRED} Codex said: ${raw.slice(0, 300)}`;
81
+ }
57
82
  class CodexRpcError extends Error {
58
83
  code;
59
84
  constructor(error) {
@@ -605,10 +630,47 @@ export const CodexDriver = {
605
630
  }
606
631
  else
607
632
  await refreshModels();
633
+ // Codex's own ChatGPT login (not ChatGPT plan, whose tokens OpenMausBot
634
+ // holds, nor Company routing) can be refused by OpenAI while `codex login
635
+ // status` still reports it. A refusal marks it the way a rejected API key
636
+ // is marked (key-rejections.ts): its credential home, plus the stored
637
+ // auth file, so a sign-in made anywhere else starts over. A later turn
638
+ // that succeeds, a new sign-in and sign-out clear it. Only a stored
639
+ // ChatGPT login is marked: an API-key login (`codex login --with-api-key`)
640
+ // cannot be fixed by the ChatGPT sign-in Settings offers.
641
+ const ownLogin = !plan && !config.managed;
642
+ const loginMark = () => {
643
+ const home = ownLogin ? codexHome(childEnv()) : null;
644
+ if (!home)
645
+ return null;
646
+ let stored = "";
647
+ try {
648
+ stored = readFileSync(join(home, "auth.json"), "utf8");
649
+ }
650
+ catch {
651
+ return null; /* keyring, or none */
652
+ }
653
+ try {
654
+ const auth = JSON.parse(stored);
655
+ const chatgpt = typeof auth.auth_mode === "string" ? /chatgpt/i.test(auth.auth_mode) : Boolean(auth.tokens);
656
+ if (!chatgpt)
657
+ return null;
658
+ }
659
+ catch {
660
+ return null;
661
+ }
662
+ return [`codex-login:${home}`, stored];
663
+ };
664
+ const loginRefused = () => { const mark = loginMark(); if (mark)
665
+ noteKeyRejected(...mark); };
666
+ const loginAccepted = (mark = loginMark()) => { if (mark)
667
+ noteKeyAccepted(...mark); };
668
+ const loginRejected = () => { const mark = loginMark(); return mark !== null && keyRejected(...mark); };
608
669
  const authentication = new CodexDeviceAuthController({
609
670
  cli: config.cli,
610
671
  environment: childEnv,
611
- onAuthenticated: refreshModels,
672
+ signInRejected: loginRejected,
673
+ onAuthenticated: async () => { loginAccepted(); await refreshModels(); },
612
674
  });
613
675
  const listeners = new Set();
614
676
  const active = new Map();
@@ -690,6 +752,12 @@ export const CodexDriver = {
690
752
  // a retry relaunches the whole app-server; the backoff is scaled down in
691
753
  // tests so a fake's transient failures don't stall real seconds
692
754
  const retryScale = Number(process.env.FAKE_CODEX_RETRY_SCALE ?? "1");
755
+ // Only a turn on the official provider says anything about Codex's
756
+ // ChatGPT login: a custom provider's 401 is its own key's, and its
757
+ // success proves nothing about ChatGPT. No model means the catalog's
758
+ // default, which is provider-qualified when config.toml picks another.
759
+ const chatgptTurn = ownLogin &&
760
+ decodeCodexSelection(turn.model || models.default).modelProvider === OFFICIAL_CODEX_PROVIDER;
693
761
  const launchAttempt = async (attempt) => {
694
762
  const env = childEnv();
695
763
  if (planToken)
@@ -784,6 +852,13 @@ export const CodexDriver = {
784
852
  const state = {
785
853
  settled: false,
786
854
  lastError: "",
855
+ // whether lastError went out marked setup (a sign-in to fix)
856
+ lastErrorSetup: false,
857
+ // an error Codex said it would retry itself (willRetry), kept only
858
+ // to explain a turn that then fails without words of its own
859
+ retryError: "",
860
+ // Codex started recovering its model provider's sign-in this turn
861
+ authRecovery: false,
787
862
  lastText: "",
788
863
  sawStreamDelta: false,
789
864
  // codex reports token usage as a running total for this app-server
@@ -1122,6 +1197,25 @@ export const CodexDriver = {
1122
1197
  message: `Codex automatic review ${outcome}${target}. Action did not run. Retry stays ${retryMode}. Select Ask for human approval in approval settings.`,
1123
1198
  });
1124
1199
  };
1200
+ // The turn's failure, said once. An error notification and the
1201
+ // turn/completed after it usually carry the same words; the second
1202
+ // only speaks again to deliver a sign-in flag the first lacked.
1203
+ // Codex's own refused sign-in reads as one plain sentence and marks
1204
+ // the login, so Settings asks for a new sign-in too.
1205
+ const turnError = (error) => {
1206
+ const raw = String(error.message);
1207
+ const refused = chatgptTurn && loginMark() !== null && (codexSignInRefused(error) ||
1208
+ (state.authRecovery && !/\b403\b|forbidden/i.test(raw) && /\b401\b|unauthorized/i.test(raw)));
1209
+ if (refused)
1210
+ loginRefused();
1211
+ const message = refused ? codexSignInExpired(raw) : codexUserError(raw, plan);
1212
+ const setup = refused || classifyError({ text: message }).reason === "auth";
1213
+ if (message === state.lastError && (state.lastErrorSetup || !setup))
1214
+ return;
1215
+ state.lastError = message;
1216
+ state.lastErrorSetup ||= setup;
1217
+ emit({ ...base(threadId, turnId), type: "runtime.error", message, ...(setup ? { setup: true } : {}) });
1218
+ };
1125
1219
  const handleNotification = (msg) => {
1126
1220
  const p = msg.params ?? {};
1127
1221
  // An app-server also emits notifications for native helper threads.
@@ -1322,27 +1416,43 @@ export const CodexDriver = {
1322
1416
  if (reviewWarning && !timedOutReview)
1323
1417
  reviewNotice("warning");
1324
1418
  const t = p.turn ?? {};
1325
- const message = typeof t.error?.message === "string" ? codexUserError(t.error.message, plan) : "";
1326
- if (t.status !== "completed" && message && message !== state.lastError) {
1327
- state.lastError = message;
1328
- emit({ ...base(threadId, turnId), type: "runtime.error", message,
1329
- ...(classifyError({ text: message }).reason === "auth" ? { setup: true } : {}),
1330
- });
1419
+ if (t.status === "completed") {
1420
+ if (chatgptTurn)
1421
+ loginAccepted();
1422
+ }
1423
+ else if (typeof t.error?.message === "string") {
1424
+ turnError(t.error);
1425
+ }
1426
+ else if (t.status === "failed" && !state.lastError && state.retryError) {
1427
+ // Codex gave up retrying without a final word: its last one
1428
+ turnError({ message: state.retryError });
1331
1429
  }
1332
1430
  void settle(t.status === "completed", t.status === "completed" ? null :
1333
- (classifyError({ text: message || state.lastError }).reason === "provider_safety" ? "provider_safety" : (message || t.status || "failed")));
1431
+ (classifyError({ text: state.lastError }).reason === "provider_safety" ? "provider_safety" : (state.lastError || t.status || "failed")));
1334
1432
  break;
1335
1433
  }
1336
- case "error":
1337
- // shape drift: 0.144 sends {message}, 0.139 nests it under
1338
- // {error:{message}} — surface either (agentcal armor)
1339
- {
1340
- const message = p.message ?? p.error?.message;
1341
- if (message) {
1342
- state.lastError = codexUserError(String(message), plan);
1343
- emit({ ...base(threadId, turnId), type: "runtime.error", message: state.lastError });
1344
- }
1434
+ case "error": {
1435
+ // shape drift: 0.144 sends {message}, 0.139 and 0.160 nest it
1436
+ // under {error:{message, codexErrorInfo}} — surface either
1437
+ // (agentcal armor)
1438
+ const error = p.error && typeof p.error === "object" ? p.error : { message: p.message };
1439
+ if (!error.message)
1440
+ break;
1441
+ // 0.160 reports each of its own reconnects ("Reconnecting...
1442
+ // 1/5") with willRetry: true. Those are not the turn's failure;
1443
+ // the final error, or turn/completed, says how it ended.
1444
+ if (p.willRetry === true) {
1445
+ state.retryError = String(error.message);
1446
+ break;
1345
1447
  }
1448
+ turnError(error);
1449
+ break;
1450
+ }
1451
+ case "modelProvider/authRecoveryStarted":
1452
+ state.authRecovery = true;
1453
+ break;
1454
+ case "modelProvider/authRecoveryCompleted":
1455
+ state.authRecovery = false;
1346
1456
  break;
1347
1457
  }
1348
1458
  };
@@ -1732,8 +1842,10 @@ export const CodexDriver = {
1732
1842
  }
1733
1843
  catch (e) {
1734
1844
  const failure = e instanceof Error ? e : { text: String(e) };
1735
- const message = codexUserError(e instanceof Error ? e.message : String(e), plan);
1736
- const needsAuth = /(?:\b401\b|unauthorized|missing bearer|authentication required)/i.test(message);
1845
+ const raw = e instanceof Error ? e.message : String(e);
1846
+ const refused = chatgptTurn && loginMark() !== null && codexSignInRefused({ message: raw });
1847
+ const message = refused ? codexSignInExpired(raw) : codexUserError(raw, plan);
1848
+ const needsAuth = refused || /(?:\b401\b|unauthorized|missing bearer|authentication required)/i.test(message);
1737
1849
  const verdict = classifyError(failure);
1738
1850
  // Three guards hold here: main's abandoned attempt never retries,
1739
1851
  // neither does a Company session already recovered once from canonical
@@ -1767,6 +1879,8 @@ export const CodexDriver = {
1767
1879
  // abandoned marks an attempt retired by a retry; its late rpc
1768
1880
  // timeouts must neither report a spurious error nor relaunch again
1769
1881
  if (!state.settled && !abandoned) {
1882
+ if (refused)
1883
+ loginRefused();
1770
1884
  emit({
1771
1885
  ...base(threadId, turnId),
1772
1886
  type: "runtime.error",
@@ -1797,6 +1911,11 @@ export const CodexDriver = {
1797
1911
  const authenticated = await new Promise((resolve) => {
1798
1912
  execCli(config.cli, ["login", "status"], { timeout: 8000, env }, (err, stdout, stderr) => resolve(!err && /^logged in\b/im.test(`${stdout}\n${stderr ?? ""}`)));
1799
1913
  });
1914
+ // Signed in as far as the CLI knows, but OpenAI refused it on a real turn.
1915
+ if (authenticated && loginRejected()) {
1916
+ return { state: "available", version, authenticated: false, reason: CODEX_SIGN_IN_EXPIRED,
1917
+ update: await codexReleaseUpdate(version, config.cli), billing: "subscription" };
1918
+ }
1800
1919
  // Display identity only, so Settings can say whose ChatGPT account the
1801
1920
  // bots run on; the status command above stays the authority on sign-in.
1802
1921
  const email = authenticated ? await codexAccountEmail(config.cli, env) : null;
@@ -1837,8 +1956,12 @@ export const CodexDriver = {
1837
1956
  },
1838
1957
  cancelAuthentication: () => (planAuth ?? authentication).cancel(),
1839
1958
  signOut: async () => {
1840
- if (!planAuth)
1841
- return authentication.signOut();
1959
+ if (!planAuth) {
1960
+ const mark = loginMark();
1961
+ await authentication.signOut();
1962
+ loginAccepted(mark);
1963
+ return;
1964
+ }
1842
1965
  planSigningOut = true;
1843
1966
  planGeneration++;
1844
1967
  try {
@@ -0,0 +1,343 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { realpathSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { basename, dirname, isAbsolute, join, resolve } from "node:path";
5
+ import { stripVTControlCharacters } from "node:util";
6
+ import { deviceSignInPrompt } from "../../shared/device-sign-in.js";
7
+ import { killCliTree, spawnCli } from "../procs.js";
8
+ const MAX_OUTPUT = 16_384;
9
+ // Two configured instances can use the same on-disk login. Only the auth
10
+ // operation is exclusive: normal turns are not blocked by this lock.
11
+ const authenticatingHomes = new Set();
12
+ /** The real path of a credential home, so two spellings of one home share
13
+ * one sign-in lock. A missing tail keeps its name under its real parent. */
14
+ export function canonicalPath(path) {
15
+ try {
16
+ return realpathSync(path);
17
+ }
18
+ catch {
19
+ const parent = dirname(path);
20
+ return parent === path ? path : join(canonicalPath(parent), basename(path));
21
+ }
22
+ }
23
+ /** A fixed login command, not a remotely accessible terminal. CLI output
24
+ * stays in bounded private memory; only a device page and code are exposed. */
25
+ export class DeviceAuthController {
26
+ flow = null;
27
+ command = null;
28
+ disposed = false;
29
+ spec;
30
+ options;
31
+ constructor(spec, options) {
32
+ this.spec = spec;
33
+ this.options = options;
34
+ }
35
+ /** The credential home the lock is held on, for this environment. */
36
+ home(env, action) {
37
+ const { homeEnv, homeDir, product } = this.spec;
38
+ const home = env.HOME || env.USERPROFILE || homedir();
39
+ const named = env[homeEnv];
40
+ if (!isAbsolute(home) || (named && !isAbsolute(named))) {
41
+ throw new Error(`Use an absolute HOME and ${homeEnv} path for this server's ${product} provider before ${action}.`);
42
+ }
43
+ return { home, homeKey: canonicalPath(resolve(named || join(home, homeDir))) };
44
+ }
45
+ async start() {
46
+ const { product, account, status } = this.spec;
47
+ if (this.disposed)
48
+ throw new Error("This provider was removed. Refresh Settings before signing in.");
49
+ if (this.flow?.status.phase === "waiting") {
50
+ if (this.flow.ready)
51
+ return { ...this.flow.status, phase: "waiting" };
52
+ throw new Error(`A ${account} sign-in is already starting. Please wait for the code.`);
53
+ }
54
+ await this.flow?.stopping;
55
+ if (this.disposed)
56
+ throw new Error("This provider was removed. Refresh Settings before signing in.");
57
+ const env = this.options.environment();
58
+ const { home, homeKey } = this.home(env, "signing in");
59
+ if (authenticatingHomes.has(homeKey)) {
60
+ throw new Error(`A ${account} sign-in is already running for this server account. Finish or cancel it before starting another.`);
61
+ }
62
+ authenticatingHomes.add(homeKey);
63
+ return new Promise((resolveStart, reject) => {
64
+ const flow = {
65
+ status: {
66
+ phase: "waiting", flowId: randomUUID(), authorizationUrl: null,
67
+ expiresAt: new Date(Date.now() + (this.options.lifetimeMs ?? 15 * 60_000)).toISOString(),
68
+ },
69
+ child: null, ready: false, resolve: resolveStart, reject, homeKey,
70
+ startupTimer: setTimeout(() => this.finish(flow, "failed", `${product} did not provide a sign-in code in time. Check the server connection and update ${product}, then try again.`), this.options.startupTimeoutMs ?? 30_000),
71
+ expiryTimer: setTimeout(() => this.finish(flow, "expired", `The ${account} sign-in code expired. Start sign-in again.`), this.options.lifetimeMs ?? 15 * 60_000),
72
+ };
73
+ flow.startupTimer.unref();
74
+ flow.expiryTimer.unref();
75
+ this.flow = flow;
76
+ const login = () => this.run(flow, [...this.spec.loginArgs], env, home, (loginCode, loginOutput) => {
77
+ if (loginCode !== 0 || !flow.ready) {
78
+ this.finish(flow, "failed", this.spec.failure(loginOutput));
79
+ return;
80
+ }
81
+ // A successful command is not enough: confirm the sign-in the way
82
+ // this client's bots will find it, with the same executable and
83
+ // environment.
84
+ flow.startupTimer = setTimeout(() => this.finish(flow, "failed", `${product} finished sign-in but could not confirm the account. Refresh Settings and try again.`), this.options.startupTimeoutMs ?? 30_000);
85
+ flow.startupTimer.unref();
86
+ this.confirm(flow, env, home, (signedIn) => this.finish(flow, signedIn ? "succeeded" : "failed", `${product} finished sign-in but did not confirm a ${account} account. Refresh Settings and try again.`));
87
+ }, true);
88
+ // Never overwrite a working login just because Connect was clicked
89
+ // twice. One the provider refused is not working, whatever status says.
90
+ if (!status) {
91
+ login();
92
+ return;
93
+ }
94
+ this.run(flow, [...status.args], env, home, (code, output) => {
95
+ const state = status.read(code, output);
96
+ if (state === "signed-in" && !this.options.signInRejected?.())
97
+ this.finish(flow, "succeeded");
98
+ else if (state === "signed-in" || state === "signed-out")
99
+ login();
100
+ else if (state === "other")
101
+ this.finish(flow, "failed", `${product} already has a different sign-in method on this server. Ask the server administrator to review it before changing accounts.`);
102
+ else
103
+ this.finish(flow, "failed", `${product} could not confirm the existing sign-in on this server. Update ${product} and check its login status before trying again.`);
104
+ });
105
+ });
106
+ }
107
+ async get(flowId) {
108
+ if (!flowId || this.flow?.status.flowId !== flowId)
109
+ throw new Error("This sign-in is no longer available. Start sign-in again.");
110
+ return { ...this.flow.status };
111
+ }
112
+ async cancel() {
113
+ if (this.flow?.status.phase === "waiting")
114
+ this.finish(this.flow, "cancelled", `${this.spec.account} sign-in cancelled.`);
115
+ await this.flow?.stopping;
116
+ if (this.flow?.terminationFailed)
117
+ throw new Error(this.flow.status.message);
118
+ if (this.command && !await this.stopChild(this.command)) {
119
+ throw new Error(`${this.spec.product} could not be stopped on this server. Ask the server administrator to stop the account command before trying again.`);
120
+ }
121
+ }
122
+ async dispose() {
123
+ this.disposed = true;
124
+ await this.cancel();
125
+ this.flow = null;
126
+ }
127
+ /** Remove the sign-in the CLI stores for this server account so a
128
+ * different account can connect. A sign-in in progress is never pulled
129
+ * away underneath the browser completing it. */
130
+ async signOut() {
131
+ const { product, account, status, logoutArgs } = this.spec;
132
+ if (!status || !logoutArgs)
133
+ throw new Error(`Signing out of ${account} is not available from here.`);
134
+ if (this.disposed)
135
+ throw new Error("This provider was removed. Refresh Settings before signing out.");
136
+ if (this.flow?.status.phase === "waiting")
137
+ throw new Error(`Finish or cancel the ${account} sign-in in progress before signing out.`);
138
+ await this.flow?.stopping;
139
+ if (this.disposed)
140
+ throw new Error("This provider was removed. Refresh Settings before signing out.");
141
+ const env = this.options.environment();
142
+ const { home, homeKey } = this.home(env, "signing out");
143
+ if (authenticatingHomes.has(homeKey)) {
144
+ throw new Error(`A ${account} sign-in is running for this server account. Finish or cancel it before signing out.`);
145
+ }
146
+ authenticatingHomes.add(homeKey);
147
+ try {
148
+ const before = await this.exec([...status.args], env, home);
149
+ const state = status.read(before.code, before.output);
150
+ if (state === "signed-out")
151
+ return;
152
+ if (state !== "signed-in") {
153
+ throw new Error(`${product} did not confirm a ${account} sign-in. Other authentication methods will not be removed; ask the server administrator to check the account.`);
154
+ }
155
+ const logout = await this.exec([...logoutArgs], env, home);
156
+ if (logout.code !== 0)
157
+ throw new Error(`${product} could not remove the sign-in on this server. Check the server's ${product} installation and try again.`);
158
+ // The command's own report is not enough: confirm with the same status
159
+ // check that decides whether bots may run on this account.
160
+ const after = await this.exec([...status.args], env, home);
161
+ if (status.read(after.code, after.output) !== "signed-out") {
162
+ throw new Error(`${product} still reports a sign-in on this server. Update ${product} and check its login status before trying again.`);
163
+ }
164
+ }
165
+ finally {
166
+ // If the OS cannot stop a command, it may still change credentials.
167
+ // Keep the home reserved until that exact child actually exits.
168
+ const child = this.command;
169
+ if (child && child.exitCode === null && child.signalCode === null) {
170
+ child.once("close", () => authenticatingHomes.delete(homeKey));
171
+ }
172
+ else
173
+ authenticatingHomes.delete(homeKey);
174
+ }
175
+ }
176
+ /** After a login command succeeded: the status command when the CLI has
177
+ * one, else the stored sign-in a turn checks for. */
178
+ confirm(flow, env, home, done) {
179
+ const status = this.spec.status;
180
+ if (status) {
181
+ this.run(flow, [...status.args], env, home, (code, output) => done(status.read(code, output) === "signed-in"));
182
+ return;
183
+ }
184
+ let signedIn = false;
185
+ try {
186
+ signedIn = this.spec.signedIn?.(env) === true;
187
+ }
188
+ catch { /* unreadable: not signed in */ }
189
+ done(signedIn);
190
+ }
191
+ startFailure(error) {
192
+ const { product, install } = this.spec;
193
+ return error.code === "ENOENT"
194
+ ? `${product} is not installed on this server. ${install}`
195
+ : `${product} could not start on this server. Check the configured CLI path and its executable permissions.`;
196
+ }
197
+ /** One bounded, non-interactive command. Its output stays here; callers
198
+ * see an exit code and a status-line match, never the text. */
199
+ exec(args, env, cwd) {
200
+ const { product } = this.spec;
201
+ return new Promise((resolveExec, rejectExec) => {
202
+ if (this.disposed) {
203
+ rejectExec(new Error("This provider was removed. Refresh Settings before signing out."));
204
+ return;
205
+ }
206
+ let child;
207
+ try {
208
+ child = spawnCli(this.options.cli, args, { env: { ...env, NO_COLOR: "1" }, cwd, stdio: ["pipe", "pipe", "pipe"] });
209
+ }
210
+ catch {
211
+ rejectExec(new Error(`${product} could not start on this server. Install or update the configured ${product} CLI, then try again.`));
212
+ return;
213
+ }
214
+ this.command = child;
215
+ child.stdin.end();
216
+ let output = "";
217
+ const receive = (chunk) => {
218
+ if (output.length < MAX_OUTPUT)
219
+ output += chunk.toString("utf8").slice(0, MAX_OUTPUT - output.length);
220
+ };
221
+ child.stdout.on("data", receive);
222
+ child.stderr.on("data", receive);
223
+ // A hung CLI must not hold the credential-home lock forever.
224
+ const timer = setTimeout(() => {
225
+ void this.stopChild(child).catch(() => false).then((stopped) => {
226
+ if (!stopped)
227
+ rejectExec(new Error(`${product} could not be stopped on this server. Ask the server administrator to stop the account command before trying again.`));
228
+ });
229
+ }, this.options.startupTimeoutMs ?? 30_000);
230
+ timer.unref();
231
+ child.once("error", (error) => {
232
+ clearTimeout(timer);
233
+ rejectExec(new Error(this.startFailure(error)));
234
+ });
235
+ child.once("close", (code) => {
236
+ clearTimeout(timer);
237
+ if (this.command === child)
238
+ this.command = null;
239
+ resolveExec({ code, output: stripVTControlCharacters(output) });
240
+ });
241
+ });
242
+ }
243
+ run(flow, args, env, cwd, done, parsePrompt = false) {
244
+ const { product, provider } = this.spec;
245
+ if (flow.status.phase !== "waiting")
246
+ return;
247
+ let child;
248
+ try {
249
+ child = spawnCli(this.options.cli, args, { env: { ...env, NO_COLOR: "1" }, cwd, stdio: ["pipe", "pipe", "pipe"] });
250
+ }
251
+ catch {
252
+ this.finish(flow, "failed", `${product} could not start on this server. Install or update the configured ${product} CLI, then try again.`);
253
+ return;
254
+ }
255
+ flow.child = child;
256
+ child.stdin.end();
257
+ let output = "";
258
+ const receive = (chunk) => {
259
+ if (flow.status.phase !== "waiting")
260
+ return;
261
+ if (output.length + chunk.length > MAX_OUTPUT) {
262
+ this.finish(flow, "failed", `${product} returned an unexpected sign-in response. Update the server's ${product} CLI and try again.`);
263
+ return;
264
+ }
265
+ output += chunk.toString("utf8");
266
+ const prompt = parsePrompt && !flow.ready ? deviceSignInPrompt(provider, stripVTControlCharacters(output)) : null;
267
+ if (prompt) {
268
+ flow.status = { ...flow.status, ...prompt };
269
+ flow.ready = true;
270
+ clearTimeout(flow.startupTimer);
271
+ flow.resolve({ ...flow.status, phase: "waiting" });
272
+ }
273
+ };
274
+ child.stdout.on("data", receive);
275
+ child.stderr.on("data", receive);
276
+ child.once("error", (error) => this.finish(flow, "failed", this.startFailure(error)));
277
+ child.once("close", (code) => {
278
+ if (flow.child === child)
279
+ flow.child = null;
280
+ if (flow.status.phase === "waiting")
281
+ done(code, stripVTControlCharacters(output));
282
+ output = "";
283
+ });
284
+ }
285
+ finish(flow, phase, message) {
286
+ const { product, account } = this.spec;
287
+ if (flow.status.phase !== "waiting")
288
+ return;
289
+ clearTimeout(flow.startupTimer);
290
+ clearTimeout(flow.expiryTimer);
291
+ flow.status = {
292
+ phase, flowId: flow.status.flowId, authorizationUrl: null, expiresAt: null,
293
+ ...(phase !== "succeeded" && message ? { message } : {}),
294
+ };
295
+ if (!flow.ready) {
296
+ if (phase === "succeeded")
297
+ flow.resolve({ ...flow.status, phase });
298
+ else
299
+ flow.reject(new Error(message ?? `${account} sign-in did not finish.`));
300
+ }
301
+ flow.stopping = this.stopChild(flow.child).catch(() => false).then((stopped) => {
302
+ const release = () => authenticatingHomes.delete(flow.homeKey);
303
+ if (stopped) {
304
+ release();
305
+ return;
306
+ }
307
+ flow.terminationFailed = true;
308
+ flow.status = { ...flow.status, phase: "failed", message: `${product} could not be stopped on this server. Ask the server administrator to stop the login process before trying again.` };
309
+ // Retain the credential-home lock until the OS actually reports exit.
310
+ const child = flow.child;
311
+ if (!child || child.exitCode !== null || child.signalCode !== null)
312
+ release();
313
+ else
314
+ child.once("close", release);
315
+ });
316
+ if (phase === "succeeded")
317
+ void this.options.onAuthenticated?.().catch(() => { });
318
+ }
319
+ async stopChild(child) {
320
+ if (!child || await killCliTree(child, this.options.terminateTimeoutMs ?? 1500))
321
+ return true;
322
+ // A broken CLI may ignore SIGTERM. Do not leave a stale device flow able
323
+ // to write credentials after the user cancelled it.
324
+ if (process.platform !== "win32" && child.pid) {
325
+ try {
326
+ process.kill(-child.pid, "SIGKILL");
327
+ }
328
+ catch {
329
+ child.kill("SIGKILL");
330
+ }
331
+ }
332
+ else
333
+ child.kill("SIGKILL");
334
+ await new Promise((resolveStop) => {
335
+ if (child.exitCode !== null || child.signalCode !== null)
336
+ return resolveStop();
337
+ const timer = setTimeout(resolveStop, 1500);
338
+ timer.unref();
339
+ child.once("close", () => { clearTimeout(timer); resolveStop(); });
340
+ });
341
+ return child.exitCode !== null || child.signalCode !== null;
342
+ }
343
+ }