@zhigang1992/happy-cli 0.12.1

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 (47) hide show
  1. package/README.md +60 -0
  2. package/bin/happy-mcp.mjs +32 -0
  3. package/bin/happy.mjs +35 -0
  4. package/dist/codex/happyMcpStdioBridge.cjs +80 -0
  5. package/dist/codex/happyMcpStdioBridge.d.cts +2 -0
  6. package/dist/codex/happyMcpStdioBridge.d.mts +2 -0
  7. package/dist/codex/happyMcpStdioBridge.mjs +78 -0
  8. package/dist/index-BOBrKhX5.cjs +6655 -0
  9. package/dist/index-DsHtmQqP.mjs +6624 -0
  10. package/dist/index.cjs +42 -0
  11. package/dist/index.d.cts +1 -0
  12. package/dist/index.d.mts +1 -0
  13. package/dist/index.mjs +39 -0
  14. package/dist/lib.cjs +31 -0
  15. package/dist/lib.d.cts +817 -0
  16. package/dist/lib.d.mts +817 -0
  17. package/dist/lib.mjs +21 -0
  18. package/dist/list-BW6QBLa1.cjs +328 -0
  19. package/dist/list-hET5tyMc.mjs +326 -0
  20. package/dist/prompt-DXkgjktW.cjs +203 -0
  21. package/dist/prompt-Dz7G8yGx.mjs +201 -0
  22. package/dist/runCodex-CLGYMNs2.mjs +1335 -0
  23. package/dist/runCodex-CylcX5Ug.cjs +1338 -0
  24. package/dist/types-BsjUgWOx.cjs +2264 -0
  25. package/dist/types-CGco5Y-r.mjs +2213 -0
  26. package/package.json +126 -0
  27. package/scripts/claude_local_launcher.cjs +98 -0
  28. package/scripts/claude_remote_launcher.cjs +13 -0
  29. package/scripts/ripgrep_launcher.cjs +33 -0
  30. package/scripts/unpack-tools.cjs +163 -0
  31. package/tools/archives/difftastic-LICENSE +21 -0
  32. package/tools/archives/difftastic-arm64-darwin.tar.gz +0 -0
  33. package/tools/archives/difftastic-arm64-linux.tar.gz +0 -0
  34. package/tools/archives/difftastic-x64-darwin.tar.gz +0 -0
  35. package/tools/archives/difftastic-x64-linux.tar.gz +0 -0
  36. package/tools/archives/difftastic-x64-win32.tar.gz +0 -0
  37. package/tools/archives/ripgrep-LICENSE +3 -0
  38. package/tools/archives/ripgrep-arm64-darwin.tar.gz +0 -0
  39. package/tools/archives/ripgrep-arm64-linux.tar.gz +0 -0
  40. package/tools/archives/ripgrep-x64-darwin.tar.gz +0 -0
  41. package/tools/archives/ripgrep-x64-linux.tar.gz +0 -0
  42. package/tools/archives/ripgrep-x64-win32.tar.gz +0 -0
  43. package/tools/licenses/difftastic-LICENSE +21 -0
  44. package/tools/licenses/ripgrep-LICENSE +3 -0
  45. package/tools/unpacked/difft +0 -0
  46. package/tools/unpacked/rg +0 -0
  47. package/tools/unpacked/ripgrep.node +0 -0
