very-happy-cli 0.2.191 → 0.2.192

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 (212) hide show
  1. package/dist/{AcpBackend-DgrIc1vH.cjs → AcpBackend-BQO4ShOy.cjs} +3 -3
  2. package/dist/{AcpBackend-CCy_9AfR.mjs → AcpBackend-CGHTDJd9.mjs} +3 -3
  3. package/dist/{AcpSessionManager-CQnxx7gD.mjs → AcpSessionManager-G0xD6Jbq.mjs} +2 -2
  4. package/dist/{AcpSessionManager-DVOzCD3P.cjs → AcpSessionManager-LlUMmcpB.cjs} +2 -2
  5. package/dist/{BasePermissionHandler-DYLN6Ec9.mjs → BasePermissionHandler-BmTIg376.mjs} +1 -1
  6. package/dist/{BasePermissionHandler-C9Ag7yvs.cjs → BasePermissionHandler-N6Ip3tFt.cjs} +1 -1
  7. package/dist/account-CCVT-HO_.mjs +240 -0
  8. package/dist/account-DtaouikP.cjs +245 -0
  9. package/dist/accountService-Bddy0zwL.cjs +571 -0
  10. package/dist/accountService-Dd9uqde2.mjs +566 -0
  11. package/dist/{acpSessionResume-Bi7pA1n_.mjs → acpSessionResume-BWEUxNtC.mjs} +1 -1
  12. package/dist/{acpSessionResume-TvP_4Zq2.cjs → acpSessionResume-BnHDk5eD.cjs} +1 -1
  13. package/dist/{agentHome-DGv105SR.mjs → agentHome-B0VnjkZW.mjs} +4 -4
  14. package/dist/{agentHome-DNUKJWOY.cjs → agentHome-CqQ29YY7.cjs} +4 -4
  15. package/dist/{api-jfeMRg5R.mjs → api-_LeBScjg.mjs} +10 -10
  16. package/dist/{api-BBxZ7y2z.cjs → api-hMDsC6Wg.cjs} +10 -10
  17. package/dist/{apiMachine-DRJ7y-BB.mjs → apiMachine-CgRldeJ6.mjs} +76 -21
  18. package/dist/{apiMachine-DqyjKBZG.cjs → apiMachine-CqW2m6Zr.cjs} +81 -26
  19. package/dist/{attachmentContent-BO2njyza.cjs → attachmentContent-BEeT2J5n.cjs} +2 -2
  20. package/dist/{attachmentContent-Dm_RIs5L.mjs → attachmentContent-CyptLIfq.mjs} +2 -2
  21. package/dist/{auth-DnxoVkkf.cjs → auth-C9NvNHhL.cjs} +5 -5
  22. package/dist/{auth-DLR3ksCF.cjs → auth-CA1OClsW.cjs} +8 -8
  23. package/dist/{auth-BYDtjVNb.mjs → auth-CFQikywl.mjs} +8 -8
  24. package/dist/{auth-DC6rg8lJ.mjs → auth-DL8_J9vu.mjs} +5 -5
  25. package/dist/{auto-D5Jhukq1.mjs → auto-CKI05w1D.mjs} +17 -17
  26. package/dist/{auto-CwO0u8hB.cjs → auto-uQOxlxLp.cjs} +17 -17
  27. package/dist/{bootstrap-rLaL3kTa.mjs → bootstrap-DaZ0Np7X.mjs} +2 -2
  28. package/dist/{bootstrap-sly4qPPY.cjs → bootstrap-DsZGc69k.cjs} +2 -2
  29. package/dist/{browser-CHpVgyni.mjs → browser-BUIaSHK2.mjs} +1 -1
  30. package/dist/{browser-BTgZ9d4i.cjs → browser-Ft0ASDm7.cjs} +1 -1
  31. package/dist/claudeAccountEnv-BOBpJ3k8.cjs +137 -0
  32. package/dist/claudeAccountEnv-ON24i0qv.mjs +132 -0
  33. package/dist/{claudeLocal-Bgb5GGsq.mjs → claudeLocal-B1ZVtryl.mjs} +5 -5
  34. package/dist/{claudeLocal-1vuTFcL8.cjs → claudeLocal-BMf9t4Fa.cjs} +5 -5
  35. package/dist/{claudeLocalLauncher-T7EfT68h.mjs → claudeLocalLauncher-Bp8bqF4y.mjs} +10 -10
  36. package/dist/{claudeLocalLauncher-DOsL6HFY.cjs → claudeLocalLauncher-C8TeJcfF.cjs} +10 -10
  37. package/dist/{claudeSessionFork-CPvi6yDX.mjs → claudeSessionFork-8AA47z8Y.mjs} +1 -1
  38. package/dist/{claudeSessionFork-Cko4SaVi.cjs → claudeSessionFork-YiktY55n.cjs} +1 -1
  39. package/dist/{client-Bi20Ka0h.mjs → client-Bm4oKvW7.mjs} +2 -2
  40. package/dist/{client-Bh1aUPh-.mjs → client-BmPaBnDK.mjs} +4 -4
  41. package/dist/{client-C-OdTbrU.cjs → client-CFHZfh9x.cjs} +4 -4
  42. package/dist/{client-BscskEBk.cjs → client-Crh8_cNx.cjs} +2 -2
  43. package/dist/{client-BXD66ZF5.mjs → client-Cxlp_D4I.mjs} +2 -2
  44. package/dist/{client-C5-C0t2a.cjs → client-D8XROyZc.cjs} +2 -2
  45. package/dist/codex/happyMcpStdioBridge.cjs +16 -16
  46. package/dist/codex/happyMcpStdioBridge.mjs +16 -16
  47. package/dist/{codexAppServerClient-DXhAf6i-.mjs → codexAppServerClient-BWJbLCQn.mjs} +3 -3
  48. package/dist/{codexAppServerClient-DKXeikEe.cjs → codexAppServerClient-q8GHQhyC.cjs} +3 -3
  49. package/dist/{codexCommand-CIaOiiOj.mjs → codexCommand-BfXfRQr4.mjs} +50 -48
  50. package/dist/{codexCommand-DvbbpYBS.cjs → codexCommand-BgpGg-Zy.cjs} +50 -48
  51. package/dist/{codexTermination-BszWfyk5.cjs → codexTermination-CVUF0X75.cjs} +1 -1
  52. package/dist/{codexTermination-BcQdEDaw.mjs → codexTermination-s9fd1gkA.mjs} +1 -1
  53. package/dist/{config-Di3Cf6js.cjs → config-BAjyTyYp.cjs} +3 -3
  54. package/dist/{config-OCEcVVK1.mjs → config-BF8XgLyc.mjs} +3 -3
  55. package/dist/{configuration-DfPBa-9d.cjs → configuration-CXEVKAyF.cjs} +1 -1
  56. package/dist/{configuration-ECqXu34R.mjs → configuration-IhRiLDVe.mjs} +1 -1
  57. package/dist/{connect-BTfAUhk8.mjs → connect-LZh1gr08.mjs} +13 -13
  58. package/dist/{connect-BPQRuOw5.cjs → connect-rCS56arw.cjs} +13 -13
  59. package/dist/{context-Co7hUaW-.cjs → context-3_S_mWz9.cjs} +1 -1
  60. package/dist/{context-CfgTFpCB.mjs → context-DO6F5YwH.mjs} +1 -1
  61. package/dist/{controlClient-ClI7A0qE.mjs → controlClient-8ILulwjc.mjs} +14 -5
  62. package/dist/{controlClient-C13_pSKG.cjs → controlClient-j7p5p3_7.cjs} +15 -4
  63. package/dist/{createSessionMetadata-Cf78KHtt.cjs → createSessionMetadata-DwdD_uVo.cjs} +2 -2
  64. package/dist/{createSessionMetadata-B0eT_Kfj.mjs → createSessionMetadata-oyaTZm1b.mjs} +2 -2
  65. package/dist/daemonAccounts-BCjDgoNt.cjs +51 -0
  66. package/dist/daemonAccounts-BJgt6IJe.mjs +27 -0
  67. package/dist/{defaultPermissionMode-oqTupStc.cjs → defaultPermissionMode-BFShzF55.cjs} +1 -1
  68. package/dist/{defaultPermissionMode-m6z2QVyP.mjs → defaultPermissionMode-Lt3PUCwY.mjs} +1 -1
  69. package/dist/{deterministicJson-CpFFgUL_.cjs → deterministicJson-DUN0v3St.cjs} +13 -13
  70. package/dist/{deterministicJson-BtSwbsok.mjs → deterministicJson-Dfp-7wUZ.mjs} +13 -13
  71. package/dist/{doctor-lsxmAK4o.mjs → doctor-B_UwMcVT.mjs} +7 -7
  72. package/dist/{doctor-BEU0_1Xv.cjs → doctor-FgUYTbAT.cjs} +7 -7
  73. package/dist/{downloadTarget-CikzJv1h.cjs → downloadTarget-BrrQEDxg.cjs} +6 -6
  74. package/dist/{downloadTarget-BXqXhNF7.mjs → downloadTarget-C0d6jRx-.mjs} +6 -6
  75. package/dist/{ensureDaemonRunning-BUuH-pbE.cjs → ensureDaemonRunning-Cq4FYI5Q.cjs} +5 -5
  76. package/dist/{ensureDaemonRunning-B_9WAlbU.mjs → ensureDaemonRunning-KUMFfIil.mjs} +5 -5
  77. package/dist/{handleResumeCommand-BK9XKH_l.mjs → handleResumeCommand-BGhVo3QH.mjs} +5 -5
  78. package/dist/{handleResumeCommand-Dj7oi2KO.cjs → handleResumeCommand-Cl9GIL5F.cjs} +5 -5
  79. package/dist/{index-BdOJOZ6J.mjs → index-BjXjMhGY.mjs} +4 -4
  80. package/dist/{index-CLUHaPU8.cjs → index-BzAYnYct.cjs} +110 -0
  81. package/dist/{index-CmZusg8Q.cjs → index-CQ_hLLCj.cjs} +3 -3
  82. package/dist/{index-Dg2NAF_-.cjs → index-CRipkiqo.cjs} +4 -4
  83. package/dist/{index-D3c7CLot.cjs → index-CZaLMmPC.cjs} +4 -4
  84. package/dist/{index-Cxso1rg4.mjs → index-Ca1Tt96A.mjs} +45 -41
  85. package/dist/{index-CauRYQKr.cjs → index-D8ODb0_U.cjs} +44 -40
  86. package/dist/{index-Bq8NKSCF.mjs → index-DYD3GM1m.mjs} +104 -1
  87. package/dist/{index-BjZnpGWX.mjs → index-JQDyJ3Li.mjs} +3 -3
  88. package/dist/{index-DuK9XYbZ.mjs → index-v5EmjT8l.mjs} +4 -4
  89. package/dist/index.cjs +2 -2
  90. package/dist/index.mjs +2 -2
  91. package/dist/{install-DXllkuy0.cjs → install-ClUA9tbC.cjs} +3 -3
  92. package/dist/{install-DTIveLOS.mjs → install-D6EHRtAN.mjs} +3 -3
  93. package/dist/lib.cjs +12 -12
  94. package/dist/lib.d.cts +282 -0
  95. package/dist/lib.d.mts +282 -0
  96. package/dist/lib.mjs +12 -12
  97. package/dist/{lidState-CD81ryTy.mjs → lidState-CZOXXdzv.mjs} +1 -1
  98. package/dist/{lidState-C9_DoF9i.cjs → lidState-DqoN7zH4.cjs} +1 -1
  99. package/dist/{localHappyAgentAuth-CCjUvOfi.cjs → localHappyAgentAuth-BnGCpHRX.cjs} +1 -1
  100. package/dist/{localHappyAgentAuth-Cg-m1lwm.mjs → localHappyAgentAuth-YHxDZ4x4.mjs} +1 -1
  101. package/dist/{logger-Ct2zvaq0.cjs → logger-8su64lqR.cjs} +2 -2
  102. package/dist/{logger-GcbI0eg2.mjs → logger-Fd_rNvgd.mjs} +2 -2
  103. package/dist/{machineMetadata-CXRmFNOV.mjs → machineMetadata-1HIIC7Bc.mjs} +3 -3
  104. package/dist/{machineMetadata-DDCVWb_x.cjs → machineMetadata-DYXt3p6u.cjs} +3 -3
  105. package/dist/{main-omGr_ONk.mjs → main-BI6GIzUL.mjs} +92 -48
  106. package/dist/{main-BHC-WIcM.cjs → main-C_GrcYkn.cjs} +92 -48
  107. package/dist/{mcp-xUzii0m8.cjs → mcp-BycIv9oQ.cjs} +18 -15
  108. package/dist/{mcp-D5hxmRAq.mjs → mcp-XGoxywno.mjs} +18 -15
  109. package/dist/{mirrorProtocol-Dfl8Ahyf.cjs → mirrorProtocol-DVnB8EO8.cjs} +3 -3
  110. package/dist/{mirrorProtocol-Lcx20Oby.mjs → mirrorProtocol-DXT3rv7T.mjs} +3 -3
  111. package/dist/{package-BsUHyqWe.mjs → package-6KkRAops.mjs} +7 -7
  112. package/dist/{package-9n7wd2dT.cjs → package-iuLlSiSF.cjs} +7 -7
  113. package/dist/{panels-BfknEmt7.cjs → panels-0C89q0Tu.cjs} +5 -5
  114. package/dist/{panels-CpEKWWbI.mjs → panels-B5Di2zb2.mjs} +5 -5
  115. package/dist/{peerTools-CElYh-5u.cjs → peerTools-CANTX_mG.cjs} +5 -5
  116. package/dist/{peerTools-CwCe6tmJ.mjs → peerTools-CKJ-IDM4.mjs} +5 -5
  117. package/dist/{persistence-A2NeERZJ.cjs → persistence-B4ttN-fR.cjs} +2 -2
  118. package/dist/{persistence-Cpw4yJs8.mjs → persistence-DWcHe035.mjs} +2 -2
  119. package/dist/{piRunnerArgs-BnFU0K73.cjs → piRunnerArgs-BOkfxyak.cjs} +1 -1
  120. package/dist/{piRunnerArgs-Bqmu16He.mjs → piRunnerArgs-Bl5GpBoN.mjs} +2 -2
  121. package/dist/{piRuntime-Cgn1b0OX.mjs → piRuntime-BhwxzdQf.mjs} +1 -1
  122. package/dist/{piRuntime-DpS9TAIs.cjs → piRuntime-DzrIiZU8.cjs} +1 -1
  123. package/dist/{piTerminal-rmve-VlI.cjs → piTerminal-BdS7ol7v.cjs} +20 -17
  124. package/dist/{piTerminal-BGdps8f3.mjs → piTerminal-DnA2CbGr.mjs} +20 -17
  125. package/dist/{pushNotifications-23YSd-0l.cjs → pushNotifications-BqFoLye2.cjs} +5 -3
  126. package/dist/{pushNotifications-XAM8__Pg.mjs → pushNotifications-DkQ0yvFs.mjs} +5 -3
  127. package/dist/{query-u2GX-I0C.cjs → query-BQ4br3yn.cjs} +1 -1
  128. package/dist/{query-SZcYnJoW.mjs → query-BRJYSkb1.mjs} +1 -1
  129. package/dist/{rateLimitReporter-COUkf446.mjs → rateLimitReporter-BRbYkmuP.mjs} +3 -3
  130. package/dist/{rateLimitReporter-CaTzBe3x.cjs → rateLimitReporter-DK5SQuCc.cjs} +3 -3
  131. package/dist/{rateLimitWindows-B2Kx6L0S.cjs → rateLimitWindows-DBfiuYeg.cjs} +1 -1
  132. package/dist/{rateLimitWindows-j_qQk0KY.mjs → rateLimitWindows-Da5AR-4u.mjs} +1 -1
  133. package/dist/reconnectEnv-B31lY4nR.cjs +27 -0
  134. package/dist/reconnectEnv-DeSvHl3q.mjs +24 -0
  135. package/dist/{registerCommonHandlers-D1MiSfcB.cjs → registerCommonHandlers-m6pxxf2J.cjs} +2 -2
  136. package/dist/{registerCommonHandlers-DRRfinzK.mjs → registerCommonHandlers-yQ7Ru-l0.mjs} +2 -2
  137. package/dist/{registerKillSessionHandler-hvCsEn7b.cjs → registerKillSessionHandler-BAOIa_Fs.cjs} +6 -6
  138. package/dist/{registerKillSessionHandler-Cpug_r5C.mjs → registerKillSessionHandler-BDNpi7YO.mjs} +6 -6
  139. package/dist/{remoteSessionClient-BdnJ_n8C.mjs → remoteSessionClient-CZ7aaNgj.mjs} +5 -5
  140. package/dist/{remoteSessionClient-6ymeMVa4.cjs → remoteSessionClient-iJMXRN_D.cjs} +5 -5
  141. package/dist/{reportProgressTool-XgQBzxoD.mjs → reportProgressTool-DfQhPu0s.mjs} +3 -3
  142. package/dist/{reportProgressTool-tzQLCLIw.cjs → reportProgressTool-DpFs7pSe.cjs} +3 -3
  143. package/dist/{run-Bt0AklUU.mjs → run-CwN28mcj.mjs} +211 -51
  144. package/dist/{run-DYL_wuj7.cjs → run-p-xp1_HY.cjs} +210 -50
  145. package/dist/{runClaude-CBEpYO4S.cjs → runClaude-D6U1Z575.cjs} +62 -44
  146. package/dist/{runClaude-C3rii_S6.mjs → runClaude-DRKtAGTm.mjs} +62 -44
  147. package/dist/{runClaudeDeps-DlVfMG4F.mjs → runClaudeDeps-BheVcIlD.mjs} +56 -47
  148. package/dist/{runClaudeDeps-CYuozSC6.cjs → runClaudeDeps-Dkofokgb.cjs} +51 -42
  149. package/dist/{runGemini-CEI3b90u.cjs → runGemini-C8q3YCc0.cjs} +33 -33
  150. package/dist/{runGemini-DkYhRk9S.mjs → runGemini-owbvhFbi.mjs} +33 -33
  151. package/dist/{runOpenClaw-BgjD6E4d.cjs → runOpenClaw-DGeN66-t.cjs} +18 -18
  152. package/dist/{runOpenClaw-DpprWCoz.mjs → runOpenClaw-Dky3-mjO.mjs} +18 -18
  153. package/dist/{sandbox-XCDUbH72.cjs → sandbox-D2CPyoCA.cjs} +4 -4
  154. package/dist/{sandbox-DJ7A7lsy.mjs → sandbox-sq_wy9Gl.mjs} +4 -4
  155. package/dist/{selfCheck-BYUDB1Uq.cjs → selfCheck-BgLvQKSt.cjs} +39 -37
  156. package/dist/selfCheck-vkfrgQ7X.mjs +88 -0
  157. package/dist/{send-CASDBCyJ.cjs → send-Cd10YhXh.cjs} +8 -8
  158. package/dist/{send-Ba63huxv.mjs → send-K9vg-8t-.mjs} +8 -8
  159. package/dist/{server-cZoV9XRt.cjs → server-DRrV64r0.cjs} +6 -6
  160. package/dist/{server-w3W0toNd.mjs → server-De4W1zuK.mjs} +4 -4
  161. package/dist/{sessionLock-BmLA2S8K.cjs → sessionLock-BDtSzzKS.cjs} +10 -3
  162. package/dist/{sessionLock-G2PMqvsh.mjs → sessionLock-Dl6i7IgA.mjs} +10 -4
  163. package/dist/{sessionOps-DXlTmS7J.cjs → sessionOps-DvnEH4PL.cjs} +4 -4
  164. package/dist/{sessionOps-DPw5k8vV.mjs → sessionOps-gU88-W9F.mjs} +4 -4
  165. package/dist/sessionProvider-CKcIo7KO.mjs +108 -0
  166. package/dist/sessionProvider-CbSZeZrl.cjs +113 -0
  167. package/dist/{sessionScanner-AHjnicxi.cjs → sessionScanner-7RtcCeyD.cjs} +3 -3
  168. package/dist/{sessionScanner-BCXpdZJN.mjs → sessionScanner-DR32uSby.mjs} +3 -3
  169. package/dist/{sessions-BiBXOBx0.cjs → sessions-BvuMjgvJ.cjs} +10 -10
  170. package/dist/{sessions-Clk8MR5Y.mjs → sessions-DTt2Eguk.mjs} +10 -10
  171. package/dist/{setupOfflineReconnection-DI-QZGYz.mjs → setupOfflineReconnection-BGnvhRfb.mjs} +2 -2
  172. package/dist/{setupOfflineReconnection-BKLfOd-i.cjs → setupOfflineReconnection-DduOsw6p.cjs} +2 -2
  173. package/dist/{spawn-4tsp1uhh.mjs → spawn-CL3cUc7b.mjs} +26 -17
  174. package/dist/{spawn-D5omsx1Q.cjs → spawn-DMB6rRPA.cjs} +26 -17
  175. package/dist/{spawnAgents-CtkkIFHd.cjs → spawnAgents-CClb7buD.cjs} +1 -1
  176. package/dist/{spawnAgents-CjoU6ZOS.mjs → spawnAgents-CRMfOJhh.mjs} +1 -1
  177. package/dist/{spawnHappyCLI-CIA9Sc_5.mjs → spawnHappyCLI-Cj_6IICe.mjs} +1 -1
  178. package/dist/{spawnHappyCLI-CF_gLi92.cjs → spawnHappyCLI-DJdhX_Qx.cjs} +1 -1
  179. package/dist/{startFileWatcher-CDO6fb2m.mjs → startFileWatcher-DikVa8kg.mjs} +1 -1
  180. package/dist/{startFileWatcher-9Stpxe7p.cjs → startFileWatcher-LnOmVW6H.cjs} +1 -1
  181. package/dist/{startupSessionCreate-CcF7rGGB.cjs → startupSessionCreate-B3ND-917.cjs} +3 -3
  182. package/dist/{startupSessionCreate-BtR4iYEC.mjs → startupSessionCreate-CDdaLaMq.mjs} +3 -3
  183. package/dist/store--XN-7MS0.mjs +269 -0
  184. package/dist/store-DV__wCvP.cjs +289 -0
  185. package/dist/{streamRelay-BhI6jqF-.cjs → streamRelay-DFdOaLOn.cjs} +1 -1
  186. package/dist/{streamRelay-DMwOMTKf.mjs → streamRelay-sABnxEXq.mjs} +1 -1
  187. package/dist/{sync-C0PRuTMj.mjs → sync-JoEZKRo8.mjs} +1 -1
  188. package/dist/{sync-Ba8N6xba.cjs → sync-_2lsZ1U2.cjs} +1 -1
  189. package/dist/{systemPrompt-DV5IReD4.cjs → systemPrompt-CJEvNCuW.cjs} +2 -2
  190. package/dist/{systemPrompt-D0q8eyjy.mjs → systemPrompt-Zq4HyrZ5.mjs} +2 -2
  191. package/dist/{teams-z3Gp-KlV.cjs → teams-BNZafnrT.cjs} +7 -7
  192. package/dist/{teams-BO3_arwM.mjs → teams-qz4LqKJ2.mjs} +7 -7
  193. package/dist/{template-DLR_0hfj.mjs → template-CJ8BWSsc.mjs} +1 -1
  194. package/dist/{template-B_5l6pkc.cjs → template-LgvBbOna.cjs} +1 -1
  195. package/dist/{time-Cy0a-7YX.cjs → time-CaUlWSNJ.cjs} +1 -1
  196. package/dist/{time-D0jvDRhn.mjs → time-bzmet4s5.mjs} +1 -1
  197. package/dist/{titleGenerator-RGHWP2YL.cjs → titleGenerator-BuIIu_JP.cjs} +17 -13
  198. package/dist/{titleGenerator-AGQsXskb.mjs → titleGenerator-CbTtJ_1D.mjs} +16 -12
  199. package/dist/{todo-CzIDPLFy.cjs → todo-CQ_BTf9C.cjs} +6 -6
  200. package/dist/{todo-BZ954vsz.mjs → todo-DIrVF_Ak.mjs} +6 -6
  201. package/dist/{tools-B1x1j6tz.cjs → tools-BnmmFZji.cjs} +1 -1
  202. package/dist/{tools-Bei5i03L.mjs → tools-cLOjBvPn.mjs} +1 -1
  203. package/dist/{uninstall-B4T_e3Mr.mjs → uninstall-C5OuW6dE.mjs} +3 -3
  204. package/dist/{uninstall-C3cnIvz1.cjs → uninstall-uEEGKB84.cjs} +3 -3
  205. package/dist/wrapperAccount-DXlD3bsO.mjs +106 -0
  206. package/dist/wrapperAccount-DzoGqS2b.cjs +110 -0
  207. package/package.json +7 -7
  208. package/dist/providerBinding-B-Qbx9W2.cjs +0 -140
  209. package/dist/providerBinding-CYubGg-Z.mjs +0 -132
  210. package/dist/selfCheck-C-rNljKV.mjs +0 -86
  211. package/dist/sessionProvider-DUn91LhJ.mjs +0 -109
  212. package/dist/sessionProvider-Dg691XQ4.cjs +0 -114
