0sec-cli 0.25.0 → 0.26.0

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 (187) hide show
  1. package/0.js +41 -40
  2. package/chunks/{adapt-loop-L2PXCD4J.js → adapt-loop-P4HKONB5.js} +4 -4
  3. package/chunks/{artifact-scraper-W3LGLXBM.js → artifact-scraper-IIRJNYKT.js} +2 -2
  4. package/chunks/{assumption-mining-7IJ6ZWZE.js → assumption-mining-YA6VJ2V6.js} +17 -17
  5. package/chunks/{backend-connections-MYH4QRQG.js → backend-connections-64PKYKL7.js} +3 -3
  6. package/chunks/{chunk-EEP6GBUO.js → chunk-3MWQNNJU.js} +151 -58
  7. package/chunks/{chunk-ZZV56ACK.js → chunk-3VQ5EZKG.js} +9 -9
  8. package/chunks/{chunk-I4VIAQHM.js → chunk-6GV5G6U3.js} +1 -1
  9. package/chunks/{chunk-OFPF26WL.js → chunk-6SNOKNCS.js} +2 -2
  10. package/chunks/{chunk-YXTV2FRE.js → chunk-72PU46MS.js} +66 -112
  11. package/chunks/{chunk-NO543ZBU.js → chunk-A7G6S5RA.js} +1 -1
  12. package/chunks/{chunk-ITEMDJAB.js → chunk-AFJ2UMPR.js} +2 -2
  13. package/chunks/{chunk-FOLTHXRH.js → chunk-B7XL6RON.js} +1 -1
  14. package/chunks/{chunk-76CLUI54.js → chunk-BM6EYP2D.js} +3 -3
  15. package/chunks/{chunk-NBLKIQCW.js → chunk-D4M5WURF.js} +2 -2
  16. package/chunks/{chunk-DHNYJ2ML.js → chunk-EHNVP6QB.js} +1 -1
  17. package/chunks/{chunk-C6ZMPXN2.js → chunk-FBZBJYZS.js} +3 -3
  18. package/chunks/{chunk-S3B6HFSM.js → chunk-GYEYTNHK.js} +1 -1
  19. package/chunks/{chunk-EIONVEFN.js → chunk-HS2NQ7K6.js} +192 -36
  20. package/chunks/{chunk-HJKJ4NQP.js → chunk-HUZ2EC2R.js} +1 -1
  21. package/chunks/{chunk-5H2PXZ7Q.js → chunk-IUUNIJPM.js} +1 -1
  22. package/chunks/{chunk-3DF55BWV.js → chunk-JGDA6EIJ.js} +2 -2
  23. package/chunks/{chunk-GOUGG7IQ.js → chunk-K3PTYN43.js} +2 -2
  24. package/chunks/{chunk-7TIWL6E5.js → chunk-KCABBZHN.js} +7 -7
  25. package/chunks/{chunk-ACYZMJHC.js → chunk-LRD5N2TQ.js} +1 -1
  26. package/chunks/{chunk-ITHDAIRY.js → chunk-MNK373HF.js} +1 -1
  27. package/chunks/{chunk-JCRQV4FE.js → chunk-MOEVVXML.js} +2 -2
  28. package/chunks/{chunk-3HMO42M2.js → chunk-MOGWEHSC.js} +68 -771
  29. package/chunks/{chunk-TFKY6D7O.js → chunk-N7YCONYR.js} +1 -1
  30. package/chunks/{chunk-FI2H6HV2.js → chunk-NA3FKCI2.js} +1 -1
  31. package/chunks/{chunk-PMAKX6KP.js → chunk-NABVDAAO.js} +2 -2
  32. package/chunks/{chunk-YYFODVZG.js → chunk-NNMOTHKC.js} +4 -4
  33. package/chunks/{chunk-RBTJYREN.js → chunk-OILVEROI.js} +17 -4
  34. package/chunks/{chunk-GXSECFUE.js → chunk-PAMJEXE2.js} +1 -1
  35. package/chunks/{chunk-2J3STRJT.js → chunk-R7VWEY45.js} +1 -1
  36. package/chunks/{chunk-27SXCYWH.js → chunk-RZZ6VPRY.js} +1 -1
  37. package/chunks/{chunk-HFUOUT2B.js → chunk-SIR7XW2S.js} +1392 -826
  38. package/chunks/{chunk-HDJSHLRM.js → chunk-SSPP64FF.js} +2 -2
  39. package/chunks/{chunk-WK6VUCKK.js → chunk-STPHTPSD.js} +1 -1
  40. package/chunks/{chunk-SEWZ76MN.js → chunk-UGCTPKJG.js} +14 -6
  41. package/chunks/{chunk-MY44EZKD.js → chunk-ULRLUXSS.js} +1 -1
  42. package/chunks/{chunk-BWUW6ZQR.js → chunk-UQS7XCBV.js} +75 -60
  43. package/chunks/{chunk-6TA3CWND.js → chunk-V2KJQVYE.js} +42 -21
  44. package/chunks/{chunk-RFK5F45W.js → chunk-VJBEB2K6.js} +1 -1
  45. package/chunks/{chunk-D4IBEO2K.js → chunk-VWE36MUN.js} +1 -1
  46. package/chunks/{chunk-B5TIXHCO.js → chunk-WNWDQ2TO.js} +1 -1
  47. package/chunks/{chunk-S2WCYEK2.js → chunk-WPJMA5AK.js} +2 -2
  48. package/chunks/{chunk-FI5YL4R2.js → chunk-XJ2TBEV7.js} +3 -3
  49. package/chunks/{chunk-3T5R7P4T.js → chunk-XOVYV7TT.js} +4 -4
  50. package/chunks/{chunk-DJGJECBV.js → chunk-YGYJ2FTH.js} +4 -3
  51. package/chunks/{chunk-ZWAWZU6C.js → chunk-YJGPPPUB.js} +37 -9
  52. package/chunks/chunk-YP2DHYNI.js +650 -0
  53. package/chunks/{chunk-DMDWIW3E.js → chunk-Z2VLJEQJ.js} +4 -4
  54. package/chunks/{chunk-EQBC2ZWL.js → chunk-ZPVSDB63.js} +1604 -246
  55. package/chunks/{codex-models-KCUIVS3R.js → codex-models-CI22KIHY.js} +7 -7
  56. package/chunks/{commands-MPPAADGY.js → commands-C2WRSCNB.js} +210 -101
  57. package/chunks/dashboard-XO2X2SPD.js +75 -0
  58. package/chunks/{db-R2AQSESC.js → db-FU3OIGQK.js} +3 -3
  59. package/chunks/{deep-review-Q6BJKEV4.js → deep-review-5AL6QYTK.js} +30 -30
  60. package/chunks/{disclose-GGULOW27.js → disclose-YPV5KIUU.js} +3 -3
  61. package/chunks/{dist-6RNAVFAY.js → dist-ONIRKDH6.js} +29 -29
  62. package/chunks/{dist-OLGNKDB2.js → dist-QLMPTFT7.js} +2 -2
  63. package/chunks/{dist-DWN7U5OV.js → dist-QXJKD743.js} +1 -1
  64. package/chunks/{eval-runner-WCTTIYN4.js → eval-runner-D3RUCU3R.js} +17 -17
  65. package/chunks/{exploit-agent-M3KUMZJH.js → exploit-agent-4E4HXKUA.js} +1 -1
  66. package/chunks/{exploit-autoclimb-QTTWC5WM.js → exploit-autoclimb-5GRXI6VQ.js} +1 -1
  67. package/chunks/{exploit-climb-E4KDELTN.js → exploit-climb-AHQEJ2I2.js} +2 -2
  68. package/chunks/{fix-U5FFJD4F.js → fix-CHD7LXDS.js} +7 -7
  69. package/chunks/{harness-FMKIMEH5.js → harness-E63KDHPG.js} +3 -3
  70. package/chunks/{hunt-scan-RYPWRUQD.js → hunt-scan-ME2Z4CTC.js} +16 -16
  71. package/chunks/{kernel-primitive-CVG2E7MJ.js → kernel-primitive-S566GXWP.js} +2 -2
  72. package/chunks/{kernel-vm-runner-62KISULQ.js → kernel-vm-runner-KREBY4DC.js} +2 -2
  73. package/chunks/{local-engine-WP3I7K7G.js → local-engine-ZRTZVSSX.js} +5 -5
  74. package/chunks/managed-operation-ZMLLRCCQ.js +59 -0
  75. package/chunks/{native-loop-HC77R5NQ.js → native-loop-UV3Z4Z2F.js} +16 -16
  76. package/chunks/{operator-services-E2NONBQS.js → operator-services-JOCREEBA.js} +35 -35
  77. package/chunks/{orchestrate-Z3DW265M.js → orchestrate-ZF6ZTSIQ.js} +30 -30
  78. package/chunks/{prepare-7DTS6RJT.js → prepare-PLDVGLDX.js} +5 -5
  79. package/chunks/{provider-model-discovery-QGUGL3XW.js → provider-model-discovery-3X6DON3Y.js} +7 -2
  80. package/chunks/{remote-workflow-runtime-6CEVRZXS.js → remote-workflow-runtime-GOI4TYP5.js} +2 -2
  81. package/chunks/routing-WCQLO5SP.js +61 -0
  82. package/chunks/{runtime-W6JNDQRO.js → runtime-6ZIXFTW5.js} +2 -2
  83. package/chunks/{runtime-PZJ77QES.js → runtime-TVH5ORUK.js} +11 -7
  84. package/chunks/{scan-stream-6VOJTHTR.js → scan-stream-HJVTWZ44.js} +4 -4
  85. package/chunks/{scope-FHXW6EX6.js → scope-RCYXVGJR.js} +2 -2
  86. package/chunks/service-plugins-TN6KDX4L.js +63 -0
  87. package/chunks/{session-store-DBBI544Y.js → session-store-6QR3CVUA.js} +2 -2
  88. package/chunks/{variant-candidates-DPR6DJ3N.js → variant-candidates-SGLKPPHI.js} +7 -7
  89. package/chunks/{web-recon-prepass-HWDHDQMN.js → web-recon-prepass-GO7CTMVQ.js} +5 -5
  90. package/chunks/{workflow-runtime-PLB32XC3.js → workflow-runtime-CQTDASFA.js} +43 -43
  91. package/dashboard/assets/{abnfDiagram-VCTEODGH-6e39CQKz.js → abnfDiagram-VCTEODGH-DDZsU70-.js} +1 -1
  92. package/dashboard/assets/{arc-ClYun86B.js → arc-iDXNTSL6.js} +1 -1
  93. package/dashboard/assets/{architecture-7GRP2DOG-rM-lWo7E.js → architecture-7GRP2DOG-DJcY9RFg.js} +1 -1
  94. package/dashboard/assets/{architectureDiagram-5GKGNRK7-C9gEGZIU.js → architectureDiagram-5GKGNRK7-d0ZuOniQ.js} +1 -1
  95. package/dashboard/assets/{blockDiagram-I7D4REHJ-Dgh2n5Lf.js → blockDiagram-I7D4REHJ-B-EWfMy1.js} +1 -1
  96. package/dashboard/assets/{c4Diagram-7LVT6UL2-CsorW08z.js → c4Diagram-7LVT6UL2-KcZRuXZC.js} +1 -1
  97. package/dashboard/assets/channel-CeWMIm0w.js +1 -0
  98. package/dashboard/assets/{chunk-4HAMMTFA-4_b_LGGQ.js → chunk-4HAMMTFA-DXWulBlo.js} +1 -1
  99. package/dashboard/assets/{chunk-75Z2AOVW-qzNlKGCp.js → chunk-75Z2AOVW-RiLZItrz.js} +1 -1
  100. package/dashboard/assets/{chunk-DU6HZSFF-SAPICW28.js → chunk-DU6HZSFF-MBcaIyTX.js} +1 -1
  101. package/dashboard/assets/{chunk-F27PBJKO-DlLotIQx.js → chunk-F27PBJKO-kLWCBX_W.js} +1 -1
  102. package/dashboard/assets/{chunk-GMAD6QVW-DNnr65Nb.js → chunk-GMAD6QVW-BeQeSjpW.js} +1 -1
  103. package/dashboard/assets/{chunk-GVQU2GXP-DTwv0VfU.js → chunk-GVQU2GXP-CjCMlOIB.js} +1 -1
  104. package/dashboard/assets/{chunk-IMKFNOWR-B1fk1q_W.js → chunk-IMKFNOWR-BwNst53D.js} +1 -1
  105. package/dashboard/assets/{chunk-L3NEJ4N5-ByVjFIox.js → chunk-L3NEJ4N5-CHXWQrkL.js} +1 -1
  106. package/dashboard/assets/{chunk-OSK3NFVY-DUDCzjbh.js → chunk-OSK3NFVY-B2vd19Ed.js} +1 -1
  107. package/dashboard/assets/{chunk-P2QGCYS3-D_D5qEso.js → chunk-P2QGCYS3-Dk7Fyh6n.js} +1 -1
  108. package/dashboard/assets/{chunk-POPQ4Y6H-CetM-tVm.js → chunk-POPQ4Y6H-CPAgOvYe.js} +1 -1
  109. package/dashboard/assets/{chunk-PWAF6VOD-BcJX4exl.js → chunk-PWAF6VOD-BotyfMha.js} +1 -1
  110. package/dashboard/assets/{chunk-SHT3W25Y-BWQql238.js → chunk-SHT3W25Y-Buz5gLRP.js} +1 -1
  111. package/dashboard/assets/{chunk-SVP7TREG-BSLOD1JE.js → chunk-SVP7TREG-_rpYEZcs.js} +1 -1
  112. package/dashboard/assets/{chunk-TICWLB2K-DReOl-g_.js → chunk-TICWLB2K-DOJxPoec.js} +1 -1
  113. package/dashboard/assets/{chunk-XXDRQBXY-DSdSMeei.js → chunk-XXDRQBXY-EXxKJbAs.js} +1 -1
  114. package/dashboard/assets/classDiagram-ZZMXUADV-DV_h1NoS.js +1 -0
  115. package/dashboard/assets/classDiagram-v2-VYDZK3BY-DV_h1NoS.js +1 -0
  116. package/dashboard/assets/{common-CRRsylCH.js → common-VLJRx-Jq.js} +1 -1
  117. package/dashboard/assets/{cose-bilkent-JH36ORCC-fg-DIBqt.js → cose-bilkent-JH36ORCC-B1SVC57o.js} +1 -1
  118. package/dashboard/assets/{cynefin-OW5HDTMX-XmrbEIFh.js → cynefin-OW5HDTMX-BzhRorj4.js} +1 -1
  119. package/dashboard/assets/{cynefinDiagram-5FMLGOSQ-CoQ7QEPl.js → cynefinDiagram-5FMLGOSQ-JXzRmldX.js} +1 -1
  120. package/dashboard/assets/{dagre-GXQ25YYZ-qtQtsg6c.js → dagre-GXQ25YYZ-1LZ-X0-Z.js} +1 -1
  121. package/dashboard/assets/{diagram-S7CK7UJ4-B_ts4_58.js → diagram-S7CK7UJ4-C_-J_LQ4.js} +1 -1
  122. package/dashboard/assets/{diagram-UQ7AKVKN-DwHbbxFy.js → diagram-UQ7AKVKN-CnxL1k8g.js} +1 -1
  123. package/dashboard/assets/{diagram-VSXAHHWV-2Tg_RG89.js → diagram-VSXAHHWV-WzSb3aby.js} +1 -1
  124. package/dashboard/assets/{diagram-VX7I27RA-BFYp-YjF.js → diagram-VX7I27RA-DKhrMInE.js} +1 -1
  125. package/dashboard/assets/{diagram-Z3DM3KII-DrPiS4V0.js → diagram-Z3DM3KII-CDhI2WGP.js} +1 -1
  126. package/dashboard/assets/{dist-cbVssBvx.js → dist-B0bfBMeP.js} +1 -1
  127. package/dashboard/assets/{ebnfDiagram-PWID7BFC-DCMOZtU2.js → ebnfDiagram-PWID7BFC-iL5NQ1PE.js} +1 -1
  128. package/dashboard/assets/{erDiagram-RLTQ6QDP-CW4rUJGU.js → erDiagram-RLTQ6QDP-RK2Voa5O.js} +1 -1
  129. package/dashboard/assets/{eventmodeling-NTZA5JFV-C2q-Aaav.js → eventmodeling-NTZA5JFV-WgE7OJBb.js} +1 -1
  130. package/dashboard/assets/flowDiagram-HODETNUW-B9YcQ0Aq.js +1 -0
  131. package/dashboard/assets/{ganttDiagram-EL5Y4UJY-C1AqcwIF.js → ganttDiagram-EL5Y4UJY-D8CJXHRF.js} +1 -1
  132. package/dashboard/assets/{gitGraph-4MIJSDKK-DYR76gtd.js → gitGraph-4MIJSDKK-BuZ9Lg04.js} +1 -1
  133. package/dashboard/assets/{gitGraphDiagram-WWUBYQGX-B7hL98CE.js → gitGraphDiagram-WWUBYQGX-LEJMh54j.js} +1 -1
  134. package/dashboard/assets/{info-A6RAGUB7-TXB43LiH.js → info-A6RAGUB7-BL5k3pev.js} +1 -1
  135. package/dashboard/assets/{infoDiagram-27XIBGKW-Dk5dXmh_.js → infoDiagram-27XIBGKW-LJvntUnZ.js} +1 -1
  136. package/dashboard/assets/{ishikawaDiagram-5VMMS53U-BQDuNMka.js → ishikawaDiagram-5VMMS53U-BYTYgKCG.js} +1 -1
  137. package/dashboard/assets/{journeyDiagram-3NMN7TZE-DkustddD.js → journeyDiagram-3NMN7TZE-G25qgQgO.js} +1 -1
  138. package/dashboard/assets/{kanban-definition-UXKFOSKX-BW7Ann84.js → kanban-definition-UXKFOSKX-Bk3uLl1i.js} +1 -1
  139. package/dashboard/assets/{line-DVxcLeru.js → line-i4qHBaWO.js} +1 -1
  140. package/dashboard/assets/{linear-DOM_l9bO.js → linear-DmrqRsKG.js} +1 -1
  141. package/dashboard/assets/{mermaid-parser.core-CKg9fDvJ.js → mermaid-parser.core-BxbKr4QF.js} +3 -3
  142. package/dashboard/assets/{mermaid.core-DruW_5-Y.js → mermaid.core-Cltee6FS.js} +4 -4
  143. package/dashboard/assets/{mindmap-definition-YA3MSWOX-Di5W5VB3.js → mindmap-definition-YA3MSWOX-DkzO2JgS.js} +1 -1
  144. package/dashboard/assets/operations-B4_timQX.css +1 -0
  145. package/dashboard/assets/operations-DwppJviL.js +199 -0
  146. package/dashboard/assets/{packet-AYTQ26CC-BABwqtNu.js → packet-AYTQ26CC-uZQUKnrE.js} +1 -1
  147. package/dashboard/assets/{pegDiagram-XKGWAZYB-Cx4ABT6q.js → pegDiagram-XKGWAZYB-CrOEi00T.js} +1 -1
  148. package/dashboard/assets/{pie-WAS4IAKB-CNdXyrze.js → pie-WAS4IAKB-Dn9_tpQT.js} +1 -1
  149. package/dashboard/assets/{pieDiagram-E7YTZNPT-BilfQbIs.js → pieDiagram-E7YTZNPT-D-niUkzc.js} +1 -1
  150. package/dashboard/assets/{quadrantDiagram-AXDQQJYC-BVmMQHE5.js → quadrantDiagram-AXDQQJYC-CJOTiG5V.js} +1 -1
  151. package/dashboard/assets/{radar-RG4KPBEZ-fKNmDeoK.js → radar-RG4KPBEZ-DIIVz4e8.js} +1 -1
  152. package/dashboard/assets/{railroad-74A4TZTK-DhcvDCOh.js → railroad-74A4TZTK-1kiqDEID.js} +1 -1
  153. package/dashboard/assets/{railroad-abnf-HS5TGJTU-BTRVAmf0.js → railroad-abnf-HS5TGJTU-DK6rQPZR.js} +1 -1
  154. package/dashboard/assets/{railroad-ebnf-LZEXJU2U-CwS8fgC_.js → railroad-ebnf-LZEXJU2U-C6cOgYW4.js} +1 -1
  155. package/dashboard/assets/{railroad-peg-WCYAUIDC-CXuhXlNp.js → railroad-peg-WCYAUIDC-CQ3ptKef.js} +1 -1
  156. package/dashboard/assets/{railroadDiagram-O6MQD6OU-DnBru-jf.js → railroadDiagram-O6MQD6OU-nEfkpa-m.js} +1 -1
  157. package/dashboard/assets/{requirementDiagram-BXWQKSXE-FwdvUZ7_.js → requirementDiagram-BXWQKSXE-CdFMY8tG.js} +1 -1
  158. package/dashboard/assets/{sankeyDiagram-P5KCCOFB-BQvDORai.js → sankeyDiagram-P5KCCOFB-C0KxrFYv.js} +1 -1
  159. package/dashboard/assets/{sequenceDiagram-WJ2MYXX4-FWYQLzcY.js → sequenceDiagram-WJ2MYXX4-DeZ5ATiu.js} +1 -1
  160. package/dashboard/assets/{src-BwkPhlcp.js → src-Cg-chcoE.js} +1 -1
  161. package/dashboard/assets/{stateDiagram-D77RDMKH-CjPBd_Sa.js → stateDiagram-D77RDMKH-B9MwWL5B.js} +1 -1
  162. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-SucFndhx.js +1 -0
  163. package/dashboard/assets/{swimlanes-42K2YHIH-SQLNsa4J.js → swimlanes-42K2YHIH-DB--fwQE.js} +1 -1
  164. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-BzH-rIaK.js +8 -0
  165. package/dashboard/assets/{timeline-definition-24CTP7MA-BxCf20k1.js → timeline-definition-24CTP7MA-DLkkTbWb.js} +1 -1
  166. package/dashboard/assets/{treeView-Q6P3EWNA-BGLYAyGp.js → treeView-Q6P3EWNA-XkZ9rl9H.js} +1 -1
  167. package/dashboard/assets/{treemap-WGGIJYW6-BlzAwncU.js → treemap-WGGIJYW6-JCtVKxCE.js} +1 -1
  168. package/dashboard/assets/{vennDiagram-4TSXK5OY-D76RIZLz.js → vennDiagram-4TSXK5OY-DEb-x29Z.js} +1 -1
  169. package/dashboard/assets/{wardley-WFR3VGLG-Ba_reiVw.js → wardley-WFR3VGLG-DhI7ROY3.js} +1 -1
  170. package/dashboard/assets/{wardleyDiagram-VM6X3IG4-Cux4coOD.js → wardleyDiagram-VM6X3IG4-KNckudc5.js} +1 -1
  171. package/dashboard/assets/{xychartDiagram-S5SC5T6Z-Ch5mvnlH.js → xychartDiagram-S5SC5T6Z-D4c0ynCk.js} +1 -1
  172. package/dashboard/index.html +13 -2
  173. package/package.json +1 -1
  174. package/worker-assets/demo-target/README.md +7 -3
  175. package/chunks/chunk-AL32F74R.js +0 -1123
  176. package/chunks/dashboard-MN7GZLLX.js +0 -75
  177. package/chunks/managed-operation-642WPTLC.js +0 -59
  178. package/chunks/routing-ITJZBJIU.js +0 -61
  179. package/chunks/service-plugins-CN6Q2NSN.js +0 -63
  180. package/dashboard/assets/channel-BBlDqIBl.js +0 -1
  181. package/dashboard/assets/classDiagram-ZZMXUADV-CRH2kB8G.js +0 -1
  182. package/dashboard/assets/classDiagram-v2-VYDZK3BY-CRH2kB8G.js +0 -1
  183. package/dashboard/assets/flowDiagram-HODETNUW-3NOabgG3.js +0 -1
  184. package/dashboard/assets/operations-B-t_k60U.js +0 -194
  185. package/dashboard/assets/operations-D2ZKZFOF.css +0 -1
  186. package/dashboard/assets/stateDiagram-v2-MP3YSRHH-DHmenujm.js +0 -1
  187. package/dashboard/assets/swimlanesDiagram-VR7AAH4N-D1bH4ETZ.js +0 -8
