@zonease/happy 0.6.39 → 0.6.41
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/bin/happy.mjs +10 -0
- package/dist/{api-CIZKyfSn.mjs → api-K2-jr9ar.mjs} +86 -6
- package/dist/{api-CwOCQeLH.cjs → api-XeHlmApX.cjs} +87 -7
- package/dist/{auth-BIleVCw0.cjs → auth-BQvEuSs5.cjs} +2 -2
- package/dist/{auth-Cas9DR3b.cjs → auth-BbvPcnkY.cjs} +4 -4
- package/dist/{auth-0VnlXT9f.mjs → auth-CjLkoM3m.mjs} +4 -4
- package/dist/{auth-BE8dD20T.mjs → auth-DS8fzlin.mjs} +2 -2
- package/dist/{browser-Dll5hxOV.mjs → browser-C05Ak6RL.mjs} +1 -1
- package/dist/{browser-Cc08m7of.cjs → browser-C05SP_Tt.cjs} +1 -1
- package/dist/{claudeLocal-WkgLbl1a.cjs → claudeLocal-CpDhLCcZ.cjs} +1 -1
- package/dist/{claudeLocal-CPT3zcIU.mjs → claudeLocal-DJNRlHIC.mjs} +1 -1
- package/dist/{config-Draa-5XC.cjs → config-B0mns9fF.cjs} +1 -1
- package/dist/{config-rTT4qTU5.mjs → config-DWWtjKQx.mjs} +1 -1
- package/dist/{connect-CJZ73syK.cjs → connect-BxCScVNX.cjs} +4 -4
- package/dist/{connect-BfC1tYP_.mjs → connect-DXQC1CJe.mjs} +4 -4
- package/dist/{controlClient-DZMIsKsT.cjs → controlClient-DgELDZgM.cjs} +10 -1
- package/dist/{controlClient-CM_QcJnB.mjs → controlClient-DgjVRN8D.mjs} +10 -2
- package/dist/deviceKeys-BpIAWz13.cjs +182 -0
- package/dist/deviceKeys-CejCdWpw.mjs +175 -0
- package/dist/{doctor-DZYB6IVc.mjs → doctor-B-LCMVN9.mjs} +3 -3
- package/dist/{doctor-Cya9YSA0.cjs → doctor-DznasgP3.cjs} +3 -3
- package/dist/{downloadImage-MQMrUUxS.cjs → downloadImage-B_ygLAXY.cjs} +5 -5
- package/dist/{downloadImage-DfSFLb-h.mjs → downloadImage-ia5SzlCV.mjs} +3 -3
- package/dist/{enroll-BxlbVftP.cjs → enroll-BvfpRUGJ.cjs} +3 -3
- package/dist/{enroll-C52x8oly.mjs → enroll-HjUqyGnD.mjs} +3 -3
- package/dist/{evidence-Ccd9iYcj.mjs → evidence-BEQd1dCh.mjs} +1 -1
- package/dist/{evidence-CjWBG5rX.cjs → evidence-CVgTjBrq.cjs} +1 -1
- package/dist/{formatImageMessage-DbyG8c2j.cjs → formatImageMessage-CmJTP_hU.cjs} +1 -1
- package/dist/{formatImageMessage-B4lSxlk2.mjs → formatImageMessage-DVs57t3x.mjs} +1 -1
- package/dist/index.cjs +58 -43
- package/dist/index.mjs +58 -43
- package/dist/{install-C_cp8b2-.cjs → install-2Yl_L582.cjs} +2 -2
- package/dist/{install-oRAjVLjP.mjs → install-B3mMGISS.mjs} +1 -1
- package/dist/{install-BokHRgFW.cjs → install-Ck22tYHP.cjs} +1 -1
- package/dist/{install-DAeCn8ae.mjs → install-UTz_vYvB.mjs} +2 -2
- package/dist/lib.cjs +3 -3
- package/dist/lib.d.cts +77 -0
- package/dist/lib.d.mts +77 -0
- package/dist/lib.mjs +3 -3
- package/dist/{loadableToolOutput-Cuygmd4K.mjs → loadableToolOutput-4EvraaNY.mjs} +3 -3
- package/dist/{loadableToolOutput-DDCJjywt.cjs → loadableToolOutput-BZYlaqHn.cjs} +3 -3
- package/dist/{persistence-BFjvtUad.mjs → persistence-CIUFyOwz.mjs} +2 -2
- package/dist/{persistence-JLUn_Nou.cjs → persistence-DrfN7TzY.cjs} +1 -1
- package/dist/push-CCOXCcM_.cjs +80 -0
- package/dist/push-USXj_pv0.mjs +78 -0
- package/dist/{run-BDn2aE3Q.cjs → run-D3CopmEb.cjs} +45 -9
- package/dist/{run-DBZqN6Kn.mjs → run-Dy6KX6m-.mjs} +45 -9
- package/dist/{runClaude-DNHvERX0.mjs → runClaude-CWux2RDq.mjs} +14 -14
- package/dist/{runClaude-uaKxPZPm.cjs → runClaude-aHzvx6Ha.cjs} +15 -15
- package/dist/{runCodex-C-RTM0wA.mjs → runCodex-D0ZxSj3O.mjs} +13 -13
- package/dist/{runCodex-82UrZLme.cjs → runCodex-G-Aq531U.cjs} +13 -13
- package/dist/{runGemini-Bm6-4Xm2.mjs → runGemini-DZC2i6vA.mjs} +15 -15
- package/dist/{runGemini-CXMr4Jwb.cjs → runGemini-DxGgDAIM.cjs} +15 -15
- package/dist/{runOneShot-1B6RMYT7.cjs → runOneShot-BgT-JNMA.cjs} +2 -2
- package/dist/{runOneShot-ioARRHrx.mjs → runOneShot-cxlk7VKA.mjs} +2 -2
- package/dist/{serve-CwibwU6N.mjs → serve-CKyvJNs0.mjs} +6 -6
- package/dist/{serve-BtdAhkIE.cjs → serve-Dr3wPrtK.cjs} +6 -6
- package/dist/{session-D--F87zL.cjs → session-dYzbOo_W.cjs} +5 -5
- package/dist/{session-2sU4Bu1R.mjs → session-vf2ZjFto.mjs} +5 -5
- package/dist/{sessionKeyCache-D2BwO91C.mjs → sessionKeyCache-D2u3JUys.mjs} +1 -1
- package/dist/{sessionKeyCache-4Tp8pJ3N.cjs → sessionKeyCache-dDquDzn0.cjs} +1 -1
- package/dist/{sessionList-BCSw3qYt.mjs → sessionList-C1k2PNg_.mjs} +2 -2
- package/dist/{sessionList-ICJsjNtJ.cjs → sessionList-DmmtC7uR.cjs} +2 -2
- package/dist/{sessionSummary-lHGBWQSb.mjs → sessionSummary-5a1QtFVS.mjs} +3 -3
- package/dist/{sessionSummary-Bkz52BPh.cjs → sessionSummary-DGLoVOxd.cjs} +3 -3
- package/dist/{spawnHappyCLI-D_V-AAoP.cjs → spawnHappyCLI-CarRI4GM.cjs} +1 -1
- package/dist/{spawnHappyCLI-CoORX0YW.mjs → spawnHappyCLI-D3EkTFIn.mjs} +1 -1
- package/dist/{ssh-DL_AkRAD.mjs → ssh-B0hvEYIl.mjs} +137 -103
- package/dist/{ssh-BTOlhhxi.cjs → ssh-CBgVwKsB.cjs} +142 -106
- package/dist/{task-CSpaC9HX.cjs → task-CMunPKCV.cjs} +6 -6
- package/dist/{task-CQzrHRZe.mjs → task-CRo6W-3_.mjs} +6 -6
- package/dist/{uninstall-nFMFGUVM.mjs → uninstall-BALE2up0.mjs} +2 -2
- package/dist/{uninstall-BiKyRAb1.cjs → uninstall-BJ3eEGM4.cjs} +2 -2
- package/dist/{update-Dw8pgsAT.cjs → update-Bb3iijy8.cjs} +3 -3
- package/dist/{update-BcqRHXf2.mjs → update-BfjtLrhO.mjs} +3 -3
- package/package.json +1 -1
- package/dist/deviceExec-CU1R9CRb.cjs +0 -84
- package/dist/deviceExec-D93AOVV4.mjs +0 -81
package/bin/happy.mjs
CHANGED
|
@@ -2,8 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
import { execFileSync } from 'child_process';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
+
import { homedir } from 'os';
|
|
5
6
|
import { join, dirname } from 'path';
|
|
6
7
|
|
|
8
|
+
// V8 keeps compiled bytecode here between runs. Set before the child starts, so
|
|
9
|
+
// it covers the entry's own imports too — half a command's time goes into
|
|
10
|
+
// compiling this bundle. Mirrors configuration.happyHomeDir; a wrong guess only
|
|
11
|
+
// costs a cache miss.
|
|
12
|
+
if (!process.env.NODE_COMPILE_CACHE) {
|
|
13
|
+
const happyHome = process.env.HAPPY_HOME_DIR || join(homedir(), '.happy');
|
|
14
|
+
process.env.NODE_COMPILE_CACHE = join(happyHome, 'compile-cache');
|
|
15
|
+
}
|
|
16
|
+
|
|
7
17
|
// Check if we're already running with the flags
|
|
8
18
|
const hasNoWarnings = process.execArgv.includes('--no-warnings');
|
|
9
19
|
const hasNoDeprecation = process.execArgv.includes('--no-deprecation');
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import axios from 'axios';
|
|
2
|
-
import { l as logger, c as configuration,
|
|
2
|
+
import { l as logger, c as configuration, e as encodeBase64, f as encrypt, g as decrypt, h as decodeBase64, i as isDebug, B as encryptLegacy, a as readSettings, C as getRandomBytes, D as libsodiumEncryptForPublicKey } from './persistence-CIUFyOwz.mjs';
|
|
3
3
|
import { EventEmitter } from 'node:events';
|
|
4
4
|
import { io } from 'socket.io-client';
|
|
5
5
|
import { z } from 'zod';
|
|
@@ -24,7 +24,7 @@ import tweetnacl from 'tweetnacl';
|
|
|
24
24
|
import { encode, decode } from '@stablelib/base64';
|
|
25
25
|
import { createInterface } from 'node:readline';
|
|
26
26
|
import { Expo } from 'expo-server-sdk';
|
|
27
|
-
import { c as cacheSessionKey } from './sessionKeyCache-
|
|
27
|
+
import { c as cacheSessionKey } from './sessionKeyCache-D2u3JUys.mjs';
|
|
28
28
|
import chalk from 'chalk';
|
|
29
29
|
|
|
30
30
|
z.object({
|
|
@@ -1548,7 +1548,7 @@ function spawnShell(opts) {
|
|
|
1548
1548
|
}
|
|
1549
1549
|
const shell = process.env.SHELL || (process.platform === "win32" ? "powershell.exe" : "bash");
|
|
1550
1550
|
const cwd = opts.cwd ?? process.cwd();
|
|
1551
|
-
const shellArgs = process.platform
|
|
1551
|
+
const shellArgs = process.platform === "win32" ? [] : isBashShell(shell) ? ["--rcfile", createHappyBashRc(), "-i"] : ["-l", "-i"];
|
|
1552
1552
|
const shellEnv = { ...process.env };
|
|
1553
1553
|
delete shellEnv.NO_COLOR;
|
|
1554
1554
|
delete shellEnv.NODE_DISABLE_COLORS;
|
|
@@ -1724,6 +1724,10 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
1724
1724
|
cwd: data.cwd === "/" ? void 0 : data.cwd,
|
|
1725
1725
|
timeout: data.timeout || 3e4,
|
|
1726
1726
|
// Default 30 seconds timeout
|
|
1727
|
+
// node's 1MB default kills the child and reports failure once
|
|
1728
|
+
// output crosses it — the command has already succeeded by
|
|
1729
|
+
// then, and the caller sees a truncated result with an error.
|
|
1730
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
1727
1731
|
// launchd and systemd hand the daemon a bare PATH, so without
|
|
1728
1732
|
// this a command that works when typed into the device terminal
|
|
1729
1733
|
// fails here with "command not found".
|
|
@@ -2265,19 +2269,24 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
2265
2269
|
};
|
|
2266
2270
|
});
|
|
2267
2271
|
const outboundStates = /* @__PURE__ */ new Map();
|
|
2268
|
-
const emitEncrypted = (event, payload) => {
|
|
2272
|
+
const emitEncrypted = (event, payload, reliable = false) => {
|
|
2269
2273
|
const socket = rpcHandlerManager.getSocket();
|
|
2270
2274
|
if (!socket || !socket.connected) {
|
|
2271
2275
|
return;
|
|
2272
2276
|
}
|
|
2273
2277
|
const envelope = { sessionId: payload.sessionId, ptyId: payload.ptyId };
|
|
2274
|
-
if (
|
|
2278
|
+
if (reliable) envelope.reliable = true;
|
|
2279
|
+
if (event === "pty-output" && payload.data !== void 0) {
|
|
2275
2280
|
const key = rpcHandlerManager.getEncryptionKey();
|
|
2276
2281
|
const variant = rpcHandlerManager.getEncryptionVariant();
|
|
2277
2282
|
envelope.data = encodeBase64(encrypt(key, variant, payload.data));
|
|
2278
2283
|
} else if (event === "pty-exit" && typeof payload.exitCode === "number") {
|
|
2279
2284
|
envelope.exitCode = payload.exitCode;
|
|
2280
2285
|
}
|
|
2286
|
+
if (reliable) {
|
|
2287
|
+
socket.emit(event, envelope);
|
|
2288
|
+
return;
|
|
2289
|
+
}
|
|
2281
2290
|
socket.volatile.emit(event, envelope);
|
|
2282
2291
|
};
|
|
2283
2292
|
const splitOnUtf8Boundary = (merged) => {
|
|
@@ -2334,7 +2343,73 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
2334
2343
|
outboundStates.delete(ptyId);
|
|
2335
2344
|
};
|
|
2336
2345
|
rpcHandlerManager.registerHandler("pty-start", async (data) => {
|
|
2337
|
-
logger.debug("[pty-start] request", { cols: data.cols, rows: data.rows, cwd: data.cwd });
|
|
2346
|
+
logger.debug("[pty-start] request", { cols: data.cols, rows: data.rows, cwd: data.cwd, exec: !!data.exec });
|
|
2347
|
+
if (data.exec) {
|
|
2348
|
+
const execId = randomUUID();
|
|
2349
|
+
const child = spawn$1(process.env.SHELL || "/bin/sh", ["-c", data.exec.command], {
|
|
2350
|
+
cwd: data.cwd,
|
|
2351
|
+
env: await resolveLoginShellEnv(),
|
|
2352
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
2353
|
+
});
|
|
2354
|
+
const killTimer = setTimeout(() => child.kill("SIGTERM"), data.exec.timeoutMs ?? 3e5);
|
|
2355
|
+
child.stdout?.pause();
|
|
2356
|
+
child.stderr?.pause();
|
|
2357
|
+
setImmediate(() => {
|
|
2358
|
+
child.stdout?.resume();
|
|
2359
|
+
child.stderr?.resume();
|
|
2360
|
+
});
|
|
2361
|
+
const pending = { stdout: [], stderr: [] };
|
|
2362
|
+
let pendingBytes = 0;
|
|
2363
|
+
let frameCount = 0;
|
|
2364
|
+
let flushTimer = null;
|
|
2365
|
+
const flushExec = () => {
|
|
2366
|
+
if (flushTimer) {
|
|
2367
|
+
clearTimeout(flushTimer);
|
|
2368
|
+
flushTimer = null;
|
|
2369
|
+
}
|
|
2370
|
+
pendingBytes = 0;
|
|
2371
|
+
frameCount++;
|
|
2372
|
+
for (const stream of ["stdout", "stderr"]) {
|
|
2373
|
+
if (pending[stream].length === 0) continue;
|
|
2374
|
+
const chunk = Buffer.concat(pending[stream]);
|
|
2375
|
+
pending[stream] = [];
|
|
2376
|
+
emitEncrypted("pty-output", {
|
|
2377
|
+
sessionId,
|
|
2378
|
+
ptyId: execId,
|
|
2379
|
+
data: { stream, chunk: chunk.toString("base64") }
|
|
2380
|
+
}, true);
|
|
2381
|
+
}
|
|
2382
|
+
};
|
|
2383
|
+
for (const [stream, source] of [["stdout", child.stdout], ["stderr", child.stderr]]) {
|
|
2384
|
+
source?.on("data", (chunk) => {
|
|
2385
|
+
pending[stream].push(chunk);
|
|
2386
|
+
pendingBytes += chunk.length;
|
|
2387
|
+
if (pendingBytes >= PTY_OUTPUT_FLUSH_BYTES) {
|
|
2388
|
+
flushExec();
|
|
2389
|
+
return;
|
|
2390
|
+
}
|
|
2391
|
+
if (!flushTimer) flushTimer = setTimeout(flushExec, PTY_OUTPUT_FLUSH_MS);
|
|
2392
|
+
});
|
|
2393
|
+
}
|
|
2394
|
+
child.on("close", (code, signal) => {
|
|
2395
|
+
clearTimeout(killTimer);
|
|
2396
|
+
logger.debug(`[exec] close code=${code} signal=${signal} pending=${pendingBytes}`);
|
|
2397
|
+
flushExec();
|
|
2398
|
+
logger.debug(`[exec] flushed ${frameCount} frames, emitting exit`);
|
|
2399
|
+
emitEncrypted("pty-exit", { sessionId, ptyId: execId, exitCode: code ?? (signal ? 143 : 1) }, true);
|
|
2400
|
+
});
|
|
2401
|
+
child.on("error", (error) => {
|
|
2402
|
+
clearTimeout(killTimer);
|
|
2403
|
+
emitEncrypted("pty-output", {
|
|
2404
|
+
sessionId,
|
|
2405
|
+
ptyId: execId,
|
|
2406
|
+
data: { stream: "stderr", chunk: Buffer.from(`${error.message}
|
|
2407
|
+
`).toString("base64") }
|
|
2408
|
+
}, true);
|
|
2409
|
+
emitEncrypted("pty-exit", { sessionId, ptyId: execId, exitCode: 1 }, true);
|
|
2410
|
+
});
|
|
2411
|
+
return { ok: true, ptyId: execId };
|
|
2412
|
+
}
|
|
2338
2413
|
try {
|
|
2339
2414
|
const { ptyId, term } = spawnShell({
|
|
2340
2415
|
cols: data.cols,
|
|
@@ -6179,6 +6254,11 @@ class ApiMachineClient {
|
|
|
6179
6254
|
});
|
|
6180
6255
|
}
|
|
6181
6256
|
socket;
|
|
6257
|
+
/** The daemon's live connection. Reused for device RPC so a CLI command does
|
|
6258
|
+
* not spend ~500ms building its own TLS + WebSocket handshake. */
|
|
6259
|
+
get rpcSocket() {
|
|
6260
|
+
return this.socket;
|
|
6261
|
+
}
|
|
6182
6262
|
keepAliveInterval = null;
|
|
6183
6263
|
rpcHandlerManager;
|
|
6184
6264
|
claudeCache = new SessionCache({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var axios = require('axios');
|
|
4
|
-
var logger = require('./persistence-
|
|
4
|
+
var logger = require('./persistence-DrfN7TzY.cjs');
|
|
5
5
|
var node_events = require('node:events');
|
|
6
6
|
var socket_ioClient = require('socket.io-client');
|
|
7
7
|
var z = require('zod');
|
|
@@ -26,7 +26,7 @@ var tweetnacl = require('tweetnacl');
|
|
|
26
26
|
var base64 = require('@stablelib/base64');
|
|
27
27
|
var node_readline = require('node:readline');
|
|
28
28
|
var expoServerSdk = require('expo-server-sdk');
|
|
29
|
-
var sessionKeyCache = require('./sessionKeyCache-
|
|
29
|
+
var sessionKeyCache = require('./sessionKeyCache-dDquDzn0.cjs');
|
|
30
30
|
var chalk = require('chalk');
|
|
31
31
|
|
|
32
32
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
@@ -1395,7 +1395,7 @@ function resolveToolsDir() {
|
|
|
1395
1395
|
}
|
|
1396
1396
|
function findToolsDir() {
|
|
1397
1397
|
try {
|
|
1398
|
-
const manifest = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('api-
|
|
1398
|
+
const manifest = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('api-XeHlmApX.cjs', document.baseURI).href))).resolve(`${toolsPackageName()}/package.json`);
|
|
1399
1399
|
return path.dirname(manifest);
|
|
1400
1400
|
} catch {
|
|
1401
1401
|
}
|
|
@@ -1551,7 +1551,7 @@ function spawnShell(opts) {
|
|
|
1551
1551
|
}
|
|
1552
1552
|
const shell = process.env.SHELL || (process.platform === "win32" ? "powershell.exe" : "bash");
|
|
1553
1553
|
const cwd = opts.cwd ?? process.cwd();
|
|
1554
|
-
const shellArgs = process.platform
|
|
1554
|
+
const shellArgs = process.platform === "win32" ? [] : isBashShell(shell) ? ["--rcfile", createHappyBashRc(), "-i"] : ["-l", "-i"];
|
|
1555
1555
|
const shellEnv = { ...process.env };
|
|
1556
1556
|
delete shellEnv.NO_COLOR;
|
|
1557
1557
|
delete shellEnv.NODE_DISABLE_COLORS;
|
|
@@ -1727,6 +1727,10 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
1727
1727
|
cwd: data.cwd === "/" ? void 0 : data.cwd,
|
|
1728
1728
|
timeout: data.timeout || 3e4,
|
|
1729
1729
|
// Default 30 seconds timeout
|
|
1730
|
+
// node's 1MB default kills the child and reports failure once
|
|
1731
|
+
// output crosses it — the command has already succeeded by
|
|
1732
|
+
// then, and the caller sees a truncated result with an error.
|
|
1733
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
1730
1734
|
// launchd and systemd hand the daemon a bare PATH, so without
|
|
1731
1735
|
// this a command that works when typed into the device terminal
|
|
1732
1736
|
// fails here with "command not found".
|
|
@@ -2268,19 +2272,24 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
2268
2272
|
};
|
|
2269
2273
|
});
|
|
2270
2274
|
const outboundStates = /* @__PURE__ */ new Map();
|
|
2271
|
-
const emitEncrypted = (event, payload) => {
|
|
2275
|
+
const emitEncrypted = (event, payload, reliable = false) => {
|
|
2272
2276
|
const socket = rpcHandlerManager.getSocket();
|
|
2273
2277
|
if (!socket || !socket.connected) {
|
|
2274
2278
|
return;
|
|
2275
2279
|
}
|
|
2276
2280
|
const envelope = { sessionId: payload.sessionId, ptyId: payload.ptyId };
|
|
2277
|
-
if (
|
|
2281
|
+
if (reliable) envelope.reliable = true;
|
|
2282
|
+
if (event === "pty-output" && payload.data !== void 0) {
|
|
2278
2283
|
const key = rpcHandlerManager.getEncryptionKey();
|
|
2279
2284
|
const variant = rpcHandlerManager.getEncryptionVariant();
|
|
2280
2285
|
envelope.data = logger.encodeBase64(logger.encrypt(key, variant, payload.data));
|
|
2281
2286
|
} else if (event === "pty-exit" && typeof payload.exitCode === "number") {
|
|
2282
2287
|
envelope.exitCode = payload.exitCode;
|
|
2283
2288
|
}
|
|
2289
|
+
if (reliable) {
|
|
2290
|
+
socket.emit(event, envelope);
|
|
2291
|
+
return;
|
|
2292
|
+
}
|
|
2284
2293
|
socket.volatile.emit(event, envelope);
|
|
2285
2294
|
};
|
|
2286
2295
|
const splitOnUtf8Boundary = (merged) => {
|
|
@@ -2337,7 +2346,73 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory, sessionId)
|
|
|
2337
2346
|
outboundStates.delete(ptyId);
|
|
2338
2347
|
};
|
|
2339
2348
|
rpcHandlerManager.registerHandler("pty-start", async (data) => {
|
|
2340
|
-
logger.logger.debug("[pty-start] request", { cols: data.cols, rows: data.rows, cwd: data.cwd });
|
|
2349
|
+
logger.logger.debug("[pty-start] request", { cols: data.cols, rows: data.rows, cwd: data.cwd, exec: !!data.exec });
|
|
2350
|
+
if (data.exec) {
|
|
2351
|
+
const execId = node_crypto.randomUUID();
|
|
2352
|
+
const child = child_process.spawn(process.env.SHELL || "/bin/sh", ["-c", data.exec.command], {
|
|
2353
|
+
cwd: data.cwd,
|
|
2354
|
+
env: await resolveLoginShellEnv(),
|
|
2355
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
2356
|
+
});
|
|
2357
|
+
const killTimer = setTimeout(() => child.kill("SIGTERM"), data.exec.timeoutMs ?? 3e5);
|
|
2358
|
+
child.stdout?.pause();
|
|
2359
|
+
child.stderr?.pause();
|
|
2360
|
+
setImmediate(() => {
|
|
2361
|
+
child.stdout?.resume();
|
|
2362
|
+
child.stderr?.resume();
|
|
2363
|
+
});
|
|
2364
|
+
const pending = { stdout: [], stderr: [] };
|
|
2365
|
+
let pendingBytes = 0;
|
|
2366
|
+
let frameCount = 0;
|
|
2367
|
+
let flushTimer = null;
|
|
2368
|
+
const flushExec = () => {
|
|
2369
|
+
if (flushTimer) {
|
|
2370
|
+
clearTimeout(flushTimer);
|
|
2371
|
+
flushTimer = null;
|
|
2372
|
+
}
|
|
2373
|
+
pendingBytes = 0;
|
|
2374
|
+
frameCount++;
|
|
2375
|
+
for (const stream of ["stdout", "stderr"]) {
|
|
2376
|
+
if (pending[stream].length === 0) continue;
|
|
2377
|
+
const chunk = Buffer.concat(pending[stream]);
|
|
2378
|
+
pending[stream] = [];
|
|
2379
|
+
emitEncrypted("pty-output", {
|
|
2380
|
+
sessionId,
|
|
2381
|
+
ptyId: execId,
|
|
2382
|
+
data: { stream, chunk: chunk.toString("base64") }
|
|
2383
|
+
}, true);
|
|
2384
|
+
}
|
|
2385
|
+
};
|
|
2386
|
+
for (const [stream, source] of [["stdout", child.stdout], ["stderr", child.stderr]]) {
|
|
2387
|
+
source?.on("data", (chunk) => {
|
|
2388
|
+
pending[stream].push(chunk);
|
|
2389
|
+
pendingBytes += chunk.length;
|
|
2390
|
+
if (pendingBytes >= PTY_OUTPUT_FLUSH_BYTES) {
|
|
2391
|
+
flushExec();
|
|
2392
|
+
return;
|
|
2393
|
+
}
|
|
2394
|
+
if (!flushTimer) flushTimer = setTimeout(flushExec, PTY_OUTPUT_FLUSH_MS);
|
|
2395
|
+
});
|
|
2396
|
+
}
|
|
2397
|
+
child.on("close", (code, signal) => {
|
|
2398
|
+
clearTimeout(killTimer);
|
|
2399
|
+
logger.logger.debug(`[exec] close code=${code} signal=${signal} pending=${pendingBytes}`);
|
|
2400
|
+
flushExec();
|
|
2401
|
+
logger.logger.debug(`[exec] flushed ${frameCount} frames, emitting exit`);
|
|
2402
|
+
emitEncrypted("pty-exit", { sessionId, ptyId: execId, exitCode: code ?? (signal ? 143 : 1) }, true);
|
|
2403
|
+
});
|
|
2404
|
+
child.on("error", (error) => {
|
|
2405
|
+
clearTimeout(killTimer);
|
|
2406
|
+
emitEncrypted("pty-output", {
|
|
2407
|
+
sessionId,
|
|
2408
|
+
ptyId: execId,
|
|
2409
|
+
data: { stream: "stderr", chunk: Buffer.from(`${error.message}
|
|
2410
|
+
`).toString("base64") }
|
|
2411
|
+
}, true);
|
|
2412
|
+
emitEncrypted("pty-exit", { sessionId, ptyId: execId, exitCode: 1 }, true);
|
|
2413
|
+
});
|
|
2414
|
+
return { ok: true, ptyId: execId };
|
|
2415
|
+
}
|
|
2341
2416
|
try {
|
|
2342
2417
|
const { ptyId, term } = spawnShell({
|
|
2343
2418
|
cols: data.cols,
|
|
@@ -6182,6 +6257,11 @@ class ApiMachineClient {
|
|
|
6182
6257
|
});
|
|
6183
6258
|
}
|
|
6184
6259
|
socket;
|
|
6260
|
+
/** The daemon's live connection. Reused for device RPC so a CLI command does
|
|
6261
|
+
* not spend ~500ms building its own TLS + WebSocket handshake. */
|
|
6262
|
+
get rpcSocket() {
|
|
6263
|
+
return this.socket;
|
|
6264
|
+
}
|
|
6185
6265
|
keepAliveInterval = null;
|
|
6186
6266
|
rpcHandlerManager;
|
|
6187
6267
|
claudeCache = new SessionCache({
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var logger = require('./persistence-
|
|
3
|
+
var logger = require('./persistence-DrfN7TzY.cjs');
|
|
4
4
|
var node_crypto = require('node:crypto');
|
|
5
5
|
var tweetnacl = require('tweetnacl');
|
|
6
6
|
var axios = require('axios');
|
|
7
7
|
var qrcode = require('qrcode-terminal');
|
|
8
8
|
var time = require('./time-Bj2HRkKH.cjs');
|
|
9
|
-
var browser = require('./browser-
|
|
9
|
+
var browser = require('./browser-C05SP_Tt.cjs');
|
|
10
10
|
var React = require('react');
|
|
11
11
|
var ink = require('ink');
|
|
12
12
|
require('node:fs/promises');
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
|
-
var logger = require('./persistence-
|
|
5
|
-
var auth = require('./auth-
|
|
4
|
+
var logger = require('./persistence-DrfN7TzY.cjs');
|
|
5
|
+
var auth = require('./auth-BQvEuSs5.cjs');
|
|
6
6
|
var fs = require('node:fs');
|
|
7
7
|
var node_readline = require('node:readline');
|
|
8
|
-
var controlClient = require('./controlClient-
|
|
8
|
+
var controlClient = require('./controlClient-DgELDZgM.cjs');
|
|
9
9
|
var os = require('node:os');
|
|
10
10
|
require('node:fs/promises');
|
|
11
11
|
require('node:path');
|
|
@@ -16,7 +16,7 @@ require('fs');
|
|
|
16
16
|
require('axios');
|
|
17
17
|
require('qrcode-terminal');
|
|
18
18
|
require('./time-Bj2HRkKH.cjs');
|
|
19
|
-
require('./browser-
|
|
19
|
+
require('./browser-C05SP_Tt.cjs');
|
|
20
20
|
require('open');
|
|
21
21
|
require('react');
|
|
22
22
|
require('ink');
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { r as readCredentials, a as readSettings, c as configuration, l as logger, b as clearCredentials, d as clearMachineId } from './persistence-
|
|
3
|
-
import { authAndSetupMachineIfNeeded } from './auth-
|
|
2
|
+
import { r as readCredentials, a as readSettings, c as configuration, l as logger, b as clearCredentials, d as clearMachineId } from './persistence-CIUFyOwz.mjs';
|
|
3
|
+
import { authAndSetupMachineIfNeeded } from './auth-DS8fzlin.mjs';
|
|
4
4
|
import { existsSync, rmSync } from 'node:fs';
|
|
5
5
|
import { createInterface } from 'node:readline';
|
|
6
|
-
import { checkIfDaemonRunningAndCleanupStaleState, stopDaemon } from './controlClient-
|
|
6
|
+
import { checkIfDaemonRunningAndCleanupStaleState, stopDaemon } from './controlClient-DgjVRN8D.mjs';
|
|
7
7
|
import os from 'node:os';
|
|
8
8
|
import 'node:fs/promises';
|
|
9
9
|
import 'node:path';
|
|
@@ -14,7 +14,7 @@ import 'fs';
|
|
|
14
14
|
import 'axios';
|
|
15
15
|
import 'qrcode-terminal';
|
|
16
16
|
import './time-DgsBLJA_.mjs';
|
|
17
|
-
import './browser-
|
|
17
|
+
import './browser-C05Ak6RL.mjs';
|
|
18
18
|
import 'open';
|
|
19
19
|
import 'react';
|
|
20
20
|
import 'ink';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { e as encodeBase64, c as configuration, l as logger, r as readCredentials, u as updateSettings, i as isDebug, s as encodeBase64Url, h as decodeBase64, t as writeCredentialsLegacy, w as writeCredentialsDataKey } from './persistence-CIUFyOwz.mjs';
|
|
2
2
|
import { randomBytes, randomUUID } from 'node:crypto';
|
|
3
3
|
import tweetnacl from 'tweetnacl';
|
|
4
4
|
import axios from 'axios';
|
|
5
5
|
import qrcode from 'qrcode-terminal';
|
|
6
6
|
import { d as delay } from './time-DgsBLJA_.mjs';
|
|
7
|
-
import { o as openBrowser } from './browser-
|
|
7
|
+
import { o as openBrowser } from './browser-C05Ak6RL.mjs';
|
|
8
8
|
import React, { useState } from 'react';
|
|
9
9
|
import { useInput, Box, Text, render } from 'ink';
|
|
10
10
|
import 'node:fs/promises';
|
|
@@ -5,7 +5,7 @@ var path = require('node:path');
|
|
|
5
5
|
var node_readline = require('node:readline');
|
|
6
6
|
var fs = require('node:fs');
|
|
7
7
|
var node_crypto = require('node:crypto');
|
|
8
|
-
var logger = require('./persistence-
|
|
8
|
+
var logger = require('./persistence-DrfN7TzY.cjs');
|
|
9
9
|
var os = require('node:os');
|
|
10
10
|
var projectPath = require('./projectPath-ChLhdOyt.cjs');
|
|
11
11
|
var prompt = require('./prompt-BTWDZZO0.cjs');
|
|
@@ -3,7 +3,7 @@ import { resolve, join } from 'node:path';
|
|
|
3
3
|
import { createInterface } from 'node:readline';
|
|
4
4
|
import { existsSync, readFileSync, readdirSync, statSync, mkdirSync } from 'node:fs';
|
|
5
5
|
import { randomUUID } from 'node:crypto';
|
|
6
|
-
import { l as logger } from './persistence-
|
|
6
|
+
import { l as logger } from './persistence-CIUFyOwz.mjs';
|
|
7
7
|
import { homedir } from 'node:os';
|
|
8
8
|
import { p as projectPath } from './projectPath-BTBIMB57.mjs';
|
|
9
9
|
import { g as getBaseSystemPrompt } from './prompt-BsAZsPbo.mjs';
|
|
@@ -4,7 +4,7 @@ var fs = require('fs');
|
|
|
4
4
|
var path = require('path');
|
|
5
5
|
var os = require('os');
|
|
6
6
|
var child_process = require('child_process');
|
|
7
|
-
var logger = require('./persistence-
|
|
7
|
+
var logger = require('./persistence-DrfN7TzY.cjs');
|
|
8
8
|
var constants = require('./constants-E_UWYTo3.cjs');
|
|
9
9
|
require('node:fs/promises');
|
|
10
10
|
require('node:fs');
|
|
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { homedir } from 'os';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
|
-
import { l as logger } from './persistence-
|
|
5
|
+
import { l as logger } from './persistence-CIUFyOwz.mjs';
|
|
6
6
|
import { D as DEFAULT_GEMINI_MODEL, G as GEMINI_MODEL_ENV } from './constants-pmXZGibX.mjs';
|
|
7
7
|
import 'node:fs/promises';
|
|
8
8
|
import 'node:fs';
|
|
@@ -4,11 +4,11 @@ var chalk = require('chalk');
|
|
|
4
4
|
var fs = require('fs');
|
|
5
5
|
var os = require('os');
|
|
6
6
|
var path = require('path');
|
|
7
|
-
var logger = require('./persistence-
|
|
8
|
-
var api = require('./api-
|
|
7
|
+
var logger = require('./persistence-DrfN7TzY.cjs');
|
|
8
|
+
var api = require('./api-XeHlmApX.cjs');
|
|
9
9
|
var http = require('http');
|
|
10
10
|
var crypto = require('crypto');
|
|
11
|
-
var browser = require('./browser-
|
|
11
|
+
var browser = require('./browser-C05SP_Tt.cjs');
|
|
12
12
|
var child_process = require('child_process');
|
|
13
13
|
var util = require('util');
|
|
14
14
|
require('node:fs/promises');
|
|
@@ -34,7 +34,7 @@ require('ws');
|
|
|
34
34
|
require('@stablelib/base64');
|
|
35
35
|
require('node:readline');
|
|
36
36
|
require('expo-server-sdk');
|
|
37
|
-
require('./sessionKeyCache-
|
|
37
|
+
require('./sessionKeyCache-dDquDzn0.cjs');
|
|
38
38
|
require('open');
|
|
39
39
|
|
|
40
40
|
const CLIENT_ID$2 = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
@@ -2,11 +2,11 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
3
3
|
import { homedir } from 'os';
|
|
4
4
|
import { join } from 'path';
|
|
5
|
-
import { r as readCredentials } from './persistence-
|
|
6
|
-
import { A as ApiClient } from './api-
|
|
5
|
+
import { r as readCredentials } from './persistence-CIUFyOwz.mjs';
|
|
6
|
+
import { A as ApiClient } from './api-K2-jr9ar.mjs';
|
|
7
7
|
import { createServer } from 'http';
|
|
8
8
|
import { randomBytes, createHash } from 'crypto';
|
|
9
|
-
import { o as openBrowser } from './browser-
|
|
9
|
+
import { o as openBrowser } from './browser-C05Ak6RL.mjs';
|
|
10
10
|
import { exec } from 'child_process';
|
|
11
11
|
import { promisify } from 'util';
|
|
12
12
|
import 'node:fs/promises';
|
|
@@ -32,7 +32,7 @@ import 'ws';
|
|
|
32
32
|
import '@stablelib/base64';
|
|
33
33
|
import 'node:readline';
|
|
34
34
|
import 'expo-server-sdk';
|
|
35
|
-
import './sessionKeyCache-
|
|
35
|
+
import './sessionKeyCache-D2u3JUys.mjs';
|
|
36
36
|
import 'open';
|
|
37
37
|
|
|
38
38
|
const CLIENT_ID$2 = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var logger = require('./persistence-
|
|
3
|
+
var logger = require('./persistence-DrfN7TzY.cjs');
|
|
4
4
|
var projectPath = require('./projectPath-ChLhdOyt.cjs');
|
|
5
5
|
var fs = require('fs');
|
|
6
6
|
var path = require('path');
|
|
@@ -63,6 +63,14 @@ async function notifyDaemonSessionStarted(sessionId, metadata) {
|
|
|
63
63
|
metadata
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
|
+
async function execOnDeviceViaDaemon(deviceId, command, timeoutMs) {
|
|
67
|
+
const response = await daemonPost("/device-exec", { deviceId, command, timeoutMs });
|
|
68
|
+
if (!response || response.error || response.ok !== true) {
|
|
69
|
+
logger.logger.debug(`[CONTROL CLIENT] Device exec via daemon unavailable: ${response?.error ?? "no daemon"}`);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return response.result;
|
|
73
|
+
}
|
|
66
74
|
async function listDaemonSessions() {
|
|
67
75
|
const result = await daemonPost("/list");
|
|
68
76
|
return result.children || [];
|
|
@@ -160,6 +168,7 @@ async function waitForProcessDeath(pid, timeout) {
|
|
|
160
168
|
|
|
161
169
|
exports.checkIfDaemonRunningAndCleanupStaleState = checkIfDaemonRunningAndCleanupStaleState;
|
|
162
170
|
exports.cleanupDaemonState = cleanupDaemonState;
|
|
171
|
+
exports.execOnDeviceViaDaemon = execOnDeviceViaDaemon;
|
|
163
172
|
exports.isDaemonRunningCurrentlyInstalledHappyVersion = isDaemonRunningCurrentlyInstalledHappyVersion;
|
|
164
173
|
exports.listDaemonSessions = listDaemonSessions;
|
|
165
174
|
exports.notifyDaemonSessionStarted = notifyDaemonSessionStarted;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { l as logger,
|
|
1
|
+
import { l as logger, m as readDaemonState, n as clearDaemonState } from './persistence-CIUFyOwz.mjs';
|
|
2
2
|
import { p as projectPath } from './projectPath-BTBIMB57.mjs';
|
|
3
3
|
import { readFileSync } from 'fs';
|
|
4
4
|
import { join } from 'path';
|
|
@@ -61,6 +61,14 @@ async function notifyDaemonSessionStarted(sessionId, metadata) {
|
|
|
61
61
|
metadata
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
|
+
async function execOnDeviceViaDaemon(deviceId, command, timeoutMs) {
|
|
65
|
+
const response = await daemonPost("/device-exec", { deviceId, command, timeoutMs });
|
|
66
|
+
if (!response || response.error || response.ok !== true) {
|
|
67
|
+
logger.debug(`[CONTROL CLIENT] Device exec via daemon unavailable: ${response?.error ?? "no daemon"}`);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return response.result;
|
|
71
|
+
}
|
|
64
72
|
async function listDaemonSessions() {
|
|
65
73
|
const result = await daemonPost("/list");
|
|
66
74
|
return result.children || [];
|
|
@@ -156,4 +164,4 @@ async function waitForProcessDeath(pid, timeout) {
|
|
|
156
164
|
throw new Error("Process did not die within timeout");
|
|
157
165
|
}
|
|
158
166
|
|
|
159
|
-
export { checkIfDaemonRunningAndCleanupStaleState, cleanupDaemonState, isDaemonRunningCurrentlyInstalledHappyVersion, listDaemonSessions, notifyDaemonSessionStarted, stopDaemon, stopDaemonHttp, stopDaemonSession };
|
|
167
|
+
export { checkIfDaemonRunningAndCleanupStaleState, cleanupDaemonState, execOnDeviceViaDaemon, isDaemonRunningCurrentlyInstalledHappyVersion, listDaemonSessions, notifyDaemonSessionStarted, stopDaemon, stopDaemonHttp, stopDaemonSession };
|