very-happy-cli 0.2.150 → 0.2.151
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.
- package/dist/{AcpBackend-C-dhGJgd.mjs → AcpBackend-BjTA5gUB.mjs} +2 -2
- package/dist/{AcpBackend-CXawaWWx.cjs → AcpBackend-blE9IEod.cjs} +2 -2
- package/dist/{AcpSessionManager-DKOtSqJc.mjs → AcpSessionManager-D-9mrp40.mjs} +1 -1
- package/dist/{AcpSessionManager-TrwEZR7y.cjs → AcpSessionManager-bF8PYu_B.cjs} +1 -1
- package/dist/{agentGuidance-Dla-BXO8.cjs → agentGuidance-BXa9ikrZ.cjs} +1 -1
- package/dist/{agentGuidance-DrfhtVP1.mjs → agentGuidance-Dvo3cZMW.mjs} +1 -1
- package/dist/{agentHome-Dm-Wjs38.mjs → agentHome-CeFDNzvq.mjs} +2 -2
- package/dist/{agentHome-rylNIkix.cjs → agentHome-D6MSfwnp.cjs} +2 -2
- package/dist/codex/happyMcpStdioBridge.cjs +2 -2
- package/dist/codex/happyMcpStdioBridge.mjs +2 -2
- package/dist/{config-Dhu6LU0h.mjs → config-C-A1XF62.mjs} +4 -4
- package/dist/{config-CgPu2wtS.cjs → config-Cadw1sAk.cjs} +4 -4
- package/dist/{index-DEVkDRas.cjs → index-BKGspSWk.cjs} +7 -7
- package/dist/{index-CpNYvMTJ.mjs → index-CIyjJy8D.mjs} +214 -59
- package/dist/{index-K6mUS0jF.cjs → index-CqtfRzug.cjs} +220 -62
- package/dist/{index-CzpooENj.mjs → index-DEp6CmmS.mjs} +8 -8
- package/dist/{index-BsYH1sjV.mjs → index-DYQgcgL2.mjs} +4 -4
- package/dist/{index-DvfCUuDK.cjs → index-vyRqLjDv.cjs} +4 -4
- package/dist/index.cjs +4 -4
- package/dist/index.mjs +4 -4
- package/dist/{installTerminalHooks-NIbsQ1wi.cjs → installTerminalHooks-Bf_adbl3.cjs} +4 -4
- package/dist/{installTerminalHooks-BF_tmw9V.mjs → installTerminalHooks-Ch_yTtEA.mjs} +4 -4
- package/dist/lib.cjs +2 -2
- package/dist/lib.mjs +2 -2
- package/dist/{limits-FThmm7WR.mjs → limits-DS-bnYYp.mjs} +7 -7
- package/dist/{limits-Dyma1REp.cjs → limits-DwcY3kyi.cjs} +7 -7
- package/dist/{mcp-_TVUSg8W.cjs → mcp-CMxEZ6-0.cjs} +4 -4
- package/dist/{mcp-DzydgXpf.mjs → mcp-zu8n8TkR.mjs} +4 -4
- package/dist/{piRuntime-ACOhil6t.mjs → piRuntime-Cu6cXZ6N.mjs} +2 -2
- package/dist/{piRuntime-CSAiJk0X.cjs → piRuntime-D3ny0mVg.cjs} +2 -2
- package/dist/{piTerminal-BlE4vbvZ.mjs → piTerminal-M677UP7y.mjs} +6 -6
- package/dist/{piTerminal-DHxGB3Ic.cjs → piTerminal-kDSd_r9X.cjs} +6 -6
- package/dist/{runGemini-BMYCU16c.cjs → runGemini-DuwdVV1O.cjs} +6 -6
- package/dist/{runGemini-D5IV1MoF.mjs → runGemini-DvJwQVGp.mjs} +6 -6
- package/dist/{runOpenClaw-CWPXrKMJ.mjs → runOpenClaw-BG82bF18.mjs} +5 -5
- package/dist/{runOpenClaw-Qs4eFtcS.cjs → runOpenClaw-BsvtCE_H.cjs} +5 -5
- package/dist/{send-qXWGilm8.cjs → send-aUkjhey7.cjs} +20 -6
- package/dist/{send-Dv0km8UI.mjs → send-o6WM-1G8.mjs} +20 -6
- package/dist/{sessions-CpIdDhH7.cjs → sessions-B3vP18kz.cjs} +56 -10
- package/dist/{sessions-DoULfKui.mjs → sessions-DlU3foY_.mjs} +56 -10
- package/dist/{spawn-DqzG1bTH.cjs → spawn-DH6_p4-f.cjs} +166 -27
- package/dist/spawn-DxHIIqhi.mjs +397 -0
- package/dist/{teams-ByEgUzsH.cjs → teams-BW8D1n3o.cjs} +4 -4
- package/dist/{teams-4mhNh5cj.mjs → teams-DoAA_CcN.mjs} +4 -4
- package/dist/{todo-D7SDXL0c.cjs → todo-Bcc2XxGh.cjs} +3 -3
- package/dist/{todo-C9IAUf0K.mjs → todo-BhJbG5eq.mjs} +3 -3
- package/dist/{types-BD542hb1.mjs → types-BN3eiipi.mjs} +46 -3
- package/dist/{types-D2Gkpe0N.cjs → types-CPubg05Z.cjs} +52 -2
- package/package.json +7 -7
- package/dist/spawn-DQuOmUP7.mjs +0 -258
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "very-happy-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.151",
|
|
4
4
|
"description": "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.",
|
|
5
5
|
"author": "Kirill Dubovitskiy",
|
|
6
6
|
"contributors": [
|
|
@@ -117,12 +117,12 @@
|
|
|
117
117
|
"zod": "^4.0.0"
|
|
118
118
|
},
|
|
119
119
|
"optionalDependencies": {
|
|
120
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
121
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
122
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
123
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
124
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
125
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
120
|
+
"very-happy-tools-arm64-darwin": "0.2.151",
|
|
121
|
+
"very-happy-tools-x64-darwin": "0.2.151",
|
|
122
|
+
"very-happy-tools-arm64-linux": "0.2.151",
|
|
123
|
+
"very-happy-tools-x64-linux": "0.2.151",
|
|
124
|
+
"very-happy-tools-arm64-win32": "0.2.151",
|
|
125
|
+
"very-happy-tools-x64-win32": "0.2.151"
|
|
126
126
|
},
|
|
127
127
|
"devDependencies": {
|
|
128
128
|
"@slopus/happy-wire": "workspace:*",
|
package/dist/spawn-DQuOmUP7.mjs
DELETED
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { readFileSync, statSync } from 'node:fs';
|
|
3
|
-
import { resolve } from 'node:path';
|
|
4
|
-
import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession } from './types-BD542hb1.mjs';
|
|
5
|
-
import { s as sessionWebUrl, i as isValidSpawnOrigin, a as sanitizeSpawnPermissionMode, A as ALLOWED_SPAWN_PERMISSION_MODES, S as SPAWN_AGENTS, w as waitForSessionKey, b as sendUserMessage } from './index-CpNYvMTJ.mjs';
|
|
6
|
-
import { l as logger } from './limits-FThmm7WR.mjs';
|
|
7
|
-
import 'axios';
|
|
8
|
-
import 'node:events';
|
|
9
|
-
import 'socket.io-client';
|
|
10
|
-
import 'zod';
|
|
11
|
-
import '@paralleldrive/cuid2';
|
|
12
|
-
import 'node:crypto';
|
|
13
|
-
import 'child_process';
|
|
14
|
-
import 'util';
|
|
15
|
-
import 'fs/promises';
|
|
16
|
-
import 'crypto';
|
|
17
|
-
import 'path';
|
|
18
|
-
import 'cross-spawn';
|
|
19
|
-
import './projectPath-CSpqWdxp.mjs';
|
|
20
|
-
import 'url';
|
|
21
|
-
import 'os';
|
|
22
|
-
import 'node:fs/promises';
|
|
23
|
-
import 'node:os';
|
|
24
|
-
import 'node:child_process';
|
|
25
|
-
import 'node-pty';
|
|
26
|
-
import 'fs';
|
|
27
|
-
import 'tweetnacl';
|
|
28
|
-
import 'node:readline';
|
|
29
|
-
import '@anthropic-ai/sandbox-runtime';
|
|
30
|
-
import 'expo-server-sdk';
|
|
31
|
-
import './agentGuidance-DrfhtVP1.mjs';
|
|
32
|
-
import 'ink';
|
|
33
|
-
import 'react';
|
|
34
|
-
import '@anthropic-ai/claude-agent-sdk';
|
|
35
|
-
import 'ps-list';
|
|
36
|
-
import 'tmp';
|
|
37
|
-
import 'open';
|
|
38
|
-
import 'fastify';
|
|
39
|
-
import 'fastify-type-provider-zod';
|
|
40
|
-
import 'node:module';
|
|
41
|
-
import 'node:util';
|
|
42
|
-
import '@modelcontextprotocol/sdk/server/mcp.js';
|
|
43
|
-
import 'node:http';
|
|
44
|
-
import '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
45
|
-
import 'http';
|
|
46
|
-
import 'inquirer';
|
|
47
|
-
import 'node:url';
|
|
48
|
-
import 'node:readline/promises';
|
|
49
|
-
|
|
50
|
-
function parseEnvAssignment(raw) {
|
|
51
|
-
const eq = raw.indexOf("=");
|
|
52
|
-
if (eq <= 0) throw new Error(`--env expects KEY=VALUE, got: ${raw}`);
|
|
53
|
-
const key = raw.slice(0, eq);
|
|
54
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) throw new Error(`--env key is not a valid variable name: ${key}`);
|
|
55
|
-
return [key, raw.slice(eq + 1)];
|
|
56
|
-
}
|
|
57
|
-
function parseSpawnArgs(args) {
|
|
58
|
-
const options = { json: false, help: false };
|
|
59
|
-
for (let i = 0; i < args.length; i++) {
|
|
60
|
-
const arg = args[i];
|
|
61
|
-
if (arg === "--dir" || arg === "-d") {
|
|
62
|
-
const value = args[++i];
|
|
63
|
-
if (value === void 0) throw new Error("--dir requires a value");
|
|
64
|
-
options.dir = value;
|
|
65
|
-
} else if (arg === "--prompt" || arg === "-p") {
|
|
66
|
-
const value = args[++i];
|
|
67
|
-
if (value === void 0) throw new Error("--prompt requires a value");
|
|
68
|
-
options.prompt = value;
|
|
69
|
-
} else if (arg === "--prompt-file") {
|
|
70
|
-
const value = args[++i];
|
|
71
|
-
if (value === void 0) throw new Error("--prompt-file requires a value");
|
|
72
|
-
options.promptFile = value;
|
|
73
|
-
} else if (arg === "--spawned-by") {
|
|
74
|
-
const value = args[++i];
|
|
75
|
-
if (value === void 0) throw new Error("--spawned-by requires a value");
|
|
76
|
-
if (!isValidSpawnOrigin(value)) {
|
|
77
|
-
throw new Error("--spawned-by must be 1-24 chars of [a-z0-9] plus - or _, starting with a letter or digit");
|
|
78
|
-
}
|
|
79
|
-
options.spawnedBy = value;
|
|
80
|
-
} else if (arg === "--permission-mode") {
|
|
81
|
-
const value = args[++i];
|
|
82
|
-
if (value === void 0) throw new Error("--permission-mode requires a value");
|
|
83
|
-
if (sanitizeSpawnPermissionMode(value) === null) {
|
|
84
|
-
throw new Error(`--permission-mode must be one of: ${ALLOWED_SPAWN_PERMISSION_MODES.join(", ")}`);
|
|
85
|
-
}
|
|
86
|
-
options.permissionMode = value;
|
|
87
|
-
} else if (arg === "--agent") {
|
|
88
|
-
const value = args[++i];
|
|
89
|
-
if (value === void 0) throw new Error("--agent requires a value");
|
|
90
|
-
if (!SPAWN_AGENTS.includes(value)) {
|
|
91
|
-
throw new Error(`--agent must be one of: ${SPAWN_AGENTS.join(", ")}`);
|
|
92
|
-
}
|
|
93
|
-
options.agent = value;
|
|
94
|
-
} else if (arg === "--env") {
|
|
95
|
-
const value = args[++i];
|
|
96
|
-
if (value === void 0) throw new Error("--env requires a value");
|
|
97
|
-
const [key, val] = parseEnvAssignment(value);
|
|
98
|
-
options.env = { ...options.env ?? {}, [key]: val };
|
|
99
|
-
} else if (arg === "--json") {
|
|
100
|
-
options.json = true;
|
|
101
|
-
} else if (arg === "--help" || arg === "-h") {
|
|
102
|
-
options.help = true;
|
|
103
|
-
} else {
|
|
104
|
-
throw new Error(`Unknown argument: ${arg}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (options.prompt !== void 0 && options.promptFile !== void 0) {
|
|
108
|
-
throw new Error("--prompt and --prompt-file are mutually exclusive");
|
|
109
|
-
}
|
|
110
|
-
return options;
|
|
111
|
-
}
|
|
112
|
-
function printHelp() {
|
|
113
|
-
console.log(`
|
|
114
|
-
${chalk.bold("very-happy spawn")} - Spawn a remote session via the local daemon (for automation)
|
|
115
|
-
|
|
116
|
-
${chalk.bold("Usage:")}
|
|
117
|
-
very-happy spawn --dir <path> [--prompt <text> | --prompt-file <file>]
|
|
118
|
-
[--spawned-by <name>] [--permission-mode <mode>]
|
|
119
|
-
[--agent <name>] [--env KEY=VALUE]... [--json]
|
|
120
|
-
|
|
121
|
-
${chalk.bold("Options:")}
|
|
122
|
-
--dir, -d <path> Working directory for the new session (required)
|
|
123
|
-
--prompt, -p <text> First message to send after the session starts
|
|
124
|
-
--prompt-file <file> Read the first message from a file (UTF-8)
|
|
125
|
-
--spawned-by <name> Tag the new session with its origin (e.g. tanka).
|
|
126
|
-
1-24 chars: [a-z0-9] plus - or _. Shows as a chip in
|
|
127
|
-
the web list and is searchable as #<name>.
|
|
128
|
-
--permission-mode <m> Permission mode for the new session: default,
|
|
129
|
-
acceptEdits, plan, yolo, bypassPermissions.
|
|
130
|
-
WITHOUT this the session runs in 'default' and stops
|
|
131
|
-
at the first un-allowlisted tool waiting for someone
|
|
132
|
-
to approve \u2014 if nothing is watching, it just hangs.
|
|
133
|
-
Unattended dispatchers want bypassPermissions.
|
|
134
|
-
--agent <name> Backend to run: claude (default), codex, gemini,
|
|
135
|
-
openclaw, pi (needs pi-acp on the daemon's PATH).
|
|
136
|
-
--env KEY=VALUE Extra environment for the session process. Repeatable.
|
|
137
|
-
\${VAR} is expanded against the daemon's environment;
|
|
138
|
-
an unresolved reference fails the spawn.
|
|
139
|
-
--json Machine-readable output: {"sessionId", "url"}
|
|
140
|
-
-h, --help Show this help
|
|
141
|
-
|
|
142
|
-
${chalk.bold("Behavior:")}
|
|
143
|
-
Requires the Very Happy daemon to be running on this machine (same semantics
|
|
144
|
-
as spawning from the web: an offline machine cannot spawn). Without
|
|
145
|
-
--prompt / --prompt-file the session is spawned idle.
|
|
146
|
-
|
|
147
|
-
${chalk.bold("Exit codes:")}
|
|
148
|
-
0 success
|
|
149
|
-
1 spawn failed (no session created)
|
|
150
|
-
2 session spawned but first message failed (session URL still printed)
|
|
151
|
-
`);
|
|
152
|
-
}
|
|
153
|
-
async function sendFirstMessage(sessionId, text) {
|
|
154
|
-
const persisted = await waitForSessionKey(sessionId, 15e3);
|
|
155
|
-
await sendUserMessage(sessionId, persisted, text, "cli-spawn");
|
|
156
|
-
}
|
|
157
|
-
async function handleSpawnCommand(args) {
|
|
158
|
-
let options;
|
|
159
|
-
try {
|
|
160
|
-
options = parseSpawnArgs(args);
|
|
161
|
-
} catch (error) {
|
|
162
|
-
console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
163
|
-
console.error(`Run ${chalk.cyan("very-happy spawn --help")} for usage.`);
|
|
164
|
-
process.exit(1);
|
|
165
|
-
}
|
|
166
|
-
if (options.help) {
|
|
167
|
-
printHelp();
|
|
168
|
-
process.exit(0);
|
|
169
|
-
}
|
|
170
|
-
if (!options.dir) {
|
|
171
|
-
console.error(chalk.red("Error:"), "--dir is required");
|
|
172
|
-
console.error(`Run ${chalk.cyan("very-happy spawn --help")} for usage.`);
|
|
173
|
-
process.exit(1);
|
|
174
|
-
}
|
|
175
|
-
const directory = resolve(options.dir);
|
|
176
|
-
let prompt = options.prompt;
|
|
177
|
-
if (options.promptFile !== void 0) {
|
|
178
|
-
try {
|
|
179
|
-
prompt = readFileSync(resolve(options.promptFile), "utf8");
|
|
180
|
-
} catch (error) {
|
|
181
|
-
console.error(chalk.red("Error:"), `Failed to read --prompt-file: ${error instanceof Error ? error.message : String(error)}`);
|
|
182
|
-
process.exit(1);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
if (prompt !== void 0 && prompt.trim().length === 0) {
|
|
186
|
-
console.error(chalk.red("Error:"), "Prompt is empty");
|
|
187
|
-
process.exit(1);
|
|
188
|
-
}
|
|
189
|
-
try {
|
|
190
|
-
if (!statSync(directory).isDirectory()) {
|
|
191
|
-
console.error(chalk.red("Error:"), `Not a directory: ${directory}`);
|
|
192
|
-
process.exit(1);
|
|
193
|
-
}
|
|
194
|
-
} catch {
|
|
195
|
-
console.error(chalk.red("Error:"), `Directory does not exist: ${directory}`);
|
|
196
|
-
process.exit(1);
|
|
197
|
-
}
|
|
198
|
-
if (!await checkIfDaemonRunningAndCleanupStaleState()) {
|
|
199
|
-
console.error(chalk.red("Error:"), "Happy daemon is not running on this machine.");
|
|
200
|
-
console.error(`Start it with ${chalk.cyan("very-happy daemon start")} and retry.`);
|
|
201
|
-
process.exit(1);
|
|
202
|
-
}
|
|
203
|
-
logger.debug(`[SPAWN CMD] Spawning session in ${directory}`);
|
|
204
|
-
const result = await spawnDaemonSession(directory, void 0, {
|
|
205
|
-
spawnedBy: options.spawnedBy,
|
|
206
|
-
permissionMode: options.permissionMode,
|
|
207
|
-
agent: options.agent,
|
|
208
|
-
environmentVariables: options.env
|
|
209
|
-
});
|
|
210
|
-
if (result?.error || !result?.success || !result?.sessionId) {
|
|
211
|
-
const message = result?.error || "Daemon returned no session ID";
|
|
212
|
-
console.error(chalk.red("Error:"), `Failed to spawn session: ${message}`);
|
|
213
|
-
process.exit(1);
|
|
214
|
-
}
|
|
215
|
-
const sessionId = result.sessionId;
|
|
216
|
-
const url = sessionWebUrl(sessionId);
|
|
217
|
-
let promptError = null;
|
|
218
|
-
if (prompt !== void 0) {
|
|
219
|
-
try {
|
|
220
|
-
await sendFirstMessage(sessionId, prompt);
|
|
221
|
-
} catch (error) {
|
|
222
|
-
promptError = error instanceof Error ? error.message : String(error);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (options.json) {
|
|
226
|
-
const payload = { sessionId, url };
|
|
227
|
-
if (options.spawnedBy !== void 0) {
|
|
228
|
-
payload.spawnedBy = options.spawnedBy;
|
|
229
|
-
}
|
|
230
|
-
if (options.permissionMode !== void 0) {
|
|
231
|
-
payload.permissionMode = options.permissionMode;
|
|
232
|
-
}
|
|
233
|
-
if (options.agent !== void 0) {
|
|
234
|
-
payload.agent = options.agent;
|
|
235
|
-
}
|
|
236
|
-
if (prompt !== void 0) {
|
|
237
|
-
payload.promptDelivered = promptError === null;
|
|
238
|
-
}
|
|
239
|
-
if (promptError !== null) {
|
|
240
|
-
payload.error = `Session spawned but first message failed: ${promptError}`;
|
|
241
|
-
}
|
|
242
|
-
console.log(JSON.stringify(payload));
|
|
243
|
-
} else {
|
|
244
|
-
console.log(`${chalk.bold("Session:")} ${sessionId}`);
|
|
245
|
-
console.log(`${chalk.bold("URL:")} ${url}`);
|
|
246
|
-
if (prompt !== void 0 && promptError === null) {
|
|
247
|
-
console.log(chalk.green("First message sent."));
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
if (promptError !== null) {
|
|
251
|
-
console.error(chalk.red("Error:"), `Session ${sessionId} was spawned, but sending the first message failed: ${promptError}`);
|
|
252
|
-
console.error(`The session likely exists \u2014 open ${url} and send the message manually.`);
|
|
253
|
-
process.exit(2);
|
|
254
|
-
}
|
|
255
|
-
process.exit(0);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
export { SPAWN_AGENTS, handleSpawnCommand, parseEnvAssignment, parseSpawnArgs, sessionWebUrl };
|