very-happy-cli 0.2.159 → 0.2.160

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 (258) hide show
  1. package/dist/{AcpBackend-DUYFlyfN.cjs → AcpBackend-Bm2rdke8.cjs} +78 -76
  2. package/dist/{AcpBackend-VsfkZiVF.mjs → AcpBackend-mzv8Dhba.mjs} +4 -2
  3. package/dist/{AcpSessionManager-Bdv8LWXh.cjs → AcpSessionManager-BAY1Pggx.cjs} +9 -9
  4. package/dist/{AcpSessionManager-rYtVb0kN.mjs → AcpSessionManager-CoMWFVw3.mjs} +1 -1
  5. package/dist/BasePermissionHandler-CFHAxumV.cjs +157 -0
  6. package/dist/BasePermissionHandler-m3WVholL.mjs +155 -0
  7. package/dist/BaseReasoningProcessor-BFa9_rZA.cjs +200 -0
  8. package/dist/BaseReasoningProcessor-CYrKBXGm.mjs +198 -0
  9. package/dist/RemoteModeDisplay-D-HewyXg.mjs +150 -0
  10. package/dist/RemoteModeDisplay-NC1gPHtj.cjs +153 -0
  11. package/dist/agentAttachments-Dbw8iMCZ.cjs +20 -0
  12. package/dist/agentAttachments-M_B5qEF2.mjs +18 -0
  13. package/dist/agentGuidance-B5NATuFa.cjs +28 -0
  14. package/dist/agentGuidance-CQuNlNx8.mjs +20 -0
  15. package/dist/{agentHome-CHh4lmjM.cjs → agentHome-CboCeKWq.cjs} +14 -28
  16. package/dist/{agentHome-CvsJyeQB.mjs → agentHome-Dj1C43aJ.mjs} +8 -22
  17. package/dist/api-CLMUr-SX.mjs +3339 -0
  18. package/dist/api-CgundNNX.cjs +3346 -0
  19. package/dist/{types-Dh-s4Lqs.mjs → apiMachine-B9dLW_p5.mjs} +9116 -16205
  20. package/dist/{types-BbvK1Tr_.cjs → apiMachine-Bn8482VM.cjs} +9104 -16247
  21. package/dist/assistantTools-BTqPnlFl.cjs +380 -0
  22. package/dist/assistantTools-D6tuc6o4.mjs +376 -0
  23. package/dist/attachmentContent-DpiTJZb4.cjs +88 -0
  24. package/dist/attachmentContent-_kxRznNf.mjs +82 -0
  25. package/dist/attachmentLimits-CzVrqgLR.cjs +354 -0
  26. package/dist/attachmentLimits-yba1uHFO.mjs +348 -0
  27. package/dist/auth-BDOVh5h5.cjs +220 -0
  28. package/dist/auth-Cwutmdsa.mjs +225 -0
  29. package/dist/auth-PYHZQNPp.mjs +218 -0
  30. package/dist/auth-ba4WMYrN.cjs +227 -0
  31. package/dist/authRelay-BdYkC1Po.cjs +156 -0
  32. package/dist/authRelay-DSAvg1uv.mjs +143 -0
  33. package/dist/{auto-DKmEls8Z.cjs → auto-BOX_fgmR.cjs} +70 -79
  34. package/dist/{auto-nb8GhRRy.mjs → auto-BXu14yP_.mjs} +27 -36
  35. package/dist/backgroundTaskActivity-8PdPxrvy.mjs +149 -0
  36. package/dist/backgroundTaskActivity-CBvUdj39.cjs +157 -0
  37. package/dist/bootstrap-B5G1TijC.cjs +116 -0
  38. package/dist/bootstrap-hxXPCFMx.mjs +112 -0
  39. package/dist/browser-Y6Bl8L_O.cjs +22 -0
  40. package/dist/browser-jh2P0UVZ.mjs +20 -0
  41. package/dist/claudeCliPath-BqkaH2oR.mjs +8 -0
  42. package/dist/claudeCliPath-U4HHmV4r.cjs +10 -0
  43. package/dist/claudeLocal-BaY4fZKi.mjs +339 -0
  44. package/dist/claudeLocal-CRGG4Pea.cjs +343 -0
  45. package/dist/claudeLocalLauncher-D4T7MTqd.mjs +152 -0
  46. package/dist/claudeLocalLauncher-DyEbVzUN.cjs +154 -0
  47. package/dist/cliUpdate-DsKXPFYp.cjs +120 -0
  48. package/dist/cliUpdate-Y34VGe9Y.mjs +112 -0
  49. package/dist/client-3Ac-O4pw.cjs +104 -0
  50. package/dist/client-BPNbmtvO.cjs +119 -0
  51. package/dist/client-CeGKqqcJ.mjs +100 -0
  52. package/dist/client-ClR0K8zX.mjs +112 -0
  53. package/dist/codex/happyMcpStdioBridge.cjs +33 -14
  54. package/dist/codex/happyMcpStdioBridge.mjs +26 -7
  55. package/dist/codexAppServerClient-I3teiV-N.mjs +1088 -0
  56. package/dist/codexAppServerClient-q2FjnRcK.cjs +1090 -0
  57. package/dist/codexCommand-4zcccIoq.cjs +2088 -0
  58. package/dist/codexCommand-Cc9gcbdX.mjs +2086 -0
  59. package/dist/codexThreadFork-BH9IZPqD.cjs +350 -0
  60. package/dist/codexThreadFork-slzAseLx.mjs +338 -0
  61. package/dist/{config-ClLtM6F3.mjs → config-CTx_jb-C.mjs} +7 -40
  62. package/dist/{config-DLx-vW3I.cjs → config-Ci9Kpgwa.cjs} +26 -59
  63. package/dist/configuration-BSYpcPwE.cjs +181 -0
  64. package/dist/configuration-RfeNjFmd.mjs +170 -0
  65. package/dist/connect-BpOdzNbE.mjs +682 -0
  66. package/dist/connect-C2CiOUFs.cjs +684 -0
  67. package/dist/constants-BC4St0xd.mjs +11 -0
  68. package/dist/constants-VJ0N6WuG.cjs +17 -0
  69. package/dist/contentLogMetadata-BlWI0egu.mjs +51 -0
  70. package/dist/contentLogMetadata-ZSFk_NjQ.cjs +54 -0
  71. package/dist/context-DsDr6E2t.cjs +69 -0
  72. package/dist/context-H0Bcb9S_.mjs +65 -0
  73. package/dist/controlClient-BGbDcgWS.mjs +260 -0
  74. package/dist/controlClient-Bcwv3D21.cjs +279 -0
  75. package/dist/createSessionMetadata-BJxEnM-o.cjs +58 -0
  76. package/dist/createSessionMetadata-CVVkGjxV.mjs +54 -0
  77. package/dist/defaultPermissionMode-BnxJPVHT.mjs +4 -0
  78. package/dist/defaultPermissionMode-CxmTXUQR.cjs +7 -0
  79. package/dist/detectCLI-CSGMlV51.mjs +58 -0
  80. package/dist/detectCLI-DR9ZaN6B.cjs +61 -0
  81. package/dist/deterministicJson-C5CYTVpm.cjs +507 -0
  82. package/dist/deterministicJson-CzkFJWw1.mjs +502 -0
  83. package/dist/doctor-BPkYWSuq.mjs +75 -0
  84. package/dist/doctor-D2YJ-Yn2.cjs +395 -0
  85. package/dist/doctor-DOvByjbk.mjs +391 -0
  86. package/dist/doctor-u46qYYKX.cjs +79 -0
  87. package/dist/doctorReadiness-BCZGcN0a.cjs +151 -0
  88. package/dist/doctorReadiness-C208SMN9.mjs +142 -0
  89. package/dist/editPaths-BVfS_FFL.mjs +68 -0
  90. package/dist/editPaths-Bqp4OFPw.cjs +73 -0
  91. package/dist/ensureDaemonRunning-BCwNrMyv.cjs +64 -0
  92. package/dist/ensureDaemonRunning-Dqa2pOjY.mjs +61 -0
  93. package/dist/handleResumeCommand-BvXYf5El.mjs +240 -0
  94. package/dist/handleResumeCommand-C2cKchpX.cjs +245 -0
  95. package/dist/ids-B6ZC0HGt.cjs +13 -0
  96. package/dist/ids-DU6sLx4C.mjs +10 -0
  97. package/dist/index-B6UGRQ7h.mjs +102 -0
  98. package/dist/{index-BEOMECtE.cjs → index-B6pAdvJx.cjs} +121 -91
  99. package/dist/index-Bu5Zi_a9.cjs +182 -0
  100. package/dist/index-D3kI0hDR.cjs +107 -0
  101. package/dist/index-DA7yINuk.cjs +994 -0
  102. package/dist/index-DDeHXrIX.cjs +71 -0
  103. package/dist/index-DKLU_fD0.mjs +158 -0
  104. package/dist/{index-2mCaeKyf.mjs → index-DMZqWwsP.mjs} +68 -38
  105. package/dist/index-DVkMGPyS.mjs +68 -0
  106. package/dist/index-qdS1friN.mjs +949 -0
  107. package/dist/index.cjs +5 -46
  108. package/dist/index.mjs +5 -46
  109. package/dist/{install-BPhJppvd.mjs → install-BO_W7VhL.mjs} +37 -37
  110. package/dist/install-BgoC2e_2.cjs +88 -0
  111. package/dist/install-CFY3tYtJ.mjs +86 -0
  112. package/dist/{install-BOHrUaFM.cjs → install-Cs5qAPrB.cjs} +38 -38
  113. package/dist/{installPiTools-DuZ6jZvX.cjs → installPiTools-BKnXjrVu.cjs} +2 -3
  114. package/dist/{installPiTools-Cj7yU9Fc.mjs → installPiTools-B_CdM5_2.mjs} +1 -2
  115. package/dist/{installTerminalHooks-Cou3WUf3.cjs → installTerminalHooks-BQZbvxsZ.cjs} +5 -40
  116. package/dist/{installTerminalHooks-WeznjkuC.mjs → installTerminalHooks-By7gBMEF.mjs} +3 -38
  117. package/dist/lib.cjs +28 -19
  118. package/dist/lib.d.cts +12 -2
  119. package/dist/lib.d.mts +12 -2
  120. package/dist/lib.mjs +23 -14
  121. package/dist/lidState-BeDfxxEX.cjs +305 -0
  122. package/dist/lidState-CeEt442o.mjs +297 -0
  123. package/dist/limits-C-a7gr04.cjs +43 -0
  124. package/dist/limits-DIo7rEBR.mjs +36 -0
  125. package/dist/localHappyAgentAuth-C-HQyiv6.mjs +82 -0
  126. package/dist/localHappyAgentAuth-D6rFhaoc.cjs +86 -0
  127. package/dist/logger-6HYUEXNk.mjs +271 -0
  128. package/dist/logger-CS0mw3fa.cjs +275 -0
  129. package/dist/loginShellEnv-BkuYtExZ.cjs +182 -0
  130. package/dist/loginShellEnv-Dw8M7tkI.mjs +167 -0
  131. package/dist/machineMetadata-DyDbODYd.cjs +41 -0
  132. package/dist/machineMetadata-oOzBfDfs.mjs +38 -0
  133. package/dist/main-BkxJP6JQ.cjs +941 -0
  134. package/dist/main-BwNIAI1A.mjs +939 -0
  135. package/dist/manager-BQ4flvQZ.mjs +101 -0
  136. package/dist/manager-Cly8xVIR.cjs +105 -0
  137. package/dist/{mcp-Dy3f_K0h.mjs → mcp-B1A4I3TK.mjs} +27 -33
  138. package/dist/{mcp-CPYbtsYG.cjs → mcp-Hszd7qpS.cjs} +42 -48
  139. package/dist/messageBuffer-BWlGgR3A.mjs +71 -0
  140. package/dist/messageBuffer-fJMH6uY8.cjs +73 -0
  141. package/dist/mirrorProtocol-BNLtoWjO.mjs +170 -0
  142. package/dist/mirrorProtocol-BUtmg1ws.cjs +186 -0
  143. package/dist/oneShotPrompts-CL0dip9C.cjs +16 -0
  144. package/dist/oneShotPrompts-DT4p6RNd.mjs +12 -0
  145. package/dist/package-BhaKlnxz.mjs +171 -0
  146. package/dist/package-BwMrPwqH.cjs +173 -0
  147. package/dist/path-B7zW-WwE.cjs +18 -0
  148. package/dist/path-D2wdaNSk.mjs +15 -0
  149. package/dist/peerTools-BTqw97Gb.mjs +272 -0
  150. package/dist/peerTools-BvKtHXj8.cjs +283 -0
  151. package/dist/permissionMode-Cr5JCbB7.mjs +80 -0
  152. package/dist/permissionMode-CrV-XuMs.cjs +87 -0
  153. package/dist/persistence-HGW_ZVs9.mjs +372 -0
  154. package/dist/persistence-yKTH3-5X.cjs +414 -0
  155. package/dist/piExtension.mjs +2 -1
  156. package/dist/piRunnerArgs-BNloJCCg.cjs +66 -0
  157. package/dist/piRunnerArgs-BuX1UFWy.mjs +59 -0
  158. package/dist/{piRuntime-kLZNpAAl.mjs → piRuntime-CSGkwCKQ.mjs} +2 -2
  159. package/dist/{piRuntime-NtF0YqjH.cjs → piRuntime-C_H7MJCM.cjs} +4 -4
  160. package/dist/{piTerminal-B0fEOV_2.mjs → piTerminal-C8a1OrNQ.mjs} +32 -35
  161. package/dist/{piTerminal-9J0GAKzb.cjs → piTerminal-DNCZ6yTM.cjs} +32 -35
  162. package/dist/previewPath-B0rBdhy1.cjs +83 -0
  163. package/dist/previewPath-CXN4Vag0.mjs +81 -0
  164. package/dist/projectPath-BTBIMB57.mjs +10 -0
  165. package/dist/projectPath-ChLhdOyt.cjs +13 -0
  166. package/dist/registerCommonHandlers-Ccvsz7Ou.mjs +536 -0
  167. package/dist/registerCommonHandlers-DskirN-_.cjs +538 -0
  168. package/dist/registerKillSessionHandler-DZeLXWcB.cjs +361 -0
  169. package/dist/registerKillSessionHandler-GYvHdipX.mjs +358 -0
  170. package/dist/remoteSessionClient-B0LraSB9.cjs +634 -0
  171. package/dist/remoteSessionClient-CYnXRynE.mjs +612 -0
  172. package/dist/resources-BdFBQi8r.mjs +117 -0
  173. package/dist/resources-JDPugcDq.cjs +120 -0
  174. package/dist/run-CJzxoHVh.cjs +5762 -0
  175. package/dist/run-D3ifupU3.mjs +5739 -0
  176. package/dist/runClaude-Ba01qT-u.mjs +848 -0
  177. package/dist/runClaude-Da3RirzE.cjs +850 -0
  178. package/dist/runClaudeDeps-DOt79DjU.mjs +3624 -0
  179. package/dist/runClaudeDeps-DOzEBMls.cjs +3649 -0
  180. package/dist/{runGemini-DV6Ouadt.mjs → runGemini-BGeTz57m.mjs} +58 -31
  181. package/dist/{runGemini-F-mqx3_K.cjs → runGemini-DSr9LIxL.cjs} +202 -175
  182. package/dist/{runOpenClaw-Qqo9j63M.cjs → runOpenClaw-B1mTxN35.cjs} +64 -65
  183. package/dist/{runOpenClaw-D7MlPS5n.mjs → runOpenClaw-CogSedIc.mjs} +31 -32
  184. package/dist/sandbox-CG7IyDTU.cjs +187 -0
  185. package/dist/sandbox-DTe6d54R.mjs +180 -0
  186. package/dist/selfCheck-C9mVrQwf.mjs +84 -0
  187. package/dist/selfCheck-Dc-mNSLb.cjs +87 -0
  188. package/dist/{send-4qJTCAYW.cjs → send-B7J_eaG3.cjs} +16 -9
  189. package/dist/{send-CLhYXNgy.mjs → send-CBXJKc6O.mjs} +12 -5
  190. package/dist/server-CZTP_iOn.cjs +407 -0
  191. package/dist/server-DcVBv04l.mjs +404 -0
  192. package/dist/sessionLock-Bys1PNSo.cjs +205 -0
  193. package/dist/sessionLock-D-EG2CfG.mjs +197 -0
  194. package/dist/sessionModeFile-DMl3dw3r.mjs +32 -0
  195. package/dist/sessionModeFile-RSm0NQkH.cjs +36 -0
  196. package/dist/sessionOps-Dn8z85h_.cjs +783 -0
  197. package/dist/sessionOps-SuHW8Dfe.mjs +760 -0
  198. package/dist/sessionScanner-BOrGjMXL.cjs +209 -0
  199. package/dist/sessionScanner-CX3onqXh.mjs +206 -0
  200. package/dist/{sessions-CzIH2rGp.mjs → sessions-BEG_HTSi.mjs} +17 -8
  201. package/dist/{sessions-Bh1pyddi.cjs → sessions-D74aJbhL.cjs} +37 -28
  202. package/dist/setupOfflineReconnection-ByElY60m.cjs +74 -0
  203. package/dist/setupOfflineReconnection-DpvWTt69.mjs +72 -0
  204. package/dist/smallFastModel-BLNgMrwR.mjs +18 -0
  205. package/dist/smallFastModel-D_uxGMo3.cjs +21 -0
  206. package/dist/{spawn-CPIWlPOM.mjs → spawn-B7yro0b2.mjs} +26 -38
  207. package/dist/{spawn-CmFOSVdW.cjs → spawn-DgR0RKRs.cjs} +52 -64
  208. package/dist/spawnAgents-BGQiEF-w.cjs +52 -0
  209. package/dist/spawnAgents-DZzZ9jMI.mjs +45 -0
  210. package/dist/spawnHappyCLI-B2H5s4B_.mjs +64 -0
  211. package/dist/spawnHappyCLI-DBhwZT7O.cjs +66 -0
  212. package/dist/specialCommands-BSqhYg5X.mjs +52 -0
  213. package/dist/specialCommands-DSsTeRej.cjs +54 -0
  214. package/dist/startFileWatcher-B4VsLgjD.cjs +71 -0
  215. package/dist/startFileWatcher-DErVWZE4.mjs +69 -0
  216. package/dist/startupPlan-BLMbfQIH.cjs +12 -0
  217. package/dist/startupPlan-DFMyNgAs.mjs +10 -0
  218. package/dist/streamRelay-BiKw59Cc.cjs +233 -0
  219. package/dist/streamRelay-FPVbHpbM.mjs +231 -0
  220. package/dist/sync-C8gyQFMc.mjs +69 -0
  221. package/dist/sync-DccIKZ5_.cjs +71 -0
  222. package/dist/systemPrompt-BwTPWfMu.cjs +97 -0
  223. package/dist/systemPrompt-DX521JJz.mjs +94 -0
  224. package/dist/{teams-CEahj4cm.mjs → teams-C32F1hqd.mjs} +9 -40
  225. package/dist/{teams-CB1R9-Z9.cjs → teams-Dl8g8kTI.cjs} +14 -45
  226. package/dist/template-BaHAmH2K.cjs +129 -0
  227. package/dist/template-CiOPa2rd.mjs +121 -0
  228. package/dist/{terminalTitleSuggest-DKgX3osW.mjs → terminalTitleSuggest-CeKsX_V6.mjs} +1 -9
  229. package/dist/{terminalTitleSuggest-Dji8I0Jy.cjs → terminalTitleSuggest-DhvRFX3H.cjs} +0 -10
  230. package/dist/terminals-B_bfC9c2.cjs +250 -0
  231. package/dist/terminals-Dlg0x3nY.mjs +235 -0
  232. package/dist/time-D0XyHOid.mjs +38 -0
  233. package/dist/time-DCuTyook.cjs +42 -0
  234. package/dist/titleGenerator-CQ8CoGhg.mjs +166 -0
  235. package/dist/titleGenerator-ChzMJsyg.cjs +172 -0
  236. package/dist/tmuxSocket-B8Yx20sT.mjs +19 -0
  237. package/dist/tmuxSocket-D-Xt6Vn-.cjs +24 -0
  238. package/dist/{todo-DqyRI4wP.cjs → todo-BvUOTa8G.cjs} +15 -12
  239. package/dist/{todo-Cknp5D4U.mjs → todo-CZ6cFrrn.mjs} +11 -8
  240. package/dist/tools-BZtHF_qQ.mjs +177 -0
  241. package/dist/tools-Be3AoAwu.cjs +63 -0
  242. package/dist/tools-DQj0AeLk.cjs +180 -0
  243. package/dist/tools-DkluDcG4.mjs +60 -0
  244. package/dist/trimIdent-4gvk9Wk6.cjs +22 -0
  245. package/dist/trimIdent-BAjmv_TG.mjs +20 -0
  246. package/dist/types-CRS-srZK.cjs +66 -0
  247. package/dist/types-CkqAACXx.mjs +64 -0
  248. package/dist/uninstall-BkLzaJ6I.mjs +47 -0
  249. package/dist/uninstall-x-TUtf5H.cjs +49 -0
  250. package/package.json +7 -7
  251. package/dist/agentGuidance-BRDN1NoZ.cjs +0 -2217
  252. package/dist/agentGuidance-KgvYuF3R.mjs +0 -2145
  253. package/dist/index-BF6WfgV5.mjs +0 -19624
  254. package/dist/index-C-JazrMB.mjs +0 -52
  255. package/dist/index-blDSadUR.cjs +0 -58
  256. package/dist/index-rH3DrQ5B.cjs +0 -19688
  257. package/dist/limits-BH5CV5vR.cjs +0 -2683
  258. package/dist/limits-CjRj8IX5.mjs +0 -2558