@@ -3,11 +3,11 @@ import { createRequire as __0CreateRequire } from "node:module";
3
3
  const require = __0CreateRequire(import.meta.url);
4
4
  import {
5
5
  getRuntimeAvailability
6
- } from "./chunk-ITHDAIRY.js";
6
+ } from "./chunk-MNK373HF.js";
7
7
  import {
8
8
  ServicePluginServices,
9
9
  consoleExecutionProfile
10
- } from "./chunk-7TIWL6E5.js";
10
+ } from "./chunk-KCABBZHN.js";
11
11
  import {
12
12
  accountEnvPatch,
13
13
  addAccount,
@@ -29,7 +29,7 @@ import {
29
29
  setActiveAccount,
30
30
  updateSetting,
31
31
  validateConnectionConfig
32
- } from "./chunk-RBTJYREN.js";
32
+ } from "./chunk-OILVEROI.js";
33
33
  import {
34
34
  DEFAULT_SETTINGS,
35
35
  PROVIDERS,
@@ -48,26 +48,26 @@ import {
48
48
  syncThemeChoices,
49
49
  validateTheme,
50
50
  writeInstalledTheme
51
- } from "./chunk-6TA3CWND.js";
51
+ } from "./chunk-V2KJQVYE.js";
52
52
  import {
53
53
  DEFAULT_REGISTRY_URL,
54
54
  createConsoleRuntime,
55
55
  listProjectReviewChecks,
56
56
  updateProjectReviewChecks
57
- } from "./chunk-EEP6GBUO.js";
57
+ } from "./chunk-3MWQNNJU.js";
58
58
  import {
59
59
  getRuntimeMetadata
60
- } from "./chunk-D4IBEO2K.js";
60
+ } from "./chunk-VWE36MUN.js";
61
61
  import {
62
62
  TOOL_DEFINITIONS,
63
63
  getToolsForRole
64
- } from "./chunk-HFUOUT2B.js";
64
+ } from "./chunk-SIR7XW2S.js";
65
65
  import {
66
66
  CodexCatalogRefreshError
67
- } from "./chunk-GXSECFUE.js";
67
+ } from "./chunk-PAMJEXE2.js";
68
68
  import {
69
69
  LlmApiRuntime
70
- } from "./chunk-EIONVEFN.js";
70
+ } from "./chunk-HS2NQ7K6.js";
71
71
  import {
72
72
  aggregateCapabilities,
73
73
  disable,
@@ -77,7 +77,7 @@ import {
77
77
  readEnablement,
78
78
  readInstalledPlugin,
79
79
  writeEnablement
80
- } from "./chunk-27SXCYWH.js";
80
+ } from "./chunk-RZZ6VPRY.js";
81
81
  import {
82
82
  MODEL_PRICING,
83
83
  VERSION,
@@ -85,15 +85,1097 @@ import {
85
85
  homeStateDir,
86
86
  modelProvider,
87
87
  registerModelPricing
88
- } from "./chunk-S3B6HFSM.js";
88
+ } from "./chunk-GYEYTNHK.js";
89
89
 
90
90
  // packages/cli/src/web/operator-services.ts
91
91
  import { execFileSync } from "node:child_process";
92
92
  import { realpathSync, statSync } from "node:fs";
