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,220 @@
1
+ 'use strict';
2
+
3
+ var chalk = require('chalk');
4
+ var persistence = require('./persistence-yKTH3-5X.cjs');
5
+ var auth = require('./auth-ba4WMYrN.cjs');
6
+ var configuration = require('./configuration-BSYpcPwE.cjs');
7
+ var node_fs = require('node:fs');
8
+ var node_readline = require('node:readline');
9
+ var controlClient = require('./controlClient-Bcwv3D21.cjs');
10
+ var logger = require('./logger-CS0mw3fa.cjs');
11
+ var os = require('node:os');
12
+ var authRelay = require('./authRelay-BdYkC1Po.cjs');
13
+ require('node:fs/promises');
14
+ require('zod');
15
+ require('node:path');
16
+ require('./package-BwMrPwqH.cjs');
17
+ require('node:crypto');
18
+ require('tweetnacl');
19
+ require('node:util');
20
+ require('axios');
21
+ require('./time-DCuTyook.cjs');
22
+ require('./browser-Y6Bl8L_O.cjs');
23
+ require('open');
24
+
25
+ function localMachineIdentityStatus(machineId) {
26
+ if (machineId) {
27
+ return {
28
+ configured: true,
29
+ label: "Local machine identity configured (relay registration not checked)"
30
+ };
31
+ }
32
+ return {
33
+ configured: false,
34
+ label: "Local machine identity missing",
35
+ nextStep: 'Run "very-happy auth login --force" to create and register one'
36
+ };
37
+ }
38
+
39
+ const DEFAULT_SERVER_URL = "https://veryhappy.dev";
40
+ async function handleAuthCommand(args) {
41
+ const subcommand = args[0];
42
+ if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
43
+ showAuthHelp();
44
+ return;
45
+ }
46
+ switch (subcommand) {
47
+ case "login":
48
+ await handleAuthLogin(args.slice(1));
49
+ break;
50
+ case "logout":
51
+ await handleAuthLogout();
52
+ break;
53
+ case "status":
54
+ await handleAuthStatus();
55
+ break;
56
+ default:
57
+ console.error(chalk.red(`Unknown auth subcommand: ${subcommand}`));
58
+ showAuthHelp();
59
+ process.exit(1);
60
+ }
61
+ }
62
+ function showAuthHelp() {
63
+ console.log(`
64
+ ${chalk.bold("very-happy auth")} - Authentication management
65
+
66
+ ${chalk.bold("Usage:")}
67
+ very-happy auth login [--force] Authenticate with Very Happy
68
+ very-happy auth logout Remove authentication and machine data
69
+ very-happy auth status Show authentication status
70
+ very-happy auth help Show this help message
71
+
72
+ ${chalk.bold("Options:")}
73
+ --force Clear credentials, machine ID, and stop daemon before re-auth
74
+
75
+ ${chalk.gray("Security: the configured Very Happy server is a trusted relay and account service.")}
76
+ ${chalk.gray("It can recover account material, access relayed content, and act through capabilities")}
77
+ ${chalk.gray("exposed by an online daemon. Use a server you trust.")}
78
+ `);
79
+ }
80
+ function printDaemonNextStep() {
81
+ console.log(chalk.bold("\nNext: start the machine daemon"));
82
+ if (process.env.HAPPY_SERVER_URL || process.env.HAPPY_WEBAPP_URL) {
83
+ console.log(chalk.yellow(" Keep the same HAPPY_SERVER_URL and HAPPY_WEBAPP_URL environment when starting it."));
84
+ }
85
+ console.log(` ${chalk.cyan("very-happy daemon start")}`);
86
+ console.log(chalk.gray(" It starts in the background and keeps this machine available in Web."));
87
+ }
88
+ async function handleAuthLogin(args) {
89
+ const forceAuth = args.includes("--force") || args.includes("-f");
90
+ if (forceAuth) {
91
+ console.log(chalk.yellow("Force authentication requested."));
92
+ console.log(chalk.gray("This will:"));
93
+ console.log(chalk.gray(" \u2022 Clear existing credentials"));
94
+ console.log(chalk.gray(" \u2022 Clear machine ID"));
95
+ console.log(chalk.gray(" \u2022 Stop daemon if running"));
96
+ console.log(chalk.gray(" \u2022 Re-authenticate and register machine\n"));
97
+ try {
98
+ logger.logger.debug("Stopping daemon for force auth...");
99
+ await controlClient.stopDaemon();
100
+ console.log(chalk.gray("\u2713 Stopped daemon"));
101
+ } catch (error) {
102
+ logger.logger.debug("Daemon was not running or failed to stop:", error);
103
+ }
104
+ await persistence.clearCredentials();
105
+ console.log(chalk.gray("\u2713 Cleared credentials"));
106
+ await persistence.clearMachineId();
107
+ console.log(chalk.gray("\u2713 Cleared machine ID"));
108
+ console.log("");
109
+ }
110
+ if (!forceAuth) {
111
+ const existingCreds = await persistence.readCredentials();
112
+ const settings = await persistence.readSettings();
113
+ if (existingCreds && settings?.machineId) {
114
+ const relayProblem = authRelay.credentialRelayProblem(existingCreds.authServerUrl, configuration.configuration.serverUrl);
115
+ if (relayProblem) {
116
+ console.log(chalk.red(`\u2717 ${relayProblem}`));
117
+ console.log(chalk.yellow(" Use a separate HAPPY_HOME_DIR for each relay (recommended),"));
118
+ console.log(chalk.yellow(" or run 'very-happy auth login --force' to replace this home's credentials."));
119
+ process.exitCode = 1;
120
+ return;
121
+ }
122
+ console.log(chalk.green("\u2713 Already authenticated"));
123
+ console.log(chalk.gray(` Machine ID: ${settings.machineId}`));
124
+ console.log(chalk.gray(` Host: ${os.hostname()}`));
125
+ console.log(chalk.gray(` Use 'very-happy auth login --force' to re-authenticate`));
126
+ printDaemonNextStep();
127
+ return;
128
+ } else if (existingCreds && !settings?.machineId) {
129
+ console.log(chalk.yellow("\u26A0\uFE0F Credentials exist but machine ID is missing"));
130
+ console.log(chalk.gray(" This can happen if --auth flag was used previously"));
131
+ console.log(chalk.gray(" Fixing by setting up machine...\n"));
132
+ }
133
+ }
134
+ try {
135
+ const result = await auth.authAndSetupMachineIfNeeded();
136
+ console.log(chalk.green("\n\u2713 Authentication successful"));
137
+ console.log(chalk.gray(` Machine ID: ${result.machineId}`));
138
+ printDaemonNextStep();
139
+ } catch (error) {
140
+ console.error(chalk.red("Authentication failed:"), error instanceof Error ? error.message : "Unknown error");
141
+ process.exit(1);
142
+ }
143
+ }
144
+ async function handleAuthLogout() {
145
+ const happyDir = configuration.configuration.happyHomeDir;
146
+ const credentials = await persistence.readCredentials();
147
+ if (!credentials) {
148
+ console.log(chalk.yellow("Not currently authenticated"));
149
+ return;
150
+ }
151
+ console.log(chalk.blue("This will log you out of Happy"));
152
+ console.log(chalk.yellow("\u26A0\uFE0F You will need to re-authenticate to use Happy again"));
153
+ const rl = node_readline.createInterface({
154
+ input: process.stdin,
155
+ output: process.stdout
156
+ });
157
+ const answer = await new Promise((resolve) => {
158
+ rl.question(chalk.yellow("Are you sure you want to log out? (y/N): "), resolve);
159
+ });
160
+ rl.close();
161
+ if (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
162
+ try {
163
+ try {
164
+ await controlClient.stopDaemon();
165
+ console.log(chalk.gray("Stopped daemon"));
166
+ } catch {
167
+ }
168
+ if (node_fs.existsSync(happyDir)) {
169
+ node_fs.rmSync(happyDir, { recursive: true, force: true });
170
+ }
171
+ console.log(chalk.green("\u2713 Successfully logged out"));
172
+ console.log(chalk.gray(' Run "very-happy auth login" to authenticate again'));
173
+ } catch (error) {
174
+ throw new Error(`Failed to logout: ${error instanceof Error ? error.message : "Unknown error"}`);
175
+ }
176
+ } else {
177
+ console.log(chalk.blue("Logout cancelled"));
178
+ }
179
+ }
180
+ async function handleAuthStatus() {
181
+ const credentials = await persistence.readCredentials();
182
+ const settings = await persistence.readSettings();
183
+ console.log(chalk.bold("\nAuthentication Status\n"));
184
+ if (!credentials) {
185
+ console.log(chalk.red("\u2717 Not authenticated"));
186
+ console.log(chalk.gray(' Run "very-happy auth login" to authenticate'));
187
+ return;
188
+ }
189
+ const relayProblem = authRelay.credentialRelayProblem(credentials.authServerUrl, configuration.configuration.serverUrl);
190
+ if (relayProblem) {
191
+ console.log(chalk.red(`\u2717 Credentials found, but not valid for the configured relay: ${relayProblem}`));
192
+ console.log(chalk.gray(" Use another HAPPY_HOME_DIR or run 'very-happy auth login --force'."));
193
+ } else {
194
+ console.log(chalk.green("\u2713 Authenticated to the configured relay"));
195
+ console.log(chalk.gray(` Relay: ${credentials.authServerUrl ?? DEFAULT_SERVER_URL}`));
196
+ }
197
+ const machineIdentity = localMachineIdentityStatus(settings?.machineId);
198
+ if (machineIdentity.configured) {
199
+ console.log(chalk.green(`\u2713 ${machineIdentity.label}`));
200
+ console.log(chalk.gray(` Machine ID: ${settings.machineId}`));
201
+ console.log(chalk.gray(` Host: ${os.hostname()}`));
202
+ } else {
203
+ console.log(chalk.yellow(`\u26A0\uFE0F ${machineIdentity.label}`));
204
+ console.log(chalk.gray(` ${machineIdentity.nextStep}`));
205
+ }
206
+ console.log(chalk.gray(`
207
+ Data directory: ${configuration.configuration.happyHomeDir}`));
208
+ try {
209
+ const running = await controlClient.checkIfDaemonRunningAndCleanupStaleState();
210
+ if (running) {
211
+ console.log(chalk.green("\u2713 Daemon running"));
212
+ } else {
213
+ console.log(chalk.gray("\u2717 Daemon not running"));
214
+ }
215
+ } catch {
216
+ console.log(chalk.gray("\u2717 Daemon not running"));
217
+ }
218
+ }
219
+
220
+ exports.handleAuthCommand = handleAuthCommand;
@@ -0,0 +1,225 @@
1
+ import { e as encodeBase64, c as credentialRelayProblem, f as encodeBase64Url, d as decodeBase64 } from './authRelay-DSAvg1uv.mjs';
2
+ import { c as configuration } from './configuration-RfeNjFmd.mjs';
3
+ import { randomUUID, randomBytes } from 'node:crypto';
4
+ import tweetnacl from 'tweetnacl';
5
+ import axios from 'axios';
6
+ import { d as delay } from './time-D0XyHOid.mjs';
7
+ import { readCredentials, readSettingsOutcome, updateSettings, writeCredentialsLegacy, writeCredentialsDataKey } from './persistence-HGW_ZVs9.mjs';
8
+ import { o as openBrowser } from './browser-jh2P0UVZ.mjs';
9
+ import { l as logger } from './logger-6HYUEXNk.mjs';
10
+
11
+ function generateWebAuthUrl(publicKey) {
12
+ const publicKeyBase64 = encodeBase64(publicKey, "base64url");
13
+ return `${configuration.webappUrl}/terminal/connect#key=${publicKeyBase64}`;
14
+ }
15
+
16
+ function decideMachineId(input) {
17
+ const { read, newAuth } = input;
18
+ if (read.kind === "unreadable") {
19
+ return {
20
+ action: "refuse",
21
+ reason: `settings exist but could not be read (${read.error}); refusing to mint a new machine id \u2014 fix or remove the settings file, or run \`very-happy auth login --force\` to deliberately re-register this machine`
22
+ };
23
+ }
24
+ if (newAuth) return { action: "mint", reason: "new-auth" };
25
+ if (read.kind === "absent") return { action: "mint", reason: "no-settings-file" };
26
+ const existing = read.settings.machineId;
27
+ if (typeof existing === "string" && existing.length > 0) {
28
+ return { action: "reuse", machineId: existing };
29
+ }
30
+ return { action: "mint", reason: "no-machine-id" };
31
+ }
32
+
33
+ async function doAuth() {
34
+ console.clear();
35
+ const secret = new Uint8Array(randomBytes(32));
36
+ const keypair = tweetnacl.box.keyPair.fromSecretKey(secret);
37
+ const claimSecret = encodeBase64Url(randomBytes(32));
38
+ try {
39
+ if (process.env.DEBUG) {
40
+ console.log(`[AUTH DEBUG] Sending auth request to: ${configuration.serverUrl}/v1/auth/request`);
41
+ }
42
+ const createResponse = await axios.post(`${configuration.serverUrl}/v1/auth/request`, {
43
+ publicKey: encodeBase64(keypair.publicKey),
44
+ supportsV2: true,
45
+ supportsClaimSecret: true,
46
+ claimSecret,
47
+ pairingAction: "create"
48
+ }, {
49
+ headers: {
50
+ "X-Happy-Client": `cli/${configuration.currentCliVersion}`
51
+ }
52
+ });
53
+ if (createResponse.data?.protocolVersion !== 3 || createResponse.data?.claimSecretRequired !== true) {
54
+ console.log("This server does not support secure CLI pairing. Upgrade the server before signing in.");
55
+ return null;
56
+ }
57
+ if (process.env.DEBUG) {
58
+ console.log(`[AUTH DEBUG] Auth request sent successfully`);
59
+ }
60
+ } catch {
61
+ if (process.env.DEBUG) {
62
+ console.log("[AUTH DEBUG] Failed to send secure auth request");
63
+ }
64
+ console.log("Failed to create authentication request, please try again later.");
65
+ return null;
66
+ }
67
+ return await doWebAuth(keypair, claimSecret);
68
+ }
69
+ async function doWebAuth(keypair, claimSecret) {
70
+ console.clear();
71
+ console.log("\nWeb Authentication\n");
72
+ const webUrl = generateWebAuthUrl(keypair.publicKey);
73
+ console.log("Opening your browser...");
74
+ const browserOpened = await openBrowser(webUrl);
75
+ if (browserOpened) {
76
+ console.log("\u2713 Browser opened\n");
77
+ console.log("Complete authentication in your browser window.");
78
+ } else {
79
+ console.log("Could not open browser automatically.");
80
+ }
81
+ console.log("\nIf the browser did not open, please copy and paste this URL:");
82
+ console.log(webUrl);
83
+ console.log("");
84
+ return await waitForAuthentication(keypair, claimSecret);
85
+ }
86
+ async function waitForAuthentication(keypair, claimSecret) {
87
+ process.stdout.write("Waiting for authentication");
88
+ let dots = 0;
89
+ let cancelled = false;
90
+ const handleInterrupt = () => {
91
+ cancelled = true;
92
+ console.log("\n\nAuthentication cancelled.");
93
+ process.exit(0);
94
+ };
95
+ process.on("SIGINT", handleInterrupt);
96
+ try {
97
+ while (!cancelled) {
98
+ try {
99
+ const response = await axios.post(`${configuration.serverUrl}/v1/auth/request`, {
100
+ publicKey: encodeBase64(keypair.publicKey),
101
+ supportsV2: true,
102
+ supportsClaimSecret: true,
103
+ claimSecret,
104
+ pairingAction: "poll"
105
+ }, {
106
+ headers: {
107
+ "X-Happy-Client": `cli/${configuration.currentCliVersion}`
108
+ }
109
+ });
110
+ if (response.data?.protocolVersion !== 3 || response.data?.claimSecretRequired !== true) {
111
+ console.log("\n\nThis server does not support secure CLI pairing. Upgrade the server before signing in.");
112
+ return null;
113
+ }
114
+ if (response.data.state === "authorized") {
115
+ let token = response.data.token;
116
+ let r = decodeBase64(response.data.response);
117
+ let decrypted = decryptWithEphemeralKey(r, keypair.secretKey);
118
+ if (decrypted) {
119
+ if (decrypted.length === 32) {
120
+ const credentials = {
121
+ secret: decrypted,
122
+ token
123
+ };
124
+ await writeCredentialsLegacy(credentials);
125
+ console.log("\n\n\u2713 Authentication successful\n");
126
+ return {
127
+ encryption: {
128
+ type: "legacy",
129
+ secret: decrypted
130
+ },
131
+ token
132
+ };
133
+ } else {
134
+ if (decrypted[0] === 0) {
135
+ const credentials = {
136
+ publicKey: decrypted.slice(1, 33),
137
+ machineKey: randomBytes(32),
138
+ token
139
+ };
140
+ await writeCredentialsDataKey(credentials);
141
+ console.log("\n\n\u2713 Authentication successful\n");
142
+ return {
143
+ encryption: {
144
+ type: "dataKey",
145
+ publicKey: credentials.publicKey,
146
+ machineKey: credentials.machineKey
147
+ },
148
+ token
149
+ };
150
+ } else {
151
+ console.log("\n\nFailed to decrypt response. Please try again.");
152
+ return null;
153
+ }
154
+ }
155
+ } else {
156
+ console.log("\n\nFailed to decrypt response. Please try again.");
157
+ return null;
158
+ }
159
+ }
160
+ } catch (error) {
161
+ console.log("\n\nFailed to check authentication status. Please try again.");
162
+ return null;
163
+ }
164
+ process.stdout.write("\rWaiting for authentication" + ".".repeat(dots % 3 + 1) + " ");
165
+ dots++;
166
+ await delay(1e3);
167
+ }
168
+ } finally {
169
+ process.off("SIGINT", handleInterrupt);
170
+ }
171
+ return null;
172
+ }
173
+ function decryptWithEphemeralKey(encryptedBundle, recipientSecretKey) {
174
+ const ephemeralPublicKey = encryptedBundle.slice(0, 32);
175
+ const nonce = encryptedBundle.slice(32, 32 + tweetnacl.box.nonceLength);
176
+ const encrypted = encryptedBundle.slice(32 + tweetnacl.box.nonceLength);
177
+ const decrypted = tweetnacl.box.open(encrypted, nonce, ephemeralPublicKey, recipientSecretKey);
178
+ if (!decrypted) {
179
+ return null;
180
+ }
181
+ return decrypted;
182
+ }
183
+ async function authAndSetupMachineIfNeeded() {
184
+ logger.debug("[AUTH] Starting auth and machine setup...");
185
+ let credentials = await readCredentials();
186
+ let newAuth = false;
187
+ if (credentials) {
188
+ const relayProblem = credentialRelayProblem(credentials.authServerUrl, configuration.serverUrl);
189
+ if (relayProblem) {
190
+ throw new Error(
191
+ `${relayProblem} Use a separate HAPPY_HOME_DIR for this relay, or run \`very-happy auth login --force\` before starting an agent or daemon.`
192
+ );
193
+ }
194
+ }
195
+ if (!credentials) {
196
+ logger.debug("[AUTH] No credentials found, starting authentication flow...");
197
+ const authResult = await doAuth();
198
+ if (!authResult) {
199
+ throw new Error("Authentication failed or was cancelled");
200
+ }
201
+ credentials = authResult;
202
+ newAuth = true;
203
+ } else {
204
+ logger.debug("[AUTH] Using existing credentials");
205
+ }
206
+ const decision = decideMachineId({
207
+ read: await readSettingsOutcome(),
208
+ newAuth
209
+ });
210
+ if (decision.action === "refuse") {
211
+ throw new Error(`Cannot establish this machine's identity: ${decision.reason}`);
212
+ }
213
+ let machineId;
214
+ if (decision.action === "reuse") {
215
+ machineId = decision.machineId;
216
+ } else {
217
+ machineId = randomUUID();
218
+ logger.warn(`[AUTH] Registering a NEW machine id (${decision.reason})`);
219
+ await updateSettings(async (s) => ({ ...s, machineId }));
220
+ }
221
+ logger.debug(`[AUTH] Machine ID: ${machineId}`);
222
+ return { credentials, machineId };
223
+ }
224
+
225
+ export { authAndSetupMachineIfNeeded as a };
@@ -0,0 +1,218 @@
1
+ import chalk from 'chalk';
2
+ import { readCredentials, readSettings, clearCredentials, clearMachineId } from './persistence-HGW_ZVs9.mjs';
3
+ import { a as authAndSetupMachineIfNeeded } from './auth-Cwutmdsa.mjs';
4
+ import { c as configuration } from './configuration-RfeNjFmd.mjs';
5
+ import { existsSync, rmSync } from 'node:fs';
6
+ import { createInterface } from 'node:readline';
7
+ import { c as checkIfDaemonRunningAndCleanupStaleState, a as stopDaemon } from './controlClient-BGbDcgWS.mjs';
8
+ import { l as logger } from './logger-6HYUEXNk.mjs';
9
+ import os from 'node:os';
10
+ import { c as credentialRelayProblem } from './authRelay-DSAvg1uv.mjs';
11
+ import 'node:fs/promises';
12
+ import 'zod';
13
+ import 'node:path';
14
+ import './package-BhaKlnxz.mjs';
15
+ import 'node:crypto';
16
+ import 'tweetnacl';
17
+ import 'node:util';
18
+ import 'axios';
19
+ import './time-D0XyHOid.mjs';
20
+ import './browser-jh2P0UVZ.mjs';
21
+ import 'open';
22
+
23
+ function localMachineIdentityStatus(machineId) {
24
+ if (machineId) {
25
+ return {
26
+ configured: true,
27
+ label: "Local machine identity configured (relay registration not checked)"
28
+ };
29
+ }
30
+ return {
31
+ configured: false,
32
+ label: "Local machine identity missing",
33
+ nextStep: 'Run "very-happy auth login --force" to create and register one'
34
+ };
35
+ }
36
+
37
+ const DEFAULT_SERVER_URL = "https://veryhappy.dev";
38
+ async function handleAuthCommand(args) {
39
+ const subcommand = args[0];
40
+ if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
41
+ showAuthHelp();
42
+ return;
43
+ }
44
+ switch (subcommand) {
45
+ case "login":
46
+ await handleAuthLogin(args.slice(1));
47
+ break;
48
+ case "logout":
49
+ await handleAuthLogout();
50
+ break;
51
+ case "status":
52
+ await handleAuthStatus();
53
+ break;
54
+ default:
55
+ console.error(chalk.red(`Unknown auth subcommand: ${subcommand}`));
56
+ showAuthHelp();
57
+ process.exit(1);
58
+ }
59
+ }
60
+ function showAuthHelp() {
61
+ console.log(`
62
+ ${chalk.bold("very-happy auth")} - Authentication management
63
+
64
+ ${chalk.bold("Usage:")}
65
+ very-happy auth login [--force] Authenticate with Very Happy
66
+ very-happy auth logout Remove authentication and machine data
67
+ very-happy auth status Show authentication status
68
+ very-happy auth help Show this help message
69
+
70
+ ${chalk.bold("Options:")}
71
+ --force Clear credentials, machine ID, and stop daemon before re-auth
72
+
73
+ ${chalk.gray("Security: the configured Very Happy server is a trusted relay and account service.")}
74
+ ${chalk.gray("It can recover account material, access relayed content, and act through capabilities")}
75
+ ${chalk.gray("exposed by an online daemon. Use a server you trust.")}
76
+ `);
77
+ }
78
+ function printDaemonNextStep() {
79
+ console.log(chalk.bold("\nNext: start the machine daemon"));
80
+ if (process.env.HAPPY_SERVER_URL || process.env.HAPPY_WEBAPP_URL) {
81
+ console.log(chalk.yellow(" Keep the same HAPPY_SERVER_URL and HAPPY_WEBAPP_URL environment when starting it."));
82
+ }
83
+ console.log(` ${chalk.cyan("very-happy daemon start")}`);
84
+ console.log(chalk.gray(" It starts in the background and keeps this machine available in Web."));
85
+ }
86
+ async function handleAuthLogin(args) {
87
+ const forceAuth = args.includes("--force") || args.includes("-f");
88
+ if (forceAuth) {
89
+ console.log(chalk.yellow("Force authentication requested."));
90
+ console.log(chalk.gray("This will:"));
91
+ console.log(chalk.gray(" \u2022 Clear existing credentials"));
92
+ console.log(chalk.gray(" \u2022 Clear machine ID"));
93
+ console.log(chalk.gray(" \u2022 Stop daemon if running"));
94
+ console.log(chalk.gray(" \u2022 Re-authenticate and register machine\n"));
95
+ try {
96
+ logger.debug("Stopping daemon for force auth...");
97
+ await stopDaemon();
98
+ console.log(chalk.gray("\u2713 Stopped daemon"));
99
+ } catch (error) {
100
+ logger.debug("Daemon was not running or failed to stop:", error);
101
+ }
102
+ await clearCredentials();
103
+ console.log(chalk.gray("\u2713 Cleared credentials"));
104
+ await clearMachineId();
105
+ console.log(chalk.gray("\u2713 Cleared machine ID"));
106
+ console.log("");
107
+ }
108
+ if (!forceAuth) {
109
+ const existingCreds = await readCredentials();
110
+ const settings = await readSettings();
111
+ if (existingCreds && settings?.machineId) {
112
+ const relayProblem = credentialRelayProblem(existingCreds.authServerUrl, configuration.serverUrl);
113
+ if (relayProblem) {
114
+ console.log(chalk.red(`\u2717 ${relayProblem}`));
115
+ console.log(chalk.yellow(" Use a separate HAPPY_HOME_DIR for each relay (recommended),"));
116
+ console.log(chalk.yellow(" or run 'very-happy auth login --force' to replace this home's credentials."));
117
+ process.exitCode = 1;
118
+ return;
119
+ }
120
+ console.log(chalk.green("\u2713 Already authenticated"));
121
+ console.log(chalk.gray(` Machine ID: ${settings.machineId}`));
122
+ console.log(chalk.gray(` Host: ${os.hostname()}`));
123
+ console.log(chalk.gray(` Use 'very-happy auth login --force' to re-authenticate`));
124
+ printDaemonNextStep();
125
+ return;
126
+ } else if (existingCreds && !settings?.machineId) {
127
+ console.log(chalk.yellow("\u26A0\uFE0F Credentials exist but machine ID is missing"));
128
+ console.log(chalk.gray(" This can happen if --auth flag was used previously"));
129
+ console.log(chalk.gray(" Fixing by setting up machine...\n"));
130
+ }
131
+ }
132
+ try {
133
+ const result = await authAndSetupMachineIfNeeded();
134
+ console.log(chalk.green("\n\u2713 Authentication successful"));
135
+ console.log(chalk.gray(` Machine ID: ${result.machineId}`));
136
+ printDaemonNextStep();
137
+ } catch (error) {
138
+ console.error(chalk.red("Authentication failed:"), error instanceof Error ? error.message : "Unknown error");
139
+ process.exit(1);
140
+ }
141
+ }
142
+ async function handleAuthLogout() {
143
+ const happyDir = configuration.happyHomeDir;
144
+ const credentials = await readCredentials();
145
+ if (!credentials) {
146
+ console.log(chalk.yellow("Not currently authenticated"));
147
+ return;
148
+ }
149
+ console.log(chalk.blue("This will log you out of Happy"));
150
+ console.log(chalk.yellow("\u26A0\uFE0F You will need to re-authenticate to use Happy again"));
151
+ const rl = createInterface({
152
+ input: process.stdin,
153
+ output: process.stdout
154
+ });
155
+ const answer = await new Promise((resolve) => {
156
+ rl.question(chalk.yellow("Are you sure you want to log out? (y/N): "), resolve);
157
+ });
158
+ rl.close();
159
+ if (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
160
+ try {
161
+ try {
162
+ await stopDaemon();
163
+ console.log(chalk.gray("Stopped daemon"));
164
+ } catch {
165
+ }
166
+ if (existsSync(happyDir)) {
167
+ rmSync(happyDir, { recursive: true, force: true });
168
+ }
169
+ console.log(chalk.green("\u2713 Successfully logged out"));
170
+ console.log(chalk.gray(' Run "very-happy auth login" to authenticate again'));
171
+ } catch (error) {
172
+ throw new Error(`Failed to logout: ${error instanceof Error ? error.message : "Unknown error"}`);
173
+ }
174
+ } else {
175
+ console.log(chalk.blue("Logout cancelled"));
176
+ }
177
+ }
178
+ async function handleAuthStatus() {
179
+ const credentials = await readCredentials();
180
+ const settings = await readSettings();
181
+ console.log(chalk.bold("\nAuthentication Status\n"));
182
+ if (!credentials) {
183
+ console.log(chalk.red("\u2717 Not authenticated"));
184
+ console.log(chalk.gray(' Run "very-happy auth login" to authenticate'));
185
+ return;
186
+ }
187
+ const relayProblem = credentialRelayProblem(credentials.authServerUrl, configuration.serverUrl);
188
+ if (relayProblem) {
189
+ console.log(chalk.red(`\u2717 Credentials found, but not valid for the configured relay: ${relayProblem}`));
190
+ console.log(chalk.gray(" Use another HAPPY_HOME_DIR or run 'very-happy auth login --force'."));
191
+ } else {
192
+ console.log(chalk.green("\u2713 Authenticated to the configured relay"));
193
+ console.log(chalk.gray(` Relay: ${credentials.authServerUrl ?? DEFAULT_SERVER_URL}`));
194
+ }
195
+ const machineIdentity = localMachineIdentityStatus(settings?.machineId);
196
+ if (machineIdentity.configured) {
197
+ console.log(chalk.green(`\u2713 ${machineIdentity.label}`));
198
+ console.log(chalk.gray(` Machine ID: ${settings.machineId}`));
199
+ console.log(chalk.gray(` Host: ${os.hostname()}`));
200
+ } else {
201
+ console.log(chalk.yellow(`\u26A0\uFE0F ${machineIdentity.label}`));
202
+ console.log(chalk.gray(` ${machineIdentity.nextStep}`));
203
+ }
204
+ console.log(chalk.gray(`
205
+ Data directory: ${configuration.happyHomeDir}`));
206
+ try {
207
+ const running = await checkIfDaemonRunningAndCleanupStaleState();
208
+ if (running) {
209
+ console.log(chalk.green("\u2713 Daemon running"));
210
+ } else {
211
+ console.log(chalk.gray("\u2717 Daemon not running"));
212
+ }
213
+ } catch {
214
+ console.log(chalk.gray("\u2717 Daemon not running"));
215
+ }
216
+ }
217
+
218
+ export { handleAuthCommand };