happy-coder 0.3.1-beta.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/index.cjs +76 -27
  2. package/dist/index.mjs +76 -27
  3. package/dist/lib.cjs +1 -1
  4. package/dist/lib.d.cts +1 -0
  5. package/dist/lib.d.mts +1 -0
  6. package/dist/lib.mjs +1 -1
  7. package/dist/{types-CzYKFAYa.mjs → types-VkaGP8up.mjs} +1 -1
  8. package/dist/{types-D7u2DxfV.cjs → types-eN-YHsuj.cjs} +1 -0
  9. package/package.json +8 -6
  10. package/dist/index-B2GqfEZV.cjs +0 -1564
  11. package/dist/index-QItBXhux.mjs +0 -1540
  12. package/dist/install-B0DnBGS_.mjs +0 -29
  13. package/dist/install-B2r_gX72.cjs +0 -109
  14. package/dist/install-C809w0Cj.cjs +0 -31
  15. package/dist/install-DEPy62QN.mjs +0 -97
  16. package/dist/install-GZIzyuIE.cjs +0 -99
  17. package/dist/install-HKe7dyS4.mjs +0 -107
  18. package/dist/run-BmEaINbl.cjs +0 -250
  19. package/dist/run-DMbKhYfb.mjs +0 -247
  20. package/dist/run-FBXkmmN7.mjs +0 -32
  21. package/dist/run-q2To6b-c.cjs +0 -34
  22. package/dist/types-BG9AgCI4.mjs +0 -875
  23. package/dist/types-BRICSarm.mjs +0 -870
  24. package/dist/types-BTQRfIr3.cjs +0 -892
  25. package/dist/types-BX4xv8Ty.mjs +0 -881
  26. package/dist/types-BeUppqJU.cjs +0 -886
  27. package/dist/types-C6Wx_bRW.cjs +0 -886
  28. package/dist/types-CEvzGLMI.cjs +0 -882
  29. package/dist/types-CKUdOV6c.mjs +0 -875
  30. package/dist/types-CNuBtNA5.cjs +0 -884
  31. package/dist/types-Cg4664gs.cjs +0 -879
  32. package/dist/types-CkPUFpfr.cjs +0 -885
  33. package/dist/types-D39L8JSd.mjs +0 -850
  34. package/dist/types-DD9P_5rj.mjs +0 -868
  35. package/dist/types-DNu8okOb.mjs +0 -874
  36. package/dist/types-DXK5YldG.cjs +0 -892
  37. package/dist/types-DYBiuNUQ.cjs +0 -883
  38. package/dist/types-Df5dlWLV.mjs +0 -871
  39. package/dist/types-fXgEaaqP.mjs +0 -861
  40. package/dist/types-hotUTaWz.cjs +0 -863
  41. package/dist/types-ikrrEcJm.mjs +0 -873
  42. package/dist/types-mykDX2xe.cjs +0 -872
  43. package/dist/types-tLWMaptR.mjs +0 -879
  44. package/dist/uninstall-BGgl5V8F.mjs +0 -29
  45. package/dist/uninstall-BWHglipH.mjs +0 -40
  46. package/dist/uninstall-C42CoSCI.cjs +0 -53
  47. package/dist/uninstall-CLkTtlMv.mjs +0 -51
  48. package/dist/uninstall-CdHMb6wi.cjs +0 -31
  49. package/dist/uninstall-FXyyAuGU.cjs +0 -42
