@zonease/happy 0.6.38 → 0.6.39

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 (109) hide show
  1. package/dist/{types-BWpRU1VN.mjs → api-CIZKyfSn.mjs} +136 -1725
  2. package/dist/{types-DvTsFaqR.cjs → api-CwOCQeLH.cjs} +317 -1961
  3. package/dist/auth-0VnlXT9f.mjs +181 -0
  4. package/dist/auth-BE8dD20T.mjs +270 -0
  5. package/dist/auth-BIleVCw0.cjs +274 -0
  6. package/dist/auth-Cas9DR3b.cjs +183 -0
  7. package/dist/browser-Cc08m7of.cjs +22 -0
  8. package/dist/browser-Dll5hxOV.mjs +20 -0
  9. package/dist/claudeLocal-CPT3zcIU.mjs +344 -0
  10. package/dist/claudeLocal-WkgLbl1a.cjs +352 -0
  11. package/dist/codex/happyMcpStdioBridge.cjs +4 -1
  12. package/dist/codex/happyMcpStdioBridge.mjs +4 -1
  13. package/dist/common-BdNgghUJ.mjs +75 -0
  14. package/dist/common-CZvSRU4p.cjs +83 -0
  15. package/dist/{config-0Xnc8ARM.cjs → config-Draa-5XC.cjs} +21 -34
  16. package/dist/{config-_GW4YBCP.mjs → config-rTT4qTU5.mjs} +7 -20
  17. package/dist/connect-BfC1tYP_.mjs +679 -0
  18. package/dist/connect-CJZ73syK.cjs +681 -0
  19. package/dist/{constants-B4x1K7by.cjs → constants-E_UWYTo3.cjs} +2 -2
  20. package/dist/{constants-BO9OAFOT.mjs → constants-pmXZGibX.mjs} +1 -1
  21. package/dist/controlClient-CM_QcJnB.mjs +159 -0
  22. package/dist/controlClient-DZMIsKsT.cjs +168 -0
  23. package/dist/deviceExec-CU1R9CRb.cjs +84 -0
  24. package/dist/deviceExec-D93AOVV4.mjs +81 -0
  25. package/dist/diagnose-B3D1a_v0.cjs +60 -0
  26. package/dist/diagnose-CuRKXxt1.mjs +58 -0
  27. package/dist/doctor-C08m5Z9f.cjs +78 -0
  28. package/dist/doctor-Cya9YSA0.cjs +214 -0
  29. package/dist/doctor-DZYB6IVc.mjs +211 -0
  30. package/dist/doctor-ON7pN5G5.mjs +74 -0
  31. package/dist/downloadImage-DfSFLb-h.mjs +887 -0
  32. package/dist/downloadImage-MQMrUUxS.cjs +897 -0
  33. package/dist/enroll-BxlbVftP.cjs +115 -0
  34. package/dist/enroll-C52x8oly.mjs +113 -0
  35. package/dist/evidence-Ccd9iYcj.mjs +127 -0
  36. package/dist/evidence-CjWBG5rX.cjs +129 -0
  37. package/dist/formatImageMessage-B4lSxlk2.mjs +43 -0
  38. package/dist/formatImageMessage-DbyG8c2j.cjs +46 -0
  39. package/dist/github-DKcyF1zp.mjs +57 -0
  40. package/dist/github-h9GhJJ_C.cjs +59 -0
  41. package/dist/index-CDTNgfUf.cjs +578 -0
  42. package/dist/index-CPKdvi7J.mjs +554 -0
  43. package/dist/index.cjs +812 -40
  44. package/dist/index.mjs +813 -40
  45. package/dist/install-BokHRgFW.cjs +98 -0
  46. package/dist/install-C_cp8b2-.cjs +96 -0
  47. package/dist/install-DAeCn8ae.mjs +94 -0
  48. package/dist/install-oRAjVLjP.mjs +95 -0
  49. package/dist/lib.cjs +18 -12
  50. package/dist/lib.mjs +13 -7
  51. package/dist/{loadableToolOutput-va3RLplh.mjs → loadableToolOutput-Cuygmd4K.mjs} +4 -2
  52. package/dist/{loadableToolOutput-5vdQB98M.cjs → loadableToolOutput-DDCJjywt.cjs} +63 -61
  53. package/dist/mcpToolSchemas-CjeTfrAs.mjs +62 -0
  54. package/dist/mcpToolSchemas-DK42yoZ_.cjs +64 -0
  55. package/dist/persistence-BFjvtUad.mjs +944 -0
  56. package/dist/persistence-JLUn_Nou.cjs +996 -0
  57. package/dist/projectPath-BTBIMB57.mjs +10 -0
  58. package/dist/projectPath-ChLhdOyt.cjs +13 -0
  59. package/dist/prompt-BTWDZZO0.cjs +25 -0
  60. package/dist/prompt-BsAZsPbo.mjs +22 -0
  61. package/dist/release-BMEzNONE.mjs +168 -0
  62. package/dist/release-EhOJeAZe.cjs +171 -0
  63. package/dist/run-BDn2aE3Q.cjs +2152 -0
  64. package/dist/run-DBZqN6Kn.mjs +2128 -0
  65. package/dist/runClaude-DNHvERX0.mjs +3763 -0
  66. package/dist/runClaude-uaKxPZPm.cjs +3766 -0
  67. package/dist/{runCodex-skq0j05d.cjs → runCodex-82UrZLme.cjs} +169 -153
  68. package/dist/{runCodex-DiKzBf9q.mjs → runCodex-C-RTM0wA.mjs} +36 -20
  69. package/dist/{runGemini-BeqrVq8R.mjs → runGemini-Bm6-4Xm2.mjs} +34 -17
  70. package/dist/{runGemini-CVp-CEIh.cjs → runGemini-CXMr4Jwb.cjs} +212 -195
  71. package/dist/{runOneShot-BQNkNW61.cjs → runOneShot-1B6RMYT7.cjs} +31 -55
  72. package/dist/{runOneShot-ltCpHbBB.mjs → runOneShot-ioARRHrx.mjs} +14 -38
  73. package/dist/{serve-BECdtivY.cjs → serve-BtdAhkIE.cjs} +35 -58
  74. package/dist/{serve-BNdoEDVx.mjs → serve-CwibwU6N.mjs} +12 -35
  75. package/dist/session-2sU4Bu1R.mjs +108 -0
  76. package/dist/session-D--F87zL.cjs +110 -0
  77. package/dist/sessionKeyCache-4Tp8pJ3N.cjs +36 -0
  78. package/dist/sessionKeyCache-D2BwO91C.mjs +33 -0
  79. package/dist/sessionList-BCSw3qYt.mjs +51 -0
  80. package/dist/sessionList-ICJsjNtJ.cjs +54 -0
  81. package/dist/sessionSummary-Bkz52BPh.cjs +393 -0
  82. package/dist/sessionSummary-lHGBWQSb.mjs +387 -0
  83. package/dist/spawnHappyCLI-CoORX0YW.mjs +66 -0
  84. package/dist/spawnHappyCLI-D_V-AAoP.cjs +70 -0
  85. package/dist/ssh-BTOlhhxi.cjs +333 -0
  86. package/dist/ssh-DL_AkRAD.mjs +328 -0
  87. package/dist/systemdScope-BeOtAkhk.mjs +25 -0
  88. package/dist/systemdScope-DW3-UoKB.cjs +29 -0
  89. package/dist/task-CQzrHRZe.mjs +165 -0
  90. package/dist/task-CSpaC9HX.cjs +167 -0
  91. package/dist/time-Bj2HRkKH.cjs +33 -0
  92. package/dist/time-DgsBLJA_.mjs +29 -0
  93. package/dist/trimIdent-4gvk9Wk6.cjs +22 -0
  94. package/dist/trimIdent-BAjmv_TG.mjs +20 -0
  95. package/dist/types-BoJh4Qfv.mjs +57 -0
  96. package/dist/types-DWeB7aqh.cjs +59 -0
  97. package/dist/uninstall-BiKyRAb1.cjs +77 -0
  98. package/dist/uninstall-nFMFGUVM.mjs +75 -0
  99. package/dist/update-BcqRHXf2.mjs +109 -0
  100. package/dist/update-Dw8pgsAT.cjs +111 -0
  101. package/dist/workflowCommon-B0d01Y_a.mjs +56 -0
  102. package/dist/workflowCommon-Bl568-rt.cjs +62 -0
  103. package/dist/workflowReports-BEWuQesA.cjs +113 -0
  104. package/dist/workflowReports-Dd8-4-8f.mjs +108 -0
  105. package/package.json +1 -1
  106. package/dist/index-BbCDDvoB.cjs +0 -11376
  107. package/dist/index-vvZXdswy.mjs +0 -11336
  108. package/dist/mcpToolSchemas-CdPXJQmb.mjs +0 -175
  109. package/dist/mcpToolSchemas-f-kttjFw.cjs +0 -186