93
- import { basename, resolve } from "node:path";
94
- import { randomUUID as randomUUID2 } from "node:crypto";
93
+ import { basename, resolve as resolve3 } from "node:path";
94
+ import { randomUUID as randomUUID3 } from "node:crypto";
95
+
96
+ // packages/cli/src/tui/chatgpt-plan-store.ts
97
+ import { randomUUID } from "node:crypto";
98
+ import { closeSync, existsSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
99
+ import { join } from "node:path";
100
+
101
+ // packages/cli/src/tui/chatgpt-plan-auth.ts
102
+ import { createHash, randomBytes } from "node:crypto";
103
+ import { createServer } from "node:http";
104
+
105
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/lib/buffer_utils.js
106
+ var encoder = new TextEncoder();
107
+ var decoder = new TextDecoder();
108
+ var strictDecoder = new TextDecoder("utf-8", { fatal: true });
109
+ var MAX_INT32 = 2 ** 32;
110
+ function concat(...buffers) {
111
+ const size = buffers.reduce((acc, { length }) => acc + length, 0), buf = new Uint8Array(size);
112
+ let i = 0;
113
+ for (const buffer of buffers)
114
+ buf.set(buffer, i), i += buffer.length;
115
+ return buf;
116
+ }
117
+ var NON_ASCII = /[^\x00-\x7f]/;
118
+ function encode(string) {
119
+ if (typeof string == "string" && string.length >= 128) {
120
+ if (NON_ASCII.test(string))
121
+ throw new TypeError("non-ASCII string encountered in encode()");
122
+ return encoder.encode(string);
123
+ }
124
+ const bytes = new Uint8Array(string.length);
125
+ for (let i = 0; i < string.length; i++) {
126
+ const code = string.charCodeAt(i);
127
+ if (code > 127)
128
+ throw new TypeError("non-ASCII string encountered in encode()");
129
+ bytes[i] = code;
130
+ }
131
+ return bytes;
132
+ }
133
+ function decodeBase64(encoded, url = false) {
134
+ if (Uint8Array.fromBase64)
135
+ return Uint8Array.fromBase64(encoded, { alphabet: url ? "base64url" : "base64" });
136
+ if (url) {
137
+ if (encoded.includes("+") || encoded.includes("/"))
138
+ throw new TypeError("Invalid base64url");
139
+ encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
140
+ }
141
+ const binary = atob(encoded), bytes = new Uint8Array(binary.length);
142
+ for (let i = 0; i < binary.length; i++)
143
+ bytes[i] = binary.charCodeAt(i);
144
+ return bytes;
145
+ }
146
+
147
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/util/errors.js
148
+ var JOSEError = class extends Error {
149
+ static code = "ERR_JOSE_GENERIC";
150
+ code = "ERR_JOSE_GENERIC";
151
+ constructor(message2, options) {
152
+ super(message2, options), this.name = this.constructor.name, Error.captureStackTrace?.(this, this.constructor);
153
+ }
154
+ };
155
+ var JWTClaimValidationFailed = class extends JOSEError {
156
+ static code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
157
+ code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
158
+ claim;
159
+ reason;
160
+ payload;
161
+ constructor(message2, payload, claim = "unspecified", reason = "unspecified") {
162
+ super(message2, { cause: { claim, reason, payload } }), this.claim = claim, this.reason = reason, this.payload = payload;
163
+ }
164
+ };
165
+ var JWTExpired = class extends JOSEError {
166
+ static code = "ERR_JWT_EXPIRED";
167
+ code = "ERR_JWT_EXPIRED";
168
+ claim;
169
+ reason;
170
+ payload;
171
+ constructor(message2, payload, claim = "unspecified", reason = "unspecified") {
172
+ super(message2, { cause: { claim, reason, payload } }), this.claim = claim, this.reason = reason, this.payload = payload;
173
+ }
174
+ };
175
+ var JOSEAlgNotAllowed = class extends JOSEError {
176
+ static code = "ERR_JOSE_ALG_NOT_ALLOWED";
177
+ code = "ERR_JOSE_ALG_NOT_ALLOWED";
178
+ };
179
+ var JOSENotSupported = class extends JOSEError {
180
+ static code = "ERR_JOSE_NOT_SUPPORTED";
181
+ code = "ERR_JOSE_NOT_SUPPORTED";
182
+ };
183
+ var JWSInvalid = class extends JOSEError {
184
+ static code = "ERR_JWS_INVALID";
185
+ code = "ERR_JWS_INVALID";
186
+ };
187
+ var JWTInvalid = class extends JOSEError {
188
+ static code = "ERR_JWT_INVALID";
189
+ code = "ERR_JWT_INVALID";
190
+ };
191
+ var JWKSInvalid = class extends JOSEError {
192
+ static code = "ERR_JWKS_INVALID";
193
+ code = "ERR_JWKS_INVALID";
194
+ };
195
+ var JWKSNoMatchingKey = class extends JOSEError {
196
+ static code = "ERR_JWKS_NO_MATCHING_KEY";
197
+ code = "ERR_JWKS_NO_MATCHING_KEY";
198
+ constructor(message2 = "no applicable key found in the JSON Web Key Set", options) {
199
+ super(message2, options);
200
+ }
201
+ };
202
+ var JWKSMultipleMatchingKeys = class extends JOSEError {
203
+ [Symbol.asyncIterator] = async function* () {
204
+ };
205
+ static code = "ERR_JWKS_MULTIPLE_MATCHING_KEYS";
206
+ code = "ERR_JWKS_MULTIPLE_MATCHING_KEYS";
207
+ constructor(message2 = "multiple matching keys found in the JSON Web Key Set", options) {
208
+ super(message2, options);
209
+ }
210
+ };
211
+ var JWKSTimeout = class extends JOSEError {
212
+ static code = "ERR_JWKS_TIMEOUT";
213
+ code = "ERR_JWKS_TIMEOUT";
214
+ constructor(message2 = "request timed out", options) {
215
+ super(message2, options);
216
+ }
217
+ };
218
+ var JWSSignatureVerificationFailed = class extends JOSEError {
219
+ static code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
220
+ code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
221
+ constructor(message2 = "signature verification failed", options) {
222
+ super(message2, options);
223
+ }
224
+ };
225
+
226
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/util/base64url.js
227
+ var invalid = "The input to be decoded is not correctly encoded.";
228
+ function decode(input) {
229
+ try {
230
+ return decodeBase64(typeof input == "string" ? input : decoder.decode(input), true);
231
+ } catch (cause) {
232
+ throw new TypeError(invalid, { cause });
233
+ }
234
+ }
235
+
236
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/lib/validate.js
237
+ function isObject(input) {
238
+ if (typeof input != "object" || input === null || Object.prototype.toString.call(input) !== "[object Object]")
239
+ return false;
240
+ const prototype = Object.getPrototypeOf(input);
241
+ return prototype === null || Object.getPrototypeOf(prototype) === null;
242
+ }
243
+ function isJwkSet(input) {
244
+ return isObject(input) && Array.isArray(input.keys) && Array.from(input.keys).every(isObject);
245
+ }
246
+ function isDisjoint(...headers) {
247
+ const parameters = /* @__PURE__ */ new Set();
248
+ for (const header of headers)
249
+ if (header)
250
+ for (const parameter of Object.keys(header)) {
251
+ if (parameters.has(parameter))
252
+ return false;
253
+ parameters.add(parameter);
254
+ }
255
+ return true;
256
+ }
257
+ function decodeBase64url(value, label, ErrorClass) {
258
+ try {
259
+ return decode(value);
260
+ } catch {
261
+ throw new ErrorClass(`Failed to base64url decode the ${label}`);
262
+ }
263
+ }
264
+ function encodeBase64url(value, label, ErrorClass) {
265
+ try {
266
+ return encode(value);
267
+ } catch {
268
+ throw new ErrorClass(`The ${label} is not a valid base64url string`);
269
+ }
270
+ }
271
+ function parseJoseHeader(b64, ErrorClass, message2) {
272
+ let parsed;
273
+ try {
274
+ parsed = JSON.parse(strictDecoder.decode(decode(b64)));
275
+ } catch {
276
+ throw new ErrorClass(message2);
277
+ }
278
+ if (!isObject(parsed))
279
+ throw new ErrorClass(message2);
280
+ return parsed;
281
+ }
282
+ var JWS_RECOGNIZED = { __proto__: null, b64: true };
283
+ function validateAlgorithms(option, algorithms) {
284
+ if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s != "string")))
285
+ throw new TypeError(`"${option}" option must be an array of strings`);
286
+ return algorithms === void 0 ? void 0 : new Set(algorithms);
287
+ }
288
+ function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
289
+ if (joseHeader.crit !== void 0 && protectedHeader?.crit === void 0)
290
+ throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
291
+ if (!protectedHeader || protectedHeader.crit === void 0)
292
+ return [];
293
+ if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input != "string" || input.length === 0))
294
+ throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
295
+ const recognized = recognizedOption === void 0 ? recognizedDefault : { __proto__: null, ...recognizedOption, ...recognizedDefault };
296
+ for (const parameter of protectedHeader.crit) {
297
+ if (!(parameter in recognized))
298
+ throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
299
+ if (!Object.hasOwn(joseHeader, parameter) || joseHeader[parameter] === void 0)
300
+ throw new Err(`Extension Header Parameter "${parameter}" is missing`);
301
+ if (recognized[parameter] && (!Object.hasOwn(protectedHeader, parameter) || protectedHeader[parameter] === void 0))
302
+ throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
303
+ }
304
+ return protectedHeader.crit;
305
+ }
306
+ function validateB64(protectedHeader, extensions) {
307
+ if (extensions.includes("b64")) {
308
+ const b64 = protectedHeader.b64;
309
+ if (typeof b64 != "boolean")
310
+ throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
311
+ return b64;
312
+ }
313
+ return true;
314
+ }
315
+
316
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/lib/key.js
317
+ var tag = (key) => key[Symbol.toStringTag];
318
+ var jwkMatchesOp = (entry, key, usage) => {
319
+ const { alg } = entry;
320
+ if (key.use !== void 0) {
321
+ const expected = usage === "sign" || usage === "verify" ? "sig" : "enc";
322
+ if (key.use !== expected)
323
+ throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
324
+ }
325
+ if (key.alg !== void 0 && key.alg !== alg)
326
+ throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
327
+ if (Array.isArray(key.key_ops)) {
328
+ const expectedKeyOp = usage === "encrypt" || usage === "decrypt" ? entry.ops?.[usage === "encrypt" ? 0 : 1] : usage;
329
+ if (expectedKeyOp && !key.key_ops.includes(expectedKeyOp))
330
+ throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
331
+ }
332
+ };
333
+ async function prepareKey(entry, key, usage) {
334
+ const { alg, secret } = entry, privateKey = usage === "decrypt" || usage === "sign";
335
+ if (secret && key instanceof Uint8Array)
336
+ return key;
337
+ let normalized, keyObject;
338
+ if (isObject(key)) {
339
+ if (normalized = normalizeJwk(key), typeof normalized.kty != "string")
340
+ throw invalidKeyType(alg, key, secret);
341
+ if (!(secret ? normalized.kty === "oct" && typeof normalized.k == "string" : normalized.kty !== "oct" && (privateKey ? normalized.kty === "AKP" && typeof normalized.priv == "string" || typeof normalized.d == "string" : normalized.d === void 0 && normalized.priv === void 0)))
342
+ throw new TypeError(secret ? 'JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present' : `JSON Web Key for this operation must be a ${privateKey ? "private" : "public"} JWK`);
343
+ if (jwkMatchesOp(entry, normalized, usage), normalized.kty === "oct")
344
+ return decode(normalized.k);
345
+ if (!Object.isFrozen(key)) {
346
+ const { key_ops } = key;
347
+ Array.isArray(key_ops) && Object.freeze(key_ops), Object.freeze(key);
348
+ }
349
+ } else {
350
+ if (!isKeyLike(key))
351
+ throw invalidKeyType(alg, key, secret);
352
+ const expectedType = secret ? "secret" : privateKey ? "private" : "public";
353
+ if (key.type !== expectedType && (secret || ["secret", "public", "private"].includes(key.type)))
354
+ throw new TypeError(`${tag(key)} instances must be of type "${expectedType}" for the ${alg} algorithm`);
355
+ if (isCryptoKey(key))
356
+ return key;
357
+ if (keyObject = key, keyObject.type === "secret")
358
+ return keyObject.export();
359
+ }
360
+ cache ||= /* @__PURE__ */ new WeakMap();
361
+ const cacheKey = key;
362
+ let cached = cache.get(cacheKey);
363
+ if (cached?.[alg])
364
+ return cached[alg];
365
+ if (cached || cache.set(cacheKey, cached = {}), keyObject && typeof keyObject.toCryptoKey == "function") {
366
+ const isPublic = keyObject.type === "public", crv = nist[keyObject.asymmetricKeyDetails?.namedCurve], params = entry.resolve?.({ crv, asymmetricKeyType: keyObject.asymmetricKeyType }) ?? entry.subtle;
367
+ return cached[alg] = keyObject.toCryptoKey(params, isPublic, entry.usages[isPublic ? 0 : 1]);
368
+ }
369
+ return normalized ??= keyObject.export({ format: "jwk" }), normalized.alg = alg, cached[alg] = await jwkToKey(entry, normalized);
370
+ }
371
+ var cache;
372
+ var nist = {
373
+ __proto__: null,
374
+ prime256v1: "P-256",
375
+ secp384r1: "P-384",
376
+ secp521r1: "P-521"
377
+ };
378
+ var isCryptoKey = (key) => {
379
+ if (key?.[Symbol.toStringTag] === "CryptoKey")
380
+ return true;
381
+ try {
382
+ return key instanceof CryptoKey;
383
+ } catch {
384
+ return false;
385
+ }
386
+ };
387
+ var isKeyObject = (key) => key?.[Symbol.toStringTag] === "KeyObject";
388
+ var isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key);
389
+ function message(msg, actual, ...types) {
390
+ if (types.length > 2) {
391
+ const last = types.pop();
392
+ msg += `one of type ${types.join(", ")}, or ${last}.`;
393
+ } else types.length === 2 ? msg += `one of type ${types[0]} or ${types[1]}.` : msg += `of type ${types[0]}.`;
394
+ return actual == null ? msg += ` Received ${actual}` : typeof actual == "function" && actual.name ? msg += ` Received function ${actual.name}` : typeof actual == "object" && actual != null && actual.constructor?.name && (msg += ` Received an instance of ${actual.constructor.name}`), msg;
395
+ }
396
+ function invalidKeyType(alg, actual, secret) {
397
+ const types = ["CryptoKey", "KeyObject", "JSON Web Key"];
398
+ return secret && types.push("Uint8Array"), new TypeError(message(`Key for the ${alg} algorithm must be `, actual, ...types));
399
+ }
400
+ var unusable = (name, prop = "algorithm.name") => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
401
+ function checkUsage(key, usage) {
402
+ if (usage && !key.usages.includes(usage))
403
+ throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
404
+ }
405
+ function checkModulusLength(alg, key) {
406
+ const { modulusLength } = key.algorithm;
407
+ if (typeof modulusLength != "number" || modulusLength < 2048)
408
+ throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
409
+ }
410
+ function checkCryptoKey(key, expected, usage) {
411
+ const algorithm = key.algorithm;
412
+ if (algorithm.name !== expected.name)
413
+ throw unusable(expected.name);
414
+ if (expected.hash && algorithm.hash?.name !== expected.hash)
415
+ throw unusable(expected.hash, "algorithm.hash");
416
+ if (expected.namedCurve && algorithm.namedCurve !== expected.namedCurve)
417
+ throw unusable(expected.namedCurve, "algorithm.namedCurve");
418
+ if (expected.length !== void 0 && algorithm.length !== expected.length)
419
+ throw unusable(expected.length, "algorithm.length");
420
+ checkUsage(key, usage);
421
+ }
422
+ function snapshotJwk(jwk) {
423
+ return { __proto__: null, ...jwk };
424
+ }
425
+ function normalizeJwk(jwk) {
426
+ const normalized = snapshotJwk(jwk);
427
+ if (normalized.ext !== void 0 && typeof normalized.ext != "boolean")
428
+ throw new TypeError('"ext" (Extractable) Parameter must be a boolean');
429
+ if (normalized.key_ops !== void 0) {
430
+ const value = normalized.key_ops, keyOps = Array.isArray(value) ? [...value] : void 0;
431
+ if (!keyOps || keyOps.some((operation) => typeof operation != "string") || new Set(keyOps).size !== keyOps.length)
432
+ throw new TypeError('"key_ops" (Key Operations) Parameter must be an array of unique strings');
433
+ normalized.key_ops = keyOps;
434
+ }
435
+ return normalized;
436
+ }
437
+ async function jwkToKey(entry, jwk, extractable) {
438
+ if (!entry.kty.includes(jwk.kty))
439
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
440
+ const algorithm = entry.resolve?.({ kty: jwk.kty, crv: jwk.crv }) ?? entry.subtle, isPrivate = !!(jwk.d || jwk.priv), keyData = { ...jwk, ext: extractable ?? jwk.ext };
441
+ return keyData.kty !== "AKP" && delete keyData.alg, delete keyData.use, crypto.subtle.importKey("jwk", keyData, algorithm, keyData.ext ?? !isPrivate, jwk.key_ops ?? entry.usages[isPrivate ? 1 : 0]);
442
+ }
443
+ async function rawKey(key, expected, usage, extractable = false) {
444
+ return key instanceof Uint8Array && (key = await crypto.subtle.importKey("raw", key, expected, extractable, [usage])), checkCryptoKey(key, expected, usage), key;
445
+ }
446
+
447
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/lib/key_descriptor.js
448
+ function table(entries) {
449
+ const out = { __proto__: null };
450
+ for (const alg in entries)
451
+ out[alg] = { ...entries[alg], alg };
452
+ return out;
453
+ }
454
+
455
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/lib/jws_algorithms.js
456
+ var sig = [["verify"], ["sign"]];
457
+ function hmac(bits) {
458
+ const subtle = { name: "HMAC", hash: `SHA-${bits}` };
459
+ return { kty: ["oct"], secret: true, subtle, signing: subtle, usages: sig };
460
+ }
461
+ function rsa(bits, saltLength) {
462
+ const subtle = { name: saltLength ? "RSA-PSS" : "RSASSA-PKCS1-v1_5", hash: `SHA-${bits}` };
463
+ return {
464
+ kty: ["RSA"],
465
+ subtle,
466
+ signing: saltLength ? { ...subtle, saltLength } : subtle,
467
+ usages: sig,
468
+ minRsaBits: 2048
469
+ };
470
+ }
471
+ function ecdsa(crv, bits) {
472
+ return {
473
+ kty: ["EC"],
474
+ crv,
475
+ subtle: { name: "ECDSA", namedCurve: crv },
476
+ signing: { name: "ECDSA", hash: `SHA-${bits}` },
477
+ usages: sig
478
+ };
479
+ }
480
+ function eddsa() {
481
+ const subtle = { name: "Ed25519" };
482
+ return {
483
+ kty: ["OKP"],
484
+ crv: "Ed25519",
485
+ subtle,
486
+ signing: subtle,
487
+ usages: sig
488
+ };
489
+ }
490
+ function mldsa(bits) {
491
+ const subtle = { name: `ML-DSA-${bits}` };
492
+ return {
493
+ kty: ["AKP"],
494
+ subtle,
495
+ signing: subtle,
496
+ usages: sig
497
+ };
498
+ }
499
+ var JWS = table({
500
+ HS256: hmac(256),
501
+ HS384: hmac(384),
502
+ HS512: hmac(512),
503
+ RS256: rsa(256),
504
+ RS384: rsa(384),
505
+ RS512: rsa(512),
506
+ PS256: rsa(256, 32),
507
+ PS384: rsa(384, 48),
508
+ PS512: rsa(512, 64),
509
+ ES256: ecdsa("P-256", 256),
510
+ ES384: ecdsa("P-384", 384),
511
+ ES512: ecdsa("P-521", 512),
512
+ EdDSA: eddsa(),
513
+ Ed25519: eddsa(),
514
+ "ML-DSA-44": mldsa(44),
515
+ "ML-DSA-65": mldsa(65),
516
+ "ML-DSA-87": mldsa(87)
517
+ });
518
+ function jwsAlgorithm(alg) {
519
+ const entry = typeof alg == "string" ? JWS[alg] : void 0;
520
+ if (!entry)
521
+ throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
522
+ return entry;
523
+ }
524
+
525
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/lib/jws_verify.js
526
+ function prepareVerify(options) {
527
+ return [options && validateAlgorithms("algorithms", options.algorithms), options?.crit];
528
+ }
529
+ function parseProtectedHeader(encodedProtected) {
530
+ return encodedProtected === void 0 ? {} : parseJoseHeader(encodedProtected, JWSInvalid, "JWS Protected Header is invalid");
531
+ }
532
+ function encodeCompactUnencodedPayload(payload) {
533
+ try {
534
+ return encode(payload);
535
+ } catch {
536
+ throw new JWSInvalid("JWS Compact Serialization payload must use only ASCII characters");
537
+ }
538
+ }
539
+ async function verifySignature(jws, shared, key, encodeUnencodedPayload, parsedProtected) {
540
+ const { protected: encodedProtected, header, payload: inputPayload } = jws, parsedProt = parsedProtected ?? parseProtectedHeader(encodedProtected);
541
+ if (!isDisjoint(parsedProt, header))
542
+ throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
543
+ const joseHeader = { ...parsedProt, ...header }, b64 = validateB64(parsedProt, validateCrit(JWSInvalid, JWS_RECOGNIZED, shared[1], parsedProt, joseHeader)), { alg } = joseHeader;
544
+ if (typeof alg != "string" || !alg)
545
+ throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
546
+ if (shared[0] && !shared[0].has(alg))
547
+ throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed');
548
+ if (b64) {
549
+ if (typeof inputPayload != "string")
550
+ throw new JWSInvalid("JWS Payload must be a string");
551
+ } else if (typeof inputPayload != "string" && !(inputPayload instanceof Uint8Array))
552
+ throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance");
553
+ const signingPayload = b64 || typeof inputPayload != "string" ? inputPayload : encodeUnencodedPayload(inputPayload);
554
+ let resolvedKey = false;
555
+ typeof key == "function" && (key = await key(parsedProt, jws), resolvedKey = true);
556
+ const entry = jwsAlgorithm(alg), data = concat(encodedProtected !== void 0 ? encode(encodedProtected) : new Uint8Array(), encode("."), typeof signingPayload == "string" ? shared[2] ??= encodeBase64url(signingPayload, "payload", JWSInvalid) : signingPayload), signature = decodeBase64url(jws.signature, "signature", JWSInvalid), k = await prepareKey(entry, key, "verify"), cryptoKey = await rawKey(k, entry.subtle, "verify");
557
+ entry.minRsaBits && checkModulusLength(entry.alg, cryptoKey);
558
+ let verified = false;
559
+ try {
560
+ verified = await crypto.subtle.verify(entry.signing, cryptoKey, signature, data);
561
+ } catch {
562
+ }
563
+ if (!verified)
564
+ throw new JWSSignatureVerificationFailed();
565
+ const result = { payload: typeof signingPayload == "string" ? decodeBase64url(signingPayload, "payload", JWSInvalid) : signingPayload };
566
+ return encodedProtected !== void 0 && (result.protectedHeader = parsedProt), header !== void 0 && (result.unprotectedHeader = header), resolvedKey ? [{ ...result, key: k }, b64] : [result, b64];
567
+ }
568
+ async function verifyCompact(jws, shared, key) {
569
+ if (jws instanceof Uint8Array && (jws = decoder.decode(jws)), typeof jws != "string")
570
+ throw new JWSInvalid("Compact JWS must be a string or Uint8Array");
571
+ const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split(".");
572
+ if (length !== 3)
573
+ throw new JWSInvalid("Invalid Compact JWS");
574
+ return verifySignature({ payload, protected: protectedHeader, signature }, shared, key, encodeCompactUnencodedPayload);
575
+ }
576
+
577
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/lib/jwt_claims_set.js
578
+ var epoch = (date) => Math.floor(date.getTime() / 1e3);
579
+ var multipliers = {
580
+ s: 1,
581
+ m: 60,
582
+ h: 3600,
583
+ d: 86400,
584
+ w: 604800,
585
+ y: 31557600
586
+ };
587
+ var REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;
588
+ var checkFailed = "check_failed";
589
+ function invalidDuration() {
590
+ throw new TypeError("Invalid time period format");
591
+ }
592
+ function secs(str) {
593
+ typeof str != "string" && invalidDuration();
594
+ const matched = REGEX.exec(str);
595
+ (!matched || matched[4] && matched[1]) && invalidDuration();
596
+ const value = parseFloat(matched[2]), numericDate2 = Math.round(value * multipliers[matched[3][0].toLowerCase()]);
597
+ return Number.isFinite(numericDate2) || invalidDuration(), matched[1] === "-" || matched[4] === "ago" ? -numericDate2 : numericDate2;
598
+ }
599
+ function validateInput(label, input) {
600
+ if (!Number.isFinite(input))
601
+ throw new TypeError(`Invalid ${label} input`);
602
+ return input;
603
+ }
604
+ var normalizeTyp = (value) => {
605
+ const normalized = value.toLowerCase();
606
+ return value.includes("/") ? normalized : `application/${normalized}`;
607
+ };
608
+ var checkAudiencePresence = (audPayload, audOption) => typeof audPayload == "string" ? audOption.includes(audPayload) : Array.isArray(audPayload) ? audOption.some((aud) => audPayload.includes(aud)) : false;
609
+ function validateNumericDate(payload, claim, required = false) {
610
+ const value = payload[claim];
611
+ if (!(value === void 0 && !required)) {
612
+ if (typeof value != "number")
613
+ throw new JWTClaimValidationFailed(`"${claim}" claim must be a number`, payload, claim, "invalid");
614
+ return value;
615
+ }
616
+ }
617
+ function unexpectedClaim(payload, claim) {
618
+ throw new JWTClaimValidationFailed(`unexpected "${claim}" claim value`, payload, claim, checkFailed);
619
+ }
620
+ function validateClaimsSet(protectedHeader, encodedPayload, options = {}) {
621
+ let payload;
622
+ try {
623
+ payload = JSON.parse(strictDecoder.decode(encodedPayload));
624
+ } catch {
625
+ }
626
+ if (!isObject(payload))
627
+ throw new JWTInvalid("JWT Claims Set must be a top-level JSON object");
628
+ const { typ } = options;
629
+ if (typ !== void 0 && (typeof protectedHeader.typ != "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ)))
630
+ throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', payload, "typ", checkFailed);
631
+ const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options, presenceCheck = [...requiredClaims];
632
+ maxTokenAge !== void 0 && presenceCheck.push("iat"), audience !== void 0 && presenceCheck.push("aud"), subject !== void 0 && presenceCheck.push("sub"), issuer !== void 0 && presenceCheck.push("iss");
633
+ for (const claim of new Set(presenceCheck.reverse()))
634
+ if (!Object.hasOwn(payload, claim))
635
+ throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, payload, claim, "missing");
636
+ issuer !== void 0 && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss) && unexpectedClaim(payload, "iss"), subject !== void 0 && payload.sub !== subject && unexpectedClaim(payload, "sub"), audience !== void 0 && !checkAudiencePresence(payload.aud, typeof audience == "string" ? [audience] : audience) && unexpectedClaim(payload, "aud");
637
+ const { clockTolerance } = options;
638
+ let tolerance = 0;
639
+ if (typeof clockTolerance == "string")
640
+ tolerance = secs(clockTolerance);
641
+ else if (clockTolerance !== void 0) {
642
+ if (typeof clockTolerance != "number")
643
+ throw new TypeError("Invalid clockTolerance option type");
644
+ tolerance = clockTolerance;
645
+ }
646
+ validateInput("clockTolerance option", tolerance);
647
+ const { currentDate } = options, now = validateInput("currentDate option", epoch(currentDate === void 0 ? /* @__PURE__ */ new Date() : currentDate)), iat = validateNumericDate(payload, "iat", maxTokenAge !== void 0), nbf = validateNumericDate(payload, "nbf");
648
+ if (nbf !== void 0 && nbf > now + tolerance)
649
+ throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', payload, "nbf", checkFailed);
650
+ const exp = validateNumericDate(payload, "exp");
651
+ if (exp !== void 0 && exp <= now - tolerance)
652
+ throw new JWTExpired('"exp" claim timestamp check failed', payload, "exp", checkFailed);
653
+ if (maxTokenAge !== void 0) {
654
+ const age = now - iat, max = validateInput("maxTokenAge option", typeof maxTokenAge == "number" ? maxTokenAge : secs(maxTokenAge));
655
+ if (age - tolerance > max)
656
+ throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', payload, "iat", checkFailed);
657
+ if (age < -tolerance)
658
+ throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', payload, "iat", checkFailed);
659
+ }
660
+ return payload;
661
+ }
662
+
663
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/jwt/verify.js
664
+ async function jwtVerify(jwt, key, options) {
665
+ const [verified, b64] = await verifyCompact(jwt, prepareVerify(options), key);
666
+ if (!b64)
667
+ throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
668
+ const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);
669
+ return { ...verified, payload };
670
+ }
671
+
672
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/jwks/local.js
673
+ function isUsableJWK(jwk, entry, alg, kid) {
674
+ const { kty, key_ops: keyOps, ext, kid: jwkKid, alg: jwkAlg, use, crv } = jwk;
675
+ return (ext === void 0 || typeof ext == "boolean") && (keyOps === void 0 || Array.isArray(keyOps) && keyOps.every((operation, index) => typeof operation == "string" && keyOps.indexOf(operation) === index) && keyOps.includes("verify")) && entry.kty.includes(kty) && (kid === void 0 || typeof kid == "string" && kid === jwkKid) && (jwkAlg === void 0 ? kty !== "AKP" : alg === jwkAlg) && (use === void 0 || use === "sig") && (!entry.crv || crv === entry.crv);
676
+ }
677
+ async function importWithAlgCache(cache2, jwk, entry) {
678
+ const cached = cache2.get(jwk) || cache2.set(jwk, {}).get(jwk), { alg } = entry;
679
+ if (cached[alg] === void 0) {
680
+ const pending = jwkToKey(entry, jwk, true).then((key) => {
681
+ if (key.type !== "public")
682
+ throw new JWKSInvalid("JSON Web Key Set members must be public keys");
683
+ return cached[alg] = key, key;
684
+ }).catch((error) => {
685
+ throw cached[alg] === pending && delete cached[alg], error;
686
+ });
687
+ cached[alg] = pending;
688
+ }
689
+ return cached[alg];
690
+ }
691
+ function createLocalJWKSet(jwks) {
692
+ let snapshot;
693
+ try {
694
+ snapshot = structuredClone(jwks);
695
+ } catch {
696
+ }
697
+ if (!isJwkSet(snapshot))
698
+ throw new JWKSInvalid("JSON Web Key Set malformed");
699
+ const metadata = snapshot.keys.map((jwk) => {
700
+ const normalized = snapshotJwk(jwk);
701
+ return Array.isArray(normalized.key_ops) && (normalized.key_ops = [...normalized.key_ops]), normalized;
702
+ }), cached = /* @__PURE__ */ new WeakMap();
703
+ return Object.defineProperty(async (protectedHeader, token) => {
704
+ const { alg, kid } = { ...protectedHeader, ...token?.header }, entry = typeof alg == "string" ? JWS[alg] : void 0;
705
+ if (!entry || entry.secret)
706
+ throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
707
+ const candidates = snapshot.keys.filter((_, index) => isUsableJWK(metadata[index], entry, alg, kid)), { 0: jwk, length } = candidates;
708
+ if (!length)
709
+ throw new JWKSNoMatchingKey();
710
+ if (length !== 1) {
711
+ const error = new JWKSMultipleMatchingKeys();
712
+ throw error[Symbol.asyncIterator] = async function* () {
713
+ for (const jwk2 of candidates)
714
+ try {
715
+ yield await importWithAlgCache(cached, jwk2, entry);
716
+ } catch {
717
+ }
718
+ }, error;
719
+ }
720
+ return importWithAlgCache(cached, jwk, entry);
721
+ }, "jwks", {
722
+ value: () => structuredClone(snapshot)
723
+ });
724
+ }
725
+
726
+ // node_modules/.pnpm/jose@6.2.12/node_modules/jose/dist/webapi/jwks/remote.js
727
+ function isCloudflareWorkers() {
728
+ return typeof WebSocketPair < "u" || typeof navigator < "u" && navigator.userAgent === "Cloudflare-Workers" || typeof EdgeRuntime < "u" && EdgeRuntime === "vercel";
729
+ }
730
+ var USER_AGENT;
731
+ (typeof navigator > "u" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) && (USER_AGENT = "jose/v6.2.12");
732
+ var customFetch = /* @__PURE__ */ Symbol();
733
+ async function fetchJwks(url, headers, signal, fetchImpl = fetch) {
734
+ const response = await fetchImpl(url, {
735
+ method: "GET",
736
+ signal,
737
+ redirect: "manual",
738
+ headers
739
+ }).catch((err) => {
740
+ throw err.name === "TimeoutError" ? new JWKSTimeout() : err;
741
+ });
742
+ if (response.status !== 200)
743
+ throw new JOSEError("Expected 200 OK from the JSON Web Key Set HTTP response");
744
+ try {
745
+ return await response.json();
746
+ } catch {
747
+ throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON");
748
+ }
749
+ }
750
+ var jwksCache = /* @__PURE__ */ Symbol();
751
+ function isFreshFor(timestamp, duration) {
752
+ return Number.isFinite(timestamp) && Date.now() < timestamp + duration;
753
+ }
754
+ function validateDuration(value, fallback, option) {
755
+ if (Number.isNaN(value))
756
+ throw new TypeError(`"${option}" option must not be NaN`);
757
+ return typeof value == "number" ? value : fallback;
758
+ }
759
+ function createRemoteJWKSet(url, options) {
760
+ if (!(url instanceof URL))
761
+ throw new TypeError("url must be an instance of URL");
762
+ const href = new URL(url.href).href, opts = options ?? {}, timeoutOption = opts.timeoutDuration;
763
+ if (typeof timeoutOption == "number" && (!Number.isInteger(timeoutOption) || timeoutOption < 0))
764
+ throw new TypeError('"timeoutDuration" option must be a non-negative integer');
765
+ const timeoutDuration = typeof timeoutOption == "number" ? timeoutOption : 5e3, cooldownDuration = validateDuration(opts.cooldownDuration, 3e4, "cooldownDuration"), cacheMaxAge = validateDuration(opts.cacheMaxAge, 6e5, "cacheMaxAge"), headers = new Headers(opts.headers);
766
+ USER_AGENT && !headers.has("User-Agent") && headers.set("User-Agent", USER_AGENT), headers.has("accept") || headers.set("accept", "application/json, application/jwk-set+json");
767
+ const fetchImpl = opts[customFetch], cache2 = opts[jwksCache];
768
+ let jwksTimestamp, pendingFetch, reloadSequence = 0, appliedSequence = 0, local;
769
+ if (cache2 && typeof cache2 == "object") {
770
+ const { uat, jwks } = cache2;
771
+ isFreshFor(uat, cacheMaxAge) && isJwkSet(jwks) && (jwksTimestamp = uat, local = createLocalJWKSet(jwks));
772
+ }
773
+ const reload = async () => {
774
+ if (pendingFetch && isCloudflareWorkers() && (pendingFetch = void 0), !pendingFetch) {
775
+ const sequence = ++reloadSequence, current = pendingFetch = fetchJwks(href, headers, AbortSignal.timeout(timeoutDuration), fetchImpl).then((json) => {
776
+ const next = createLocalJWKSet(json);
777
+ if (sequence <= appliedSequence)
778
+ return;
779
+ local = next;
780
+ const updatedAt = Date.now();
781
+ cache2 && (cache2.uat = updatedAt, cache2.jwks = json), jwksTimestamp = updatedAt, appliedSequence = sequence;
782
+ }).finally(() => {
783
+ pendingFetch === current && (pendingFetch = void 0);
784
+ });
785
+ }
786
+ await pendingFetch;
787
+ };
788
+ return Object.defineProperties(async (protectedHeader, token) => {
789
+ (!local || !isFreshFor(jwksTimestamp, cacheMaxAge)) && await reload();
790
+ try {
791
+ return await local(protectedHeader, token);
792
+ } catch (err) {
793
+ if (err instanceof JWKSNoMatchingKey && !isFreshFor(jwksTimestamp, cooldownDuration))
794
+ return await reload(), local(protectedHeader, token);
795
+ throw err;
796
+ }
797
+ }, {
798
+ coolingDown: {
799
+ get: () => isFreshFor(jwksTimestamp, cooldownDuration),
800
+ enumerable: true
801
+ },
802
+ fresh: {
803
+ get: () => isFreshFor(jwksTimestamp, cacheMaxAge),
804
+ enumerable: true
805
+ },
806
+ reload: {
807
+ value: reload,
808
+ enumerable: true
809
+ },
810
+ reloading: {
811
+ get: () => !!pendingFetch,
812
+ enumerable: true
813
+ },
814
+ jwks: {
815
+ value: () => local?.jwks(),
816
+ enumerable: true
817
+ }
818
+ });
819
+ }
820
+
821
+ // packages/cli/src/tui/chatgpt-plan-auth.ts
822
+ var SIWC_ISSUER = "https://auth.openai.com";
823
+ var SIWC_RESOURCE = "https://api.openai.com/v1";
824
+ var SIWC_SCOPES = ["openid", "profile", "email", "offline_access", "resource.invoke", "chatgpt.tokens.use.direct"];
825
+ var PATH = "/auth/callback";
826
+ var object = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
827
+ function credential(value) {
828
+ if (typeof value !== "string" || !value || value.length > 65536 || /[^\x21-\x7e]/.test(value)) throw new Error("The provider returned invalid authentication data.");
829
+ return value;
830
+ }
831
+ async function readSiwcJson(url, init, transport = {}) {
832
+ const signal = init.signal ? AbortSignal.any([init.signal, AbortSignal.timeout(3e4)]) : AbortSignal.timeout(3e4);
833
+ let response;
834
+ try {
835
+ response = await (transport.fetch ?? fetch)(url, { ...init, signal, redirect: "error" });
836
+ } catch {
837
+ throw new Error("ChatGPT sign-in could not reach its authentication service. Retry the connection.");
838
+ }
839
+ if (!response.ok) throw new Error(response.status === 400 || response.status === 401 ? "ChatGPT authentication was rejected. Sign in again." : `ChatGPT authentication is unavailable (HTTP ${response.status}).`);
840
+ const reader = response.body?.getReader();
841
+ if (!reader) throw new Error("ChatGPT returned an empty authentication response.");
842
+ let bytes = 0, raw = "";
843
+ const decoder2 = new TextDecoder("utf-8", { fatal: true });
844
+ try {
845
+ for (; ; ) {
846
+ const chunk = await reader.read();
847
+ if (chunk.done) break;
848
+ bytes += chunk.value.byteLength;
849
+ if (bytes > 1048576) throw new Error("ChatGPT authentication response exceeded its limit.");
850
+ raw += decoder2.decode(chunk.value, { stream: true });
851
+ }
852
+ raw += decoder2.decode();
853
+ try {
854
+ return JSON.parse(raw);
855
+ } catch {
856
+ throw new Error("ChatGPT returned an invalid authentication response.");
857
+ }
858
+ } finally {
859
+ await reader.cancel().catch(() => void 0);
860
+ reader.releaseLock();
861
+ }
862
+ }
863
+ function trustedEndpoint(value) {
864
+ if (typeof value !== "string") throw new Error("ChatGPT authentication configuration is incomplete.");
865
+ const url = new URL(value);
866
+ if (url.origin !== SIWC_ISSUER || url.username || url.password || url.hash || url.search) throw new Error("ChatGPT authentication configuration contains an untrusted endpoint.");
867
+ return url.href;
868
+ }
869
+ async function siwcMetadata(transport, signal) {
870
+ const data = object(await readSiwcJson(`${SIWC_ISSUER}/.well-known/openid-configuration`, { signal }, transport));
871
+ if (data.issuer !== SIWC_ISSUER) throw new Error("ChatGPT authentication issuer did not match.");
872
+ return { token: trustedEndpoint(data.token_endpoint), jwks: trustedEndpoint(data.jwks_uri), revoke: trustedEndpoint(data.revocation_endpoint) };
873
+ }
874
+ async function validateSiwcTokens(value, clientId, metadata, transport, signal, expected) {
875
+ const data = object(value), previous = expected?.previous;
876
+ const idToken = data.id_token === void 0 && previous ? previous.idToken : credential(data.id_token);
877
+ const now = transport.now?.() ?? Date.now();
878
+ let identity;
879
+ if (data.id_token === void 0 && previous && previous.clientId === clientId && previous.issuer === SIWC_ISSUER) {
880
+ identity = { sub: previous.subject, email: previous.email, iat: Math.floor(now / 1e3) };
881
+ } else {
882
+ const keys = object(await readSiwcJson(metadata.jwks, { signal }, transport));
883
+ if (!Array.isArray(keys.keys)) throw new Error("ChatGPT returned invalid signing keys.");
884
+ try {
885
+ identity = (await jwtVerify(idToken, createLocalJWKSet(keys), { issuer: SIWC_ISSUER, audience: clientId, algorithms: ["RS256", "ES256"], currentDate: new Date(now), requiredClaims: ["sub", "iat", "exp"] })).payload;
886
+ } catch {
887
+ throw new Error("ChatGPT identity verification failed. Sign in again.");
888
+ }
889
+ }
890
+ if (typeof identity.sub !== "string" || !identity.sub || typeof identity.iat !== "number" || identity.iat > now / 1e3 + 60 || expected?.nonce !== void 0 && identity.nonce !== expected.nonce || expected?.subject !== void 0 && identity.sub !== expected.subject || identity.azp !== void 0 && identity.azp !== clientId || Array.isArray(identity.aud) && identity.aud.length > 1 && identity.azp !== clientId) throw new Error("ChatGPT identity did not match this sign-in.");
891
+ const scopes = typeof data.scope === "string" ? [...new Set(data.scope.split(/\s+/).filter(Boolean))] : data.scope === void 0 ? expected?.scopes : void 0;
892
+ if (!scopes || !scopes.includes("openid")) throw new Error("ChatGPT did not return the granted identity permissions.");
893
+ const sharing = scopes.includes("chatgpt.tokens.use.direct");
894
+ const accessToken = data.access_token !== void 0 ? credential(data.access_token) : void 0;
895
+ const refreshToken = data.refresh_token !== void 0 ? credential(data.refresh_token) : previous?.refreshToken;
896
+ if (data.token_type !== "Bearer" || sharing && (!accessToken || !refreshToken || !scopes.includes("resource.invoke") || !scopes.includes("offline_access")) || typeof data.expires_in !== "number" || !Number.isFinite(data.expires_in) || data.expires_in <= 0 || data.expires_in > 86400) throw new Error("ChatGPT did not return a usable token grant.");
897
+ const earliest = data.earliest_refresh_at;
898
+ const earliestRefreshAt = typeof earliest === "number" ? earliest * 1e3 : typeof earliest === "string" ? Date.parse(earliest) : void 0;
899
+ if (earliestRefreshAt !== void 0 && !Number.isFinite(earliestRefreshAt)) throw new Error("ChatGPT returned an invalid refresh schedule.");
900
+ const email = typeof identity.email === "string" && identity.email.length <= 320 && !/[\x00-\x1f\x7f]/.test(identity.email) ? identity.email : void 0;
901
+ return { clientId, subject: identity.sub, issuer: SIWC_ISSUER, ...email ? { email } : {}, scopes, idToken, ...accessToken ? { accessToken } : {}, ...refreshToken ? { refreshToken } : {}, expiresAt: now + data.expires_in * 1e3, ...earliestRefreshAt !== void 0 ? { earliestRefreshAt } : {}, status: "connected" };
902
+ }
903
+ async function refreshSiwcProfile(profile, transport = {}, signal, checkpoint) {
904
+ if (!profile.refreshToken || profile.status !== "connected") throw new Error("Sign in with ChatGPT again before continuing.");
905
+ const metadata = await siwcMetadata(transport, signal);
906
+ const value = await readSiwcJson(metadata.token, { method: "POST", signal, headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "refresh_token", client_id: profile.clientId, refresh_token: profile.refreshToken, resource: SIWC_RESOURCE }).toString() }, transport);
907
+ const body = object(value), receipt = {};
908
+ for (const key of ["access_token", "refresh_token", "id_token", "token_type", "expires_in", "scope", "earliest_refresh_at"]) {
909
+ const field = body[key];
910
+ if (field !== void 0) receipt[key] = typeof field === "string" && field.length <= 65536 || typeof field === "number" || typeof field === "boolean" || field === null ? field : null;
911
+ }
912
+ await checkpoint?.(receipt);
913
+ return { id: profile.id, ...await validateSiwcTokens(value, profile.clientId, metadata, transport, signal, { subject: profile.subject, scopes: profile.scopes, previous: profile }) };
914
+ }
915
+ async function loginSiwc(options) {
916
+ if (!/^urn:uuid:[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/.test(options.hostId)) throw new Error("ChatGPT sign-in requires this installation's stable host identity.");
917
+ const abort = new AbortController();
918
+ const signal = options.signal ? AbortSignal.any([options.signal, abort.signal, AbortSignal.timeout(3e5)]) : AbortSignal.any([abort.signal, AbortSignal.timeout(3e5)]);
919
+ const state = randomBytes(32).toString("base64url"), nonce = randomBytes(32).toString("base64url"), verifier = randomBytes(64).toString("base64url");
920
+ let resolveCallback, rejectCallback;
921
+ const callback = new Promise((resolve4, reject) => {
922
+ resolveCallback = resolve4;
923
+ rejectCallback = reject;
924
+ });
925
+ void callback.catch(() => void 0);
926
+ let consumed = false, redirect = "";
927
+ const server = createServer((req, res) => {
928
+ let url;
929
+ try {
930
+ if (!redirect) throw new Error();
931
+ url = new URL(req.url ?? "/", redirect);
932
+ } catch {
933
+ res.writeHead(400);
934
+ res.end("Invalid callback.");
935
+ return;
936
+ }
937
+ if (consumed || req.method !== "GET" || req.headers.host !== new URL(redirect).host || url.origin !== new URL(redirect).origin || url.pathname !== PATH || url.searchParams.getAll("state").length !== 1 || url.searchParams.get("state") !== state) {
938
+ res.writeHead(400, { "Cache-Control": "no-store" });
939
+ res.end("This sign-in callback is not valid.");
940
+ return;
941
+ }
942
+ consumed = true;
943
+ res.writeHead(200, { "Cache-Control": "no-store", "Content-Type": "text/plain; charset=utf-8", "Content-Security-Policy": "default-src 'none'", "Referrer-Policy": "no-referrer" });
944
+ res.end("Return to 0 to finish connecting ChatGPT.");
945
+ resolveCallback(url.searchParams);
946
+ });
947
+ const stopped = () => rejectCallback(new Error("ChatGPT sign-in was cancelled or timed out."));
948
+ signal.addEventListener("abort", stopped, { once: true });
949
+ try {
950
+ signal.throwIfAborted();
951
+ await new Promise((resolve4, reject) => {
952
+ server.once("error", () => reject(new Error("The local sign-in callback could not start.")));
953
+ server.listen(0, "127.0.0.1", resolve4);
954
+ });
955
+ const address = server.address();
956
+ if (!address || typeof address === "string") throw new Error("The local sign-in callback could not start.");
957
+ redirect = `http://127.0.0.1:${address.port}${PATH}`;
958
+ const url = new URL(`${SIWC_ISSUER}/api/accounts/authorize`);
959
+ const previous = options.previous;
960
+ const parameters = { client_id: previous?.clientId ?? "dynamic_agent_client", ...previous ? {} : { agent_name_hint: "0" }, ext_agent_host_id: options.hostId, response_type: "code", redirect_uri: redirect, scope: SIWC_SCOPES.join(" "), resource: SIWC_RESOURCE, state, nonce, code_challenge_method: "S256", code_challenge: createHash("sha256").update(verifier).digest("base64url") };
961
+ for (const [key, value2] of Object.entries(parameters)) url.searchParams.set(key, value2);
962
+ void Promise.resolve().then(() => options.onAuthorize(url.href)).catch(() => rejectCallback(new Error("The browser sign-in could not be opened.")));
963
+ const params = await callback;
964
+ signal.throwIfAborted();
965
+ if (params.has("error")) throw new Error("ChatGPT sign-in was not authorized. No account was changed.");
966
+ const clientId = params.has("client_id") ? credential(params.get("client_id")) : previous?.clientId;
967
+ if (!clientId || clientId === "dynamic_agent_client" || params.getAll("client_id").length > 1 || previous && clientId !== previous.clientId || params.getAll("code").length !== 1) throw new Error("ChatGPT registration did not match this sign-in.");
968
+ const code = credential(params.get("code")), metadata = await siwcMetadata(options, signal);
969
+ const value = await readSiwcJson(metadata.token, { method: "POST", signal, headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "authorization_code", client_id: clientId, code, code_verifier: verifier, redirect_uri: redirect, resource: SIWC_RESOURCE }).toString() }, options);
970
+ return await validateSiwcTokens(value, clientId, metadata, options, signal, { nonce, ...previous ? { subject: previous.subject } : {} });
971
+ } finally {
972
+ abort.abort();
973
+ signal.removeEventListener("abort", stopped);
974
+ server.closeAllConnections();
975
+ await new Promise((resolve4) => {
976
+ if (!server.listening) resolve4();
977
+ else server.close(() => resolve4());
978
+ });
979
+ }
980
+ }
981
+
982
+ // packages/cli/src/tui/chatgpt-plan-store.ts
983
+ function paths(homeDir) {
984
+ const directory = join(homeStateDir(homeDir), "chatgpt-plan");
985
+ return { directory, file: join(directory, "accounts.json"), lock: join(directory, "write.lock") };
986
+ }
987
+ function checkPrivate(path, directory) {
988
+ const stat3 = lstatSync(path);
989
+ if (stat3.isSymbolicLink() || (directory ? !stat3.isDirectory() : !stat3.isFile()) || process.platform !== "win32" && ((stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())) throw new Error("ChatGPT connection storage must be private and owned by this user.");
990
+ }
991
+ function read(homeDir) {
992
+ const { directory, file } = paths(homeDir);
993
+ if (!existsSync(directory)) return void 0;
994
+ checkPrivate(directory, true);
995
+ if (!existsSync(file)) return void 0;
996
+ checkPrivate(file, false);
997
+ if (lstatSync(file).size > 4194304) throw new Error("ChatGPT connection storage exceeded its limit.");
998
+ let data;
999
+ try {
1000
+ data = JSON.parse(readFileSync(file, "utf8"));
1001
+ } catch {
1002
+ throw new Error("ChatGPT connection storage is invalid.");
1003
+ }
1004
+ if (data.version !== 1 || !Number.isSafeInteger(data.revision) || data.revision < 0 || !/^urn:uuid:[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/.test(data.hostId) || !Array.isArray(data.profiles) || data.profiles.length > 100) throw new Error("ChatGPT connection storage is invalid.");
1005
+ const ids = /* @__PURE__ */ new Set();
1006
+ for (const p of data.profiles) {
1007
+ if (!p || typeof p.id !== "string" || ids.has(p.id) || typeof p.subject !== "string" || !p.subject || p.issuer !== SIWC_ISSUER || !["connected", "signed-out", "reauth-required"].includes(p.status) || !Array.isArray(p.scopes) || !p.scopes.every((scope) => typeof scope === "string") || typeof p.expiresAt !== "number" || !Number.isFinite(p.expiresAt) || typeof p.idToken !== "string") throw new Error("ChatGPT connection storage is invalid.");
1008
+ if (p.epoch !== void 0 && (!Number.isSafeInteger(p.epoch) || p.epoch < 0)) throw new Error("ChatGPT connection generation is invalid.");
1009
+ credential(p.clientId);
1010
+ if (p.clientId === "dynamic_agent_client") throw new Error("ChatGPT connection storage has no issued registration.");
1011
+ if (p.accessToken !== void 0) credential(p.accessToken);
1012
+ if (p.refreshToken !== void 0) credential(p.refreshToken);
1013
+ ids.add(p.id);
1014
+ }
1015
+ if (data.activeId !== void 0 && !ids.has(data.activeId)) throw new Error("ChatGPT connection selection is invalid.");
1016
+ return data;
1017
+ }
1018
+ function write(store, homeDir) {
1019
+ const { directory, file } = paths(homeDir);
1020
+ checkPrivate(directory, true);
1021
+ const disk = read(homeDir);
1022
+ if ((disk?.revision ?? 0) !== store.revision) throw new Error("ChatGPT connection storage changed. Retry the operation.");
1023
+ const next = { ...store, revision: store.revision + 1 }, temp = join(directory, `${randomUUID()}.tmp`);
1024
+ const bytes = JSON.stringify(next);
1025
+ if (Buffer.byteLength(bytes) > 4194304) throw new Error("ChatGPT connection storage exceeded its limit.");
1026
+ const fd = openSync(temp, "wx", 384);
1027
+ try {
1028
+ writeFileSync(fd, bytes);
1029
+ fsyncSync(fd);
1030
+ } finally {
1031
+ closeSync(fd);
1032
+ }
1033
+ try {
1034
+ renameSync(temp, file);
1035
+ store.revision = next.revision;
1036
+ if (process.platform !== "win32") {
1037
+ const parent = openSync(directory, "r");
1038
+ try {
1039
+ fsyncSync(parent);
1040
+ } finally {
1041
+ closeSync(parent);
1042
+ }
1043
+ }
1044
+ } finally {
1045
+ if (existsSync(temp)) unlinkSync(temp);
1046
+ }
1047
+ }
1048
+ async function locked(homeDir, operation) {
1049
+ const { directory, lock } = paths(homeDir);
1050
+ mkdirSync(directory, { recursive: true, mode: 448 });
1051
+ checkPrivate(directory, true);
1052
+ let fd;
1053
+ const deadline = Date.now() + 5e3;
1054
+ for (; ; ) {
1055
+ try {
1056
+ fd = openSync(lock, "wx", 384);
1057
+ writeFileSync(fd, String(process.pid));
1058
+ break;
1059
+ } catch (error) {
1060
+ if (error.code !== "EEXIST" || Date.now() >= deadline) throw new Error("ChatGPT connection storage is busy. Close other connection operations and retry; an interrupted operation may require removing its stale lock.");
1061
+ await new Promise((resolve4) => setTimeout(resolve4, 25));
1062
+ }
1063
+ }
1064
+ try {
1065
+ return await operation(read(homeDir) ?? { version: 1, revision: 0, hostId: `urn:uuid:${randomUUID()}`, profiles: [] });
1066
+ } finally {
1067
+ closeSync(fd);
1068
+ unlinkSync(lock);
1069
+ }
1070
+ }
1071
+ function listChatGptPlanProfiles(homeDir) {
1072
+ const store = read(homeDir);
1073
+ return store?.profiles.map((p, index) => ({ id: p.id, label: `${p.email ?? "ChatGPT account"} \xB7 Connection ${index + 1}`, active: store.activeId === p.id, status: p.status, sharing: p.status === "connected" && p.scopes.includes("chatgpt.tokens.use.direct") && p.scopes.includes("resource.invoke") })) ?? [];
1074
+ }
1075
+ async function signInChatGptPlan(options) {
1076
+ const prepared = await locked(options.homeDir, async (store) => {
1077
+ const previous = options.profileId ? store.profiles.find((p) => p.id === options.profileId) : void 0;
1078
+ if (options.profileId && !previous) throw new Error("The selected ChatGPT connection no longer exists.");
1079
+ if (!previous && store.profiles.length >= 100) throw new Error("This host already has 100 ChatGPT registrations. Reconnect an existing connection.");
1080
+ write(store, options.homeDir);
1081
+ return { hostId: store.hostId, previous };
1082
+ });
1083
+ const result = await loginSiwc({ ...options, ...prepared });
1084
+ options.signal?.throwIfAborted();
1085
+ await locked(options.homeDir, async (store) => {
1086
+ options.signal?.throwIfAborted();
1087
+ const existing = options.profileId ? store.profiles.find((p) => p.id === options.profileId) : void 0;
1088
+ if (options.profileId && (!existing || existing.clientId !== result.clientId || existing.subject !== result.subject || (existing.epoch ?? 0) !== (prepared.previous?.epoch ?? 0))) throw new Error("The selected ChatGPT registration changed during sign-in.");
1089
+ const profile = { id: existing?.id ?? randomUUID(), ...result, epoch: (existing?.epoch ?? 0) + 1 };
1090
+ store.profiles = [...store.profiles.filter((p) => p.id !== profile.id), profile];
1091
+ store.activeId = profile.id;
1092
+ write(store, options.homeDir);
1093
+ });
1094
+ }
1095
+ async function selectChatGptPlanProfile(profileId, homeDir) {
1096
+ await locked(homeDir, async (store) => {
1097
+ if (!store.profiles.some((p) => p.id === profileId && p.status === "connected")) throw new Error("Sign in to this ChatGPT connection before selecting it.");
1098
+ store.activeId = profileId;
1099
+ write(store, homeDir);
1100
+ });
1101
+ }
1102
+ function getSiwcConnection(homeDir, profileId, transport = {}) {
1103
+ const current = read(homeDir), selected = profileId ?? current?.activeId, profile = current?.profiles.find((p) => p.id === selected);
1104
+ if (!current || !profile || profile.status !== "connected") throw new Error("Connect your ChatGPT plan in Connections before choosing this provider.");
1105
+ const binding = { accountId: profile.subject, clientId: profile.clientId, hostId: current.hostId };
1106
+ return { ...binding, resolveCredentials: async (signal) => {
1107
+ signal?.throwIfAborted();
1108
+ const result = await locked(homeDir, async (store) => {
1109
+ signal?.throwIfAborted();
1110
+ let p = store.profiles.find((p2) => p2.id === selected);
1111
+ if (!p || p.status !== "connected" || p.subject !== binding.accountId || p.clientId !== binding.clientId || store.hostId !== binding.hostId) throw new Error("This ChatGPT registration is no longer available. Reconnect it.");
1112
+ if (p.pendingRotation !== void 0) {
1113
+ const next = await validateSiwcTokens(p.pendingRotation, p.clientId, await siwcMetadata(transport), transport, void 0, { subject: p.subject, scopes: p.scopes, previous: p });
1114
+ p = { id: p.id, ...next, epoch: p.epoch };
1115
+ store.profiles = store.profiles.map((row) => row.id === p.id ? p : row);
1116
+ write(store, homeDir);
1117
+ }
1118
+ if (!p.scopes.includes("chatgpt.tokens.use.direct") || !p.scopes.includes("resource.invoke")) throw new Error("ChatGPT plan usage is not enabled for this connection. Sign in and grant plan usage, or use an API key.");
1119
+ signal?.throwIfAborted();
1120
+ const now = transport.now?.() ?? Date.now();
1121
+ if (p.expiresAt <= now + 6e4 && (p.earliestRefreshAt === void 0 || p.earliestRefreshAt <= now)) {
1122
+ if (Buffer.byteLength(JSON.stringify(store)) + 1048576 > 4194304) throw new Error("ChatGPT connection storage is full. Sign out of unused connections before refreshing.");
1123
+ const next = await refreshSiwcProfile(p, transport, void 0, async (value) => {
1124
+ p.pendingRotation = value;
1125
+ write(store, homeDir);
1126
+ });
1127
+ p = { ...next, epoch: p.epoch };
1128
+ store.profiles = store.profiles.map((row) => row.id === p.id ? p : row);
1129
+ write(store, homeDir);
1130
+ }
1131
+ if (p.expiresAt <= now || !p.accessToken || !p.scopes.includes("chatgpt.tokens.use.direct") || !p.scopes.includes("resource.invoke")) throw new Error("ChatGPT plan usage is not enabled for this connection. Sign in and grant plan usage, or use an API key.");
1132
+ return { accessToken: p.accessToken, scopes: [...p.scopes] };
1133
+ });
1134
+ signal?.throwIfAborted();
1135
+ return result;
1136
+ } };
1137
+ }
1138
+ async function signOutChatGptPlan(profileId, homeDir, transport = {}) {
1139
+ return locked(homeDir, async (store) => {
1140
+ const p = store.profiles.find((row) => row.id === profileId);
1141
+ if (!p) throw new Error("ChatGPT connection not found.");
1142
+ const pending = p.pendingRotation && typeof p.pendingRotation === "object" ? p.pendingRotation : void 0;
1143
+ let refreshToken = p.refreshToken, unknownRotation = false;
1144
+ if (pending?.refresh_token !== void 0) {
1145
+ try {
1146
+ refreshToken = credential(pending.refresh_token);
1147
+ } catch {
1148
+ unknownRotation = true;
1149
+ }
1150
+ }
1151
+ let revoked = !refreshToken && !unknownRotation;
1152
+ if (refreshToken) {
1153
+ try {
1154
+ const metadata2 = await siwcMetadata(transport);
1155
+ const response = await (transport.fetch ?? fetch)(metadata2.revoke, { method: "POST", redirect: "error", signal: AbortSignal.timeout(15e3), headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ token: refreshToken, token_type_hint: "refresh_token", client_id: p.clientId }).toString() });
1156
+ revoked = response.ok && !unknownRotation;
1157
+ } catch {
1158
+ }
1159
+ }
1160
+ const { accessToken: _access, refreshToken: _refresh, pendingRotation: _pending, ...metadata } = p;
1161
+ store.profiles = store.profiles.map((row) => row.id === p.id ? { ...metadata, epoch: (p.epoch ?? 0) + 1, idToken: "", scopes: [], expiresAt: 0, status: "signed-out" } : row);
1162
+ write(store, homeDir);
1163
+ return { revoked };
1164
+ });
1165
+ }
95
1166
 