@@ -1,250 +0,0 @@
1
- 'use strict';
2
-
3
- var types = require('./types-DYBiuNUQ.cjs');
4
- var node_events = require('node:events');
5
- var socket_ioClient = require('socket.io-client');
6
- var child_process = require('child_process');
7
- var index = require('./index-B2GqfEZV.cjs');
8
- var os = require('os');
9
- var fs = require('fs');
10
- var path = require('path');
11
- var crypto = require('crypto');
12
- require('axios');
13
- require('chalk');
14
- require('node:os');
15
- require('node:path');
16
- require('node:fs/promises');
17
- require('node:fs');
18
- require('zod');
19
- require('node:crypto');
20
- require('tweetnacl');
21
- require('expo-server-sdk');
22
- require('@anthropic-ai/claude-code');
23
- require('node:child_process');
24
- require('node:readline');
25
- require('node:url');
26
- require('@modelcontextprotocol/sdk/server/mcp.js');
27
- require('node:http');
28
- require('@modelcontextprotocol/sdk/server/streamableHttp.js');
29
- require('node:https');
30
- require('node:net');
31
- require('qrcode-terminal');
32
-
33
- class ApiDaemonSession extends node_events.EventEmitter {
34
- socket;
35
- machineIdentity;
36
- keepAliveInterval = null;
37
- token;
38
- secret;
39
- constructor(token, secret, machineIdentity) {
40
- super();
41
- this.token = token;
42
- this.secret = secret;
43
- this.machineIdentity = machineIdentity;
44
- const socket = socket_ioClient.io(types.configuration.serverUrl, {
45
- auth: {
46
- token: this.token,
47
- clientType: "machine-scoped",
48
- machineId: this.machineIdentity.machineId
49
- },
50
- path: "/v1/user-machine-daemon",
51
- reconnection: true,
52
- reconnectionAttempts: Infinity,
53
- reconnectionDelay: 1e3,
54
- reconnectionDelayMax: 5e3,
55
- transports: ["websocket"],
56
- withCredentials: true,
57
- autoConnect: false
58
- });
59
- socket.on("connect", () => {
60
- types.logger.debug("[DAEMON] Connected to server");
61
- this.emit("connected");
62
- socket.emit("machine-connect", {
63
- token: this.token,
64
- machineIdentity: types.encodeBase64(types.encrypt(this.machineIdentity, this.secret))
65
- });
66
- this.startKeepAlive();
67
- });
68
- socket.on("disconnect", () => {
69
- types.logger.debug("[DAEMON] Disconnected from server");
70
- this.emit("disconnected");
71
- this.stopKeepAlive();
72
- });
73
- socket.on("spawn-session", async (encryptedData, callback) => {
74
- try {
75
- const data2 = types.decrypt(types.decodeBase64(encryptedData), this.secret);
76
- types.logger.debug("[DAEMON] Received spawn-session request", data2);
77
- const args = [
78
- "--directory",
79
- data2.directory,
80
- "--happy-starting-mode",
81
- data2.startingMode
82
- ];
83
- if (data2.metadata) {
84
- args.push("--metadata", data2.metadata);
85
- }
86
- if (data2.startingMode === "interactive" && process.platform === "darwin") {
87
- const script = `
88
- tell application "Terminal"
89
- activate
90
- do script "cd ${data2.directory} && happy ${args.join(" ")}"
91
- end tell
92
- `;
93
- child_process.spawn("osascript", ["-e", script], { detached: true });
94
- } else {
95
- const child = child_process.spawn("happy", args, {
96
- detached: true,
97
- stdio: "ignore",
98
- cwd: data2.directory
99
- });
100
- child.unref();
101
- }
102
- const result = { success: true };
103
- socket.emit("session-spawn-result", {
104
- requestId: data2.requestId,
105
- result: types.encodeBase64(types.encrypt(result, this.secret))
106
- });
107
- callback(types.encodeBase64(types.encrypt({ success: true }, this.secret)));
108
- } catch (error) {
109
- types.logger.debug("[DAEMON] Failed to spawn session", error);
110
- const errorResult = {
111
- success: false,
112
- error: error instanceof Error ? error.message : "Unknown error"
113
- };
114
- socket.emit("session-spawn-result", {
115
- requestId: data.requestId,
116
- result: types.encodeBase64(types.encrypt(errorResult, this.secret))
117
- });
118
- callback(types.encodeBase64(types.encrypt(errorResult, this.secret)));
119
- }
120
- });
121
- socket.on("daemon-command", (data2) => {
122
- switch (data2.command) {
123
- case "shutdown":
124
- this.shutdown();
125
- break;
126
- case "status":
127
- this.emit("status-request");
128
- break;
129
- }
130
- });
131
- this.socket = socket;
132
- }
133
- startKeepAlive() {
134
- this.stopKeepAlive();
135
- this.keepAliveInterval = setInterval(() => {
136
- this.socket.volatile.emit("machine-alive", {
137
- time: Date.now()
138
- });
139
- }, 2e4);
140
- }
141
- stopKeepAlive() {
142
- if (this.keepAliveInterval) {
143
- clearInterval(this.keepAliveInterval);
144
- this.keepAliveInterval = null;
145
- }
146
- }
147
- connect() {
148
- this.socket.connect();
149
- }
150
- shutdown() {
151
- this.stopKeepAlive();
152
- this.socket.close();
153
- this.emit("shutdown");
154
- }
155
- }
156
-
157
- const DAEMON_PID_FILE = path.join(os.homedir(), ".happy", "daemon-pid");
158
- async function run() {
159
- if (!process.env.HAPPY_DAEMON_MODE) {
160
- throw new Error("This function should only be called by the daemon system with HAPPY_DAEMON_MODE environment variable set");
161
- }
162
- types.logger.info("Happy CLI daemon started successfully");
163
- if (isDaemonRunning()) {
164
- console.log("Happy daemon is already running");
165
- process.exit(0);
166
- }
167
- writePidFile();
168
- process.on("SIGINT", cleanup);
169
- process.on("SIGTERM", cleanup);
170
- process.on("exit", cleanup);
171
- try {
172
- const settings = await index.readSettings() || {};
173
- if (!settings.machineId) {
174
- settings.machineId = crypto.randomUUID();
175
- settings.machineHost = os.hostname();
176
- await index.writeSettings(settings);
177
- }
178
- const machineIdentity = {
179
- machineId: settings.machineId,
180
- machineHost: settings.machineHost || os.hostname(),
181
- platform: process.platform,
182
- version: process.env.npm_package_version || "unknown"
183
- };
184
- let credentials = await index.readCredentials();
185
- if (!credentials) {
186
- types.logger.debug("[DAEMON] No credentials found, running auth");
187
- await index.doAuth();
188
- credentials = await index.readCredentials();
189
- if (!credentials) {
190
- throw new Error("Failed to authenticate");
191
- }
192
- }
193
- const { token, secret } = credentials;
194
- const daemon = new ApiDaemonSession(token, secret, machineIdentity);
195
- daemon.on("connected", () => {
196
- types.logger.debug("[DAEMON] Successfully connected to server");
197
- });
198
- daemon.on("disconnected", () => {
199
- types.logger.debug("[DAEMON] Disconnected from server");
200
- });
201
- daemon.on("shutdown", () => {
202
- types.logger.debug("[DAEMON] Shutdown requested");
203
- cleanup();
204
- process.exit(0);
205
- });
206
- daemon.connect();
207
- setInterval(() => {
208
- }, 1e3);
209
- } catch (error) {
210
- types.logger.debug("[DAEMON] Failed to start daemon", error);
211
- cleanup();
212
- process.exit(1);
213
- }
214
- }
215
- function isDaemonRunning() {
216
- try {
217
- if (!fs.existsSync(DAEMON_PID_FILE)) {
218
- return false;
219
- }
220
- const pid = parseInt(fs.readFileSync(DAEMON_PID_FILE, "utf-8"));
221
- try {
222
- process.kill(pid, 0);
223
- return true;
224
- } catch {
225
- fs.unlinkSync(DAEMON_PID_FILE);
226
- return false;
227
- }
228
- } catch {
229
- return false;
230
- }
231
- }
232
- function writePidFile() {
233
- const happyDir = path.join(os.homedir(), ".happy");
234
- if (!fs.existsSync(happyDir)) {
235
- fs.mkdirSync(happyDir, { recursive: true });
236
- }
237
- fs.writeFileSync(DAEMON_PID_FILE, process.pid.toString());
238
- }
239
- function cleanup() {
240
- try {
241
- if (fs.existsSync(DAEMON_PID_FILE)) {
242
- fs.unlinkSync(DAEMON_PID_FILE);
243
- }
244
- } catch (error) {
245
- types.logger.debug("[DAEMON] Error cleaning up PID file", error);
246
- }
247
- }
248
-
249
- exports.isDaemonRunning = isDaemonRunning;
250
- exports.run = run;
@@ -1,247 +0,0 @@
1
- import { c as configuration, l as logger, e as encodeBase64, d as encrypt, f as decrypt, g as decodeBase64 } from './types-BRICSarm.mjs';
2
- import { EventEmitter } from 'node:events';
3
- import { io } from 'socket.io-client';
4
- import { spawn } from 'child_process';
5
- import { r as readSettings, w as writeSettings, a as readCredentials, d as doAuth } from './index-QItBXhux.mjs';
6
- import { hostname, homedir } from 'os';
7
- import { existsSync, readFileSync, unlinkSync, mkdirSync, writeFileSync } from 'fs';
8
- import { join } from 'path';
9
- import crypto from 'crypto';
10
- import 'axios';
11
- import 'chalk';
12
- import 'node:os';
13
- import 'node:path';
14
- import 'node:fs/promises';
15
- import 'node:fs';
16
- import 'zod';
17
- import 'node:crypto';
18
- import 'tweetnacl';
19
- import 'expo-server-sdk';
20
- import '@anthropic-ai/claude-code';
21
- import 'node:child_process';
22
- import 'node:readline';
23
- import 'node:url';
24
- import '@modelcontextprotocol/sdk/server/mcp.js';
25
- import 'node:http';
26
- import '@modelcontextprotocol/sdk/server/streamableHttp.js';
27
- import 'node:https';
28
- import 'node:net';
29
- import 'qrcode-terminal';
30
-
31
- class ApiDaemonSession extends EventEmitter {
32
- socket;
33
- machineIdentity;
34
- keepAliveInterval = null;
35
- token;
36
- secret;
37
- constructor(token, secret, machineIdentity) {
38
- super();
39
- this.token = token;
40
- this.secret = secret;
41
- this.machineIdentity = machineIdentity;
42
- const socket = io(configuration.serverUrl, {
43
- auth: {
44
- token: this.token,
45
- clientType: "machine-scoped",
46
- machineId: this.machineIdentity.machineId
47
- },
48
- path: "/v1/user-machine-daemon",
49
- reconnection: true,
50
- reconnectionAttempts: Infinity,
51
- reconnectionDelay: 1e3,
52
- reconnectionDelayMax: 5e3,
53
- transports: ["websocket"],
54
- withCredentials: true,
55
- autoConnect: false
56
- });
57
- socket.on("connect", () => {
58
- logger.debug("[DAEMON] Connected to server");
59
- this.emit("connected");
60
- socket.emit("machine-connect", {
61
- token: this.token,
62
- machineIdentity: encodeBase64(encrypt(this.machineIdentity, this.secret))
63
- });
64
- this.startKeepAlive();
65
- });
66
- socket.on("disconnect", () => {
67
- logger.debug("[DAEMON] Disconnected from server");
68
- this.emit("disconnected");
69
- this.stopKeepAlive();
70
- });
71
- socket.on("spawn-session", async (encryptedData, callback) => {
72
- try {
73
- const data2 = decrypt(decodeBase64(encryptedData), this.secret);
74
- logger.debug("[DAEMON] Received spawn-session request", data2);
75
- const args = [
76
- "--directory",
77
- data2.directory,
78
- "--happy-starting-mode",
79
- data2.startingMode
80
- ];
81
- if (data2.metadata) {
82
- args.push("--metadata", data2.metadata);
83
- }
84
- if (data2.startingMode === "interactive" && process.platform === "darwin") {
85
- const script = `
86
- tell application "Terminal"
87
- activate
88
- do script "cd ${data2.directory} && happy ${args.join(" ")}"
89
- end tell
90
- `;
91
- spawn("osascript", ["-e", script], { detached: true });
92
- } else {
93
- const child = spawn("happy", args, {
94
- detached: true,
95
- stdio: "ignore",
96
- cwd: data2.directory
97
- });
98
- child.unref();
99
- }
100
- const result = { success: true };
101
- socket.emit("session-spawn-result", {
102
- requestId: data2.requestId,
103
- result: encodeBase64(encrypt(result, this.secret))
104
- });
105
- callback(encodeBase64(encrypt({ success: true }, this.secret)));
106
- } catch (error) {
107
- logger.debug("[DAEMON] Failed to spawn session", error);
108
- const errorResult = {
109
- success: false,
110
- error: error instanceof Error ? error.message : "Unknown error"
111
- };
112
- socket.emit("session-spawn-result", {
113
- requestId: data.requestId,
114
- result: encodeBase64(encrypt(errorResult, this.secret))
115
- });
116
- callback(encodeBase64(encrypt(errorResult, this.secret)));
117
- }
118
- });
119
- socket.on("daemon-command", (data2) => {
120
- switch (data2.command) {
121
- case "shutdown":
122
- this.shutdown();
123
- break;
124
- case "status":
125
- this.emit("status-request");
126
- break;
127
- }
128
- });
129
- this.socket = socket;
130
- }
131
- startKeepAlive() {
132
- this.stopKeepAlive();
133
- this.keepAliveInterval = setInterval(() => {
134
- this.socket.volatile.emit("machine-alive", {
135
- time: Date.now()
136
- });
137
- }, 2e4);
138
- }
139
- stopKeepAlive() {
140
- if (this.keepAliveInterval) {
141
- clearInterval(this.keepAliveInterval);
142
- this.keepAliveInterval = null;
143
- }
144
- }
145
- connect() {
146
- this.socket.connect();
147
- }
148
- shutdown() {
149
- this.stopKeepAlive();
150
- this.socket.close();
151
- this.emit("shutdown");
152
- }
153
- }
154
-
155
- const DAEMON_PID_FILE = join(homedir(), ".happy", "daemon-pid");
156
- async function run() {
157
- if (!process.env.HAPPY_DAEMON_MODE) {
158
- throw new Error("This function should only be called by the daemon system with HAPPY_DAEMON_MODE environment variable set");
159
- }
160
- logger.info("Happy CLI daemon started successfully");
161
- if (isDaemonRunning()) {
162
- console.log("Happy daemon is already running");
163
- process.exit(0);
164
- }
165
- writePidFile();
166
- process.on("SIGINT", cleanup);
167
- process.on("SIGTERM", cleanup);
168
- process.on("exit", cleanup);
169
- try {
170
- const settings = await readSettings() || {};
171
- if (!settings.machineId) {
172
- settings.machineId = crypto.randomUUID();
173
- settings.machineHost = hostname();
174
- await writeSettings(settings);
175
- }
176
- const machineIdentity = {
177
- machineId: settings.machineId,
178
- machineHost: settings.machineHost || hostname(),
179
- platform: process.platform,
180
- version: process.env.npm_package_version || "unknown"
181
- };
182
- let credentials = await readCredentials();
183
- if (!credentials) {
184
- logger.debug("[DAEMON] No credentials found, running auth");
185
- await doAuth();
186
- credentials = await readCredentials();
187
- if (!credentials) {
188
- throw new Error("Failed to authenticate");
189
- }
190
- }
191
- const { token, secret } = credentials;
192
- const daemon = new ApiDaemonSession(token, secret, machineIdentity);
193
- daemon.on("connected", () => {
194
- logger.debug("[DAEMON] Successfully connected to server");
195
- });
196
- daemon.on("disconnected", () => {
197
- logger.debug("[DAEMON] Disconnected from server");
198
- });
199
- daemon.on("shutdown", () => {
200
- logger.debug("[DAEMON] Shutdown requested");
201
- cleanup();
202
- process.exit(0);
203
- });
204
- daemon.connect();
205
- setInterval(() => {
206
- }, 1e3);
207
- } catch (error) {
208
- logger.debug("[DAEMON] Failed to start daemon", error);
209
- cleanup();
210
- process.exit(1);
211
- }
212
- }
213
- function isDaemonRunning() {
214
- try {
215
- if (!existsSync(DAEMON_PID_FILE)) {
216
- return false;
217
- }
218
- const pid = parseInt(readFileSync(DAEMON_PID_FILE, "utf-8"));
219
- try {
220
- process.kill(pid, 0);
221
- return true;
222
- } catch {
223
- unlinkSync(DAEMON_PID_FILE);
224
- return false;
225
- }
226
- } catch {
227
- return false;
228
- }
229
- }
230
- function writePidFile() {
231
- const happyDir = join(homedir(), ".happy");
232
- if (!existsSync(happyDir)) {
233
- mkdirSync(happyDir, { recursive: true });
234
- }
235
- writeFileSync(DAEMON_PID_FILE, process.pid.toString());
236
- }
237
- function cleanup() {
238
- try {
239
- if (existsSync(DAEMON_PID_FILE)) {
240
- unlinkSync(DAEMON_PID_FILE);
241
- }
242
- } catch (error) {
243
- logger.debug("[DAEMON] Error cleaning up PID file", error);
244
- }
245
- }
246
-
247
- export { isDaemonRunning, run };
@@ -1,32 +0,0 @@
1
- import { l as logger } from './types-fXgEaaqP.mjs';
2
- import 'axios';
3
- import 'chalk';
4
- import 'fs';
5
- import 'node:os';
6
- import 'node:path';
7
- import 'node:fs/promises';
8
- import 'node:fs';
9
- import 'node:events';
10
- import 'socket.io-client';
11
- import 'zod';
12
- import 'node:crypto';
13
- import 'tweetnacl';
14
- import 'expo-server-sdk';
15
-
16
- async function run() {
17
- if (!process.env.HAPPY_DAEMON_MODE) {
18
- throw new Error("This function should only be called by the daemon system with HAPPY_DAEMON_MODE environment variable set");
19
- }
20
- logger.info("Happy CLI daemon started successfully");
21
- while (true) {
22
- try {
23
- logger.debug("Daemon heartbeat");
24
- await new Promise((resolve) => setTimeout(resolve, 3e4));
25
- } catch (error) {
26
- logger.debug("Error in daemon loop:", error);
27
- await new Promise((resolve) => setTimeout(resolve, 5e3));
28
- }
29
- }
30
- }
31
-
32
- export { run };
@@ -1,34 +0,0 @@
1
- 'use strict';
2
-
3
- var types = require('./types-mykDX2xe.cjs');
4
- require('axios');
5
- require('chalk');
6
- require('fs');
7
- require('node:os');
8
- require('node:path');
9
- require('node:fs/promises');
10
- require('node:fs');
11
- require('node:events');
12
- require('socket.io-client');
13
- require('zod');
14
- require('node:crypto');
15
- require('tweetnacl');
16
- require('expo-server-sdk');
17
-
18
- async function run() {
19
- if (!process.env.HAPPY_DAEMON_MODE) {
20
- throw new Error("This function should only be called by the daemon system with HAPPY_DAEMON_MODE environment variable set");
21
- }
22
- types.logger.info("Happy CLI daemon started successfully");
23
- while (true) {
24
- try {
25
- types.logger.debug("Daemon heartbeat");
26
- await new Promise((resolve) => setTimeout(resolve, 3e4));
27
- } catch (error) {
28
- types.logger.debug("Error in daemon loop:", error);
29
- await new Promise((resolve) => setTimeout(resolve, 5e3));
30
- }
31
- }
32
- }
33
-
34
- exports.run = run;