@@ -0,0 +1,684 @@
1
+ 'use strict';
2
+
3
+ var chalk = require('chalk');
4
+ var os = require('os');
5
+ var path = require('path');
6
+ var persistence = require('./persistence-yKTH3-5X.cjs');
7
+ var api = require('./api-CgundNNX.cjs');
8
+ var configuration = require('./configuration-BSYpcPwE.cjs');
9
+ var http = require('http');
10
+ var crypto = require('crypto');
11
+ var browser = require('./browser-Y6Bl8L_O.cjs');
12
+ var child_process = require('child_process');
13
+ var util = require('util');
14
+ require('node:fs/promises');
15
+ require('node:fs');
16
+ require('zod');
17
+ require('./authRelay-BdYkC1Po.cjs');
18
+ require('node:crypto');
19
+ require('tweetnacl');
20
+ require('./logger-CS0mw3fa.cjs');
21
+ require('node:util');
22
+ require('node:path');
23
+ require('node:os');
24
+ require('./package-BwMrPwqH.cjs');
25
+ require('axios');
26
+ require('node:events');
27
+ require('socket.io-client');
28
+ require('./attachmentLimits-CzVrqgLR.cjs');
29
+ require('./index-DA7yINuk.cjs');
30
+ require('@paralleldrive/cuid2');
31
+ require('./limits-C-a7gr04.cjs');
32
+ require('./time-DCuTyook.cjs');
33
+ require('./lidState-BeDfxxEX.cjs');
34
+ require('./registerCommonHandlers-DskirN-_.cjs');
35
+ require('fs/promises');
36
+ require('cross-spawn');
37
+ require('./projectPath-ChLhdOyt.cjs');
38
+ require('url');
39
+ require('./sync-DccIKZ5_.cjs');
40
+ require('./backgroundTaskActivity-CBvUdj39.cjs');
41
+ require('./controlClient-Bcwv3D21.cjs');
42
+ require('./contentLogMetadata-ZSFk_NjQ.cjs');
43
+ require('open');
44
+
45
+ const CLIENT_ID$2 = "app_EMoamEEZ73f0CkXaXp7hrann";
46
+ const AUTH_BASE_URL = "https://auth.openai.com";
47
+ const DEFAULT_PORT$2 = 1455;
48
+ function generatePKCE$2() {
49
+ const verifier = crypto.randomBytes(32).toString("base64url").replace(/[^a-zA-Z0-9\-._~]/g, "");
50
+ const challenge = crypto.createHash("sha256").update(verifier).digest("base64url").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
51
+ return { verifier, challenge };
52
+ }
53
+ function generateState$2() {
54
+ return crypto.randomBytes(16).toString("hex");
55
+ }
56
+ function parseJWT(token) {
57
+ const parts = token.split(".");
58
+ if (parts.length !== 3) {
59
+ throw new Error("Invalid JWT format");
60
+ }
61
+ const payload = Buffer.from(parts[1], "base64url").toString();
62
+ return JSON.parse(payload);
63
+ }
64
+ async function findAvailablePort$2() {
65
+ return new Promise((resolve) => {
66
+ const server = http.createServer();
67
+ server.listen(0, "127.0.0.1", () => {
68
+ const port = server.address().port;
69
+ server.close(() => resolve(port));
70
+ });
71
+ });
72
+ }
73
+ async function isPortAvailable$2(port) {
74
+ return new Promise((resolve) => {
75
+ const testServer = http.createServer();
76
+ testServer.once("error", () => {
77
+ testServer.close();
78
+ resolve(false);
79
+ });
80
+ testServer.listen(port, "127.0.0.1", () => {
81
+ testServer.close(() => resolve(true));
82
+ });
83
+ });
84
+ }
85
+ async function exchangeCodeForTokens$2(code, verifier, port) {
86
+ const response = await fetch(`${AUTH_BASE_URL}/oauth/token`, {
87
+ method: "POST",
88
+ headers: {
89
+ "Content-Type": "application/x-www-form-urlencoded"
90
+ },
91
+ body: new URLSearchParams({
92
+ grant_type: "authorization_code",
93
+ client_id: CLIENT_ID$2,
94
+ code,
95
+ code_verifier: verifier,
96
+ redirect_uri: `http://localhost:${port}/auth/callback`
97
+ })
98
+ });
99
+ if (!response.ok) {
100
+ const error = await response.text();
101
+ throw new Error(`Token exchange failed: ${error}`);
102
+ }
103
+ const data = await response.json();
104
+ const idTokenPayload = parseJWT(data.id_token);
105
+ let accountId = idTokenPayload.chatgpt_account_id;
106
+ if (!accountId) {
107
+ const authClaim = idTokenPayload["https://api.openai.com/auth"];
108
+ if (authClaim && typeof authClaim === "object") {
109
+ accountId = authClaim.chatgpt_account_id || authClaim.account_id;
110
+ }
111
+ }
112
+ return {
113
+ id_token: data.id_token,
114
+ access_token: data.access_token || data.id_token,
115
+ refresh_token: data.refresh_token,
116
+ account_id: accountId
117
+ };
118
+ }
119
+ async function startCallbackServer$2(state, verifier, port) {
120
+ return new Promise((resolve, reject) => {
121
+ const server = http.createServer(async (req, res) => {
122
+ const url = new URL(req.url, `http://localhost:${port}`);
123
+ if (url.pathname === "/auth/callback") {
124
+ const code = url.searchParams.get("code");
125
+ const receivedState = url.searchParams.get("state");
126
+ if (receivedState !== state) {
127
+ res.writeHead(400);
128
+ res.end("Invalid state parameter");
129
+ server.close();
130
+ reject(new Error("Invalid state parameter"));
131
+ return;
132
+ }
133
+ if (!code) {
134
+ res.writeHead(400);
135
+ res.end("No authorization code received");
136
+ server.close();
137
+ reject(new Error("No authorization code received"));
138
+ return;
139
+ }
140
+ try {
141
+ const tokens = await exchangeCodeForTokens$2(code, verifier, port);
142
+ res.writeHead(200, { "Content-Type": "text/html" });
143
+ res.end(`
144
+ <html>
145
+ <body style="font-family: sans-serif; padding: 20px;">
146
+ <h2>\u2705 Authentication Successful!</h2>
147
+ <p>You can close this window and return to your terminal.</p>
148
+ <script>setTimeout(() => window.close(), 3000);<\/script>
149
+ </body>
150
+ </html>
151
+ `);
152
+ server.close();
153
+ resolve(tokens);
154
+ } catch (error) {
155
+ res.writeHead(500);
156
+ res.end("Token exchange failed");
157
+ server.close();
158
+ reject(error);
159
+ }
160
+ }
161
+ });
162
+ server.listen(port, "127.0.0.1", () => {
163
+ });
164
+ setTimeout(() => {
165
+ server.close();
166
+ reject(new Error("Authentication timeout"));
167
+ }, 5 * 60 * 1e3);
168
+ });
169
+ }
170
+ async function authenticateCodex() {
171
+ const { verifier, challenge } = generatePKCE$2();
172
+ const state = generateState$2();
173
+ let port = DEFAULT_PORT$2;
174
+ const portAvailable = await isPortAvailable$2(port);
175
+ if (!portAvailable) {
176
+ port = await findAvailablePort$2();
177
+ }
178
+ const serverPromise = startCallbackServer$2(state, verifier, port);
179
+ await new Promise((resolve) => setTimeout(resolve, 100));
180
+ const redirect_uri = `http://localhost:${port}/auth/callback`;
181
+ const params = [
182
+ ["response_type", "code"],
183
+ ["client_id", CLIENT_ID$2],
184
+ ["redirect_uri", redirect_uri],
185
+ ["scope", "openid profile email offline_access"],
186
+ ["code_challenge", challenge],
187
+ ["code_challenge_method", "S256"],
188
+ ["id_token_add_organizations", "true"],
189
+ ["codex_cli_simplified_flow", "true"],
190
+ ["state", state]
191
+ ];
192
+ const queryString = params.map(([key, value]) => `${key}=${encodeURIComponent(value)}`).join("&");
193
+ const authUrl = `${AUTH_BASE_URL}/oauth/authorize?${queryString}`;
194
+ console.log("\u{1F4CB} Opening browser for authentication...");
195
+ console.log(`If browser doesn't open, visit:
196
+ ${authUrl}
197
+ `);
198
+ await browser.openBrowser(authUrl);
199
+ const tokens = await serverPromise;
200
+ console.log("\u{1F389} Authentication successful!");
201
+ return tokens;
202
+ }
203
+
204
+ const CLIENT_ID$1 = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
205
+ const CLAUDE_AI_AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
206
+ const TOKEN_URL$1 = "https://console.anthropic.com/v1/oauth/token";
207
+ const DEFAULT_PORT$1 = 54545;
208
+ const SCOPE = "user:inference";
209
+ function generatePKCE$1() {
210
+ const verifier = crypto.randomBytes(32).toString("base64url").replace(/[^a-zA-Z0-9\-._~]/g, "");
211
+ const challenge = crypto.createHash("sha256").update(verifier).digest("base64url").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
212
+ return { verifier, challenge };
213
+ }
214
+ function generateState$1() {
215
+ return crypto.randomBytes(32).toString("base64url");
216
+ }
217
+ async function findAvailablePort$1() {
218
+ return new Promise((resolve) => {
219
+ const server = http.createServer();
220
+ server.listen(0, "127.0.0.1", () => {
221
+ const port = server.address().port;
222
+ server.close(() => resolve(port));
223
+ });
224
+ });
225
+ }
226
+ async function isPortAvailable$1(port) {
227
+ return new Promise((resolve) => {
228
+ const testServer = http.createServer();
229
+ testServer.once("error", () => {
230
+ testServer.close();
231
+ resolve(false);
232
+ });
233
+ testServer.listen(port, "127.0.0.1", () => {
234
+ testServer.close(() => resolve(true));
235
+ });
236
+ });
237
+ }
238
+ async function exchangeCodeForTokens$1(code, verifier, port, state) {
239
+ const tokenResponse = await fetch(TOKEN_URL$1, {
240
+ method: "POST",
241
+ headers: {
242
+ "Content-Type": "application/json"
243
+ },
244
+ body: JSON.stringify({
245
+ grant_type: "authorization_code",
246
+ code,
247
+ redirect_uri: `http://localhost:${port}/callback`,
248
+ client_id: CLIENT_ID$1,
249
+ code_verifier: verifier,
250
+ state
251
+ })
252
+ });
253
+ if (!tokenResponse.ok) {
254
+ throw new Error(`Token exchange failed: ${tokenResponse.statusText}`);
255
+ }
256
+ const tokenData = await tokenResponse.json();
257
+ return {
258
+ raw: tokenData,
259
+ token: tokenData.access_token,
260
+ expires: Date.now() + tokenData.expires_in * 1e3
261
+ };
262
+ }
263
+ async function startCallbackServer$1(state, verifier, port) {
264
+ return new Promise((resolve, reject) => {
265
+ const server = http.createServer(async (req, res) => {
266
+ const url = new URL(req.url, `http://localhost:${port}`);
267
+ if (url.pathname === "/callback") {
268
+ const code = url.searchParams.get("code");
269
+ const receivedState = url.searchParams.get("state");
270
+ if (receivedState !== state) {
271
+ res.writeHead(400);
272
+ res.end("Invalid state parameter");
273
+ server.close();
274
+ reject(new Error("Invalid state parameter"));
275
+ return;
276
+ }
277
+ if (!code) {
278
+ res.writeHead(400);
279
+ res.end("No authorization code received");
280
+ server.close();
281
+ reject(new Error("No authorization code received"));
282
+ return;
283
+ }
284
+ try {
285
+ const tokens = await exchangeCodeForTokens$1(code, verifier, port, state);
286
+ res.writeHead(302, {
287
+ "Location": "https://console.anthropic.com/oauth/code/success?app=claude-code"
288
+ });
289
+ res.end();
290
+ server.close();
291
+ resolve(tokens);
292
+ } catch (error) {
293
+ res.writeHead(500);
294
+ res.end("Token exchange failed");
295
+ server.close();
296
+ reject(error);
297
+ }
298
+ }
299
+ });
300
+ server.listen(port, "127.0.0.1", () => {
301
+ });
302
+ setTimeout(() => {
303
+ server.close();
304
+ reject(new Error("Authentication timeout"));
305
+ }, 5 * 60 * 1e3);
306
+ });
307
+ }
308
+ async function authenticateClaude() {
309
+ console.log("\u{1F680} Starting Anthropic Claude authentication...");
310
+ const { verifier, challenge } = generatePKCE$1();
311
+ const state = generateState$1();
312
+ let port = DEFAULT_PORT$1;
313
+ const portAvailable = await isPortAvailable$1(port);
314
+ if (!portAvailable) {
315
+ console.log(`Port ${port} is in use, finding an available port...`);
316
+ port = await findAvailablePort$1();
317
+ }
318
+ console.log(`\u{1F4E1} Using callback port: ${port}`);
319
+ const serverPromise = startCallbackServer$1(state, verifier, port);
320
+ await new Promise((resolve) => setTimeout(resolve, 100));
321
+ const redirect_uri = `http://localhost:${port}/callback`;
322
+ const params = new URLSearchParams({
323
+ code: "true",
324
+ // This tells Claude.ai to show the code AND redirect
325
+ client_id: CLIENT_ID$1,
326
+ response_type: "code",
327
+ redirect_uri,
328
+ scope: SCOPE,
329
+ code_challenge: challenge,
330
+ code_challenge_method: "S256",
331
+ state
332
+ });
333
+ const authUrl = `${CLAUDE_AI_AUTHORIZE_URL}?${params}`;
334
+ console.log("\u{1F4CB} Opening browser for authentication...");
335
+ console.log("If browser doesn't open, visit this URL:");
336
+ console.log();
337
+ console.log(`${authUrl}`);
338
+ console.log();
339
+ await browser.openBrowser(authUrl);
340
+ try {
341
+ const tokens = await serverPromise;
342
+ console.log("\u{1F389} Authentication successful!");
343
+ console.log("\u2705 OAuth tokens received");
344
+ return tokens;
345
+ } catch (error) {
346
+ console.error("\n\u274C Failed to authenticate with Anthropic");
347
+ throw error;
348
+ }
349
+ }
350
+
351
+ const execAsync = util.promisify(child_process.exec);
352
+ const CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com";
353
+ const CLIENT_SECRET = "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";
354
+ const AUTHORIZE_URL = "https://accounts.google.com/o/oauth2/v2/auth";
355
+ const TOKEN_URL = "https://oauth2.googleapis.com/token";
356
+ const DEFAULT_PORT = 54545;
357
+ const SCOPES = [
358
+ "https://www.googleapis.com/auth/cloud-platform",
359
+ "https://www.googleapis.com/auth/userinfo.email",
360
+ "https://www.googleapis.com/auth/userinfo.profile"
361
+ ].join(" ");
362
+ function generatePKCE() {
363
+ const verifier = crypto.randomBytes(32).toString("base64url").replace(/[^a-zA-Z0-9\-._~]/g, "");
364
+ const challenge = crypto.createHash("sha256").update(verifier).digest("base64url").replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
365
+ return { verifier, challenge };
366
+ }
367
+ function generateState() {
368
+ return crypto.randomBytes(32).toString("hex");
369
+ }
370
+ async function findAvailablePort() {
371
+ return new Promise((resolve) => {
372
+ const server = http.createServer();
373
+ server.listen(0, "127.0.0.1", () => {
374
+ const port = server.address().port;
375
+ server.close(() => resolve(port));
376
+ });
377
+ });
378
+ }
379
+ async function isPortAvailable(port) {
380
+ return new Promise((resolve) => {
381
+ const testServer = http.createServer();
382
+ testServer.once("error", () => {
383
+ testServer.close();
384
+ resolve(false);
385
+ });
386
+ testServer.listen(port, "127.0.0.1", () => {
387
+ testServer.close(() => resolve(true));
388
+ });
389
+ });
390
+ }
391
+ async function exchangeCodeForTokens(code, verifier, port) {
392
+ const response = await fetch(TOKEN_URL, {
393
+ method: "POST",
394
+ headers: {
395
+ "Content-Type": "application/x-www-form-urlencoded"
396
+ },
397
+ body: new URLSearchParams({
398
+ grant_type: "authorization_code",
399
+ client_id: CLIENT_ID,
400
+ client_secret: CLIENT_SECRET,
401
+ code,
402
+ code_verifier: verifier,
403
+ redirect_uri: `http://localhost:${port}/oauth2callback`
404
+ })
405
+ });
406
+ if (!response.ok) {
407
+ const error = await response.text();
408
+ throw new Error(`Token exchange failed: ${error}`);
409
+ }
410
+ const data = await response.json();
411
+ return data;
412
+ }
413
+ async function startCallbackServer(state, verifier, port) {
414
+ return new Promise((resolve, reject) => {
415
+ const server = http.createServer(async (req, res) => {
416
+ const url = new URL(req.url, `http://localhost:${port}`);
417
+ if (url.pathname === "/oauth2callback") {
418
+ const code = url.searchParams.get("code");
419
+ const receivedState = url.searchParams.get("state");
420
+ const error = url.searchParams.get("error");
421
+ if (error) {
422
+ res.writeHead(302, {
423
+ "Location": "https://developers.google.com/gemini-code-assist/auth_failure_gemini"
424
+ });
425
+ res.end();
426
+ server.close();
427
+ reject(new Error(`Authentication error: ${error}`));
428
+ return;
429
+ }
430
+ if (receivedState !== state) {
431
+ res.writeHead(400);
432
+ res.end("State mismatch. Possible CSRF attack");
433
+ server.close();
434
+ reject(new Error("Invalid state parameter"));
435
+ return;
436
+ }
437
+ if (!code) {
438
+ res.writeHead(400);
439
+ res.end("No authorization code received");
440
+ server.close();
441
+ reject(new Error("No authorization code received"));
442
+ return;
443
+ }
444
+ try {
445
+ const tokens = await exchangeCodeForTokens(code, verifier, port);
446
+ res.writeHead(302, {
447
+ "Location": "https://developers.google.com/gemini-code-assist/auth_success_gemini"
448
+ });
449
+ res.end();
450
+ server.close();
451
+ resolve(tokens);
452
+ } catch (error2) {
453
+ res.writeHead(500);
454
+ res.end("Token exchange failed");
455
+ server.close();
456
+ reject(error2);
457
+ }
458
+ }
459
+ });
460
+ server.listen(port, "127.0.0.1", () => {
461
+ });
462
+ setTimeout(() => {
463
+ server.close();
464
+ reject(new Error("Authentication timeout"));
465
+ }, 5 * 60 * 1e3);
466
+ });
467
+ }
468
+ async function authenticateGemini() {
469
+ console.log("\u{1F680} Starting Google Gemini authentication...");
470
+ const { verifier, challenge } = generatePKCE();
471
+ const state = generateState();
472
+ let port = DEFAULT_PORT;
473
+ const portAvailable = await isPortAvailable(port);
474
+ if (!portAvailable) {
475
+ console.log(`Port ${port} is in use, finding an available port...`);
476
+ port = await findAvailablePort();
477
+ }
478
+ console.log(`\u{1F4E1} Using callback port: ${port}`);
479
+ const serverPromise = startCallbackServer(state, verifier, port);
480
+ await new Promise((resolve) => setTimeout(resolve, 100));
481
+ const redirect_uri = `http://localhost:${port}/oauth2callback`;
482
+ const params = new URLSearchParams({
483
+ client_id: CLIENT_ID,
484
+ response_type: "code",
485
+ redirect_uri,
486
+ scope: SCOPES,
487
+ access_type: "offline",
488
+ // To get refresh token
489
+ code_challenge: challenge,
490
+ code_challenge_method: "S256",
491
+ state,
492
+ prompt: "consent"
493
+ // Force consent to get refresh token
494
+ });
495
+ const authUrl = `${AUTHORIZE_URL}?${params}`;
496
+ console.log("\n\u{1F4CB} Opening browser for authentication...");
497
+ console.log("If browser doesn't open, visit this URL:");
498
+ console.log(`
499
+ ${authUrl}
500
+ `);
501
+ const platform = process.platform;
502
+ const openCommand = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
503
+ try {
504
+ await execAsync(`${openCommand} "${authUrl}"`);
505
+ } catch {
506
+ console.log("\u26A0\uFE0F Could not open browser automatically");
507
+ }
508
+ try {
509
+ const tokens = await serverPromise;
510
+ console.log("\n\u{1F389} Authentication successful!");
511
+ console.log("\u2705 OAuth tokens received");
512
+ return tokens;
513
+ } catch (error) {
514
+ console.error("\n\u274C Failed to authenticate with Google");
515
+ throw error;
516
+ }
517
+ }
518
+
519
+ function decodeJwtPayload(token) {
520
+ try {
521
+ const parts = token.split(".");
522
+ if (parts.length !== 3) {
523
+ return null;
524
+ }
525
+ const payload = parts[1];
526
+ const decoded = Buffer.from(payload, "base64url").toString("utf-8");
527
+ return JSON.parse(decoded);
528
+ } catch {
529
+ return null;
530
+ }
531
+ }
532
+
533
+ async function handleConnectCommand(args) {
534
+ const subcommand = args[0];
535
+ if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
536
+ showConnectHelp();
537
+ return;
538
+ }
539
+ switch (subcommand.toLowerCase()) {
540
+ case "codex":
541
+ await handleConnectVendor("codex", "OpenAI");
542
+ break;
543
+ case "claude":
544
+ await handleConnectVendor("claude", "Anthropic");
545
+ break;
546
+ case "gemini":
547
+ await handleConnectVendor("gemini", "Gemini");
548
+ break;
549
+ case "status":
550
+ await handleConnectStatus();
551
+ break;
552
+ default:
553
+ console.error(chalk.red(`Unknown connect target: ${subcommand}`));
554
+ showConnectHelp();
555
+ process.exit(1);
556
+ }
557
+ }
558
+ function showConnectHelp() {
559
+ console.log(`
560
+ ${chalk.bold("very-happy connect")} - Store AI vendor credentials on your configured relay
561
+
562
+ ${chalk.bold("Usage:")}
563
+ very-happy connect codex Store your Codex credential on the relay
564
+ very-happy connect claude Store your Anthropic credential on the relay
565
+ very-happy connect gemini Store your Gemini credential on the relay
566
+ very-happy connect status Show connection status for all vendors
567
+ very-happy connect help Show this help message
568
+
569
+ ${chalk.bold("Description:")}
570
+ Credentials are encrypted at rest but recoverable by the configured relay.
571
+ The relay is trusted infrastructure, not an end-to-end encrypted vault.
572
+ Use this only when you trust that relay's operator and backups.
573
+
574
+ ${chalk.bold("Examples:")}
575
+ very-happy connect codex
576
+ very-happy connect claude
577
+ very-happy connect gemini
578
+ very-happy connect status
579
+
580
+ ${chalk.bold("Notes:")}
581
+ \u2022 You must be authenticated with Happy first (run 'very-happy auth login')
582
+ \u2022 Credentials are sent to and retained by your configured relay
583
+ \u2022 Remove a credential with the corresponding account/settings controls
584
+ `);
585
+ }
586
+ async function handleConnectVendor(vendor, displayName) {
587
+ console.log(chalk.bold(`
588
+ \u{1F50C} Connecting ${displayName} to Happy cloud
589
+ `));
590
+ const credentials = await persistence.readCredentialsForConfiguredRelay();
591
+ if (!credentials) {
592
+ console.log(chalk.yellow("\u26A0\uFE0F Not authenticated with Happy"));
593
+ console.log(chalk.gray(' Please run "very-happy auth login" first'));
594
+ process.exit(1);
595
+ }
596
+ const api$1 = await api.ApiClient.create(credentials);
597
+ if (vendor === "codex") {
598
+ console.log("\u{1F680} Registering Codex token with server");
599
+ const codexAuthTokens = await authenticateCodex();
600
+ await api$1.registerVendorToken("openai", { oauth: codexAuthTokens });
601
+ console.log("\u2705 Codex token registered with server");
602
+ process.exit(0);
603
+ } else if (vendor === "claude") {
604
+ console.log("\u{1F680} Registering Anthropic token with server");
605
+ const anthropicAuthTokens = await authenticateClaude();
606
+ await api$1.registerVendorToken("anthropic", { oauth: anthropicAuthTokens });
607
+ console.log("\u2705 Anthropic token registered with server");
608
+ process.exit(0);
609
+ } else if (vendor === "gemini") {
610
+ console.log("\u{1F680} Registering Gemini token with server");
611
+ const geminiAuthTokens = await authenticateGemini();
612
+ await api$1.registerVendorToken("gemini", { oauth: geminiAuthTokens });
613
+ console.log("\u2705 Gemini token registered with server");
614
+ updateLocalGeminiCredentials(geminiAuthTokens);
615
+ process.exit(0);
616
+ } else {
617
+ throw new Error(`Unsupported vendor: ${vendor}`);
618
+ }
619
+ }
620
+ async function handleConnectStatus() {
621
+ console.log(chalk.bold("\n\u{1F50C} Connection Status\n"));
622
+ const credentials = await persistence.readCredentialsForConfiguredRelay();
623
+ if (!credentials) {
624
+ console.log(chalk.yellow("\u26A0\uFE0F Not authenticated with Happy"));
625
+ console.log(chalk.gray(' Please run "very-happy auth login" first'));
626
+ process.exit(1);
627
+ }
628
+ const api$1 = await api.ApiClient.create(credentials);
629
+ const vendors = [
630
+ { key: "gemini", name: "Gemini", display: "Google Gemini" },
631
+ { key: "openai", name: "Codex", display: "OpenAI Codex" },
632
+ { key: "anthropic", name: "Claude", display: "Anthropic Claude" }
633
+ ];
634
+ for (const vendor of vendors) {
635
+ try {
636
+ const token = await api$1.getVendorToken(vendor.key);
637
+ if (token?.oauth) {
638
+ let userInfo = "";
639
+ if (token.oauth.id_token) {
640
+ const payload = decodeJwtPayload(token.oauth.id_token);
641
+ if (payload?.email) {
642
+ userInfo = chalk.gray(` (${payload.email})`);
643
+ }
644
+ }
645
+ const expiresAt = token.oauth.expires_at || (token.oauth.expires_in ? Date.now() + token.oauth.expires_in * 1e3 : null);
646
+ const isExpired = expiresAt && expiresAt < Date.now();
647
+ if (isExpired) {
648
+ console.log(` ${chalk.yellow("\u26A0\uFE0F")} ${vendor.display}: ${chalk.yellow("expired")}${userInfo}`);
649
+ } else {
650
+ console.log(` ${chalk.green("\u2713")} ${vendor.display}: ${chalk.green("connected")}${userInfo}`);
651
+ }
652
+ } else {
653
+ console.log(` ${chalk.gray("\u25CB")} ${vendor.display}: ${chalk.gray("not connected")}`);
654
+ }
655
+ } catch {
656
+ console.log(` ${chalk.gray("\u25CB")} ${vendor.display}: ${chalk.gray("not connected")}`);
657
+ }
658
+ }
659
+ console.log("");
660
+ console.log(chalk.gray("To connect a vendor, run: very-happy connect <vendor>"));
661
+ console.log(chalk.gray("Example: very-happy connect gemini"));
662
+ console.log("");
663
+ }
664
+ function updateLocalGeminiCredentials(tokens) {
665
+ try {
666
+ const geminiDir = path.join(os.homedir(), ".gemini");
667
+ const credentialsPath = path.join(geminiDir, "oauth_creds.json");
668
+ configuration.ensurePrivateDirectorySync(geminiDir);
669
+ const credentials = {
670
+ access_token: tokens.access_token,
671
+ token_type: tokens.token_type || "Bearer",
672
+ scope: tokens.scope || "https://www.googleapis.com/auth/cloud-platform",
673
+ ...tokens.refresh_token && { refresh_token: tokens.refresh_token },
674
+ ...tokens.id_token && { id_token: tokens.id_token },
675
+ ...tokens.expires_in && { expires_in: tokens.expires_in }
676
+ };
677
+ configuration.writePrivateFileSync(credentialsPath, JSON.stringify(credentials, null, 2));
678
+ console.log(chalk.gray(` Updated local credentials: ${credentialsPath}`));
679
+ } catch (error) {
680
+ console.log(chalk.yellow(` \u26A0\uFE0F Could not update local credentials: ${error}`));
681
+ }
682
+ }
683
+
684
+ exports.handleConnectCommand = handleConnectCommand;
@@ -0,0 +1,11 @@
1
+ import { t as trimIdent } from './trimIdent-BAjmv_TG.mjs';
2
+
3
+ const GEMINI_API_KEY_ENV = "GEMINI_API_KEY";
4
+ const GOOGLE_API_KEY_ENV = "GOOGLE_API_KEY";
5
+ const GEMINI_MODEL_ENV = "GEMINI_MODEL";
6
+ const DEFAULT_GEMINI_MODEL = "gemini-2.5-pro";
7
+ const CHANGE_TITLE_INSTRUCTION = trimIdent(
8
+ `Based on this message, call functions.happy__change_title to change chat session title that would represent the current task. If chat idea would change dramatically - call this function again to update the title.`
9
+ );
10
+
11
+ export { CHANGE_TITLE_INSTRUCTION as C, DEFAULT_GEMINI_MODEL as D, GEMINI_MODEL_ENV as G, GEMINI_API_KEY_ENV as a, GOOGLE_API_KEY_ENV as b };