@@ -0,0 +1,571 @@
1
+ 'use strict';
2
+
3
+ var node_crypto = require('node:crypto');
4
+ var node_fs = require('node:fs');
5
+ var path = require('node:path');
6
+ var index = require('./index-BzAYnYct.cjs');
7
+ var node_child_process = require('node:child_process');
8
+ var claudeAccountEnv = require('./claudeAccountEnv-BOBpJ3k8.cjs');
9
+ var store = require('./store-DV__wCvP.cjs');
10
+
11
+ const CHECK_TIMEOUT_MS = 2e4;
12
+ const DEFAULT_CHECK_MODEL = "claude-haiku-4-5";
13
+ function classifyHttpCheck(kind, status, bodySnippet, now) {
14
+ if (status >= 200 && status < 300) return { status: "ok", at: now };
15
+ if (status === 401 || status === 403) {
16
+ return { status: kind === "claude-subscription" ? "expired" : "invalid", at: now, detail: `HTTP ${status}` };
17
+ }
18
+ return { status: "unverified", at: now, detail: `HTTP ${status}${bodySnippet ? `: ${sanitizeDetail(bodySnippet)}` : ""}` };
19
+ }
20
+ function classifyClaudeCheck(exitCode, output, now) {
21
+ if (exitCode === 0) return { status: "ok", at: now };
22
+ if (/\b401\b|OAuth access token is invalid|invalid.*token|token.*(expired|revoked)/i.test(output)) {
23
+ return { status: "expired", at: now, detail: sanitizeDetail(lastLine(output)) };
24
+ }
25
+ return { status: "unverified", at: now, detail: sanitizeDetail(lastLine(output) || `exit ${exitCode}`) };
26
+ }
27
+ function lastLine(text) {
28
+ return text.trim().split("\n").filter(Boolean).pop() ?? "";
29
+ }
30
+ function sanitizeDetail(text) {
31
+ return text.replace(/sk-ant-[A-Za-z0-9_-]+/g, "sk-ant-\u2026").replace(/\s+/g, " ").trim().slice(0, 200);
32
+ }
33
+ async function checkApiAccount(record, key, now = Date.now) {
34
+ const controller = new AbortController();
35
+ const timer = setTimeout(() => controller.abort(), CHECK_TIMEOUT_MS);
36
+ try {
37
+ const res = await fetch(`${record.baseUrl}/v1/messages`, {
38
+ method: "POST",
39
+ signal: controller.signal,
40
+ headers: {
41
+ "content-type": "application/json",
42
+ "anthropic-version": "2023-06-01",
43
+ "x-api-key": key,
44
+ authorization: `Bearer ${key}`
45
+ },
46
+ body: JSON.stringify({
47
+ model: record.models?.[0] ?? DEFAULT_CHECK_MODEL,
48
+ max_tokens: 1,
49
+ messages: [{ role: "user", content: "ping" }]
50
+ })
51
+ });
52
+ const text = res.ok ? "" : (await res.text().catch(() => "")).slice(0, 400);
53
+ return classifyHttpCheck(record.kind, res.status, text, now());
54
+ } catch (error) {
55
+ return { status: "unverified", at: now(), detail: sanitizeDetail(error instanceof Error ? error.message : String(error)) };
56
+ } finally {
57
+ clearTimeout(timer);
58
+ }
59
+ }
60
+ async function checkSubscriptionAccount(token, scratchDir, now = Date.now) {
61
+ node_fs.mkdirSync(scratchDir, { recursive: true });
62
+ const settingsPath = path.join(scratchDir, "check-settings.json");
63
+ node_fs.writeFileSync(settingsPath, JSON.stringify({ disableAllHooks: true }));
64
+ const env = { ...process.env };
65
+ for (const key of claudeAccountEnv.ACCOUNT_STRIPPED_ENV_KEYS) delete env[key];
66
+ env.CLAUDE_CODE_OAUTH_TOKEN = token;
67
+ return new Promise((resolve) => {
68
+ let output = "";
69
+ const child = node_child_process.spawn("claude", ["-p", "ping", "--model", "haiku", "--no-session-persistence", "--strict-mcp-config", "--settings", settingsPath], {
70
+ cwd: scratchDir,
71
+ env,
72
+ stdio: ["ignore", "pipe", "pipe"]
73
+ });
74
+ const timer = setTimeout(() => child.kill("SIGKILL"), CHECK_TIMEOUT_MS);
75
+ child.stdout.on("data", (d) => {
76
+ output += d;
77
+ });
78
+ child.stderr.on("data", (d) => {
79
+ output += d;
80
+ });
81
+ child.on("error", (error) => {
82
+ clearTimeout(timer);
83
+ resolve({ status: "unverified", at: now(), detail: sanitizeDetail(error.message) });
84
+ });
85
+ child.on("close", (code) => {
86
+ clearTimeout(timer);
87
+ resolve(classifyClaudeCheck(code, output.slice(-2e3), now()));
88
+ });
89
+ });
90
+ }
91
+
92
+ const LOGIN_CODE_TIMEOUT_MS = 10 * 6e4;
93
+ const LOGIN_URL_TIMEOUT_MS = 2e4;
94
+ const LOGIN_EXCHANGE_TIMEOUT_MS = 6e4;
95
+ const LOGIN_RETAIN_MS = 10 * 6e4;
96
+ function stripAnsi(text) {
97
+ return text.replace(/\x1b\][^\x07\x1b]*(\x07|\x1b\\)/g, "").replace(/\x1b\[[0-9;?<>=]*[ -/]*[@-~]/g, " ").replace(/\x1b[()][A-Za-z0-9]/g, "").replace(/\x1b[=>78]/g, "");
98
+ }
99
+ function findAuthorizeUrl(clean) {
100
+ const m = clean.match(/https:\/\/[^\s]*\/oauth\/authorize\?[^\s]+/);
101
+ return m ? m[0] : null;
102
+ }
103
+ function findSetupToken(clean) {
104
+ const m = clean.match(/sk-ant-oat01-[A-Za-z0-9_-]{20,}/);
105
+ return m ? m[0] : null;
106
+ }
107
+ function findLoginError(clean) {
108
+ const m = clean.match(/(OAuth error:[^\n]*?)(?:\s{2,}|Press|$)/) ?? clean.match(/(Login failed[^\n]*)/);
109
+ return m ? m[1].replace(/\s+/g, " ").trim().slice(0, 200) : null;
110
+ }
111
+ function setupTokenEnv(base) {
112
+ const env = {};
113
+ for (const [k, v] of Object.entries(base)) if (typeof v === "string") env[k] = v;
114
+ for (const key of claudeAccountEnv.ACCOUNT_STRIPPED_ENV_KEYS) delete env[key];
115
+ env.BROWSER = "true";
116
+ env.TERM = "xterm-256color";
117
+ return env;
118
+ }
119
+ class SetupTokenLoginManager {
120
+ constructor(deps) {
121
+ this.deps = deps;
122
+ this.now = deps.now ?? Date.now;
123
+ }
124
+ logins = /* @__PURE__ */ new Map();
125
+ now;
126
+ /** One login at a time per machine: a second start cancels nothing and is refused. */
127
+ activeLoginId() {
128
+ for (const [id, e] of this.logins) if (e.status.state === "waiting-code" || e.status.state === "exchanging") return id;
129
+ return null;
130
+ }
131
+ async start() {
132
+ const busy = this.activeLoginId();
133
+ if (busy) throw Object.assign(new Error("another login is in progress"), { code: "login-busy", loginId: busy });
134
+ const loginId = this.deps.newId();
135
+ const entry = {
136
+ status: { loginId, state: "starting" },
137
+ pty: null,
138
+ output: "",
139
+ timers: []
140
+ };
141
+ this.logins.set(loginId, entry);
142
+ const urlReady = new Promise((resolve) => {
143
+ entry.resolveUrl = resolve;
144
+ });
145
+ try {
146
+ entry.pty = this.deps.spawnPty(setupTokenEnv(this.deps.env));
147
+ } catch (error) {
148
+ this.finish(entry, "failed", `could not start claude setup-token: ${error instanceof Error ? error.message : String(error)}`);
149
+ return { ...entry.status };
150
+ }
151
+ entry.pty.onData((data) => this.onData(entry, data));
152
+ entry.pty.onExit(({ exitCode }) => {
153
+ entry.pty = null;
154
+ if (entry.tokenSeen) return;
155
+ if (entry.status.state === "starting" || entry.status.state === "waiting-code" || entry.status.state === "exchanging") {
156
+ this.finish(entry, "failed", findLoginError(stripAnsi(entry.output)) ?? `claude setup-token exited (${exitCode})`);
157
+ }
158
+ });
159
+ entry.timers.push(setTimeout(() => {
160
+ if (entry.status.state === "starting") this.finish(entry, "failed", "claude setup-token printed no sign-in URL");
161
+ }, LOGIN_URL_TIMEOUT_MS));
162
+ await Promise.race([urlReady, new Promise((r) => entry.timers.push(setTimeout(r, LOGIN_URL_TIMEOUT_MS + 50)))]);
163
+ return { ...entry.status };
164
+ }
165
+ submit(loginId, code) {
166
+ const entry = this.get(loginId);
167
+ if (entry.status.state !== "waiting-code" || !entry.pty) return { ...entry.status };
168
+ entry.status = { ...entry.status, state: "exchanging" };
169
+ entry.output = "";
170
+ entry.pty.write(code.trim().replace(/[\r\n]/g, "") + "\r");
171
+ entry.timers.push(setTimeout(() => {
172
+ if (entry.status.state === "exchanging" && !entry.tokenSeen) this.finish(entry, "failed", "timed out waiting for Claude to issue the token");
173
+ }, LOGIN_EXCHANGE_TIMEOUT_MS));
174
+ return { ...entry.status };
175
+ }
176
+ status(loginId) {
177
+ return { ...this.get(loginId).status };
178
+ }
179
+ cancel(loginId) {
180
+ const entry = this.get(loginId);
181
+ if (entry.status.state === "starting" || entry.status.state === "waiting-code" || entry.status.state === "exchanging") {
182
+ this.finish(entry, "canceled");
183
+ }
184
+ return { ...entry.status };
185
+ }
186
+ dispose() {
187
+ for (const entry of this.logins.values()) this.finish(entry, entry.status.state === "succeeded" ? "succeeded" : "canceled");
188
+ this.logins.clear();
189
+ }
190
+ get(loginId) {
191
+ const entry = this.logins.get(loginId);
192
+ if (!entry) throw Object.assign(new Error("unknown or expired login"), { code: "login-not-found" });
193
+ return entry;
194
+ }
195
+ onData(entry, data) {
196
+ entry.output = (entry.output + data).slice(-64e3);
197
+ const clean = stripAnsi(entry.output);
198
+ if (entry.status.state === "starting") {
199
+ const url = findAuthorizeUrl(clean);
200
+ if (url) {
201
+ const expiresAt = this.now() + LOGIN_CODE_TIMEOUT_MS;
202
+ entry.status = { ...entry.status, state: "waiting-code", url, expiresAt };
203
+ entry.timers.push(setTimeout(() => {
204
+ if (entry.status.state === "waiting-code") this.finish(entry, "expired");
205
+ }, LOGIN_CODE_TIMEOUT_MS));
206
+ entry.resolveUrl?.();
207
+ }
208
+ return;
209
+ }
210
+ if (entry.status.state !== "exchanging" || entry.tokenSeen) return;
211
+ const token = findSetupToken(clean);
212
+ if (token) {
213
+ entry.tokenSeen = true;
214
+ entry.output = "";
215
+ this.deps.onToken(entry.status.loginId, token).then(
216
+ (account) => this.finish(entry, "succeeded", void 0, account),
217
+ (error2) => this.finish(entry, "failed", error2 instanceof Error ? error2.message : String(error2))
218
+ );
219
+ return;
220
+ }
221
+ const error = findLoginError(clean);
222
+ if (error) this.finish(entry, "failed", error);
223
+ }
224
+ finish(entry, state, error, account) {
225
+ for (const t2 of entry.timers) clearTimeout(t2);
226
+ entry.timers = [];
227
+ const { loginId, url, expiresAt } = entry.status;
228
+ entry.status = { loginId, state, ...url && state !== "succeeded" ? { url } : {}, ...expiresAt ? { expiresAt } : {}, ...account ? { account } : {}, ...error ? { error } : {} };
229
+ entry.resolveUrl?.();
230
+ const pty = entry.pty;
231
+ entry.pty = null;
232
+ try {
233
+ pty?.kill();
234
+ } catch {
235
+ }
236
+ entry.output = "";
237
+ const loginId_ = loginId;
238
+ const t = setTimeout(() => this.logins.delete(loginId_), LOGIN_RETAIN_MS);
239
+ t.unref?.();
240
+ }
241
+ }
242
+
243
+ class AccountError extends Error {
244
+ constructor(code, message, sessions) {
245
+ super(message);
246
+ this.code = code;
247
+ this.sessions = sessions;
248
+ }
249
+ }
250
+ const DAEMON_DOWN = /^(No daemon running|Daemon is not running)/;
251
+ function localRestartFailure(error, stillRunning) {
252
+ return { ok: false, stillRunning, notRunning: !stillRunning && (error.startsWith("restart-precheck:not-tracked") || DAEMON_DOWN.test(error)), error };
253
+ }
254
+ function bindResultMessages(result, sessionId, target, noun) {
255
+ const bound = `Bound ${sessionId} \u2192 ${target}.`;
256
+ if (result.restart === "done") return { out: [bound, "Restarted in place (history kept)."], err: [], exitCode: 0 };
257
+ if (result.restart === "pending") return { out: [bound, "Restart in progress."], err: [], exitCode: 0 };
258
+ if (result.restart === "skipped") return { out: [bound, `Not restarted${result.error ? ` (${result.error})` : ""}; applies when the session next starts.`], err: [], exitCode: 0 };
259
+ if (result.rolledBack) return { out: [], err: [`Not switched: the restart failed (${result.error}). The session keeps running on its previous ${noun}; the binding was not changed.`], exitCode: 1 };
260
+ return { out: [], err: [`Binding to ${target} saved, but the restart failed (${result.error}); the session is not running and starts on ${target} next time.`], exitCode: 1 };
261
+ }
262
+ const BIND_RESTART_BUDGET_MS = 22e3;
263
+ class AccountService {
264
+ constructor(deps) {
265
+ this.deps = deps;
266
+ this.home = deps.home;
267
+ this.env = deps.env ?? process.env;
268
+ this.now = deps.now ?? Date.now;
269
+ }
270
+ home;
271
+ env;
272
+ now;
273
+ logins = null;
274
+ /** loginId → account to (re)write when its token arrives. */
275
+ loginTargets = /* @__PURE__ */ new Map();
276
+ state() {
277
+ return store.buildAgentProfilesState(this.home, store.readAccounts(this.home), store.defaultSecretProbe(this.env), this.now(), this.deps.daemonPid ?? process.pid);
278
+ }
279
+ summary(id) {
280
+ const record = store.readAccounts(this.home).accounts[id];
281
+ if (!record) throw new AccountError("not-found", `no account "${id}"`);
282
+ return store.summarizeAccount(this.home, id, record, store.defaultSecretProbe(this.env), this.now());
283
+ }
284
+ changed() {
285
+ try {
286
+ this.deps.onChanged?.();
287
+ } catch {
288
+ }
289
+ }
290
+ editable(id) {
291
+ const file = store.readAccountsFileV2(this.home);
292
+ const record = file.accounts[id];
293
+ if (!record) {
294
+ if (store.readAccounts(this.home).accounts[id]?.legacy) throw new AccountError("legacy-readonly", `"${id}" comes from providers.json; edit or remove it there`);
295
+ throw new AccountError("not-found", `no account "${id}"`);
296
+ }
297
+ return { file, record };
298
+ }
299
+ // ---- add / edit -----------------------------------------------------------
300
+ async add(params) {
301
+ const parsed = index.AgentProfileAddRequestSchema.safeParse(params);
302
+ if (!parsed.success) throw new AccountError("invalid-params", parsed.error.issues[0]?.message ?? "invalid params");
303
+ const req = parsed.data;
304
+ const file = store.readAccountsFileV2(this.home);
305
+ const id = store.newAccountId(req.label, "claude-api", Object.keys(store.readAccounts(this.home).accounts));
306
+ const models = [];
307
+ const contextWindows = {};
308
+ for (const m of req.models ?? []) {
309
+ if (typeof m === "string") models.push(m);
310
+ else {
311
+ models.push(m.id);
312
+ if (m.contextWindow) contextWindows[m.id] = m.contextWindow;
313
+ }
314
+ }
315
+ const record = {
316
+ label: req.label,
317
+ agent: "claude",
318
+ kind: "claude-api",
319
+ createdAt: this.now(),
320
+ baseUrl: req.baseUrl.replace(/\/+$/, ""),
321
+ key: req.key.source === "paste" ? { source: "stored" } : req.key.source === "file" ? { source: "file", path: req.key.path } : { source: "env", name: req.key.name },
322
+ ...models.length > 0 ? { models } : {},
323
+ ...Object.keys(contextWindows).length > 0 ? { contextWindows } : {}
324
+ };
325
+ if (req.key.source === "paste") store.writeAccountSecret(this.home, id, req.key.value);
326
+ file.accounts[id] = record;
327
+ store.writeAccountsFile(this.home, file);
328
+ this.changed();
329
+ return this.test(id);
330
+ }
331
+ rename(accountId, label) {
332
+ if (typeof accountId !== "string" || typeof label !== "string" || !label.trim() || label.trim().length > 60) {
333
+ throw new AccountError("invalid-params", "accountId and a 1\u201360 character label are required");
334
+ }
335
+ const { file, record } = this.editable(accountId);
336
+ record.label = label.trim();
337
+ store.writeAccountsFile(this.home, file);
338
+ this.changed();
339
+ return this.summary(accountId);
340
+ }
341
+ /**
342
+ * `force` with bound sessions: the credential is gone, so each of those
343
+ * sessions restarts in place right away and comes back `unavailable`
344
+ * (refusing turns, Q3) instead of running on the deleted credential until
345
+ * its next start. Restarts run in parallel within the bind budget; one
346
+ * still going reports 'pending'.
347
+ */
348
+ async remove(accountId, force) {
349
+ if (typeof accountId !== "string") throw new AccountError("invalid-params", "accountId is required");
350
+ const { file } = this.editable(accountId);
351
+ const sessions = store.sessionsBoundTo(store.readSessionBindings(this.home), accountId);
352
+ if (sessions.length > 0 && force !== true) {
353
+ throw new AccountError("in-use", `${sessions.length} session(s) use this account; switch them first or remove with force`, sessions);
354
+ }
355
+ delete file.accounts[accountId];
356
+ for (const [agent, id] of Object.entries(file.defaults)) if (id === accountId) delete file.defaults[agent];
357
+ store.writeAccountsFile(this.home, file);
358
+ store.removeAccountSecret(this.home, accountId);
359
+ this.changed();
360
+ if (sessions.length === 0 || !this.deps.restartSession) return { removed: true, sessions };
361
+ const restarts = {};
362
+ await Promise.all(sessions.map(async (sessionId) => {
363
+ restarts[sessionId] = await this.restartWithinBudget(sessionId);
364
+ }));
365
+ return { removed: true, sessions, restarts };
366
+ }
367
+ /** 'done' | 'skipped' (not running here) | 'pending' (still going after the budget) | 'failed' */
368
+ async restartWithinBudget(sessionId) {
369
+ const outcome = await Promise.race([
370
+ this.deps.restartSession(sessionId),
371
+ new Promise((r) => setTimeout(() => r("pending"), BIND_RESTART_BUDGET_MS).unref?.())
372
+ ]);
373
+ if (outcome === "pending") return "pending";
374
+ if (outcome.ok) return "done";
375
+ return outcome.notRunning ? "skipped" : "failed";
376
+ }
377
+ setDefault(agent, accountId) {
378
+ if (agent !== "claude") throw new AccountError("invalid-params", 'agent must be "claude"');
379
+ if (accountId !== null && typeof accountId !== "string") throw new AccountError("invalid-params", "accountId must be a string or null");
380
+ if (typeof accountId === "string") {
381
+ const record = store.readAccounts(this.home).accounts[accountId];
382
+ if (!record) throw new AccountError("not-found", `no account "${accountId}"`);
383
+ if (record.agent !== agent) throw new AccountError("invalid-params", `"${accountId}" is not a ${agent} account`);
384
+ }
385
+ const file = store.readAccountsFileV2(this.home);
386
+ if (accountId === null) delete file.defaults[agent];
387
+ else file.defaults[agent] = accountId;
388
+ store.writeAccountsFile(this.home, file);
389
+ this.changed();
390
+ return this.state();
391
+ }
392
+ // ---- check ---------------------------------------------------------------
393
+ readSecretFor(id, record) {
394
+ try {
395
+ if (record.kind === "claude-subscription" || record.key?.source === "stored") return node_fs.readFileSync(store.accountSecretPath(this.home, id), "utf8").trim() || null;
396
+ if (record.key?.source === "file") return node_fs.readFileSync(store.expandHome(record.key.path), "utf8").trim() || null;
397
+ if (record.key?.source === "env") return this.env[record.key.name]?.trim() || null;
398
+ } catch {
399
+ return null;
400
+ }
401
+ return null;
402
+ }
403
+ async test(accountId) {
404
+ if (typeof accountId !== "string") throw new AccountError("invalid-params", "accountId is required");
405
+ const record = store.readAccounts(this.home).accounts[accountId];
406
+ if (!record) throw new AccountError("not-found", `no account "${accountId}"`);
407
+ const secret = this.readSecretFor(accountId, record);
408
+ if (!secret) return this.summary(accountId);
409
+ const check = this.deps.check ? await this.deps.check(record, secret) : record.kind === "claude-subscription" ? await checkSubscriptionAccount(secret, path.join(this.home, "tmp", "account-check"), this.now) : await checkApiAccount(record, secret, this.now);
410
+ if (!record.legacy) {
411
+ const file = store.readAccountsFileV2(this.home);
412
+ if (file.accounts[accountId]) {
413
+ file.accounts[accountId].check = check;
414
+ store.writeAccountsFile(this.home, file);
415
+ this.changed();
416
+ }
417
+ return this.summary(accountId);
418
+ }
419
+ return { ...this.summary(accountId), status: check.status, checkedAt: check.at, ...check.detail ? { statusDetail: check.detail } : {} };
420
+ }
421
+ // ---- remote login (claude setup-token) -------------------------------------
422
+ loginManager() {
423
+ if (this.logins) return this.logins;
424
+ const spawnPty = this.deps.spawnPty;
425
+ if (!spawnPty) throw new AccountError("internal", "remote login is not available in this process");
426
+ this.logins = new SetupTokenLoginManager({
427
+ spawnPty,
428
+ env: this.env,
429
+ newId: () => node_crypto.randomUUID(),
430
+ now: this.now,
431
+ onToken: async (loginId, token) => {
432
+ const target = this.loginTargets.get(loginId) ?? {};
433
+ this.loginTargets.delete(loginId);
434
+ return this.storeSubscriptionToken(token, target);
435
+ }
436
+ });
437
+ return this.logins;
438
+ }
439
+ /** Also the terminal path (`very-happy account login`). */
440
+ storeSubscriptionToken(token, target) {
441
+ const file = store.readAccountsFileV2(this.home);
442
+ const now = this.now();
443
+ let id = target.accountId;
444
+ if (id) {
445
+ const record = file.accounts[id];
446
+ if (!record || record.kind !== "claude-subscription") throw new AccountError("not-found", `no subscription account "${id}"`);
447
+ record.expiresAt = now + store.SUBSCRIPTION_TOKEN_TTL_MS;
448
+ record.check = { status: "ok", at: now };
449
+ } else {
450
+ const label = target.label?.trim() || "Claude";
451
+ id = store.newAccountId(label, "claude-subscription", Object.keys(store.readAccounts(this.home).accounts));
452
+ file.accounts[id] = { label, agent: "claude", kind: "claude-subscription", createdAt: now, expiresAt: now + store.SUBSCRIPTION_TOKEN_TTL_MS, check: { status: "ok", at: now } };
453
+ }
454
+ store.writeAccountSecret(this.home, id, token);
455
+ store.writeAccountsFile(this.home, file);
456
+ this.changed();
457
+ return this.summary(id);
458
+ }
459
+ async loginStart(params) {
460
+ const parsed = index.AgentProfileLoginStartRequestSchema.safeParse(params);
461
+ if (!parsed.success) throw new AccountError("invalid-params", parsed.error.issues[0]?.message ?? "invalid params");
462
+ const { accountId, label } = parsed.data;
463
+ if (accountId) {
464
+ const record = store.readAccounts(this.home).accounts[accountId];
465
+ if (!record || record.kind !== "claude-subscription") throw new AccountError("not-found", `no subscription account "${accountId}"`);
466
+ } else if (!label) {
467
+ throw new AccountError("invalid-params", "label is required for a new account");
468
+ }
469
+ let status;
470
+ try {
471
+ status = await this.loginManager().start();
472
+ } catch (error) {
473
+ const code = error.code ?? "setup-token-failed";
474
+ throw new AccountError(code, error instanceof Error ? error.message : String(error));
475
+ }
476
+ this.loginTargets.set(status.loginId, { accountId, label });
477
+ return status;
478
+ }
479
+ loginOp(fn) {
480
+ try {
481
+ return fn(this.loginManager());
482
+ } catch (error) {
483
+ const code = error.code ?? "internal";
484
+ throw new AccountError(code, error instanceof Error ? error.message : String(error));
485
+ }
486
+ }
487
+ loginSubmit(params) {
488
+ const parsed = index.AgentProfileLoginSubmitRequestSchema.safeParse(params);
489
+ if (!parsed.success) throw new AccountError("invalid-params", "loginId and code are required");
490
+ return this.loginOp((m) => m.submit(parsed.data.loginId, parsed.data.code));
491
+ }
492
+ loginStatus(loginId) {
493
+ if (typeof loginId !== "string") throw new AccountError("invalid-params", "loginId is required");
494
+ return this.loginOp((m) => m.status(loginId));
495
+ }
496
+ loginCancel(loginId) {
497
+ if (typeof loginId !== "string") throw new AccountError("invalid-params", "loginId is required");
498
+ const status = this.loginOp((m) => m.cancel(loginId));
499
+ this.loginTargets.delete(loginId);
500
+ return status;
501
+ }
502
+ dispose() {
503
+ this.logins?.dispose();
504
+ }
505
+ // ---- sessions --------------------------------------------------------------
506
+ /** Validates and writes a session binding (no restart). */
507
+ writeBinding(sessionId, accountId, model) {
508
+ if (accountId !== null) {
509
+ const record = store.readAccounts(this.home).accounts[accountId];
510
+ if (!record) throw new AccountError("not-found", `no account "${accountId}"`);
511
+ if (model !== void 0) {
512
+ if (record.kind !== "claude-api") throw new AccountError("invalid-params", "model applies to API accounts only");
513
+ if (record.models && record.models.length > 0 && !record.models.includes(model)) {
514
+ throw new AccountError("invalid-params", `model "${model}" is not in ${accountId}'s models (${record.models.join(", ")})`);
515
+ }
516
+ }
517
+ } else if (model !== void 0) {
518
+ throw new AccountError("invalid-params", "model cannot be set for the machine login");
519
+ }
520
+ store.writeSessionBinding(this.home, sessionId, { account: accountId, ...model ? { model } : {} });
521
+ }
522
+ async bind(params) {
523
+ const parsed = index.AgentProfileBindRequestSchema.safeParse(params);
524
+ if (!parsed.success) throw new AccountError("invalid-params", parsed.error.issues[0]?.message ?? "invalid params");
525
+ const { sessionId, accountId, model, restart } = parsed.data;
526
+ const previous = store.readSessionBindingV2(this.home, sessionId);
527
+ this.writeBinding(sessionId, accountId, model);
528
+ this.changed();
529
+ if (restart === false || !this.deps.restartSession) return { bound: true, restart: "skipped" };
530
+ const outcome = await Promise.race([
531
+ this.deps.restartSession(sessionId),
532
+ new Promise((r) => setTimeout(() => r("pending"), BIND_RESTART_BUDGET_MS).unref?.())
533
+ ]);
534
+ if (outcome === "pending") return { bound: true, restart: "pending" };
535
+ if (outcome.ok) return { bound: true, restart: "done" };
536
+ if (outcome.stillRunning) {
537
+ store.writeSessionBinding(this.home, sessionId, previous);
538
+ this.changed();
539
+ return { bound: false, rolledBack: true, restart: "failed", error: outcome.error };
540
+ }
541
+ if (outcome.notRunning) return { bound: true, restart: "skipped", error: outcome.error };
542
+ return { bound: true, restart: "failed", error: outcome.error };
543
+ }
544
+ /**
545
+ * Spawn-time choice → the account a NEW session starts on.
546
+ * undefined → the machine default for this agent (none = machine login)
547
+ * null → machine login
548
+ * id → that account; must exist and be usable (Q3: never fall back)
549
+ */
550
+ resolveSpawnAccount(agent, requested) {
551
+ if (requested !== void 0 && requested !== null && typeof requested !== "string") {
552
+ throw new AccountError("invalid-params", "agentProfileId must be a string or null");
553
+ }
554
+ const file = store.readAccounts(this.home);
555
+ const id = requested === void 0 ? file.defaults[agent] ?? null : requested;
556
+ if (id === null || id === "") return null;
557
+ const record = file.accounts[id];
558
+ if (!record) throw new AccountError("agent-profile-unavailable", `agent-profile-unavailable:missing: no account "${id}" on this machine`);
559
+ if (record.agent !== agent) throw new AccountError("agent-profile-unavailable", `agent-profile-unavailable:agent-mismatch: "${id}" is a ${record.agent} account`);
560
+ const { status } = store.summarizeAccount(this.home, id, record, store.defaultSecretProbe(this.env), this.now());
561
+ if (status === "missing-secret" || status === "expired" || status === "invalid") {
562
+ throw new AccountError("agent-profile-unavailable", `agent-profile-unavailable:${status}: account "${record.label}"`);
563
+ }
564
+ return id;
565
+ }
566
+ }
567
+
568
+ exports.AccountError = AccountError;
569
+ exports.AccountService = AccountService;
570
+ exports.bindResultMessages = bindResultMessages;
571
+ exports.localRestartFailure = localRestartFailure;