package/dist/index.cjs CHANGED
@@ -1,48 +1,820 @@
1
1
  'use strict';
2
2
 
3
- require('chalk');
4
- require('./types-DvTsFaqR.cjs');
5
- require('./index-BbCDDvoB.cjs');
6
- require('zod');
7
- require('node:child_process');
8
- require('axios');
9
- require('fs');
3
+ var chalk = require('chalk');
4
+ var logger = require('./persistence-JLUn_Nou.cjs');
5
+ var z = require('zod');
6
+ var node_child_process = require('node:child_process');
7
+ require('node:fs/promises');
10
8
  require('node:fs');
11
9
  require('node:os');
12
10
  require('node:path');
13
- require('node:events');
14
- require('socket.io-client');
15
- require('@paralleldrive/cuid2');
16
11
  require('node:crypto');
17
12
  require('tweetnacl');
18
- require('node:fs/promises');
19
- require('node:util');
20
- require('child_process');
21
- require('util');
22
- require('fs/promises');
23
- require('path');
24
- require('url');
25
- require('node:module');
26
- require('ws');
27
- require('crypto');
28
- require('@stablelib/base64');
29
- require('node:readline');
30
- require('expo-server-sdk');
31
- require('./mcpToolSchemas-f-kttjFw.cjs');
32
- require('ink');
33
- require('react');
34
- require('node:url');
35
- require('ps-list');
36
- require('cross-spawn');
37
- require('os');
38
- require('tmp');
39
- require('qrcode-terminal');
40
- require('open');
41
- require('fastify');
42
- require('fastify-type-provider-zod');
43
- require('@modelcontextprotocol/sdk/server/mcp.js');
44
- require('node:http');
45
- require('@modelcontextprotocol/sdk/server/streamableHttp.js');
46
- require('@modelcontextprotocol/sdk/types.js');
47
- require('http');
13
+ require('fs');
14
+
15
+ async function spawnAndWaitForDaemon() {
16
+ const { spawnHappyCLI } = await Promise.resolve().then(function () { return require('./spawnHappyCLI-D_V-AAoP.cjs'); }).then(function (n) { return n.spawnHappyCLI$1; });
17
+ const { checkIfDaemonRunningAndCleanupStaleState } = await Promise.resolve().then(function () { return require('./controlClient-DZMIsKsT.cjs'); });
18
+ const child = spawnHappyCLI(["daemon", "start-sync"], {
19
+ detached: true,
20
+ stdio: "ignore"
21
+ });
22
+ child.unref();
23
+ for (let i = 0; i < 50; i++) {
24
+ if (await checkIfDaemonRunningAndCleanupStaleState()) {
25
+ return true;
26
+ }
27
+ await new Promise((resolve) => setTimeout(resolve, 100));
28
+ }
29
+ return false;
30
+ }
31
+ (async () => {
32
+ const args = process.argv.slice(2);
33
+ if (!args.includes("--version")) {
34
+ logger.logger.debug("Starting happy CLI with args: ", process.argv);
35
+ }
36
+ const subcommand = args[0];
37
+ if (!args.includes("--version")) ;
38
+ if (subcommand === "orchestrator-oneshot") {
39
+ try {
40
+ const { runOrchestratorOneShot } = await Promise.resolve().then(function () { return require('./runOneShot-1B6RMYT7.cjs'); });
41
+ const exitCode = await runOrchestratorOneShot(args.slice(1));
42
+ process.exit(exitCode);
43
+ } catch (error) {
44
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
45
+ if (logger.isDebug()) {
46
+ console.error(error);
47
+ }
48
+ process.exit(1);
49
+ }
50
+ return;
51
+ } else if (subcommand === "doctor") {
52
+ const { killRunawayHappyProcesses } = await Promise.resolve().then(function () { return require('./doctor-C08m5Z9f.cjs'); });
53
+ const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-Cya9YSA0.cjs'); });
54
+ if (args[1] === "clean") {
55
+ const result = await killRunawayHappyProcesses();
56
+ console.log(`Cleaned up ${result.killed} runaway processes`);
57
+ if (result.errors.length > 0) {
58
+ console.log("Errors:", result.errors);
59
+ }
60
+ process.exit(0);
61
+ }
62
+ await runDoctorCommand();
63
+ return;
64
+ } else if (subcommand === "auth") {
65
+ try {
66
+ const { handleAuthCommand } = await Promise.resolve().then(function () { return require('./auth-Cas9DR3b.cjs'); });
67
+ await handleAuthCommand(args.slice(1));
68
+ } catch (error) {
69
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
70
+ if (logger.isDebug()) {
71
+ console.error(error);
72
+ }
73
+ process.exit(1);
74
+ }
75
+ return;
76
+ } else if (subcommand === "connect") {
77
+ try {
78
+ const { handleConnectCommand } = await Promise.resolve().then(function () { return require('./connect-CJZ73syK.cjs'); });
79
+ await handleConnectCommand(args.slice(1));
80
+ } catch (error) {
81
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
82
+ if (logger.isDebug()) {
83
+ console.error(error);
84
+ }
85
+ process.exit(1);
86
+ }
87
+ return;
88
+ } else if (subcommand === "codex") {
89
+ const { authAndSetupMachineIfNeeded } = await Promise.resolve().then(function () { return require('./auth-BIleVCw0.cjs'); });
90
+ const { isDaemonRunningCurrentlyInstalledHappyVersion } = await Promise.resolve().then(function () { return require('./controlClient-DZMIsKsT.cjs'); });
91
+ const { spawnHappyCLI } = await Promise.resolve().then(function () { return require('./spawnHappyCLI-D_V-AAoP.cjs'); }).then(function (n) { return n.spawnHappyCLI$1; });
92
+ try {
93
+ const { runCodex } = await Promise.resolve().then(function () { return require('./runCodex-82UrZLme.cjs'); });
94
+ let startedBy = void 0;
95
+ for (let i = 1; i < args.length; i++) {
96
+ if (args[i] === "--started-by") {
97
+ startedBy = args[++i];
98
+ }
99
+ }
100
+ const {
101
+ credentials
102
+ } = await authAndSetupMachineIfNeeded();
103
+ logger.logger.debug("Ensuring Happy background service is running & matches our version...");
104
+ if (!await isDaemonRunningCurrentlyInstalledHappyVersion()) {
105
+ logger.logger.debug("Starting Happy background service...");
106
+ const daemonProcess = spawnHappyCLI(["daemon", "start-sync"], {
107
+ detached: true,
108
+ stdio: "ignore",
109
+ env: process.env
110
+ });
111
+ daemonProcess.unref();
112
+ await new Promise((resolve) => setTimeout(resolve, 200));
113
+ }
114
+ await runCodex({ credentials, startedBy });
115
+ } catch (error) {
116
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
117
+ if (logger.isDebug()) {
118
+ console.error(error);
119
+ }
120
+ process.exit(1);
121
+ }
122
+ return;
123
+ } else if (subcommand === "gemini") {
124
+ const { authAndSetupMachineIfNeeded } = await Promise.resolve().then(function () { return require('./auth-BIleVCw0.cjs'); });
125
+ const { isDaemonRunningCurrentlyInstalledHappyVersion } = await Promise.resolve().then(function () { return require('./controlClient-DZMIsKsT.cjs'); });
126
+ const { spawnHappyCLI } = await Promise.resolve().then(function () { return require('./spawnHappyCLI-D_V-AAoP.cjs'); }).then(function (n) { return n.spawnHappyCLI$1; });
127
+ const geminiSubcommand = args[1];
128
+ if (geminiSubcommand === "model" && args[2] === "set" && args[3]) {
129
+ const modelName = args[3];
130
+ const validModels = ["gemini-2.5-pro", "gemini-2.5-flash", "gemini-2.5-flash-lite"];
131
+ if (!validModels.includes(modelName)) {
132
+ console.error(`Invalid model: ${modelName}`);
133
+ console.error(`Available models: ${validModels.join(", ")}`);
134
+ process.exit(1);
135
+ }
136
+ try {
137
+ const { existsSync, readFileSync, writeFileSync, mkdirSync } = require("fs");
138
+ const { join } = require("path");
139
+ const { homedir } = require("os");
140
+ const configDir = join(homedir(), ".gemini");
141
+ const configPath = join(configDir, "config.json");
142
+ if (!existsSync(configDir)) {
143
+ mkdirSync(configDir, { recursive: true });
144
+ }
145
+ let config = {};
146
+ if (existsSync(configPath)) {
147
+ try {
148
+ config = JSON.parse(readFileSync(configPath, "utf-8"));
149
+ } catch (error) {
150
+ config = {};
151
+ }
152
+ }
153
+ config.model = modelName;
154
+ writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
155
+ console.log(`\u2713 Model set to: ${modelName}`);
156
+ console.log(` Config saved to: ${configPath}`);
157
+ console.log(` This model will be used in future sessions.`);
158
+ process.exit(0);
159
+ } catch (error) {
160
+ console.error("Failed to save model configuration:", error);
161
+ process.exit(1);
162
+ }
163
+ }
164
+ if (geminiSubcommand === "model" && args[2] === "get") {
165
+ try {
166
+ const { existsSync, readFileSync } = require("fs");
167
+ const { join } = require("path");
168
+ const { homedir } = require("os");
169
+ const configPaths = [
170
+ join(homedir(), ".gemini", "config.json"),
171
+ join(homedir(), ".config", "gemini", "config.json")
172
+ ];
173
+ let model = null;
174
+ for (const configPath of configPaths) {
175
+ if (existsSync(configPath)) {
176
+ try {
177
+ const config = JSON.parse(readFileSync(configPath, "utf-8"));
178
+ model = config.model || config.GEMINI_MODEL || null;
179
+ if (model) break;
180
+ } catch (error) {
181
+ }
182
+ }
183
+ }
184
+ if (model) {
185
+ console.log(`Current model: ${model}`);
186
+ } else if (process.env.GEMINI_MODEL) {
187
+ console.log(`Current model: ${process.env.GEMINI_MODEL} (from GEMINI_MODEL env var)`);
188
+ } else {
189
+ console.log("Current model: gemini-2.5-pro (default)");
190
+ }
191
+ process.exit(0);
192
+ } catch (error) {
193
+ console.error("Failed to read model configuration:", error);
194
+ process.exit(1);
195
+ }
196
+ }
197
+ if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
198
+ const projectId = args[3];
199
+ try {
200
+ const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return require('./config-Draa-5XC.cjs'); });
201
+ const { readCredentials: readCredentials2 } = await Promise.resolve().then(function () { return require('./persistence-JLUn_Nou.cjs'); }).then(function (n) { return n.persistence; });
202
+ const { ApiClient } = await Promise.resolve().then(function () { return require('./api-CwOCQeLH.cjs'); }).then(function (n) { return n.api; });
203
+ let userEmail = void 0;
204
+ try {
205
+ const credentials = await readCredentials2();
206
+ if (credentials) {
207
+ const api = await ApiClient.create(credentials);
208
+ const vendorToken = await api.getVendorToken("gemini");
209
+ if (vendorToken?.oauth?.id_token) {
210
+ const parts = vendorToken.oauth.id_token.split(".");
211
+ if (parts.length === 3) {
212
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
213
+ userEmail = payload.email;
214
+ }
215
+ }
216
+ }
217
+ } catch {
218
+ }
219
+ saveGoogleCloudProjectToConfig(projectId, userEmail);
220
+ console.log(`\u2713 Google Cloud Project set to: ${projectId}`);
221
+ if (userEmail) {
222
+ console.log(` Linked to account: ${userEmail}`);
223
+ }
224
+ console.log(` This project will be used for Google Workspace accounts.`);
225
+ process.exit(0);
226
+ } catch (error) {
227
+ console.error("Failed to save project configuration:", error);
228
+ process.exit(1);
229
+ }
230
+ }
231
+ if (geminiSubcommand === "project" && args[2] === "get") {
232
+ try {
233
+ const { readGeminiLocalConfig } = await Promise.resolve().then(function () { return require('./config-Draa-5XC.cjs'); });
234
+ const config = readGeminiLocalConfig();
235
+ if (config.googleCloudProject) {
236
+ console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
237
+ if (config.googleCloudProjectEmail) {
238
+ console.log(` Linked to account: ${config.googleCloudProjectEmail}`);
239
+ } else {
240
+ console.log(` Applies to: all accounts (global)`);
241
+ }
242
+ } else if (process.env.GOOGLE_CLOUD_PROJECT) {
243
+ console.log(`Current Google Cloud Project: ${process.env.GOOGLE_CLOUD_PROJECT} (from env var)`);
244
+ } else {
245
+ console.log("No Google Cloud Project configured.");
246
+ console.log("");
247
+ console.log('If you see "Authentication required" error, you may need to set a project:');
248
+ console.log(" happy gemini project set <your-project-id>");
249
+ console.log("");
250
+ console.log("This is required for Google Workspace accounts.");
251
+ console.log("Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca");
252
+ }
253
+ process.exit(0);
254
+ } catch (error) {
255
+ console.error("Failed to read project configuration:", error);
256
+ process.exit(1);
257
+ }
258
+ }
259
+ if (geminiSubcommand === "project" && !args[2]) {
260
+ console.log("Usage: happy gemini project <command>");
261
+ console.log("");
262
+ console.log("Commands:");
263
+ console.log(" set <project-id> Set Google Cloud Project ID");
264
+ console.log(" get Show current Google Cloud Project ID");
265
+ console.log("");
266
+ console.log("Google Workspace accounts require a Google Cloud Project.");
267
+ console.log('If you see "Authentication required" error, set your project ID.');
268
+ console.log("");
269
+ console.log("Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca");
270
+ process.exit(0);
271
+ }
272
+ try {
273
+ const { runGemini } = await Promise.resolve().then(function () { return require('./runGemini-CXMr4Jwb.cjs'); });
274
+ let startedBy = void 0;
275
+ for (let i = 1; i < args.length; i++) {
276
+ if (args[i] === "--started-by") {
277
+ startedBy = args[++i];
278
+ }
279
+ }
280
+ const {
281
+ credentials
282
+ } = await authAndSetupMachineIfNeeded();
283
+ logger.logger.debug("Ensuring Happy background service is running & matches our version...");
284
+ if (!await isDaemonRunningCurrentlyInstalledHappyVersion()) {
285
+ logger.logger.debug("Starting Happy background service...");
286
+ const daemonProcess = spawnHappyCLI(["daemon", "start-sync"], {
287
+ detached: true,
288
+ stdio: "ignore",
289
+ env: process.env
290
+ });
291
+ daemonProcess.unref();
292
+ await new Promise((resolve) => setTimeout(resolve, 200));
293
+ }
294
+ await runGemini({ credentials, startedBy });
295
+ } catch (error) {
296
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
297
+ if (logger.isDebug()) {
298
+ console.error(error);
299
+ }
300
+ process.exit(1);
301
+ }
302
+ return;
303
+ } else if (subcommand === "update") {
304
+ try {
305
+ const { handleUpdateCommand } = await Promise.resolve().then(function () { return require('./update-Dw8pgsAT.cjs'); });
306
+ await handleUpdateCommand();
307
+ } catch (error) {
308
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
309
+ if (logger.isDebug()) {
310
+ console.error(error);
311
+ }
312
+ process.exit(1);
313
+ }
314
+ return;
315
+ } else if (subcommand === "logout") {
316
+ console.log(chalk.yellow('Note: "happy logout" is deprecated. Use "happy auth logout" instead.\n'));
317
+ try {
318
+ const { handleAuthCommand } = await Promise.resolve().then(function () { return require('./auth-Cas9DR3b.cjs'); });
319
+ await handleAuthCommand(["logout"]);
320
+ } catch (error) {
321
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
322
+ if (logger.isDebug()) {
323
+ console.error(error);
324
+ }
325
+ process.exit(1);
326
+ }
327
+ return;
328
+ } else if (subcommand === "notify") {
329
+ try {
330
+ await handleNotifyCommand(args.slice(1));
331
+ } catch (error) {
332
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
333
+ if (logger.isDebug()) {
334
+ console.error(error);
335
+ }
336
+ process.exit(1);
337
+ }
338
+ return;
339
+ } else if (subcommand === "session") {
340
+ try {
341
+ const { handleSessionCommand } = await Promise.resolve().then(function () { return require('./session-D--F87zL.cjs'); });
342
+ await handleSessionCommand(args.slice(1));
343
+ } catch (error) {
344
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
345
+ if (logger.isDebug()) {
346
+ console.error(error);
347
+ }
348
+ process.exit(1);
349
+ }
350
+ return;
351
+ } else if (subcommand === "task") {
352
+ try {
353
+ const { handleTaskCommand } = await Promise.resolve().then(function () { return require('./task-CSpaC9HX.cjs'); });
354
+ await handleTaskCommand(args.slice(1));
355
+ } catch (error) {
356
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
357
+ if (logger.isDebug()) {
358
+ console.error(error);
359
+ }
360
+ process.exit(1);
361
+ }
362
+ return;
363
+ } else if (subcommand === "release") {
364
+ try {
365
+ const { handleReleaseCommand } = await Promise.resolve().then(function () { return require('./release-EhOJeAZe.cjs'); });
366
+ await handleReleaseCommand(args.slice(1));
367
+ } catch (error) {
368
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
369
+ if (logger.isDebug()) {
370
+ console.error(error);
371
+ }
372
+ process.exit(1);
373
+ }
374
+ return;
375
+ } else if (subcommand === "github") {
376
+ try {
377
+ const { handleGithubCommand } = await Promise.resolve().then(function () { return require('./github-h9GhJJ_C.cjs'); });
378
+ await handleGithubCommand(args.slice(1));
379
+ } catch (error) {
380
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
381
+ if (logger.isDebug()) {
382
+ console.error(error);
383
+ }
384
+ process.exit(1);
385
+ }
386
+ return;
387
+ } else if (subcommand === "diagnose") {
388
+ try {
389
+ const { handleDiagnoseCommand } = await Promise.resolve().then(function () { return require('./diagnose-B3D1a_v0.cjs'); });
390
+ await handleDiagnoseCommand(args.slice(1));
391
+ } catch (error) {
392
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
393
+ if (logger.isDebug()) {
394
+ console.error(error);
395
+ }
396
+ process.exit(1);
397
+ }
398
+ return;
399
+ } else if (subcommand === "evidence") {
400
+ try {
401
+ const { handleEvidenceCommand } = await Promise.resolve().then(function () { return require('./evidence-CjWBG5rX.cjs'); });
402
+ await handleEvidenceCommand(args.slice(1));
403
+ } catch (error) {
404
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
405
+ if (logger.isDebug()) {
406
+ console.error(error);
407
+ }
408
+ process.exit(1);
409
+ }
410
+ return;
411
+ } else if (subcommand === "mcp") {
412
+ const mcpSubcommand = args[1];
413
+ if (mcpSubcommand !== "serve") {
414
+ console.error(chalk.red("Usage: happy mcp serve"));
415
+ process.exit(1);
416
+ }
417
+ try {
418
+ const { runMcpServe } = await Promise.resolve().then(function () { return require('./serve-BtdAhkIE.cjs'); });
419
+ await runMcpServe();
420
+ } catch (error) {
421
+ process.stderr.write(`[happy-mcp] fatal: ${error instanceof Error ? error.message : "unknown error"}
422
+ `);
423
+ process.exit(1);
424
+ }
425
+ return;
426
+ } else if (subcommand === "ssh") {
427
+ const credentials = await logger.readCredentials();
428
+ if (!credentials) {
429
+ console.error(chalk.red("Error:"), 'Not authenticated. Run "happy auth" first.');
430
+ process.exit(1);
431
+ }
432
+ const { parseSshArgs, runOnDevice, sshDevice, sshPickAndConnect } = await Promise.resolve().then(function () { return require('./ssh-BTOlhhxi.cjs'); });
433
+ const { target, command, timeoutMs } = parseSshArgs(args.slice(1));
434
+ try {
435
+ if (command) {
436
+ if (!target) {
437
+ console.error(chalk.red("Error:"), "Which device? Usage: happy ssh <device> -- <command>");
438
+ process.exit(1);
439
+ }
440
+ process.exit(await runOnDevice(credentials, target, command, { timeoutMs }));
441
+ }
442
+ if (!target) {
443
+ process.exit(await sshPickAndConnect(credentials));
444
+ }
445
+ process.exit(await sshDevice(credentials, target));
446
+ } catch (error) {
447
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
448
+ process.exit(1);
449
+ }
450
+ } else if (subcommand === "device") {
451
+ const deviceSubcommand = args[1];
452
+ if (deviceSubcommand === "enroll") {
453
+ const { enrollDevice } = await Promise.resolve().then(function () { return require('./enroll-BxlbVftP.cjs'); });
454
+ const { install } = await Promise.resolve().then(function () { return require('./install-C_cp8b2-.cjs'); });
455
+ const token = args[2];
456
+ if (!token) {
457
+ console.error(chalk.red("Error:"), "Missing enrollment token. Usage: happy device enroll <token>");
458
+ process.exit(1);
459
+ }
460
+ try {
461
+ const result = await enrollDevice(token, { force: args.includes("--force") });
462
+ if (result.alreadyEnrolled) {
463
+ console.log("This machine is already linked to a Happy account. Re-run with --force to relink.");
464
+ } else {
465
+ console.log("Device enrolled");
466
+ }
467
+ await install();
468
+ console.log("Daemon installed and started");
469
+ } catch (error) {
470
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
471
+ process.exit(1);
472
+ }
473
+ process.exit(0);
474
+ }
475
+ console.log(`
476
+ ${chalk.bold("happy device")} - Device enrollment
477
+
478
+ ${chalk.bold("Usage:")}
479
+ happy device enroll <token> Link this machine to a Happy account and start the daemon
480
+ `);
481
+ process.exit(0);
482
+ } else if (subcommand === "daemon") {
483
+ const { startDaemon } = await Promise.resolve().then(function () { return require('./run-BDn2aE3Q.cjs'); }).then(function (n) { return n.run; });
484
+ const { install } = await Promise.resolve().then(function () { return require('./install-C_cp8b2-.cjs'); });
485
+ const { uninstall } = await Promise.resolve().then(function () { return require('./uninstall-BiKyRAb1.cjs'); });
486
+ const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-Cya9YSA0.cjs'); });
487
+ const { getLatestDaemonLog } = await Promise.resolve().then(function () { return require('./persistence-JLUn_Nou.cjs'); }).then(function (n) { return n.logger$1; });
488
+ const { listDaemonSessions, stopDaemonSession, stopDaemon } = await Promise.resolve().then(function () { return require('./controlClient-DZMIsKsT.cjs'); });
489
+ const daemonSubcommand = args[1];
490
+ if (daemonSubcommand === "list") {
491
+ try {
492
+ const sessions = await listDaemonSessions();
493
+ if (sessions.length === 0) {
494
+ console.log("No active sessions this daemon is aware of (they might have been started by a previous version of the daemon)");
495
+ } else {
496
+ console.log("Active sessions:");
497
+ console.log(JSON.stringify(sessions, null, 2));
498
+ }
499
+ } catch (error) {
500
+ console.log("No daemon running");
501
+ }
502
+ return;
503
+ } else if (daemonSubcommand === "stop-session") {
504
+ const sessionId = args[2];
505
+ if (!sessionId) {
506
+ console.error("Session ID required");
507
+ process.exit(1);
508
+ }
509
+ try {
510
+ const success = await stopDaemonSession(sessionId);
511
+ console.log(success ? "Session stopped" : "Failed to stop session");
512
+ } catch (error) {
513
+ console.log("No daemon running");
514
+ }
515
+ return;
516
+ } else if (daemonSubcommand === "start") {
517
+ const started = await spawnAndWaitForDaemon();
518
+ console.log(started ? "Daemon started successfully" : "Failed to start daemon");
519
+ process.exit(started ? 0 : 1);
520
+ } else if (daemonSubcommand === "start-sync") {
521
+ await startDaemon();
522
+ process.exit(0);
523
+ } else if (daemonSubcommand === "stop") {
524
+ await stopDaemon();
525
+ process.exit(0);
526
+ } else if (daemonSubcommand === "restart") {
527
+ await stopDaemon();
528
+ const started = await spawnAndWaitForDaemon();
529
+ console.log(started ? "Daemon restarted successfully" : "Failed to restart daemon");
530
+ process.exit(started ? 0 : 1);
531
+ } else if (daemonSubcommand === "status") {
532
+ await runDoctorCommand("daemon");
533
+ process.exit(0);
534
+ } else if (daemonSubcommand === "logs") {
535
+ const latest = await getLatestDaemonLog();
536
+ if (!latest) {
537
+ console.log("No daemon logs found");
538
+ } else {
539
+ console.log(latest.path);
540
+ }
541
+ process.exit(0);
542
+ } else if (daemonSubcommand === "enable" || daemonSubcommand === "install") {
543
+ try {
544
+ await install();
545
+ } catch (error) {
546
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
547
+ process.exit(1);
548
+ }
549
+ process.exit(0);
550
+ } else if (daemonSubcommand === "disable" || daemonSubcommand === "uninstall") {
551
+ try {
552
+ await uninstall();
553
+ } catch (error) {
554
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
555
+ process.exit(1);
556
+ }
557
+ process.exit(0);
558
+ } else {
559
+ console.log(`
560
+ ${chalk.bold("happy daemon")} - Daemon management
561
+
562
+ ${chalk.bold("Usage:")}
563
+ happy daemon start Start the daemon (detached)
564
+ happy daemon stop Stop the daemon (sessions stay alive)
565
+ happy daemon restart Restart the daemon
566
+ happy daemon status Show daemon status
567
+ happy daemon list List active sessions
568
+ happy daemon enable Enable auto-start on boot
569
+ happy daemon disable Disable auto-start on boot
570
+
571
+ If you want to kill all happy related processes run
572
+ ${chalk.cyan("happy doctor clean")}
573
+
574
+ ${chalk.bold("Note:")} The daemon runs in the background and manages Claude sessions.
575
+
576
+ ${chalk.bold("To clean up runaway processes:")} Use ${chalk.cyan("happy doctor clean")}
577
+ `);
578
+ }
579
+ return;
580
+ } else {
581
+ if (args.length > 0 && args[0] === "claude") {
582
+ args.shift();
583
+ }
584
+ const options = {};
585
+ let showHelp = false;
586
+ let showVersion = false;
587
+ let chromeOverride = void 0;
588
+ const unknownArgs = [];
589
+ for (let i = 0; i < args.length; i++) {
590
+ const arg = args[i];
591
+ if (arg === "-h" || arg === "--help") {
592
+ showHelp = true;
593
+ unknownArgs.push(arg);
594
+ } else if (arg === "-v" || arg === "--version") {
595
+ showVersion = true;
596
+ unknownArgs.push(arg);
597
+ } else if (arg === "--happy-starting-mode") {
598
+ options.startingMode = z.z.enum(["local", "remote"]).parse(args[++i]);
599
+ } else if (arg === "--yolo") {
600
+ unknownArgs.push("--dangerously-skip-permissions");
601
+ } else if (arg === "--started-by") {
602
+ options.startedBy = args[++i];
603
+ } else if (arg === "--js-runtime") {
604
+ const runtime = args[++i];
605
+ if (runtime !== "node" && runtime !== "bun") {
606
+ console.error(chalk.red(`Invalid --js-runtime value: ${runtime}. Must be 'node' or 'bun'`));
607
+ process.exit(1);
608
+ }
609
+ options.jsRuntime = runtime;
610
+ } else if (arg === "--claude-env") {
611
+ const envArg = args[++i];
612
+ if (envArg && envArg.includes("=")) {
613
+ const eqIndex = envArg.indexOf("=");
614
+ const key = envArg.substring(0, eqIndex);
615
+ const value = envArg.substring(eqIndex + 1);
616
+ options.claudeEnvVars = options.claudeEnvVars || {};
617
+ options.claudeEnvVars[key] = value;
618
+ } else {
619
+ console.error(chalk.red(`Invalid --claude-env format: ${envArg}. Expected KEY=VALUE`));
620
+ process.exit(1);
621
+ }
622
+ } else if (arg === "--chrome") {
623
+ chromeOverride = true;
624
+ } else if (arg === "--no-chrome") {
625
+ chromeOverride = false;
626
+ } else if (arg === "--settings") {
627
+ const settingsValue = args[++i];
628
+ console.warn(chalk.yellow(`\u26A0\uFE0F Warning: --settings is used internally by Happy for session tracking.`));
629
+ console.warn(chalk.yellow(` Your settings file "${settingsValue}" will be ignored.`));
630
+ console.warn(chalk.yellow(` To configure Claude, edit ~/.claude/settings.json instead.`));
631
+ } else {
632
+ unknownArgs.push(arg);
633
+ if (i + 1 < args.length && !args[i + 1].startsWith("-")) {
634
+ unknownArgs.push(args[++i]);
635
+ }
636
+ }
637
+ }
638
+ if (unknownArgs.length > 0) {
639
+ options.claudeArgs = [...options.claudeArgs || [], ...unknownArgs];
640
+ }
641
+ const settings = await logger.readSettings();
642
+ const chromeEnabled = chromeOverride ?? settings.chromeMode ?? false;
643
+ if (chromeEnabled) {
644
+ options.claudeArgs = [...options.claudeArgs || [], "--chrome"];
645
+ }
646
+ if (showHelp) {
647
+ console.log(`
648
+ ${chalk.bold("happy")} - Claude Code On the Go
649
+
650
+ ${chalk.bold("Usage:")}
651
+ happy [options] Start Claude with mobile control
652
+ happy auth Manage authentication
653
+ happy codex Start Codex mode
654
+ happy gemini Start Gemini mode (ACP)
655
+ happy connect Connect AI vendor API keys
656
+ happy session Read Happy sessions
657
+ happy task Generate task handoff briefs
658
+ happy release Verify before publishing
659
+ happy github GitHub takeover helpers
660
+ happy diagnose Diagnosis evidence helpers
661
+ happy evidence Record screenshots/log evidence
662
+ happy notify Send push notification
663
+ happy daemon Manage background service
664
+ happy daemon enable Auto-start daemon on boot
665
+ happy doctor System diagnostics & troubleshooting
666
+ happy update Upgrade happy to the latest version
667
+
668
+ ${chalk.bold("Examples:")}
669
+ happy Start session
670
+ happy --yolo Start with bypassing permissions
671
+ happy sugar for --dangerously-skip-permissions
672
+ happy --chrome Enable Chrome browser access for this session
673
+ happy --no-chrome Disable Chrome even if default is on
674
+ happy --js-runtime bun Use bun instead of node to spawn Claude Code
675
+ happy --claude-env ANTHROPIC_BASE_URL=http://127.0.0.1:3456
676
+ Use a custom API endpoint (e.g., claude-code-router)
677
+ happy auth login --force Authenticate
678
+ happy task brief --recent --project .
679
+ Generate a continuation brief
680
+ happy release guard --package happy-cli
681
+ Run checks before publishing
682
+ happy doctor Run diagnostics
683
+
684
+ ${chalk.bold("Happy AI supports ALL Claude options!")}
685
+ Use any claude flag with happy as you would with claude. Our favorite:
686
+
687
+ happy --resume
688
+
689
+ ${chalk.gray("\u2500".repeat(60))}
690
+ ${chalk.bold.cyan("Claude Code Options (from `claude --help`):")}
691
+ `);
692
+ try {
693
+ const { claudeCliPath } = await Promise.resolve().then(function () { return require('./claudeLocal-WkgLbl1a.cjs'); }).then(function (n) { return n.claudeLocal$1; });
694
+ const claudeHelp = node_child_process.execFileSync(claudeCliPath, ["--help"], { encoding: "utf8" });
695
+ console.log(claudeHelp);
696
+ } catch (e) {
697
+ console.log(chalk.yellow("Could not retrieve claude help. Make sure claude is installed."));
698
+ }
699
+ process.exit(0);
700
+ }
701
+ if (showVersion) {
702
+ const versions = [
703
+ { name: "Happy AI", version: logger.packageJson.version }
704
+ ];
705
+ const checks = [
706
+ { name: "Claude", cmd: "claude", args: ["--version"] },
707
+ { name: "Codex", cmd: "codex", args: ["--version"] },
708
+ { name: "Gemini", cmd: "gemini", args: ["--version"] }
709
+ ];
710
+ for (const { name, cmd, args: vArgs } of checks) {
711
+ try {
712
+ const ver = node_child_process.execFileSync(cmd, vArgs, { encoding: "utf-8", timeout: 5e3 }).trim();
713
+ versions.push({ name, version: ver });
714
+ } catch {
715
+ }
716
+ }
717
+ const maxName = Math.max(...versions.map((v) => v.name.length));
718
+ for (const { name, version } of versions) {
719
+ console.log(`${chalk.bold(name.padEnd(maxName))} ${chalk.cyan(version)}`);
720
+ }
721
+ process.exit(0);
722
+ }
723
+ const { authAndSetupMachineIfNeeded } = await Promise.resolve().then(function () { return require('./auth-BIleVCw0.cjs'); });
724
+ const { isDaemonRunningCurrentlyInstalledHappyVersion } = await Promise.resolve().then(function () { return require('./controlClient-DZMIsKsT.cjs'); });
725
+ const { spawnHappyCLI } = await Promise.resolve().then(function () { return require('./spawnHappyCLI-D_V-AAoP.cjs'); }).then(function (n) { return n.spawnHappyCLI$1; });
726
+ const { runClaude } = await Promise.resolve().then(function () { return require('./runClaude-uaKxPZPm.cjs'); });
727
+ const {
728
+ credentials
729
+ } = await authAndSetupMachineIfNeeded();
730
+ logger.logger.debug("Ensuring Happy background service is running & matches our version...");
731
+ if (!await isDaemonRunningCurrentlyInstalledHappyVersion()) {
732
+ logger.logger.debug("Starting Happy background service...");
733
+ const daemonProcess = spawnHappyCLI(["daemon", "start-sync"], {
734
+ detached: true,
735
+ stdio: "ignore",
736
+ env: process.env
737
+ });
738
+ daemonProcess.unref();
739
+ await new Promise((resolve) => setTimeout(resolve, 200));
740
+ }
741
+ try {
742
+ await runClaude(credentials, options);
743
+ } catch (error) {
744
+ console.error(chalk.red("Error:"), error instanceof Error ? error.message : "Unknown error");
745
+ if (logger.isDebug()) {
746
+ console.error(error);
747
+ }
748
+ process.exit(1);
749
+ }
750
+ }
751
+ })();
752
+ async function handleNotifyCommand(args) {
753
+ let message = "";
754
+ let title = "";
755
+ let showHelp = false;
756
+ for (let i = 0; i < args.length; i++) {
757
+ const arg = args[i];
758
+ if (arg === "-p" && i + 1 < args.length) {
759
+ message = args[++i];
760
+ } else if (arg === "-t" && i + 1 < args.length) {
761
+ title = args[++i];
762
+ } else if (arg === "-h" || arg === "--help") {
763
+ showHelp = true;
764
+ } else {
765
+ console.error(chalk.red(`Unknown argument for notify command: ${arg}`));
766
+ process.exit(1);
767
+ }
768
+ }
769
+ if (showHelp) {
770
+ console.log(`
771
+ ${chalk.bold("happy notify")} - Send notification
772
+
773
+ ${chalk.bold("Usage:")}
774
+ happy notify -p <message> [-t <title>] Send notification with custom message and optional title
775
+ happy notify -h, --help Show this help
776
+
777
+ ${chalk.bold("Options:")}
778
+ -p <message> Notification message (required)
779
+ -t <title> Notification title (optional, defaults to "Happy AI")
48
780
 
781
+ ${chalk.bold("Examples:")}
782
+ happy notify -p "Deployment complete!"
783
+ happy notify -p "System update complete" -t "Server Status"
784
+ happy notify -t "Alert" -p "Database connection restored"
785
+ `);
786
+ return;
787
+ }
788
+ if (!message) {
789
+ console.error(chalk.red('Error: Message is required. Use -p "your message" to specify the notification text.'));
790
+ console.log(chalk.gray('Run "happy notify --help" for usage information.'));
791
+ process.exit(1);
792
+ }
793
+ let credentials = await logger.readCredentials();
794
+ if (!credentials) {
795
+ console.error(chalk.red('Error: Not authenticated. Please run "happy auth login" first.'));
796
+ process.exit(1);
797
+ }
798
+ console.log(chalk.blue("\u{1F4F1} Sending push notification..."));
799
+ try {
800
+ const { ApiClient } = await Promise.resolve().then(function () { return require('./api-CwOCQeLH.cjs'); }).then(function (n) { return n.api; });
801
+ const api = await ApiClient.create(credentials);
802
+ const notificationTitle = title || "Happy AI";
803
+ api.push().sendToAllDevices(
804
+ notificationTitle,
805
+ message,
806
+ {
807
+ source: "cli",
808
+ timestamp: Date.now()
809
+ }
810
+ );
811
+ console.log(chalk.green("\u2713 Push notification sent successfully!"));
812
+ console.log(chalk.gray(` Title: ${notificationTitle}`));
813
+ console.log(chalk.gray(` Message: ${message}`));
814
+ console.log(chalk.gray(" Check your mobile device for the notification."));
815
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
816
+ } catch (error) {
817
+ console.error(chalk.red("\u2717 Failed to send push notification"));
818
+ throw error;
819
+ }
820
+ }