96
1167
  // packages/cli/src/tui/model-preference.ts
1168
+ async function createSelectedRuntime(config, allowChatGptPlan = true) {
1169
+ if (config.provider !== "chatgpt-plan") return createConsoleRuntime(config);
1170
+ if (!allowChatGptPlan) throw new Error("Native ChatGPT plan sign-in is available only in a user-controlled local open-source runtime. Use an API key for hosted or shared workspaces.");
1171
+ const connection = config.siwcConnection ?? getSiwcConnection(config.env?.HOME);
1172
+ if (config.model) return createConsoleRuntime({ ...config, siwcConnection: connection });
1173
+ const probe = createConsoleRuntime({ ...config, model: "probe", siwcConnection: connection });
1174
+ const catalog = await probe.availableModelCatalog(AbortSignal.timeout(1e4));
1175
+ if (!catalog.length) throw new Error("This ChatGPT connection returned no models. Check plan sharing in ChatGPT Settings.");
1176
+ probe.reconfigure({ model: catalog[0].id });
1177
+ return probe;
1178
+ }
97
1179
  async function createPreferredConsoleRuntime(config, options = {}) {
98
1180
  const env = config.env ?? process.env;
99
1181
  const envModel = env["ZERO_MODEL"]?.trim();
@@ -105,7 +1187,7 @@ async function createPreferredConsoleRuntime(config, options = {}) {
105
1187
  let runtime;
106
1188
  let retainedModel = false;
107
1189
  if (inherited && !envModel && !envProvider) {
108
- runtime = createConsoleRuntime({ ...config, model: void 0 });
1190
+ runtime = await createSelectedRuntime({ ...config, model: void 0 }, options.allowChatGptPlan);
109
1191
  if (runtime.connectionIdentity() === options.inheritedConnectionIdentity) {
110
1192
  runtime.reconfigure({ model: config.model });
111
1193
  retainedModel = config.model !== void 0;
@@ -115,7 +1197,7 @@ async function createPreferredConsoleRuntime(config, options = {}) {
115
1197
  const saved = getSettings().modelPreference;
116
1198
  if (saved && (config.provider === void 0 || config.provider === saved.providerId)) {
117
1199
  try {
118
- const candidate = createConsoleRuntime({ ...config, model: saved.model, provider: saved.providerId });
1200
+ const candidate = await createSelectedRuntime({ ...config, model: saved.model, provider: saved.providerId }, options.allowChatGptPlan);
119
1201
  if (candidate.connectionIdentity() === saved.connectionIdentity) {
120
1202
  runtime = candidate;
121
1203
  retainedModel = true;
@@ -124,7 +1206,7 @@ async function createPreferredConsoleRuntime(config, options = {}) {
124
1206
  }
125
1207
  }
126
1208
  }
127
- runtime ??= createConsoleRuntime(config);
1209
+ runtime ??= await createSelectedRuntime(config, options.allowChatGptPlan);
128
1210
  if (!explicitChoice && runtime.getConfigurationDiagnostics().provider === "chatgpt-codex") {
129
1211
  let catalog;
130
1212
  try {
@@ -156,8 +1238,8 @@ function saveAppliedModelPreference(runtime) {
156
1238
  }
157
1239
 
158
1240
  // packages/cli/src/tui/model-catalog-sync.ts
159
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
160
- import { dirname, join } from "node:path";
1241
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
1242
+ import { dirname, join as join2 } from "node:path";
161
1243
 
162
1244
  // packages/cli/src/tui/model-catalog.offline.ts
163
1245
  var OFFLINE_MODEL_CATALOG = [
@@ -257,7 +1339,7 @@ function normalizedModel(value) {
257
1339
  return model;
258
1340
  }
259
1341
  function catalogCachePath(opts = {}) {
260
- return opts.cachePath ?? join(homeStateDir(), CATALOG_CACHE_FILENAME);
1342
+ return opts.cachePath ?? join2(homeStateDir(), CATALOG_CACHE_FILENAME);
261
1343
  }
262
1344
  function normalizeModelsDev(raw) {
263
1345
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return [];
@@ -286,38 +1368,38 @@ function normalizeModelsDev(raw) {
286
1368
  }
287
1369
  function readCache(path) {
288
1370
  try {
289
- if (!existsSync(path)) return null;
290
- const parsed = JSON.parse(readFileSync(path, "utf8"));
1371
+ if (!existsSync2(path)) return null;
1372
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
291
1373
  if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.models) || !Number.isFinite(parsed.fetchedAt) || parsed.fetchedAt < 0 || typeof parsed.source !== "string") {
292
1374
  return null;
293
1375
  }
294
- const cache = parsed;
295
- const models = cache.models.flatMap((row) => {
1376
+ const cache2 = parsed;
1377
+ const models = cache2.models.flatMap((row) => {
296
1378
  const model = normalizedModel(row);
297
1379
  return model ? [model] : [];
298
1380
  });
299
- return { fetchedAt: cache.fetchedAt, source: cache.source, models };
1381
+ return { fetchedAt: cache2.fetchedAt, source: cache2.source, models };
300
1382
  } catch {
301
1383
  return null;
302
1384
  }
303
1385
  }
304
- function writeCache(path, cache) {
1386
+ function writeCache(path, cache2) {
305
1387
  try {
306
- mkdirSync(dirname(path), { recursive: true });
307
- writeFileSync(path, JSON.stringify(cache, null, 2), { mode: 384 });
1388
+ mkdirSync2(dirname(path), { recursive: true });
1389
+ writeFileSync2(path, JSON.stringify(cache2, null, 2), { mode: 384 });
308
1390
  } catch {
309
1391
  }
310
1392
  }
311
- function isCacheFresh(cache, opts = {}) {
312
- if (!cache) return false;
1393
+ function isCacheFresh(cache2, opts = {}) {
1394
+ if (!cache2) return false;
313
1395
  const now = (opts.now ?? Date.now)();
314
1396
  const ttl = opts.ttlMs ?? CATALOG_TTL_MS;
315
- const age = now - cache.fetchedAt;
1397
+ const age = now - cache2.fetchedAt;
316
1398
  return Number.isFinite(age) && age >= 0 && age < ttl;
317
1399
  }
318
1400
  function loadCatalogModels(opts = {}) {
319
- const cache = readCache(catalogCachePath(opts));
320
- if (cache && cache.models.length > 0) return cache;
1401
+ const cache2 = readCache(catalogCachePath(opts));
1402
+ if (cache2 && cache2.models.length > 0) return cache2;
321
1403
  return { fetchedAt: 0, source: "offline", models: OFFLINE_MODEL_CATALOG };
322
1404
  }
323
1405
  async function syncModelCatalog(opts = {}) {
@@ -337,13 +1419,13 @@ async function syncModelCatalog(opts = {}) {
337
1419
  const json = await res.json();
338
1420
  const models = normalizeModelsDev(json);
339
1421
  if (models.length === 0) return null;
340
- const cache = {
1422
+ const cache2 = {
341
1423
  fetchedAt: (opts.now ?? Date.now)(),
342
1424
  source: url,
343
1425
  models
344
1426
  };
345
- writeCache(path, cache);
346
- return cache;
1427
+ writeCache(path, cache2);
1428
+ return cache2;
347
1429
  } catch {
348
1430
  return null;
349
1431
  } finally {
@@ -416,24 +1498,51 @@ function buildFullModelCatalog(currentModel, opts = {}) {
416
1498
  }
417
1499
 
418
1500
  // packages/cli/src/tui/available-models.ts
1501
+ var DISCOVERY_TIMEOUT_MS = 1e4;
1502
+ async function boundedCatalog(operation, callerSignal) {
1503
+ const deadline = new AbortController();
1504
+ const signal = callerSignal ? AbortSignal.any([callerSignal, deadline.signal]) : deadline.signal;
1505
+ const timer = setTimeout(() => deadline.abort(), DISCOVERY_TIMEOUT_MS);
1506
+ let onAbort;
1507
+ try {
1508
+ return await new Promise((resolve4, reject) => {
1509
+ onAbort = () => reject(new Error(deadline.signal.aborted ? "Model discovery timed out. Retry this connection." : "Model discovery cancelled."));
1510
+ signal.addEventListener("abort", onAbort, { once: true });
1511
+ if (signal.aborted) {
1512
+ onAbort();
1513
+ return;
1514
+ }
1515
+ Promise.resolve().then(() => {
1516
+ signal.throwIfAborted();
1517
+ return operation(signal);
1518
+ }).then(resolve4, reject);
1519
+ });
1520
+ } finally {
1521
+ clearTimeout(timer);
1522
+ if (onAbort) signal.removeEventListener("abort", onAbort);
1523
+ }
1524
+ }
419
1525
  async function discoverConnectionModels(env, providerIds, signal) {
420
1526
  const results = await Promise.all(providerIds.map(async (providerId) => {
421
1527
  try {
422
- const runtime = new LlmApiRuntime({
423
- type: "api",
424
- timeout: 1e4,
425
- provider: providerId,
426
- model: "probe",
427
- env: { ...env, ZERO_SKIP_PROVIDER_BANNER: "1" }
428
- });
429
- const models = await runtime.availableModelCatalog(signal ?? AbortSignal.timeout(1e4));
1528
+ const models = await boundedCatalog(async (discoverySignal) => {
1529
+ const runtime = new LlmApiRuntime({
1530
+ type: "api",
1531
+ timeout: DISCOVERY_TIMEOUT_MS,
1532
+ provider: providerId,
1533
+ model: "probe",
1534
+ ...providerId === "chatgpt-plan" ? { siwcConnection: getSiwcConnection(env.HOME) } : {},
1535
+ env: { ...env, ZERO_SKIP_PROVIDER_BANNER: "1" }
1536
+ });
1537
+ return runtime.availableModelCatalog(discoverySignal);
1538
+ }, signal);
430
1539
  return { models: models.map((model) => ({ ...model, provider: providerId })), diagnostics: [] };
431
1540
  } catch (error) {
432
- let message = error instanceof Error ? error.message : "Model discovery failed.";
1541
+ let message2 = error instanceof Error ? error.message : "Model discovery failed.";
433
1542
  for (const [name, value] of Object.entries(env)) {
434
- if (value && /KEY|TOKEN|SECRET|PASSWORD/i.test(name)) message = message.split(value).join("[redacted]");
1543
+ if (value && /KEY|TOKEN|SECRET|PASSWORD/i.test(name)) message2 = message2.split(value).join("[redacted]");
435
1544
  }
436
- return { models: [], diagnostics: [{ providerId, message: message.slice(0, 1e3) }] };
1545
+ return { models: [], diagnostics: [{ providerId, message: message2.slice(0, 1e3) }] };
437
1546
  }
438
1547
  }));
439
1548
  return { models: results.flatMap((result) => result.models), diagnostics: results.flatMap((result) => result.diagnostics) };
@@ -479,28 +1588,28 @@ function resolveContextLimit(identity, opts = {}) {
479
1588
  return family === null ? null : { tokens: family, source: "known-family" };
480
1589
  };
481
1590
  const load = opts.loadModels ?? loadCatalogModels;
482
- const cache = load(opts.sync ?? {});
483
- const row = cache.models.find((model) => sameByokModel(model, identity));
1591
+ const cache2 = load(opts.sync ?? {});
1592
+ const row = cache2.models.find((model) => sameByokModel(model, identity));
484
1593
  const tokens = row ? positiveTokens(row.contextTokens) : null;
485
1594
  if (tokens !== null) {
486
- return { tokens, source: cache.source === "offline" ? "offline-catalog" : "synced-catalog" };
1595
+ return { tokens, source: cache2.source === "offline" ? "offline-catalog" : "synced-catalog" };
487
1596
  }
488
1597
  return familyFallback();
489
1598
  }
490
1599
 
491
1600
  // packages/cli/src/tui/device-auth.ts
492
- import { createHash, randomBytes, randomUUID } from "node:crypto";
493
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
494
- import { createServer } from "node:http";
1601
+ import { createHash as createHash2, randomBytes as randomBytes2, randomUUID as randomUUID2 } from "node:crypto";
1602
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
1603
+ import { createServer as createServer2 } from "node:http";
495
1604
  import { arch, hostname, platform as platform2, release, version as osVersion } from "node:os";
496
- import { join as join2 } from "node:path";
1605
+ import { join as join3 } from "node:path";
497
1606
 
498
1607
  // packages/cli/src/open-browser.ts
499
1608
  import { spawn } from "node:child_process";
500
1609
  import { platform } from "node:os";
501
1610
  function defaultOpenBrowser(url) {
502
1611
  const plat = platform();
503
- return new Promise((resolve2, reject) => {
1612
+ return new Promise((resolve4, reject) => {
504
1613
  const options = { detached: true, stdio: "ignore", shell: false };
505
1614
  const child = plat === "darwin" ? spawn("open", [url], options) : plat === "win32" ? spawn("powershell.exe", [
506
1615
  "-NoProfile",
@@ -511,7 +1620,7 @@ function defaultOpenBrowser(url) {
511
1620
  child.once("error", reject);
512
1621
  child.once("spawn", () => {
513
1622
  child.unref();
514
- resolve2();
1623
+ resolve4();
515
1624
  });
516
1625
  });
517
1626
  }
@@ -546,17 +1655,17 @@ var DEFAULT_INTERVAL_SECONDS = 5;
546
1655
  var SLOW_DOWN_INCREMENT_SECONDS = 5;
547
1656
  var DEFAULT_EXPIRES_IN_SECONDS = 900;
548
1657
  var defaultFetch = (url, init) => globalThis.fetch(url, init);
549
- var defaultSleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
1658
+ var defaultSleep = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
550
1659
  var PKCE_TIMEOUT_SECONDS = 300;
551
1660
  var base64url = (buffer) => buffer.toString("base64url");
552
1661
  var defaultCreatePkcePair = () => {
553
- const verifier = base64url(randomBytes(32));
554
- const challenge = base64url(createHash("sha256").update(verifier).digest());
1662
+ const verifier = base64url(randomBytes2(32));
1663
+ const challenge = base64url(createHash2("sha256").update(verifier).digest());
555
1664
  return { verifier, challenge };
556
1665
  };
557
1666
  var defaultServerFactory = async ({ onRedirect }) => {
558
1667
  let delivered = false;
559
- const server = createServer((req, res) => {
1668
+ const server = createServer2((req, res) => {
560
1669
  const requestUrl = new URL(req.url ?? "/", "http://127.0.0.1");
561
1670
  if (requestUrl.pathname !== "/callback") {
562
1671
  res.statusCode = 404;
@@ -572,9 +1681,9 @@ var defaultServerFactory = async ({ onRedirect }) => {
572
1681
  delivered = true;
573
1682
  onRedirect({ code, error });
574
1683
  });
575
- await new Promise((resolve2, reject) => {
1684
+ await new Promise((resolve4, reject) => {
576
1685
  server.once("error", reject);
577
- server.listen(0, "127.0.0.1", () => resolve2());
1686
+ server.listen(0, "127.0.0.1", () => resolve4());
578
1687
  });
579
1688
  const address = server.address();
580
1689
  const port = typeof address === "object" && address !== null ? address.port : 0;
@@ -591,7 +1700,7 @@ function isPlainObject(value) {
591
1700
  }
592
1701
  function startDeviceAuth(config, options) {
593
1702
  const env = options.env ?? process.env;
594
- const doFetch = options.fetch ?? defaultFetch;
1703
+ const transport = options.fetch ?? defaultFetch;
595
1704
  const now = options.now ?? Date.now;
596
1705
  const sleep = options.sleep ?? defaultSleep;
597
1706
  const openBrowser = options.openBrowser ?? defaultOpenBrowser;
@@ -599,19 +1708,56 @@ function startDeviceAuth(config, options) {
599
1708
  const lines = [];
600
1709
  let settled = false;
601
1710
  let cancelled = false;
1711
+ const controller = new AbortController();
1712
+ let deadlineTimer;
1713
+ const bounded = (work) => new Promise((resolve4, reject) => {
1714
+ const abort = () => {
1715
+ cleanup();
1716
+ reject(controller.signal.reason);
1717
+ };
1718
+ const cleanup = () => controller.signal.removeEventListener("abort", abort);
1719
+ if (controller.signal.aborted) {
1720
+ abort();
1721
+ return;
1722
+ }
1723
+ controller.signal.addEventListener("abort", abort, { once: true });
1724
+ work.then((value) => {
1725
+ cleanup();
1726
+ resolve4(value);
1727
+ }, (error) => {
1728
+ cleanup();
1729
+ reject(error);
1730
+ });
1731
+ });
1732
+ const doFetch = async (url, init) => {
1733
+ controller.signal.throwIfAborted();
1734
+ const response = await bounded(transport(url, { ...init, signal: controller.signal }));
1735
+ return { ...response, ok: response.ok, status: response.status, json: () => bounded(response.json()) };
1736
+ };
1737
+ const armDeadline = (ms) => {
1738
+ if (deadlineTimer !== void 0) clearTimeout(deadlineTimer);
1739
+ deadlineTimer = setTimeout(() => {
1740
+ finish("failed", `${label} sign-in timed out. Start again.`);
1741
+ controller.abort(new Error("Sign-in timed out"));
1742
+ cancelWaiter?.();
1743
+ }, ms);
1744
+ deadlineTimer.unref?.();
1745
+ };
602
1746
  const pushLine = (text2) => {
603
1747
  const value = sanitizeTuiText(text2);
604
1748
  if (value.length === 0) return;
605
1749
  lines.push(value);
606
1750
  if (lines.length > MAX_VISIBLE_LINES) lines.shift();
607
1751
  };
608
- const publish = (phase, message) => {
609
- options.onUpdate({ phase, lines: [...lines], message });
1752
+ const publish = (phase, message2) => {
1753
+ if (settled && phase === "running") return;
1754
+ options.onUpdate({ phase, lines: [...lines], message: message2 });
610
1755
  };
611
- const finish = (phase, message) => {
1756
+ const finish = (phase, message2) => {
612
1757
  if (settled) return;
613
1758
  settled = true;
614
- publish(phase, message);
1759
+ if (deadlineTimer !== void 0) clearTimeout(deadlineTimer);
1760
+ publish(phase, message2);
615
1761
  };
616
1762
  const requestDeviceCode = async (cfg) => {
617
1763
  const params = new URLSearchParams({ client_id: cfg.clientId });
@@ -692,6 +1838,7 @@ function startDeviceAuth(config, options) {
692
1838
  }
693
1839
  };
694
1840
  const persist = (record, connectedMessage) => {
1841
+ if (settled || cancelled || controller.signal.aborted) return;
695
1842
  const { store } = addAccount(loadAccountStore(options.homeDir), config.providerId, record);
696
1843
  if (!saveAccountStore(store, options.homeDir)) {
697
1844
  finish("failed", "Sign-in completed, but the private credential account store could not be saved. Try again after restoring access to the local state directory.");
@@ -720,15 +1867,28 @@ function startDeviceAuth(config, options) {
720
1867
  pushLine(`Visit: ${device.verification_uri}`);
721
1868
  publish("running", `Complete the ${label} device sign-in in your browser.`);
722
1869
  try {
723
- await openBrowser(openUrl);
1870
+ await bounded(Promise.resolve(openBrowser(openUrl)));
724
1871
  } catch {
725
1872
  pushLine("Could not open a browser automatically; open the URL above.");
726
1873
  publish("running", `Complete the ${label} device sign-in in your browser.`);
727
1874
  }
1875
+ if (settled) return;
728
1876
  let intervalSeconds = device.interval ?? DEFAULT_INTERVAL_SECONDS;
729
1877
  const deadline = now() + (device.expires_in ?? DEFAULT_EXPIRES_IN_SECONDS) * 1e3;
1878
+ armDeadline(Math.max(0, deadline - now()));
730
1879
  while (!cancelled) {
731
- await sleep(intervalSeconds * 1e3);
1880
+ if (options.sleep) await bounded(sleep(intervalSeconds * 1e3));
1881
+ else await bounded(new Promise((resolve4, reject) => {
1882
+ const abort = () => {
1883
+ clearTimeout(timer);
1884
+ reject(controller.signal.reason);
1885
+ };
1886
+ const timer = setTimeout(() => {
1887
+ controller.signal.removeEventListener("abort", abort);
1888
+ resolve4();
1889
+ }, intervalSeconds * 1e3);
1890
+ controller.signal.addEventListener("abort", abort, { once: true });
1891
+ }));
732
1892
  if (cancelled) break;
733
1893
  if (now() >= deadline) {
734
1894
  finish("failed", `${label} device sign-in timed out. Start again.`);
@@ -795,8 +1955,8 @@ function startDeviceAuth(config, options) {
795
1955
  const serverFactory = options.serverFactory ?? defaultServerFactory;
796
1956
  let resolveOutcome = () => {
797
1957
  };
798
- const outcomePromise = new Promise((resolve2) => {
799
- resolveOutcome = resolve2;
1958
+ const outcomePromise = new Promise((resolve4) => {
1959
+ resolveOutcome = resolve4;
800
1960
  });
801
1961
  let server;
802
1962
  try {
@@ -808,13 +1968,13 @@ function startDeviceAuth(config, options) {
808
1968
  return;
809
1969
  }
810
1970
  cancelWaiter = () => resolveOutcome({ type: "cancelled" });
811
- if (cancelled) {
1971
+ if (cancelled || settled) {
812
1972
  server.close();
813
1973
  finish("cancelled", `${label} browser sign-in cancelled.`);
814
1974
  return;
815
1975
  }
816
1976
  const redirectUri = `http://localhost:${server.port}/callback`;
817
- const state = base64url(randomBytes(16)).replace(/[^a-zA-Z0-9]/g, "").slice(0, 32);
1977
+ const state = base64url(randomBytes2(16)).replace(/[^a-zA-Z0-9]/g, "").slice(0, 32);
818
1978
  const authorizeUrl = new URL(cfg.authorizeUrl);
819
1979
  authorizeUrl.searchParams.set(cfg.redirectParam ?? "redirect_uri", redirectUri);
820
1980
  authorizeUrl.searchParams.set("code_challenge", challenge);
@@ -829,12 +1989,17 @@ function startDeviceAuth(config, options) {
829
1989
  pushLine(`Sign in at: ${openUrl}`);
830
1990
  publish("running", `Complete the ${label} sign-in in your browser.`);
831
1991
  try {
832
- await openBrowser(openUrl);
1992
+ await bounded(Promise.resolve(openBrowser(openUrl)));
833
1993
  } catch {
834
1994
  pushLine("Could not open a browser automatically; open the URL above.");
835
1995
  publish("running", `Complete the ${label} sign-in in your browser.`);
836
1996
  }
837
- void sleep(PKCE_TIMEOUT_SECONDS * 1e3).then(() => resolveOutcome({ type: "timeout" }));
1997
+ if (options.sleep) void bounded(sleep(PKCE_TIMEOUT_SECONDS * 1e3)).then(() => {
1998
+ finish("failed", `${label} browser sign-in timed out. Start again.`);
1999
+ controller.abort(new Error("Sign-in timed out"));
2000
+ resolveOutcome({ type: "timeout" });
2001
+ }, () => {
2002
+ });
838
2003
  const outcome = await outcomePromise;
839
2004
  server.close();
840
2005
  if (outcome.type === "cancelled" || cancelled) {
@@ -873,28 +2038,32 @@ function startDeviceAuth(config, options) {
873
2038
  persist(record, `${label} connected through browser sign-in.`);
874
2039
  };
875
2040
  let cancelWaiter;
876
- void (config.kind === "pkce-loopback" ? runPkceLoopback(config) : runDeviceCode(config));
2041
+ armDeadline((config.kind === "pkce-loopback" ? PKCE_TIMEOUT_SECONDS : DEFAULT_EXPIRES_IN_SECONDS) * 1e3);
2042
+ void (config.kind === "pkce-loopback" ? runPkceLoopback(config) : runDeviceCode(config)).catch((error) => {
2043
+ finish(cancelled ? "cancelled" : "failed", cancelled ? `${label} sign-in cancelled.` : error instanceof Error ? error.message : "Sign-in failed.");
2044
+ });
877
2045
  return {
878
2046
  cancel: () => {
879
2047
  if (settled || cancelled) return;
880
2048
  cancelled = true;
2049
+ finish("cancelled", `${label} sign-in cancelled.`);
2050
+ controller.abort(new Error("Sign-in cancelled"));
881
2051
  cancelWaiter?.();
882
2052
  }
883
2053
  };
884
2054
  }
885
- var KIMI_CLIENT_VERSION = "0.16.3";
886
2055
  var KIMI_DEVICE_ID_FILENAME = "kimi-device-id";
887
2056
  function kimiDeviceId(homeDir) {
888
- const idPath = join2(homeStateDir(homeDir), KIMI_DEVICE_ID_FILENAME);
2057
+ const idPath = join3(homeStateDir(homeDir), KIMI_DEVICE_ID_FILENAME);
889
2058
  try {
890
- const existing = readFileSync2(idPath, "utf8").trim();
2059
+ const existing = readFileSync3(idPath, "utf8").trim();
891
2060
  if (existing) return existing;
892
2061
  } catch {
893
2062
  }
894
- const deviceId = randomUUID().replace(/-/g, "");
2063
+ const deviceId = randomUUID2().replace(/-/g, "");
895
2064
  try {
896
- mkdirSync2(homeStateDir(homeDir), { recursive: true });
897
- writeFileSync2(idPath, `${deviceId}
2065
+ mkdirSync3(homeStateDir(homeDir), { recursive: true });
2066
+ writeFileSync3(idPath, `${deviceId}
898
2067
  `, { mode: 384 });
899
2068
  } catch {
900
2069
  }
@@ -911,129 +2080,93 @@ function kimiDeviceModel() {
911
2080
  }
912
2081
  function kimiFingerprintHeaders(homeDir) {
913
2082
  return {
914
- "User-Agent": `KimiCLI/${KIMI_CLIENT_VERSION}`,
915
- "X-Msh-Platform": "kimi_cli",
916
- "X-Msh-Version": KIMI_CLIENT_VERSION,
2083
+ "User-Agent": "0security",
2084
+ "X-Msh-Platform": "0security",
2085
+ "X-Msh-Version": "0",
917
2086
  "X-Msh-Device-Name": sanitizeHeaderValue(hostname()),
918
2087
  "X-Msh-Device-Model": sanitizeHeaderValue(kimiDeviceModel()),
919
2088
  "X-Msh-Os-Version": sanitizeHeaderValue(osVersion()),
920
2089
  "X-Msh-Device-Id": sanitizeHeaderValue(kimiDeviceId(homeDir))
921
2090
  };
922
2091
  }
923
- var PROVIDER_DEVICE_AUTH = {
924
- // Matches oh-my-pi rules/auth/xai-oauth.kdl and opencode packages/opencode/
925
- // src/plugin/xai.ts (fetched 2026-09-14):
926
- // https://github.com/can1357/oh-my-pi/blob/main/packages/catalog/src/compat/rules/auth/xai-oauth.kdl
927
- // https://github.com/sst/opencode/blob/dev/packages/opencode/src/plugin/xai.ts
928
- // Both use device url https://auth.x.ai/oauth2/device/code, token endpoint
929
- // https://auth.x.ai/oauth2/token, client id b1a00492-073a-47ea-816f-4c329264a828,
930
- // and scope "openid profile email offline_access grok-cli:access api:access".
931
- // The token response's `access_token` is the credential (buildOAuthRecord).
932
- xai: {
933
- kind: "device-code",
934
- providerId: "xai",
935
- deviceCodeUrl: "https://auth.x.ai/oauth2/device/code",
936
- tokenUrl: "https://auth.x.ai/oauth2/token",
937
- clientId: "b1a00492-073a-47ea-816f-4c329264a828",
938
- scopes: ["openid", "profile", "email", "offline_access", "grok-cli:access", "api:access"],
939
- toAccountRecord: buildOAuthRecord
940
- },
941
- // Matches oh-my-pi rules/auth/kimi-code.kdl + packages/ai/src/registry/oauth/
942
- // kimi.ts (fetched 2026-09-14):
943
- // https://github.com/can1357/oh-my-pi/blob/main/packages/catalog/src/compat/rules/auth/kimi-code.kdl
944
- // https://github.com/can1357/oh-my-pi/blob/main/packages/ai/src/registry/oauth/kimi.ts
945
- // base-url https://auth.kimi.com → device /api/oauth/device_authorization and
946
- // token /api/oauth/token, client id 17e5f671-d194-4dfb-9706-5516cb48c098, and
947
- // NO scopes (the kdl has no `scopes` line, so no scope param is sent). The
948
- // `kimi-fingerprint` headers-hook attaches the X-Msh-* device fingerprint to
949
- // both requests — see kimiFingerprintHeaders. Token `access_token` is the
950
- // credential (buildOAuthRecord).
951
- kimi: {
952
- kind: "device-code",
953
- providerId: "kimi",
954
- deviceCodeUrl: "https://auth.kimi.com/api/oauth/device_authorization",
955
- tokenUrl: "https://auth.kimi.com/api/oauth/token",
956
- clientId: "17e5f671-d194-4dfb-9706-5516cb48c098",
957
- scopes: [],
958
- buildHeaders: kimiFingerprintHeaders,
959
- toAccountRecord: buildOAuthRecord
960
- },
961
- // Matches opencode packages/opencode/src/plugin/github-copilot and oh-my-pi
962
- // oauth/github-copilot (fetched 2026-09-14). GitHub's device flow: device url
963
- // https://github.com/login/device/code, token endpoint
964
- // https://github.com/login/oauth/access_token, client id Ov23li8tweQw6odWQebz,
965
- // scope "read:user". The device token is long-lived and sent DIRECTLY as a
966
- // Bearer to api.githubcopilot.com — NO secondary token exchange and NO
967
- // refresh — so it is stored as a plain oauth record (buildOAuthRecord) whose
968
- // access_token accountEnvPatch writes to ZERO_COPILOT_GITHUB_TOKEN (envVars[0]).
969
- copilot: {
970
- kind: "device-code",
971
- providerId: "copilot",
972
- deviceCodeUrl: "https://github.com/login/device/code",
973
- tokenUrl: "https://github.com/login/oauth/access_token",
974
- clientId: "Ov23li8tweQw6odWQebz",
975
- scopes: ["read:user"],
976
- toAccountRecord: buildOAuthRecord
977
- },
978
- // Matches oh-my-pi rules/auth/openrouter.kdl (fetched 2026-09-14):
979
- // https://github.com/can1357/oh-my-pi/blob/main/packages/catalog/src/compat/rules/auth/openrouter.kdl
980
- // login "oauth-code" pkce=#true, standard authorize params OFF: open
981
- // https://openrouter.ai/auth?callback_url=<loopback>&code_challenge=<c>&code_challenge_method=S256
982
- // (CLIENT-ID-LESS — no client_id param), then POST JSON
983
- // { code, code_verifier, code_challenge_method: "S256" }
984
- // to https://openrouter.ai/api/v1/auth/keys, which PROVISIONS a durable
985
- // `sk-or-...` API key. The kdl's `credential { access "key" }` names the
986
- // response field `key` (buildOpenRouterKeyRecord). Stored as an api_key record
987
- // and written to OPENROUTER_API_KEY (envVars[0]) by accountEnvPatch, which
988
- // llm-api already reads — so no llm-api change.
989
- openrouter: {
990
- kind: "pkce-loopback",
991
- providerId: "openrouter",
992
- authorizeUrl: "https://openrouter.ai/auth",
993
- keysUrl: "https://openrouter.ai/api/v1/auth/keys",
994
- redirectParam: "callback_url",
995
- scopes: [],
996
- toAccountRecord: buildOpenRouterKeyRecord
997
- },
998
- // Google Gemini Code Assist — the Authorization Code + PKCE loopback flow of
999
- // the Gemini CLI. Confirmed against gemini-cli, opencode's gemini-auth plugin
1000
- // and oh-my-pi (fetched 2026-09-14), which all agree on the embedded
1001
- // installed-app client_id/secret, the accounts.google.com authorize endpoint,
1002
- // and the standard oauth2.googleapis.com/token FORM exchange:
1003
- // authorize https://accounts.google.com/o/oauth2/v2/auth
1004
- // (response_type=code, access_type=offline, prompt=consent, S256, state)
1005
- // token https://oauth2.googleapis.com/token (form-encoded)
1006
- // scopes: cloud-platform + userinfo.email + userinfo.profile.
1007
- // The token response's access_token/refresh_token/expires_in are stored as an
1008
- // oauth record (buildOAuthRecord): accountEnvPatch writes access_token to
1009
- // ZERO_GEMINI_ACCESS_TOKEN (envVars[0]) and refresh_token to
1010
- // ZERO_GEMINI_OAUTH_REFRESH_TOKEN (the /REFRESH/i var). The Code Assist
1011
- // PROJECT is resolved later, at request time, in llm-api — NOT here.
1012
- //
1013
- // Redirect path: the shared loopback server answers `/callback`; Google's
1014
- // installed-app clients accept ANY loopback path (RFC 8252 §7.3), so the
1015
- // gemini-cli's `/oauth2callback` and our `/callback` are equally valid. The
1016
- // engine threads the exact redirect_uri it built into the token exchange, so
1017
- // the two always agree.
1018
- google: {
1019
- kind: "pkce-loopback",
1020
- providerId: "google",
1021
- authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
1022
- keysUrl: "https://oauth2.googleapis.com/token",
1023
- // Public installed-app credentials (as embedded by gemini-cli/opencode);
1024
- // split only to avoid a secret-scanner false positive — value is intact.
1025
- clientId: "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com",
1026
- clientSecret: "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",
1027
- exchangeBodyMode: "form",
1028
- authorizeParams: { response_type: "code", access_type: "offline", prompt: "consent" },
1029
- scopes: [
1030
- "https://www.googleapis.com/auth/cloud-platform",
1031
- "https://www.googleapis.com/auth/userinfo.email",
1032
- "https://www.googleapis.com/auth/userinfo.profile"
1033
- ],
1034
- toAccountRecord: buildOAuthRecord
1035
- }
1036
- };
2092
+ function createProviderDeviceAuth(env = process.env) {
2093
+ const clientId = (name) => env[name]?.trim() || void 0;
2094
+ return {
2095
+ // Endpoints use the provider protocol; client identity must be registered for 0.
2096
+ ...clientId("ZERO_XAI_OAUTH_CLIENT_ID") ? { xai: {
2097
+ kind: "device-code",
2098
+ providerId: "xai",
2099
+ deviceCodeUrl: "https://auth.x.ai/oauth2/device/code",
2100
+ tokenUrl: "https://auth.x.ai/oauth2/token",
2101
+ clientId: clientId("ZERO_XAI_OAUTH_CLIENT_ID"),
2102
+ scopes: ["openid", "profile", "email", "offline_access", "grok-cli:access", "api:access"],
2103
+ toAccountRecord: buildOAuthRecord
2104
+ } } : {},
2105
+ // Never borrow the official Kimi CLI client identity for a new 0 sign-in.
2106
+ // Opt-in is only for an operator who has registered a client for 0.
2107
+ ...clientId("ZERO_KIMI_OAUTH_CLIENT_ID") ? { kimi: {
2108
+ kind: "device-code",
2109
+ providerId: "kimi",
2110
+ deviceCodeUrl: "https://auth.kimi.com/api/oauth/device_authorization",
2111
+ tokenUrl: "https://auth.kimi.com/api/oauth/token",
2112
+ clientId: clientId("ZERO_KIMI_OAUTH_CLIENT_ID"),
2113
+ scopes: [],
2114
+ buildHeaders: kimiFingerprintHeaders,
2115
+ toAccountRecord: buildOAuthRecord
2116
+ } } : {},
2117
+ // Own GitHub app registration must also be entitled to the Copilot service.
2118
+ ...clientId("ZERO_COPILOT_OAUTH_CLIENT_ID") ? { copilot: {
2119
+ kind: "device-code",
2120
+ providerId: "copilot",
2121
+ deviceCodeUrl: "https://github.com/login/device/code",
2122
+ tokenUrl: "https://github.com/login/oauth/access_token",
2123
+ clientId: clientId("ZERO_COPILOT_OAUTH_CLIENT_ID"),
2124
+ scopes: ["read:user"],
2125
+ toAccountRecord: buildOAuthRecord
2126
+ } } : {},
2127
+ // Matches oh-my-pi rules/auth/openrouter.kdl (fetched 2026-09-14):
2128
+ // https://github.com/can1357/oh-my-pi/blob/main/packages/catalog/src/compat/rules/auth/openrouter.kdl
2129
+ // login "oauth-code" pkce=#true, standard authorize params OFF: open
2130
+ // https://openrouter.ai/auth?callback_url=<loopback>&code_challenge=<c>&code_challenge_method=S256
2131
+ // (CLIENT-ID-LESS — no client_id param), then POST JSON
2132
+ // { code, code_verifier, code_challenge_method: "S256" }
2133
+ // to https://openrouter.ai/api/v1/auth/keys, which PROVISIONS a durable
2134
+ // `sk-or-...` API key. The kdl's `credential { access "key" }` names the
2135
+ // response field `key` (buildOpenRouterKeyRecord). Stored as an api_key record
2136
+ // and written to OPENROUTER_API_KEY (envVars[0]) by accountEnvPatch, which
2137
+ // llm-api already reads — so no llm-api change.
2138
+ openrouter: {
2139
+ kind: "pkce-loopback",
2140
+ providerId: "openrouter",
2141
+ authorizeUrl: "https://openrouter.ai/auth",
2142
+ keysUrl: "https://openrouter.ai/api/v1/auth/keys",
2143
+ redirectParam: "callback_url",
2144
+ scopes: [],
2145
+ toAccountRecord: buildOpenRouterKeyRecord
2146
+ },
2147
+ // Google browser sign-in requires a 0 registration entitled to Code Assist.
2148
+ ...clientId("ZERO_GOOGLE_OAUTH_CLIENT_ID") ? { google: {
2149
+ kind: "pkce-loopback",
2150
+ providerId: "google",
2151
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
2152
+ keysUrl: "https://oauth2.googleapis.com/token",
2153
+ clientId: clientId("ZERO_GOOGLE_OAUTH_CLIENT_ID"),
2154
+ ...env.ZERO_GOOGLE_OAUTH_CLIENT_SECRET ? { clientSecret: env.ZERO_GOOGLE_OAUTH_CLIENT_SECRET } : {},
2155
+ exchangeBodyMode: "form",
2156
+ authorizeParams: { response_type: "code", access_type: "offline", prompt: "consent" },
2157
+ scopes: [
2158
+ "https://www.googleapis.com/auth/cloud-platform",
2159
+ "https://www.googleapis.com/auth/userinfo.email",
2160
+ "https://www.googleapis.com/auth/userinfo.profile"
2161
+ ],
2162
+ toAccountRecord: (tokenResponse) => ({
2163
+ ...buildOAuthRecord(tokenResponse),
2164
+ oauthClient: { clientId: clientId("ZERO_GOOGLE_OAUTH_CLIENT_ID"), ...env.ZERO_GOOGLE_OAUTH_CLIENT_SECRET ? { clientSecret: env.ZERO_GOOGLE_OAUTH_CLIENT_SECRET } : {} }
2165
+ })
2166
+ } } : {}
2167
+ };
2168
+ }
2169
+ var PROVIDER_DEVICE_AUTH = createProviderDeviceAuth();
1037
2170
  function buildOAuthRecord(tokenResponse) {
1038
2171
  const tokens = {};
1039
2172
  if (typeof tokenResponse.access_token === "string") tokens.accessToken = tokenResponse.access_token;
@@ -1052,14 +2185,14 @@ function buildOpenRouterKeyRecord(exchange) {
1052
2185
  }
1053
2186
 
1054
2187
  // packages/cli/src/tui/plugin-service.ts
1055
- import { chmodSync, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
1056
- import { join as join3 } from "node:path";
2188
+ import { chmodSync, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
2189
+ import { join as join4 } from "node:path";
1057
2190
  function coreLoader(injected) {
1058
2191
  if (typeof injected === "function") return injected;
1059
2192
  if (injected) return async () => injected;
1060
2193
  let cached;
1061
2194
  return () => {
1062
- if (!cached) cached = import("./dist-6RNAVFAY.js");
2195
+ if (!cached) cached = import("./dist-ONIRKDH6.js");
1063
2196
  return cached;
1064
2197
  };
1065
2198
  }
@@ -1183,17 +2316,17 @@ function createPluginService(deps = {}) {
1183
2316
  if (!c.ensurePluginsRoot(root)) {
1184
2317
  return { ok: false, message: `Could not create the plugins root at ${root}.` };
1185
2318
  }
1186
- const dir = join3(root, item.id);
1187
- mkdirSync3(dir, { recursive: true, mode: c.PLUGIN_DIR_MODE });
2319
+ const dir = join4(root, item.id);
2320
+ mkdirSync4(dir, { recursive: true, mode: c.PLUGIN_DIR_MODE });
1188
2321
  chmodSync(dir, c.PLUGIN_DIR_MODE);
1189
- const manifestPath = join3(dir, c.PLUGIN_MANIFEST_FILE);
1190
- writeFileSync3(manifestPath, `${JSON.stringify(entry.manifest, null, 2)}
2322
+ const manifestPath = join4(dir, c.PLUGIN_MANIFEST_FILE);
2323
+ writeFileSync4(manifestPath, `${JSON.stringify(entry.manifest, null, 2)}
1191
2324
  `, {
1192
2325
  mode: c.PLUGIN_FILE_MODE
1193
2326
  });
1194
2327
  chmodSync(manifestPath, c.PLUGIN_FILE_MODE);
1195
- const entryPath = join3(dir, c.PLUGIN_ENTRY_FILE);
1196
- writeFileSync3(entryPath, entryBody, { mode: c.PLUGIN_FILE_MODE });
2328
+ const entryPath = join4(dir, c.PLUGIN_ENTRY_FILE);
2329
+ writeFileSync4(entryPath, entryBody, { mode: c.PLUGIN_FILE_MODE });
1197
2330
  chmodSync(entryPath, c.PLUGIN_FILE_MODE);
1198
2331
  return {
1199
2332
  ok: true,
@@ -1420,7 +2553,7 @@ function coreLoader2(injected) {
1420
2553
  if (injected) return async () => injected;
1421
2554
  let cached;
1422
2555
  return () => {
1423
- if (!cached) cached = import("./dist-6RNAVFAY.js");
2556
+ if (!cached) cached = import("./dist-ONIRKDH6.js");
1424
2557
  return cached;
1425
2558
  };
1426
2559
  }
@@ -1599,6 +2732,60 @@ async function createSessionPluginHostManager(deps = {}) {
1599
2732
  return { current, acquire, refresh, runPlugin, onChanged, dispose };
1600
2733
  }
1601
2734
 
2735
+ // packages/cli/src/web/chatgpt-plan-controller.ts
2736
+ var ChatGptPlanAuthController = class {
2737
+ #options;
2738
+ #abort;
2739
+ #epoch = 0;
2740
+ #status = { phase: "idle", message: "Connect your ChatGPT account.", lines: [], verificationUrl: null, userCode: null, available: true };
2741
+ constructor(options = {}) {
2742
+ this.#options = options;
2743
+ }
2744
+ status() {
2745
+ if (this.#status.phase !== "running" && this.#status.phase !== "failed" && this.#status.phase !== "cancelled") {
2746
+ const active = (this.#options.list ?? listChatGptPlanProfiles)(this.#options.homeDir).find((p) => p.active && p.status === "connected");
2747
+ if (active) return { ...this.#status, phase: "connected", message: active.sharing ? "ChatGPT plan sharing is connected." : "ChatGPT identity is connected. Grant plan usage to use models.", lines: [], verificationUrl: null };
2748
+ }
2749
+ return { ...this.#status, lines: [...this.#status.lines] };
2750
+ }
2751
+ start(profileId) {
2752
+ if (this.#abort) return this.status();
2753
+ const epoch2 = ++this.#epoch, abort = new AbortController();
2754
+ this.#abort = abort;
2755
+ this.#status = { ...this.#status, phase: "running", message: "Starting ChatGPT sign-in.", verificationUrl: null, lines: [] };
2756
+ void Promise.resolve().then(() => {
2757
+ abort.signal.throwIfAborted();
2758
+ return (this.#options.signIn ?? signInChatGptPlan)({
2759
+ homeDir: this.#options.homeDir,
2760
+ profileId,
2761
+ signal: abort.signal,
2762
+ onAuthorize: (value) => {
2763
+ if (epoch2 !== this.#epoch || abort.signal.aborted) return;
2764
+ const url = new URL(value);
2765
+ if (url.protocol !== "https:" || url.hostname !== "auth.openai.com" || url.port || url.username || url.password || url.hash || ["access_token", "refresh_token", "id_token", "id_token_hint", "api_key"].some((key) => url.searchParams.has(key))) throw new Error("Unsafe authorization destination.");
2766
+ this.#status = { ...this.#status, message: "Continue in your browser to connect ChatGPT.", verificationUrl: url.href };
2767
+ }
2768
+ });
2769
+ }).then(() => {
2770
+ if (epoch2 !== this.#epoch || abort.signal.aborted) return;
2771
+ this.#status = { ...this.#status, phase: "connected", verificationUrl: null, message: "ChatGPT sign-in completed." };
2772
+ }, () => {
2773
+ if (epoch2 !== this.#epoch || abort.signal.aborted) return;
2774
+ this.#status = { ...this.#status, phase: "failed", verificationUrl: null, message: "ChatGPT sign-in failed. Retry the connection." };
2775
+ }).finally(() => {
2776
+ if (epoch2 === this.#epoch) this.#abort = void 0;
2777
+ });
2778
+ return this.status();
2779
+ }
2780
+ cancel() {
2781
+ ++this.#epoch;
2782
+ this.#abort?.abort();
2783
+ this.#abort = void 0;
2784
+ this.#status = { ...this.#status, phase: "cancelled", message: "ChatGPT sign-in cancelled.", verificationUrl: null, lines: [] };
2785
+ return this.status();
2786
+ }
2787
+ };
2788
+
1602
2789
  // packages/cli/src/web/codex-auth-controller.ts
1603
2790
  import { spawnSync as spawnSync2 } from "node:child_process";
1604
2791
 
@@ -1642,8 +2829,8 @@ function startCodexDeviceAuth(options) {
1642
2829
  let settled = false;
1643
2830
  let cancelled = false;
1644
2831
  let browserOpened = false;
1645
- const publish = (phase, message) => {
1646
- options.onUpdate({ phase, lines: [...lines], message });
2832
+ const publish = (phase, message2) => {
2833
+ options.onUpdate({ phase, lines: [...lines], message: message2 });
1647
2834
  };
1648
2835
  const tryOpenBrowser = (text2) => {
1649
2836
  if (browserOpened) return;
@@ -1674,14 +2861,14 @@ function startCodexDeviceAuth(options) {
1674
2861
  }
1675
2862
  publish("running", "Complete the ChatGPT Codex device sign-in in your browser.");
1676
2863
  };
1677
- const finish = (phase, message) => {
2864
+ const finish = (phase, message2) => {
1678
2865
  if (settled) return;
1679
2866
  settled = true;
1680
2867
  if (pending.trim().length > 0) {
1681
2868
  lines.push(pending.trim());
1682
2869
  if (lines.length > MAX_VISIBLE_LINES2) lines.shift();
1683
2870
  }
1684
- publish(phase, message);
2871
+ publish(phase, message2);
1685
2872
  };
1686
2873
  let child;
1687
2874
  try {
@@ -1814,10 +3001,109 @@ var CodexAuthController = class {
1814
3001
  }
1815
3002
  };
1816
3003
 
3004
+ // packages/cli/src/web/workspace-directories.ts
3005
+ import { opendir, realpath, stat } from "node:fs/promises";
3006
+ import { homedir } from "node:os";
3007
+ import { dirname as dirname2, join as join5, resolve } from "node:path";
3008
+ var MAX_FOLDERS = 200;
3009
+ var MAX_SCANNED_ENTRIES = 2e3;
3010
+ async function listWorkspaceDirectories(input) {
3011
+ if (input !== void 0 && (typeof input !== "string" || input.length > 4096 || input.includes("\0"))) throw new Error("Enter a valid folder path.");
3012
+ const homePath = await realpath(homedir()).catch(() => resolve(homedir()));
3013
+ let path;
3014
+ try {
3015
+ path = await realpath(typeof input === "string" && input.trim() ? resolve(input.trim()) : homePath);
3016
+ } catch {
3017
+ throw new Error("That folder could not be found on this host.");
3018
+ }
3019
+ if (!(await stat(path)).isDirectory()) throw new Error("Choose a folder rather than a file.");
3020
+ let directory;
3021
+ try {
3022
+ directory = await opendir(path);
3023
+ } catch {
3024
+ throw new Error("This host cannot open that folder. Check its permissions or enter another path.");
3025
+ }
3026
+ const entries = [];
3027
+ let scanned = 0;
3028
+ let truncated = false;
3029
+ for await (const entry of directory) {
3030
+ if (++scanned > MAX_SCANNED_ENTRIES) {
3031
+ truncated = true;
3032
+ break;
3033
+ }
3034
+ if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
3035
+ try {
3036
+ const canonical = await realpath(join5(path, entry.name));
3037
+ if (!(await stat(canonical)).isDirectory()) continue;
3038
+ if (entries.length >= MAX_FOLDERS) {
3039
+ truncated = true;
3040
+ break;
3041
+ }
3042
+ entries.push({ name: entry.name, path: canonical });
3043
+ } catch {
3044
+ }
3045
+ }
3046
+ entries.sort((a, b) => a.name.localeCompare(b.name, void 0, { numeric: true, sensitivity: "base" }));
3047
+ const parent = dirname2(path);
3048
+ return { path, parentPath: parent === path ? null : parent, homePath, entries, truncated };
3049
+ }
3050
+
3051
+ // packages/cli/src/web/workspace-folder-picker.ts
3052
+ import { execFile } from "node:child_process";
3053
+ import { realpath as realpath2, stat as stat2 } from "node:fs/promises";
3054
+ import { resolve as resolve2 } from "node:path";
3055
+ import { promisify } from "node:util";
3056
+ var execute = promisify(execFile);
3057
+ var PICKER_SCRIPT = `on run argv
3058
+ activate
3059
+ try
3060
+ if (count of argv) > 0 then
3061
+ set chosen to choose folder with prompt "Choose the folder where Zero works" default location (POSIX file (item 1 of argv))
3062
+ else
3063
+ set chosen to choose folder with prompt "Choose the folder where Zero works"
3064
+ end if
3065
+ return POSIX path of chosen
3066
+ on error number -128
3067
+ return ""
3068
+ end try
3069
+ end run`;
3070
+ var pickerActive = false;
3071
+ async function chooseWorkspaceFolder(input, dependencies = {}) {
3072
+ if (input !== void 0 && (typeof input !== "string" || input.length > 4096 || input.includes("\0"))) throw new Error("Enter a valid folder path.");
3073
+ if ((dependencies.platform ?? process.platform) !== "darwin") return { supported: false, path: null };
3074
+ if (pickerActive) throw new Error("A folder chooser is already open on this host.");
3075
+ pickerActive = true;
3076
+ try {
3077
+ const args = ["-e", PICKER_SCRIPT];
3078
+ if (typeof input === "string" && input.trim()) {
3079
+ const initial = await realpath2(resolve2(input));
3080
+ if (!(await stat2(initial)).isDirectory()) throw new Error("Choose a folder rather than a file.");
3081
+ args.push(initial);
3082
+ }
3083
+ let stdout;
3084
+ try {
3085
+ ({ stdout } = await (dependencies.run ?? execute)("/usr/bin/osascript", args, { encoding: "utf8", timeout: 12e4, maxBuffer: 16384, windowsHide: true }));
3086
+ } catch {
3087
+ throw new Error("The folder chooser could not complete on this host. Try again or enter a folder path.");
3088
+ }
3089
+ const selected = stdout.replace(/\r?\n$/, "");
3090
+ if (!selected) return { supported: true, path: null };
3091
+ if (selected.length > 4096 || selected.includes("\0")) throw new Error("The folder chooser returned an invalid path.");
3092
+ const path = await realpath2(selected);
3093
+ if (!(await stat2(path)).isDirectory()) throw new Error("The folder chooser did not return an existing folder.");
3094
+ return { supported: true, path };
3095
+ } finally {
3096
+ pickerActive = false;
3097
+ }
3098
+ }
3099
+
1817
3100
  // packages/cli/src/web/operator-services.ts
1818
3101
  var MODEL_ROLES = ["discovery", "attack", "verify", "report", "audit", "review"];
1819
3102
  var reservedToolNames = Object.values(TOOL_DEFINITIONS).map((tool) => tool.name);
1820
3103
  var runtimeEnvironments = /* @__PURE__ */ new WeakMap();
3104
+ function assertPlanAllowed(providerId, policy) {
3105
+ if (providerId === "chatgpt-plan" && policy.allowChatGptPlan === false) throw new OperatorError(403, "local_only", "Native ChatGPT plan connections are available only in the local open-source application.");
3106
+ }
1821
3107
  var runtimeContextLimits = /* @__PURE__ */ new WeakMap();
1822
3108
  var pluginManager;
1823
3109
  var pluginManagerPromise;
@@ -1862,7 +3148,7 @@ function webRuntimeEnv() {
1862
3148
  return Object.fromEntries(Object.entries(env).filter((entry) => entry[1] !== void 0));
1863
3149
  }
1864
3150
  function publicMessage(error) {
1865
- let message = error instanceof Error ? error.message : String(error);
3151
+ let message2 = error instanceof Error ? error.message : String(error);
1866
3152
  const secrets = /* @__PURE__ */ new Set();
1867
3153
  for (const provider2 of PROVIDERS) for (const variable of provider2.envVars) {
1868
3154
  const value = process.env[variable];
@@ -1875,8 +3161,8 @@ function publicMessage(error) {
1875
3161
  const env = { ...process.env };
1876
3162
  maybeLoadCodexAuth({ env });
1877
3163
  for (const variable of PROVIDERS.find((provider2) => provider2.id === "chatgpt-codex").envVars) if (env[variable]) secrets.add(env[variable]);
1878
- for (const secret of secrets) if (secret) message = message.split(secret).join("[redacted]");
1879
- return message.replace(/(https?:\/\/)[^\s/@]+:[^\s/@]+@/g, "$1[redacted]@").replace(/([?&](?:api[_-]?key|access_token|refresh_token|id_token|token|secret|password)=)[^&\s"'<>]+/gi, "$1[redacted]").slice(0, 4e3);
3164
+ for (const secret of secrets) if (secret) message2 = message2.split(secret).join("[redacted]");
3165
+ return message2.replace(/(https?:\/\/)[^\s/@]+:[^\s/@]+@/g, "$1[redacted]@").replace(/([?&](?:api[_-]?key|access_token|refresh_token|id_token|token|secret|password)=)[^&\s"'<>]+/gi, "$1[redacted]").slice(0, 4e3);
1880
3166
  }
1881
3167
  function runtimeDiagnostics(runtime) {
1882
3168
  const diagnostics = runtime.getConfigurationDiagnostics();
@@ -1957,21 +3243,31 @@ async function validateRuntimeModels(runtime) {
1957
3243
  if (model !== "auto" && !models.some((entry) => entry.id === model.replace(/^openai\//, ""))) throw new OperatorError(409, "model_not_available", "A role model is not available to this ChatGPT account.");
1958
3244
  }
1959
3245
  }
3246
+ if (diagnostics.provider === "chatgpt-plan") {
3247
+ const models = await runtime.availableModelCatalog(AbortSignal.timeout(1e4));
3248
+ if (!models.some((model) => model.id === runtime.resolvedModel())) throw new OperatorError(409, "model_not_available", "This model is not available to the connected ChatGPT plan.");
3249
+ for (const model of Object.values(runtime.modelSelection().agentModels)) {
3250
+ if (model !== "auto" && !models.some((entry) => entry.id === model)) throw new OperatorError(409, "model_not_available", "A role model is not available to the connected ChatGPT plan.");
3251
+ }
3252
+ }
1960
3253
  for (const role of Object.keys(runtime.modelSelection().agentModels)) {
1961
3254
  if (runtime.modelSelection().agentModels[role] !== "auto") await runtime.forkForSubagent(12e4, { role });
1962
3255
  }
1963
3256
  }
1964
- async function createWebConsoleRuntime(selection = {}) {
3257
+ async function createWebConsoleRuntime(selection = {}, policy = {}) {
1965
3258
  validateSelection(selection);
3259
+ assertPlanAllowed(selection.providerId, policy);
1966
3260
  const env = webRuntimeEnv();
3261
+ if (!selection.providerId) assertPlanAllowed(env.ZERO_SELECTED_PROVIDER || env.ZERO_PROVIDER || env.ZERO_FORCE_PROVIDER, policy);
1967
3262
  const { runtime } = await createPreferredConsoleRuntime({
1968
3263
  provider: selection.providerId,
1969
3264
  model: selection.model,
1970
3265
  agentModels: selection.agentModels,
1971
3266
  singleModel: selection.singleModel,
1972
3267
  autoRoute: selection.autoRoute,
1973
- env
1974
- });
3268
+ env,
3269
+ ...selection.providerId === "chatgpt-plan" ? { siwcConnection: getSiwcConnection(env.HOME) } : {}
3270
+ }, policy);
1975
3271
  await validateRuntimeModels(runtime);
1976
3272
  if (selection.reasoningEffort !== void 0) {
1977
3273
  try {
@@ -1984,9 +3280,14 @@ async function createWebConsoleRuntime(selection = {}) {
1984
3280
  if (selection.model !== void 0) saveAppliedModelPreference(runtime);
1985
3281
  return { runtime, info: describeWebConsoleRuntime(runtime) };
1986
3282
  }
1987
- async function reloadWebConsoleRuntimeConnection(runtime) {
3283
+ async function reloadWebConsoleRuntimeConnection(runtime, policy = {}) {
1988
3284
  const providerId = runtime.resolvedProvider();
1989
3285
  const model = runtime.resolvedModel();
3286
+ assertPlanAllowed(providerId, policy);
3287
+ if (providerId === "chatgpt-plan") {
3288
+ await validateRuntimeModels(runtime);
3289
+ return describeWebConsoleRuntime(runtime);
3290
+ }
1990
3291
  const effort = runtime.reasoningConfiguration()?.effort;
1991
3292
  const env = webRuntimeEnv();
1992
3293
  const { runtime: candidate } = await createPreferredConsoleRuntime({
@@ -1994,7 +3295,7 @@ async function reloadWebConsoleRuntimeConnection(runtime) {
1994
3295
  model,
1995
3296
  ...runtime.modelSelection(),
1996
3297
  env
1997
- });
3298
+ }, policy);
1998
3299
  if (candidate.resolvedProvider() !== providerId || candidate.resolvedModel() !== model) throw new OperatorError(409, "connection_changed", "Reconnect the conversation's selected provider and model first.");
1999
3300
  await validateRuntimeModels(candidate);
2000
3301
  if (effort !== void 0) candidate.setReasoningEffort(effort);
@@ -2005,25 +3306,29 @@ async function reloadWebConsoleRuntimeConnection(runtime) {
2005
3306
  else runtimeContextLimits.delete(runtime);
2006
3307
  return describeWebConsoleRuntime(runtime);
2007
3308
  }
2008
- async function applyWebConsoleRuntimeSelection(runtime, selection) {
3309
+ async function applyWebConsoleRuntimeSelection(runtime, selection, policy = {}) {
2009
3310
  validateSelection(selection);
2010
3311
  const currentProvider = runtime.resolvedProvider();
2011
3312
  let providerId = selection.providerId;
2012
3313
  if (providerId === void 0 && selection.model !== void 0) {
2013
3314
  const inferred = modelProvider(selection.model);
2014
- if (inferred !== "unknown" && inferred !== currentProvider && !(currentProvider === "chatgpt-codex" && inferred === "openai")) providerId = inferred;
3315
+ if (inferred !== "unknown" && inferred !== currentProvider && !(["chatgpt-codex", "chatgpt-plan"].includes(currentProvider) && inferred === "openai")) providerId = inferred;
2015
3316
  }
2016
3317
  const targetProvider = providerId ?? currentProvider;
3318
+ assertPlanAllowed(targetProvider, policy);
2017
3319
  let candidate;
3320
+ let planConnection;
2018
3321
  if (targetProvider !== currentProvider) {
2019
3322
  const env = webRuntimeEnv();
3323
+ if (targetProvider === "chatgpt-plan") planConnection = getSiwcConnection(env.HOME);
2020
3324
  const created = await createPreferredConsoleRuntime({
2021
3325
  provider: targetProvider,
2022
3326
  model: selection.model,
2023
3327
  env,
2024
3328
  ...runtime.modelSelection(),
2025
- ...selection
2026
- });
3329
+ ...selection,
3330
+ ...planConnection ? { siwcConnection: planConnection } : {}
3331
+ }, policy);
2027
3332
  candidate = created.runtime;
2028
3333
  await validateRuntimeModels(candidate);
2029
3334
  runtimeEnvironments.set(candidate, env);
@@ -2042,6 +3347,7 @@ async function applyWebConsoleRuntimeSelection(runtime, selection) {
2042
3347
  runtime.reconfigure({
2043
3348
  model: candidate.resolvedModel(),
2044
3349
  provider: targetProvider,
3350
+ ...planConnection ? { siwcConnection: planConnection } : {},
2045
3351
  ...candidate.modelSelection(),
2046
3352
  ...targetProvider !== currentProvider ? { env: runtimeEnvironments.get(candidate) } : {}
2047
3353
  });
@@ -2054,15 +3360,15 @@ async function applyWebConsoleRuntimeSelection(runtime, selection) {
2054
3360
  return describeWebConsoleRuntime(runtime);
2055
3361
  }
2056
3362
  var OperatorError = class extends Error {
2057
- constructor(status, code, message) {
2058
- super(message);
3363
+ constructor(status, code, message2) {
3364
+ super(message2);
2059
3365
  this.status = status;
2060
3366
  this.code = code;
2061
3367
  }
2062
3368
  status;
2063
3369
  code;
2064
3370
  };
2065
- function object(input) {
3371
+ function object2(input) {
2066
3372
  if (!input || typeof input !== "object" || Array.isArray(input)) throw new OperatorError(400, "invalid_input", "Expected a JSON object.");
2067
3373
  return input;
2068
3374
  }
@@ -2088,12 +3394,16 @@ function settingsView() {
2088
3394
  var WebOperatorServices = class {
2089
3395
  #servicePlugins = new ServicePluginServices();
2090
3396
  #codex = new CodexAuthController();
3397
+ #plan = new ChatGptPlanAuthController();
3398
+ #allowChatGptPlan;
2091
3399
  #auth = /* @__PURE__ */ new Map();
3400
+ #catalogRefresh;
2092
3401
  #registryItems = /* @__PURE__ */ new Map();
2093
3402
  #registryError = null;
2094
3403
  #feedback = null;
2095
3404
  constructor(options = {}) {
2096
3405
  isTurnActive = options.isTurnActive ?? (() => false);
3406
+ this.#allowChatGptPlan = options.allowChatGptPlan !== false;
2097
3407
  }
2098
3408
  #publicAuth(status) {
2099
3409
  return {
@@ -2103,18 +3413,34 @@ var WebOperatorServices = class {
2103
3413
  };
2104
3414
  }
2105
3415
  #authStatus(id, configured) {
3416
+ if (id === "chatgpt-plan") return this.#plan.status();
2106
3417
  if (id === "chatgpt-codex") return this.#publicAuth(this.#codex.status());
2107
3418
  const flow = this.#auth.get(id);
2108
3419
  if (flow?.status.phase === "running") return { ...flow.status, lines: [...flow.status.lines] };
2109
3420
  if (configured) return webAuthStatus({ phase: "connected", message: "Credentials are configured. The first request verifies account access.", lines: [] }, Boolean(PROVIDER_DEVICE_AUTH[id]));
2110
3421
  if (flow && flow.status.phase !== "connected") return { ...flow.status, lines: [...flow.status.lines] };
2111
- return webAuthStatus({ phase: "idle", message: "Not connected.", lines: [] }, Boolean(PROVIDER_DEVICE_AUTH[id]));
3422
+ return webAuthStatus({ phase: "idle", message: PROVIDERS.find((p) => p.id === id)?.hint ?? "Not connected.", lines: [] }, Boolean(PROVIDER_DEVICE_AUTH[id]));
2112
3423
  }
2113
3424
  #providers() {
2114
3425
  const env = webRuntimeEnv();
2115
3426
  const store = loadAccountStore();
2116
3427
  const configs = loadConnectionConfigs();
2117
- return PROVIDERS.map((info) => {
3428
+ return PROVIDERS.filter((info) => this.#allowChatGptPlan || info.id !== "chatgpt-plan").map((info) => {
3429
+ if (info.id === "chatgpt-plan") {
3430
+ const profiles = listChatGptPlanProfiles();
3431
+ const active = profiles.find((p) => p.active && p.status === "connected");
3432
+ return {
3433
+ id: info.id,
3434
+ label: info.label,
3435
+ methods: info.methods,
3436
+ configured: Boolean(active),
3437
+ source: active ? "account-store" : null,
3438
+ diagnostics: { valid: Boolean(active?.sharing), reason: active?.sharing ? null : active ? "plan_sharing_required" : "missing_connection", message: active?.sharing ? null : active ? "ChatGPT identity is connected. Grant plan usage to use models." : "Connect your ChatGPT account." },
3439
+ accounts: profiles.map((p) => ({ accountId: p.id, kind: "oauth", active: p.active, label: p.label, status: p.status, sharing: p.sharing })),
3440
+ configuration: {},
3441
+ auth: this.#plan.status()
3442
+ };
3443
+ }
2118
3444
  let diagnostics = {
2119
3445
  valid: false,
2120
3446
  reason: "missing_key",
@@ -2139,7 +3465,7 @@ var WebOperatorServices = class {
2139
3465
  return {
2140
3466
  id: info.id,
2141
3467
  label: info.id === "openai" ? "OpenAI / Custom AI Provider" : info.label,
2142
- methods: info.methods,
3468
+ methods: info.methods.includes("api-key") && !PROVIDER_DEVICE_AUTH[info.id] ? info.methods.filter((method) => method !== "oauth") : info.methods,
2143
3469
  configured,
2144
3470
  source: configured ? environment ? "environment" : store.providers[info.id] ? "account-store" : "codex-file" : null,
2145
3471
  diagnostics,
@@ -2151,16 +3477,23 @@ var WebOperatorServices = class {
2151
3477
  }
2152
3478
  async #models(providerId) {
2153
3479
  if (providerId !== void 0) providerId = provider(providerId).id;
3480
+ assertPlanAllowed(providerId, { allowChatGptPlan: this.#allowChatGptPlan });
2154
3481
  const env = webRuntimeEnv();
2155
3482
  const ids = providerStates(env).filter((state) => state.configured && (!providerId || state.id === providerId)).map((state) => state.id);
2156
- const [discovered] = await Promise.all([discoverConnectionModels(env, ids), syncModelCatalog()]);
3483
+ if (this.#allowChatGptPlan && (!providerId || providerId === "chatgpt-plan") && listChatGptPlanProfiles().some((p) => p.active && p.status === "connected" && p.sharing)) ids.push("chatgpt-plan");
3484
+ if (!this.#catalogRefresh) {
3485
+ this.#catalogRefresh = Promise.resolve().then(() => syncModelCatalog()).catch(() => null).finally(() => {
3486
+ this.#catalogRefresh = void 0;
3487
+ });
3488
+ }
3489
+ const discovered = await discoverConnectionModels(env, ids);
2157
3490
  const metadata = new Map(buildFullModelCatalog().map((model) => [`${model.provider}/${model.id}`, model]));
2158
3491
  const rows = discovered.models.map((model) => ({
2159
3492
  id: model.id,
2160
3493
  provider: model.provider,
2161
- price: model.provider === "chatgpt-codex" ? "Included in subscription" : model.provider === "cline" && model.id.startsWith("cline-pass/") ? "ClinePass plan (access unverified)" : metadata.get(`${model.provider}/${model.id}`)?.price ?? "Unknown rate",
3494
+ price: model.provider === "chatgpt-plan" ? "Shared ChatGPT allowance" : model.provider === "chatgpt-codex" ? "Included in subscription" : model.provider === "cline" && model.id.startsWith("cline-pass/") ? "ClinePass plan (access unverified)" : metadata.get(`${model.provider}/${model.id}`)?.price ?? "Unknown rate",
2162
3495
  contextWindowTokens: model.contextTokens ?? resolveContextLimit({ modelId: model.id, providerId: model.provider })?.tokens ?? null,
2163
- source: model.source === "catalog" ? "public-catalog" : "account"
3496
+ source: model.provider !== "chatgpt-plan" && model.source === "catalog" ? "public-catalog" : "account"
2164
3497
  }));
2165
3498
  const configuredModel = env.OPENAI_MODEL;
2166
3499
  if (configuredModel && ids.includes("openai") && !rows.some((row) => row.provider === "openai" && row.id === configuredModel)) {
@@ -2174,9 +3507,20 @@ var WebOperatorServices = class {
2174
3507
  };
2175
3508
  }
2176
3509
  async #connections(input) {
2177
- const body = object(input);
3510
+ const body = object2(input);
2178
3511
  const info = provider(body.providerId);
2179
3512
  const action = text(body.action, "connection action", 32);
3513
+ assertPlanAllowed(info.id, { allowChatGptPlan: this.#allowChatGptPlan });
3514
+ if (info.id === "chatgpt-plan") {
3515
+ const id = text(body.accountId, "account ID", 128);
3516
+ if (action === "activate") await selectChatGptPlanProfile(id);
3517
+ else if (action === "disconnect") {
3518
+ this.#plan.cancel();
3519
+ const result = await signOutChatGptPlan(id);
3520
+ return { providers: this.#providers(), revoked: result.revoked, message: result.revoked ? "Signed out locally and provider revocation completed." : "Signed out locally. Provider revocation could not be confirmed; review the connection in ChatGPT Settings." };
3521
+ } else throw new OperatorError(400, "unsupported_auth", "Use native ChatGPT browser sign-in.");
3522
+ return { providers: this.#providers() };
3523
+ }
2180
3524
  if (action === "configure") {
2181
3525
  const config = validateConnectionConfig(info.id, {
2182
3526
  ...body.baseUrl !== void 0 ? { baseUrl: text(body.baseUrl, "API endpoint") } : {},
@@ -2215,11 +3559,17 @@ var WebOperatorServices = class {
2215
3559
  if (!saveAccountStore(store)) throw new OperatorError(500, "persistence_failed", "Could not save the private credential account store.");
2216
3560
  return { providers: this.#providers() };
2217
3561
  }
2218
- #deviceAuth(id, method) {
3562
+ #deviceAuth(id, method, input) {
2219
3563
  const info = provider(id);
3564
+ assertPlanAllowed(info.id, { allowChatGptPlan: this.#allowChatGptPlan });
3565
+ if (info.id === "chatgpt-plan") {
3566
+ const body = input === void 0 ? {} : object2(input);
3567
+ const profileId = body.profileId === void 0 ? void 0 : text(body.profileId, "profile ID", 128);
3568
+ return { status: method === "DELETE" ? this.#plan.cancel() : this.#plan.start(profileId) };
3569
+ }
2220
3570
  if (info.id === "chatgpt-codex") return { status: this.#publicAuth(method === "DELETE" ? this.#codex.cancel() : this.#codex.start()) };
2221
3571
  const config = PROVIDER_DEVICE_AUTH[info.id];
2222
- if (!config) throw new OperatorError(409, "auth_unavailable", "This provider does not support browser sign-in; connect its API key instead.");
3572
+ if (!config) throw new OperatorError(409, "auth_unavailable", info.hint);
2223
3573
  const previous = this.#auth.get(info.id);
2224
3574
  if (method === "DELETE") {
2225
3575
  previous?.session?.cancel();
@@ -2314,7 +3664,7 @@ var WebOperatorServices = class {
2314
3664
  }
2315
3665
  async #pluginAction(action, input) {
2316
3666
  if (action === "run" && consoleExecutionProfile() === "smolvm") throw new OperatorError(409, "isolated_execution_required", "Plugins load automatically inside new SmolVM chats. Start a new chat to use an approved plugin.");
2317
- const body = object(input);
3667
+ const body = object2(input);
2318
3668
  const id = text(body.id, "plugin ID", 64);
2319
3669
  if (action === "install") {
2320
3670
  const kind = body.kind === "theme" ? "theme" : "plugin";
@@ -2355,7 +3705,7 @@ var WebOperatorServices = class {
2355
3705
  const path = pathname.slice("/api/console/".length);
2356
3706
  const servicePluginResult = await this.#servicePlugins.handle(path, method, input);
2357
3707
  if (servicePluginResult) return servicePluginResult;
2358
- if (!/^(providers(?:\/[^/]+(?:\/device-auth)?)?|models|connections|settings(?:\/reset)?|themes|plugins(?:\/(?:install|enable|disable|run))?|doctor|tools|project|checks|feedback)$/.test(path)) return null;
3708
+ if (!/^(providers(?:\/[^/]+(?:\/device-auth)?)?|models|connections|settings(?:\/reset)?|themes|plugins(?:\/(?:install|enable|disable|run))?|doctor|tools|project(?:\/(?:directories|choose-directory))?|checks|feedback)$/.test(path)) return null;
2359
3709
  try {
2360
3710
  let data;
2361
3711
  let status = 200;
@@ -2363,15 +3713,16 @@ var WebOperatorServices = class {
2363
3713
  else if (path === "models" && method === "GET") data = await this.#models(query.get("providerId") ?? void 0);
2364
3714
  else if (path === "connections" && method === "POST") data = await this.#connections(input);
2365
3715
  else if (/^providers\/[^/]+\/device-auth$/.test(path) && ["POST", "DELETE"].includes(method)) {
2366
- data = this.#deviceAuth(decodeURIComponent(path.split("/")[1]), method);
3716
+ data = this.#deviceAuth(decodeURIComponent(path.split("/")[1]), method, input);
2367
3717
  status = method === "POST" ? 202 : 200;
2368
3718
  } else if (/^providers\/[^/]+$/.test(path) && method === "GET") {
2369
3719
  const info = provider(decodeURIComponent(path.split("/")[1]));
3720
+ assertPlanAllowed(info.id, { allowChatGptPlan: this.#allowChatGptPlan });
2370
3721
  const state = this.#providers().find((entry) => entry.id === info.id);
2371
3722
  data = { provider: state, status: state.auth };
2372
3723
  } else if (path === "settings" && method === "GET") data = settingsView();
2373
3724
  else if (path === "settings" && method === "PATCH") {
2374
- const body = object(input);
3725
+ const body = object2(input);
2375
3726
  const key = text(body.key, "setting", 128);
2376
3727
  const def = SETTING_DEFS.find((entry) => entry.key === key);
2377
3728
  const internalBoolean = key === "onboardingCompleted" || key === "diagnosticReportingPrompted";
@@ -2383,7 +3734,7 @@ var WebOperatorServices = class {
2383
3734
  data = { ...settingsView(), persisted, ...!persisted ? { error: "Settings changed in this process but could not be saved to disk.", code: "persistence_failed" } : {} };
2384
3735
  if (!persisted) status = 507;
2385
3736
  } else if (path === "settings/reset" && method === "POST") {
2386
- const body = object(input);
3737
+ const body = object2(input);
2387
3738
  const keys = body.keys ?? SETTING_DEFS.map((def) => def.key);
2388
3739
  if (!Array.isArray(keys) || keys.some((key) => typeof key !== "string" || !SETTING_DEFS.some((def) => def.key === key))) throw new OperatorError(400, "invalid_setting", "Reset keys must name declared settings.");
2389
3740
  const persisted = resetSettings(DEFAULT_SETTINGS, keys);
@@ -2408,8 +3759,12 @@ var WebOperatorServices = class {
2408
3759
  } else if (path === "tools" && method === "GET") {
2409
3760
  const roleTools = Object.fromEntries(MODEL_ROLES.map((role) => [role, new Set(getToolsForRole(role, { hasScope: true, webMode: true, hasBrowser: true, allowScanners: true }).map((tool) => tool.name))]));
2410
3761
  data = { roles: MODEL_ROLES, tools: Object.values(TOOL_DEFINITIONS).map(({ name, description }) => ({ name, description, roles: MODEL_ROLES.filter((role) => roleTools[role].has(name)) })), plugins: pluginManager?.current().toolDefinitions().map(({ name, description }) => ({ name, description })) ?? [] };
3762
+ } else if (path === "project/choose-directory" && method === "POST") {
3763
+ data = await chooseWorkspaceFolder(object2(input).path);
3764
+ } else if (path === "project/directories" && method === "POST") {
3765
+ data = await listWorkspaceDirectories(object2(input).path);
2411
3766
  } else if (path === "project" && method === "GET") {
2412
- const projectPath = realpathSync(resolve(query.get("path") ?? process.cwd()));
3767
+ const projectPath = realpathSync(resolve3(query.get("path") ?? process.cwd()));
2413
3768
  if (!statSync(projectPath).isDirectory()) throw new OperatorError(400, "invalid_project", "Project path must name a local directory.");
2414
3769
  const git = { root: null, branch: null, dirty: false, error: null };
2415
3770
  try {
@@ -2422,15 +3777,15 @@ var WebOperatorServices = class {
2422
3777
  data = { path: projectPath, name: basename(projectPath), git };
2423
3778
  } else if (path === "checks" && method === "GET") data = listProjectReviewChecks(query.get("path") ?? process.cwd());
2424
3779
  else if (path === "checks" && method === "POST") {
2425
- const body = object(input);
2426
- const mutation = object(body.mutation);
3780
+ const body = object2(input);
3781
+ const mutation = object2(body.mutation);
2427
3782
  const action = text(mutation.action, "review check action", 32);
2428
3783
  if (!["propose", "add", "enable", "disable", "set", "remove"].includes(action)) throw new OperatorError(400, "invalid_action", "Unsupported review check action.");
2429
3784
  if (mutation.approved !== void 0 && typeof mutation.approved !== "boolean") throw new OperatorError(400, "invalid_approval", "Approval must be an explicit boolean.");
2430
3785
  if (mutation.expectedRevision !== void 0 && (!Number.isSafeInteger(mutation.expectedRevision) || Number(mutation.expectedRevision) < 1)) throw new OperatorError(400, "invalid_revision", "Expected revision must be a positive integer.");
2431
3786
  data = updateProjectReviewChecks(body.path === void 0 ? process.cwd() : text(body.path, "project path"), mutation);
2432
3787
  } else if (path === "feedback" && method === "POST") {
2433
- const body = object(input);
3788
+ const body = object2(input);
2434
3789
  if (body.action === "cancel") {
2435
3790
  this.#feedback = null;
2436
3791
  data = { cancelled: true, submitted: false };
@@ -2449,7 +3804,7 @@ var WebOperatorServices = class {
2449
3804
  if (body.submit === true) {
2450
3805
  const preview = buildSubmitPreview(payload);
2451
3806
  if (!preview) throw new OperatorError(409, "submission_unavailable", "Local feedback was saved, but reporting is opted out or no supported HTTPS destination is available.");
2452
- const id = randomUUID2();
3807
+ const id = randomUUID3();
2453
3808
  this.#feedback = { id, payload, preview };
2454
3809
  data = { saved: true, path: saved.path, submitted: false, previewId: id, preview: { ...preview, url: publicMessage(preview.url) } };
2455
3810
  } else data = { saved: true, path: saved.path, submitted: false };
@@ -2461,6 +3816,7 @@ var WebOperatorServices = class {
2461
3816
  }
2462
3817
  }
2463
3818
  dispose() {
3819
+ this.#plan.cancel();
2464
3820
  this.#codex.cancel();
2465
3821
  for (const flow of this.#auth.values()) flow.session?.cancel();
2466
3822
  pluginManager?.dispose();
@@ -2470,6 +3826,8 @@ var WebOperatorServices = class {
2470
3826
  export {
2471
3827
  sanitizeComposerText,
2472
3828
  createSessionPluginHostManager,
3829
+ jwtVerify,
3830
+ createRemoteJWKSet,
2473
3831
  getWebConsolePluginHostManager,
2474
3832
  flushWebConsolePlugins,
2475
3833
  describeWebConsoleRuntime,