@@ -0,0 +1,203 @@
1
+ 'use strict';
2
+
3
+ var types = require('./types-BsjUgWOx.cjs');
4
+ var axios = require('axios');
5
+ var socket_ioClient = require('socket.io-client');
6
+ require('chalk');
7
+ require('fs');
8
+ require('node:fs');
9
+ require('node:os');
10
+ require('node:path');
11
+ require('node:fs/promises');
12
+ require('zod');
13
+ require('node:crypto');
14
+ require('tweetnacl');
15
+ require('node:events');
16
+ require('child_process');
17
+ require('util');
18
+ require('fs/promises');
19
+ require('crypto');
20
+ require('path');
21
+ require('url');
22
+ require('os');
23
+ require('expo-server-sdk');
24
+
25
+ const DEFAULT_TIMEOUT_MINUTES = 20;
26
+ async function promptSession(credentials, sessionId, promptText, timeoutMinutes = DEFAULT_TIMEOUT_MINUTES) {
27
+ try {
28
+ const serverUrl = types.configuration.serverUrl;
29
+ const response = await axios.get(`${serverUrl}/v2/sessions/active`, {
30
+ headers: {
31
+ "Authorization": `Bearer ${credentials.token}`
32
+ }
33
+ });
34
+ const session = response.data.sessions.find((s) => s.id === sessionId);
35
+ if (!session) {
36
+ console.error(`Session ${sessionId} not found or not active.`);
37
+ process.exit(1);
38
+ }
39
+ let agentState = {};
40
+ if (session.agentState) {
41
+ try {
42
+ const key2 = credentials.encryption.type === "legacy" ? credentials.encryption.secret : credentials.encryption.machineKey;
43
+ const decrypted = types.decrypt(
44
+ key2,
45
+ credentials.encryption.type,
46
+ types.decodeBase64(session.agentState)
47
+ );
48
+ if (decrypted) {
49
+ agentState = decrypted;
50
+ }
51
+ } catch (error) {
52
+ types.logger.debug(`Failed to decrypt agent state for session ${sessionId}:`, error);
53
+ }
54
+ }
55
+ if (agentState.thinking) {
56
+ console.error("Claude is already working on a task. Please wait for it to finish.");
57
+ process.exit(1);
58
+ }
59
+ const wsUrl = serverUrl.replace(/^http/, "ws");
60
+ const socket = socket_ioClient.io(wsUrl, {
61
+ path: "/v1/updates",
62
+ auth: {
63
+ token: credentials.token,
64
+ clientType: "session-scoped",
65
+ sessionId
66
+ },
67
+ transports: ["websocket", "polling"]
68
+ });
69
+ let isThinking = false;
70
+ let hasStartedThinking = false;
71
+ let completed = false;
72
+ await new Promise((resolve, reject) => {
73
+ const timeout = setTimeout(() => {
74
+ reject(new Error("Connection timeout"));
75
+ }, 1e4);
76
+ socket.on("connect", () => {
77
+ clearTimeout(timeout);
78
+ types.logger.debug(`Connected to WebSocket for session ${sessionId}`);
79
+ resolve();
80
+ });
81
+ socket.on("connect_error", (error) => {
82
+ clearTimeout(timeout);
83
+ reject(error);
84
+ });
85
+ });
86
+ socket.on("update", (data) => {
87
+ types.logger.debugLargeJson("[prompt] Received update:", data);
88
+ if (data.body.t === "new-message") {
89
+ try {
90
+ const key2 = credentials.encryption.type === "legacy" ? credentials.encryption.secret : credentials.encryption.machineKey;
91
+ const content = types.decrypt(
92
+ key2,
93
+ credentials.encryption.type,
94
+ types.decodeBase64(data.body.message.content.c)
95
+ );
96
+ if (!content) {
97
+ types.logger.debug("Failed to decrypt message content");
98
+ return;
99
+ }
100
+ if (content.role === "agent" && content.content?.type === "output") {
101
+ const output = content.content.data;
102
+ if (output.type === "user" && output.message?.content) {
103
+ console.log("[User]:", output.message.content);
104
+ } else if (output.type === "assistant" && output.message?.content) {
105
+ if (Array.isArray(output.message.content)) {
106
+ for (const block of output.message.content) {
107
+ if (block.type === "text") {
108
+ console.log(block.text);
109
+ } else if (block.type === "tool_use") {
110
+ console.log(`
111
+ [Tool: ${block.name}]`);
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ } catch (error) {
118
+ types.logger.debug("Failed to decrypt or process message:", error);
119
+ }
120
+ } else if (data.body.t === "update-session" && data.body.agentState) {
121
+ try {
122
+ if (data.body.agentState.value) {
123
+ const key2 = credentials.encryption.type === "legacy" ? credentials.encryption.secret : credentials.encryption.machineKey;
124
+ const updatedState = types.decrypt(
125
+ key2,
126
+ credentials.encryption.type,
127
+ types.decodeBase64(data.body.agentState.value)
128
+ );
129
+ if (updatedState) {
130
+ types.logger.debug(`[prompt] Agent state updated: thinking=${updatedState.thinking}`);
131
+ }
132
+ }
133
+ } catch (error) {
134
+ types.logger.debug("Failed to decrypt agent state:", error);
135
+ }
136
+ }
137
+ });
138
+ socket.on("ephemeral", (data) => {
139
+ if (data.type === "activity" && data.id === sessionId) {
140
+ types.logger.debug(`[prompt] Activity update: thinking=${data.thinking}, active=${data.active}`);
141
+ if (data.thinking && !hasStartedThinking) {
142
+ hasStartedThinking = true;
143
+ console.log("[Claude is thinking...]");
144
+ }
145
+ isThinking = data.thinking;
146
+ if (hasStartedThinking && !data.thinking) {
147
+ completed = true;
148
+ }
149
+ }
150
+ });
151
+ const messageContent = {
152
+ role: "user",
153
+ content: {
154
+ type: "text",
155
+ text: promptText
156
+ },
157
+ meta: {
158
+ sentFrom: "cli"
159
+ }
160
+ };
161
+ const key = credentials.encryption.type === "legacy" ? credentials.encryption.secret : credentials.encryption.machineKey;
162
+ const encryptedMessage = types.encodeBase64(types.encrypt(
163
+ key,
164
+ credentials.encryption.type,
165
+ messageContent
166
+ ));
167
+ types.logger.debug("[prompt] Sending message to session...");
168
+ socket.emit("message", {
169
+ sid: sessionId,
170
+ message: encryptedMessage
171
+ });
172
+ console.log(`[Sent prompt to session ${sessionId}]`);
173
+ const checkInterval = setInterval(() => {
174
+ if (completed) {
175
+ clearInterval(checkInterval);
176
+ socket.close();
177
+ console.log("\n[Claude has finished]");
178
+ process.exit(0);
179
+ }
180
+ }, 500);
181
+ const timeoutMs = timeoutMinutes * 60 * 1e3;
182
+ setTimeout(() => {
183
+ clearInterval(checkInterval);
184
+ socket.close();
185
+ console.error(`
186
+ Timeout waiting for Claude to complete (${timeoutMinutes} minutes).`);
187
+ process.exit(1);
188
+ }, timeoutMs);
189
+ } catch (error) {
190
+ if (axios.isAxiosError(error)) {
191
+ if (error.response?.status === 401) {
192
+ console.error("Authentication failed. Please run `happy auth` to authenticate.");
193
+ } else {
194
+ console.error(`Failed to send prompt: ${error.response?.data?.message || error.message}`);
195
+ }
196
+ } else {
197
+ console.error(`Failed to send prompt: ${error}`);
198
+ }
199
+ process.exit(1);
200
+ }
201
+ }
202
+
203
+ exports.promptSession = promptSession;
@@ -0,0 +1,201 @@
1
+ import { c as configuration, b as decrypt, d as decodeBase64, l as logger, g as encodeBase64, h as encrypt } from './types-CGco5Y-r.mjs';
2
+ import axios from 'axios';
3
+ import { io } from 'socket.io-client';
4
+ import 'chalk';
5
+ import 'fs';
6
+ import 'node:fs';
7
+ import 'node:os';
8
+ import 'node:path';
9
+ import 'node:fs/promises';
10
+ import 'zod';
11
+ import 'node:crypto';
12
+ import 'tweetnacl';
13
+ import 'node:events';
14
+ import 'child_process';
15
+ import 'util';
16
+ import 'fs/promises';
17
+ import 'crypto';
18
+ import 'path';
19
+ import 'url';
20
+ import 'os';
21
+ import 'expo-server-sdk';
22
+
23
+ const DEFAULT_TIMEOUT_MINUTES = 20;
24
+ async function promptSession(credentials, sessionId, promptText, timeoutMinutes = DEFAULT_TIMEOUT_MINUTES) {
25
+ try {
26
+ const serverUrl = configuration.serverUrl;
27
+ const response = await axios.get(`${serverUrl}/v2/sessions/active`, {
28
+ headers: {
29
+ "Authorization": `Bearer ${credentials.token}`
30
+ }
31
+ });
32
+ const session = response.data.sessions.find((s) => s.id === sessionId);
33
+ if (!session) {
34
+ console.error(`Session ${sessionId} not found or not active.`);
35
+ process.exit(1);
36
+ }
37
+ let agentState = {};
38
+ if (session.agentState) {
39
+ try {
40
+ const key2 = credentials.encryption.type === "legacy" ? credentials.encryption.secret : credentials.encryption.machineKey;
41
+ const decrypted = decrypt(
42
+ key2,
43
+ credentials.encryption.type,
44
+ decodeBase64(session.agentState)
45
+ );
46
+ if (decrypted) {
47
+ agentState = decrypted;
48
+ }
49
+ } catch (error) {
50
+ logger.debug(`Failed to decrypt agent state for session ${sessionId}:`, error);
51
+ }
52
+ }
53
+ if (agentState.thinking) {
54
+ console.error("Claude is already working on a task. Please wait for it to finish.");
55
+ process.exit(1);
56
+ }
57
+ const wsUrl = serverUrl.replace(/^http/, "ws");
58
+ const socket = io(wsUrl, {
59
+ path: "/v1/updates",
60
+ auth: {
61
+ token: credentials.token,
62
+ clientType: "session-scoped",
63
+ sessionId
64
+ },
65
+ transports: ["websocket", "polling"]
66
+ });
67
+ let isThinking = false;
68
+ let hasStartedThinking = false;
69
+ let completed = false;
70
+ await new Promise((resolve, reject) => {
71
+ const timeout = setTimeout(() => {
72
+ reject(new Error("Connection timeout"));
73
+ }, 1e4);
74
+ socket.on("connect", () => {
75
+ clearTimeout(timeout);
76
+ logger.debug(`Connected to WebSocket for session ${sessionId}`);
77
+ resolve();
78
+ });
79
+ socket.on("connect_error", (error) => {
80
+ clearTimeout(timeout);
81
+ reject(error);
82
+ });
83
+ });
84
+ socket.on("update", (data) => {
85
+ logger.debugLargeJson("[prompt] Received update:", data);
86
+ if (data.body.t === "new-message") {
87
+ try {
88
+ const key2 = credentials.encryption.type === "legacy" ? credentials.encryption.secret : credentials.encryption.machineKey;
89
+ const content = decrypt(
90
+ key2,
91
+ credentials.encryption.type,
92
+ decodeBase64(data.body.message.content.c)
93
+ );
94
+ if (!content) {
95
+ logger.debug("Failed to decrypt message content");
96
+ return;
97
+ }
98
+ if (content.role === "agent" && content.content?.type === "output") {
99
+ const output = content.content.data;
100
+ if (output.type === "user" && output.message?.content) {
101
+ console.log("[User]:", output.message.content);
102
+ } else if (output.type === "assistant" && output.message?.content) {
103
+ if (Array.isArray(output.message.content)) {
104
+ for (const block of output.message.content) {
105
+ if (block.type === "text") {
106
+ console.log(block.text);
107
+ } else if (block.type === "tool_use") {
108
+ console.log(`
109
+ [Tool: ${block.name}]`);
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
115
+ } catch (error) {
116
+ logger.debug("Failed to decrypt or process message:", error);
117
+ }
118
+ } else if (data.body.t === "update-session" && data.body.agentState) {
119
+ try {
120
+ if (data.body.agentState.value) {
121
+ const key2 = credentials.encryption.type === "legacy" ? credentials.encryption.secret : credentials.encryption.machineKey;
122
+ const updatedState = decrypt(
123
+ key2,
124
+ credentials.encryption.type,
125
+ decodeBase64(data.body.agentState.value)
126
+ );
127
+ if (updatedState) {
128
+ logger.debug(`[prompt] Agent state updated: thinking=${updatedState.thinking}`);
129
+ }
130
+ }
131
+ } catch (error) {
132
+ logger.debug("Failed to decrypt agent state:", error);
133
+ }
134
+ }
135
+ });
136
+ socket.on("ephemeral", (data) => {
137
+ if (data.type === "activity" && data.id === sessionId) {
138
+ logger.debug(`[prompt] Activity update: thinking=${data.thinking}, active=${data.active}`);
139
+ if (data.thinking && !hasStartedThinking) {
140
+ hasStartedThinking = true;
141
+ console.log("[Claude is thinking...]");
142
+ }
143
+ isThinking = data.thinking;
144
+ if (hasStartedThinking && !data.thinking) {
145
+ completed = true;
146
+ }
147
+ }
148
+ });
149
+ const messageContent = {
150
+ role: "user",
151
+ content: {
152
+ type: "text",
153
+ text: promptText
154
+ },
155
+ meta: {
156
+ sentFrom: "cli"
157
+ }
158
+ };
159
+ const key = credentials.encryption.type === "legacy" ? credentials.encryption.secret : credentials.encryption.machineKey;
160
+ const encryptedMessage = encodeBase64(encrypt(
161
+ key,
162
+ credentials.encryption.type,
163
+ messageContent
164
+ ));
165
+ logger.debug("[prompt] Sending message to session...");
166
+ socket.emit("message", {
167
+ sid: sessionId,
168
+ message: encryptedMessage
169
+ });
170
+ console.log(`[Sent prompt to session ${sessionId}]`);
171
+ const checkInterval = setInterval(() => {
172
+ if (completed) {
173
+ clearInterval(checkInterval);
174
+ socket.close();
175
+ console.log("\n[Claude has finished]");
176
+ process.exit(0);
177
+ }
178
+ }, 500);
179
+ const timeoutMs = timeoutMinutes * 60 * 1e3;
180
+ setTimeout(() => {
181
+ clearInterval(checkInterval);
182
+ socket.close();
183
+ console.error(`
184
+ Timeout waiting for Claude to complete (${timeoutMinutes} minutes).`);
185
+ process.exit(1);
186
+ }, timeoutMs);
187
+ } catch (error) {
188
+ if (axios.isAxiosError(error)) {
189
+ if (error.response?.status === 401) {
190
+ console.error("Authentication failed. Please run `happy auth` to authenticate.");
191
+ } else {
192
+ console.error(`Failed to send prompt: ${error.response?.data?.message || error.message}`);
193
+ }
194
+ } else {
195
+ console.error(`Failed to send prompt: ${error}`);
196
+ }
197
+ process.exit(1);
198
+ }
199
+ }
200
+
201
+ export { promptSession };