very-happy-cli 0.2.141 → 0.2.143
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-CnWSwaHk.cjs → AcpBackend-B8oehrfU.cjs} +2 -2
- package/dist/{AcpBackend-CWmjboOm.mjs → AcpBackend-LEgn9vol.mjs} +2 -2
- package/dist/{AcpSessionManager-Dxt78rPO.cjs → AcpSessionManager-BomdfyhZ.cjs} +1 -1
- package/dist/{AcpSessionManager-CtXoi6PN.mjs → AcpSessionManager-Yfbs5bi2.mjs} +1 -1
- package/dist/{agentGuidance-Do7cQka3.mjs → agentGuidance-BU4hxm8M.mjs} +1 -1
- package/dist/{agentGuidance-B9ENxSaS.cjs → agentGuidance-CJSl54ua.cjs} +1 -1
- package/dist/codex/happyMcpStdioBridge.cjs +2 -2
- package/dist/codex/happyMcpStdioBridge.mjs +2 -2
- package/dist/{config-Dn7nAHcA.cjs → config-CfqWoHmO.cjs} +5 -4
- package/dist/{config-DY57frJF.mjs → config-euZ_K5Lo.mjs} +5 -4
- package/dist/{index-BSVgut_Y.cjs → index-BREtikhm.cjs} +5 -4
- package/dist/{index-3STVDtNO.cjs → index-Bj68y6ee.cjs} +12 -40
- package/dist/{index-ChWePQEd.cjs → index-C510dSUn.cjs} +188 -132
- package/dist/{index-C55sW8E9.mjs → index-DoiG88oX.mjs} +169 -114
- package/dist/{index-DhfgAB8K.mjs → index-PM_SsRpw.mjs} +5 -4
- package/dist/{index-Dz6FgNFg.mjs → index-ZOMC8Gzn.mjs} +11 -39
- package/dist/index.cjs +7 -6
- package/dist/index.mjs +7 -6
- package/dist/installPiTools-BKnXjrVu.cjs +82 -0
- package/dist/installPiTools-C-Lxv4Bt.mjs +77 -0
- package/dist/{installTerminalHooks-zmtIrf3E.mjs → installTerminalHooks-BGVQqbgq.mjs} +8 -7
- package/dist/{installTerminalHooks--jkP17uE.cjs → installTerminalHooks-C_jraM1j.cjs} +9 -8
- package/dist/lib.cjs +3 -2
- package/dist/lib.d.cts +6 -1
- package/dist/lib.d.mts +6 -1
- package/dist/lib.mjs +3 -2
- package/dist/{limits-DbLWXlJm.cjs → limits-B3oVgqBJ.cjs} +29 -10
- package/dist/{limits-DT5Yk_UH.mjs → limits-uABU-yq3.mjs} +29 -11
- package/dist/{mcp-Bzy-X9kI.mjs → mcp-CfbTQXyh.mjs} +28 -14
- package/dist/{mcp-kE0n1dBF.cjs → mcp-G-3lL_KH.cjs} +29 -15
- package/dist/piExtension.d.mts +17 -0
- package/dist/piExtension.mjs +84 -0
- package/dist/piRuntime-BE6iYQwU.mjs +37 -0
- package/dist/piRuntime-CWE-1W-y.cjs +39 -0
- package/dist/piTerminal-Dyc_9pGP.cjs +132 -0
- package/dist/piTerminal-rqKn1_Zy.mjs +129 -0
- package/dist/projectPath-CSpqWdxp.mjs +10 -0
- package/dist/projectPath-ChLhdOyt.cjs +13 -0
- package/dist/{runGemini-BmdhYEzM.mjs → runGemini-BMlXIaTL.mjs} +8 -7
- package/dist/{runGemini-CxUz95A1.cjs → runGemini-C6qMFzcn.cjs} +9 -8
- package/dist/{runOpenClaw-RLIFJx61.cjs → runOpenClaw-C2_aCP7v.cjs} +6 -5
- package/dist/{runOpenClaw-CYpO3Vv8.mjs → runOpenClaw-CoO5Vp3S.mjs} +6 -5
- package/dist/{send-DT04hV8o.mjs → send-CBrJylJc.mjs} +5 -4
- package/dist/{send-BGcCrMUT.cjs → send-DGVwmB-p.cjs} +5 -4
- package/dist/{sessions-DDWTq2AG.mjs → sessions-DbLubh2N.mjs} +7 -6
- package/dist/{sessions-Jt9lrcrG.cjs → sessions-DyQXMN-8.cjs} +7 -6
- package/dist/{spawn-CdZgvthE.cjs → spawn-DIyFOn3W.cjs} +5 -4
- package/dist/{spawn-Ca0A70dX.mjs → spawn-wkkxEGdF.mjs} +5 -4
- package/dist/{teams-CzK1zg0m.mjs → teams-BTyVFK3P.mjs} +5 -4
- package/dist/{teams-DfVwVZ4x.cjs → teams-QOkGFjkJ.cjs} +5 -4
- package/dist/terminalToolContext-CFeGeaNm.mjs +7 -0
- package/dist/terminalToolContext-DoV9Gs7K.cjs +9 -0
- package/dist/{todo-4WhOom8k.mjs → todo-DoLkqdBe.mjs} +4 -3
- package/dist/{todo-D9nFaYpQ.cjs → todo-Du6pjwx_.cjs} +4 -3
- package/dist/{types-Bk3W89Z3.cjs → types-6__wqmmP.cjs} +80 -17
- package/dist/{types-CLosaeZT.mjs → types-BG4gFjLL.mjs} +79 -15
- package/package.json +11 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var axios = require('axios');
|
|
4
|
-
var persistence = require('./limits-
|
|
4
|
+
var persistence = require('./limits-B3oVgqBJ.cjs');
|
|
5
5
|
var node_events = require('node:events');
|
|
6
6
|
var socket_ioClient = require('socket.io-client');
|
|
7
7
|
var z = require('zod');
|
|
@@ -13,7 +13,7 @@ var fs = require('fs/promises');
|
|
|
13
13
|
var crypto$1 = require('crypto');
|
|
14
14
|
var path = require('path');
|
|
15
15
|
var spawn = require('cross-spawn');
|
|
16
|
-
var
|
|
16
|
+
var projectPath = require('./projectPath-ChLhdOyt.cjs');
|
|
17
17
|
var os = require('os');
|
|
18
18
|
var promises = require('node:fs/promises');
|
|
19
19
|
var path$1 = require('node:path');
|
|
@@ -28,7 +28,6 @@ var sandboxRuntime = require('@anthropic-ai/sandbox-runtime');
|
|
|
28
28
|
var expoServerSdk = require('expo-server-sdk');
|
|
29
29
|
var chalk = require('chalk');
|
|
30
30
|
|
|
31
|
-
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
32
31
|
function _interopNamespaceDefault(e) {
|
|
33
32
|
var n = Object.create(null);
|
|
34
33
|
if (e) {
|
|
@@ -1378,14 +1377,42 @@ class RpcHandlerManager {
|
|
|
1378
1377
|
}
|
|
1379
1378
|
}
|
|
1380
1379
|
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1380
|
+
function describeSocketAckDrop(drop) {
|
|
1381
|
+
switch (drop.reason) {
|
|
1382
|
+
case "no-ack":
|
|
1383
|
+
return "no ack callback on the frame (re-delivered after a transport close?); response dropped";
|
|
1384
|
+
case "handler-threw":
|
|
1385
|
+
return `handler threw: ${drop.error instanceof Error ? drop.error.message : String(drop.error)}`;
|
|
1386
|
+
case "ack-threw":
|
|
1387
|
+
return `ack callback threw: ${drop.error instanceof Error ? drop.error.message : String(drop.error)}`;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
function safeAck(ack, onDrop) {
|
|
1391
|
+
return (value) => {
|
|
1392
|
+
if (typeof ack !== "function") {
|
|
1393
|
+
onDrop({ reason: "no-ack" });
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1396
|
+
try {
|
|
1397
|
+
ack(value);
|
|
1398
|
+
} catch (error) {
|
|
1399
|
+
onDrop({ reason: "ack-threw", error });
|
|
1400
|
+
}
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1403
|
+
async function answerSocketRequest(ack, run, onDrop) {
|
|
1404
|
+
let value;
|
|
1405
|
+
try {
|
|
1406
|
+
value = await run();
|
|
1407
|
+
} catch (error) {
|
|
1408
|
+
onDrop({ reason: "handler-threw", error });
|
|
1409
|
+
return;
|
|
1410
|
+
}
|
|
1411
|
+
safeAck(ack, onDrop)(value);
|
|
1385
1412
|
}
|
|
1386
1413
|
|
|
1387
1414
|
function run$1(args, options) {
|
|
1388
|
-
const RUNNER_PATH = path.resolve(path.join(projectPath(), "scripts", "ripgrep_launcher.cjs"));
|
|
1415
|
+
const RUNNER_PATH = path.resolve(path.join(projectPath.projectPath(), "scripts", "ripgrep_launcher.cjs"));
|
|
1389
1416
|
return new Promise((resolve2, reject) => {
|
|
1390
1417
|
const child = spawn.spawn("node", [RUNNER_PATH, JSON.stringify(args)], {
|
|
1391
1418
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -1416,7 +1443,7 @@ function run$1(args, options) {
|
|
|
1416
1443
|
function getBinaryPath() {
|
|
1417
1444
|
const platformName = os.platform();
|
|
1418
1445
|
const binaryName = platformName === "win32" ? "difft.exe" : "difft";
|
|
1419
|
-
return path.resolve(path.join(projectPath(), "tools", "unpacked", binaryName));
|
|
1446
|
+
return path.resolve(path.join(projectPath.projectPath(), "tools", "unpacked", binaryName));
|
|
1420
1447
|
}
|
|
1421
1448
|
function run(args, options) {
|
|
1422
1449
|
const binaryPath = getBinaryPath();
|
|
@@ -3074,13 +3101,18 @@ async function notifyDaemonTurnEvent(sessionId, event) {
|
|
|
3074
3101
|
async function stopDaemonHttp() {
|
|
3075
3102
|
await daemonPost("/stop");
|
|
3076
3103
|
}
|
|
3077
|
-
async function pushClipboardViaDaemon(text) {
|
|
3078
|
-
const result = await daemonPost("/clipboard", { text });
|
|
3104
|
+
async function pushClipboardViaDaemon(text, terminalId) {
|
|
3105
|
+
const result = await daemonPost("/clipboard", { text, ...terminalId ? { terminalId } : {} });
|
|
3079
3106
|
if (result?.error && result.delivered === void 0) {
|
|
3080
3107
|
return { delivered: false, error: result.error };
|
|
3081
3108
|
}
|
|
3082
3109
|
return result;
|
|
3083
3110
|
}
|
|
3111
|
+
async function pushFilePreviewViaDaemon(terminalId, path, mode = "file") {
|
|
3112
|
+
const result = await daemonPost("/file-preview", { terminalId, path, mode });
|
|
3113
|
+
if (result?.error) return { delivered: false, error: result.error };
|
|
3114
|
+
return { delivered: result?.delivered === true, ...result?.delivered === true ? {} : { error: "preview was not delivered" } };
|
|
3115
|
+
}
|
|
3084
3116
|
async function setTerminalTitleViaDaemon(terminalId, title, ifAbsent = false) {
|
|
3085
3117
|
const result = await daemonPost("/terminal-title", { terminalId, title, ifAbsent });
|
|
3086
3118
|
if (result?.error) {
|
|
@@ -3281,7 +3313,11 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3281
3313
|
void this.connectSessionRelay();
|
|
3282
3314
|
});
|
|
3283
3315
|
this.socket.on("rpc-request", async (data, callback) => {
|
|
3284
|
-
|
|
3316
|
+
await answerSocketRequest(
|
|
3317
|
+
callback,
|
|
3318
|
+
() => this.rpcHandlerManager.handleRequest(data),
|
|
3319
|
+
(drop) => persistence.logger.debug(`[API] RPC ${data?.method} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
|
|
3320
|
+
);
|
|
3285
3321
|
});
|
|
3286
3322
|
this.socket.on("disconnect", (reason) => {
|
|
3287
3323
|
persistence.logger.debug(`[API] Socket disconnected: ${reason}`);
|
|
@@ -3717,9 +3753,14 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3717
3753
|
persistence.logger.debug(`[API] Session connected to regional relay ${assignment.relayId}`);
|
|
3718
3754
|
});
|
|
3719
3755
|
relaySocket.on("rpc-request", async (data, callback) => {
|
|
3720
|
-
|
|
3756
|
+
await answerSocketRequest(
|
|
3757
|
+
callback,
|
|
3758
|
+
() => this.rpcHandlerManager.handleRequest(data),
|
|
3759
|
+
(drop) => persistence.logger.debug(`[API] Relay RPC ${data?.method} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
|
|
3760
|
+
);
|
|
3721
3761
|
});
|
|
3722
|
-
relaySocket.on("session-message-deliver", async (data,
|
|
3762
|
+
relaySocket.on("session-message-deliver", async (data, rawCallback) => {
|
|
3763
|
+
const callback = safeAck(rawCallback, (drop) => persistence.logger.debug(`[API] session-message-deliver unanswered \u2014 ${describeSocketAckDrop(drop)}`));
|
|
3723
3764
|
if (data?.sessionId !== this.sessionId || !Array.isArray(data.messages) || data.messages.length === 0 || data.messages.length > 50) {
|
|
3724
3765
|
callback({ ok: false, error: "Invalid session message request" });
|
|
3725
3766
|
return;
|
|
@@ -4020,12 +4061,15 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
4020
4061
|
*/
|
|
4021
4062
|
pushClipboard(text) {
|
|
4022
4063
|
const prepared = persistence.prepareClipboardText(text);
|
|
4064
|
+
const history = persistence.prepareClipboardHistoryText(text);
|
|
4023
4065
|
if (!this.socket.connected) {
|
|
4024
4066
|
return { delivered: false, truncated: prepared.truncated, totalBytes: prepared.totalBytes };
|
|
4025
4067
|
}
|
|
4026
4068
|
this.socket.emit("clipboard-push", {
|
|
4027
4069
|
payload: persistence.encodeBase64(persistence.encrypt(this.encryptionKey, this.encryptionVariant, prepared.text)),
|
|
4028
4070
|
enc: true,
|
|
4071
|
+
historyPayload: persistence.encodeBase64(persistence.encrypt(this.encryptionKey, this.encryptionVariant, history.text)),
|
|
4072
|
+
historyTruncated: history.truncated,
|
|
4029
4073
|
truncated: prepared.truncated,
|
|
4030
4074
|
totalBytes: prepared.totalBytes
|
|
4031
4075
|
});
|
|
@@ -14840,19 +14884,34 @@ class ApiMachineClient {
|
|
|
14840
14884
|
* (terminal-path claude → `very-happy mcp` → daemon /clipboard → here).
|
|
14841
14885
|
* Encrypted with the per-machine key; the server relays without reading.
|
|
14842
14886
|
*/
|
|
14843
|
-
pushClipboard(text) {
|
|
14887
|
+
pushClipboard(text, terminalId) {
|
|
14844
14888
|
const prepared = persistence.prepareClipboardText(text);
|
|
14889
|
+
const history = persistence.prepareClipboardHistoryText(text);
|
|
14845
14890
|
if (!this.socket?.connected) {
|
|
14846
14891
|
return { delivered: false, truncated: prepared.truncated, totalBytes: prepared.totalBytes, error: "daemon is not connected to the server" };
|
|
14847
14892
|
}
|
|
14848
14893
|
this.socket.emit("clipboard-push", {
|
|
14894
|
+
...terminalId ? { terminalId } : {},
|
|
14849
14895
|
payload: persistence.encodeBase64(persistence.encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, prepared.text)),
|
|
14850
14896
|
enc: true,
|
|
14897
|
+
historyPayload: persistence.encodeBase64(persistence.encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, history.text)),
|
|
14898
|
+
historyTruncated: history.truncated,
|
|
14851
14899
|
truncated: prepared.truncated,
|
|
14852
14900
|
totalBytes: prepared.totalBytes
|
|
14853
14901
|
});
|
|
14854
14902
|
return { delivered: true, truncated: prepared.truncated, totalBytes: prepared.totalBytes };
|
|
14855
14903
|
}
|
|
14904
|
+
/** Queue a terminal preview with the machine key. Delivery does not prove a browser opened it. */
|
|
14905
|
+
pushFilePreview(terminalId, path, mode = "file") {
|
|
14906
|
+
if (!this.socket?.connected) return { delivered: false, error: "daemon is not connected to the server" };
|
|
14907
|
+
this.socket.emit("file-preview-push", {
|
|
14908
|
+
terminalId,
|
|
14909
|
+
payload: persistence.encodeBase64(persistence.encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, path)),
|
|
14910
|
+
enc: true,
|
|
14911
|
+
mode
|
|
14912
|
+
});
|
|
14913
|
+
return { delivered: true };
|
|
14914
|
+
}
|
|
14856
14915
|
/** Encrypt one base64 terminal payload with the per-machine key (same scheme
|
|
14857
14916
|
* as the live output stream) → base64 ciphertext. Used for both live output
|
|
14858
14917
|
* and the open-terminal snapshot/replay payloads. */
|
|
@@ -15734,7 +15793,11 @@ class ApiMachineClient {
|
|
|
15734
15793
|
bindRpcRequestHandler(socket, transport) {
|
|
15735
15794
|
socket.on("rpc-request", async (data, callback) => {
|
|
15736
15795
|
persistence.logger.debugLargeJson(`[API MACHINE] Received RPC request via ${transport}:`, data);
|
|
15737
|
-
|
|
15796
|
+
await answerSocketRequest(
|
|
15797
|
+
callback,
|
|
15798
|
+
() => this.rpcHandlerManager.handleRequest(data),
|
|
15799
|
+
(drop) => persistence.logger.debug(`[API MACHINE] RPC ${data?.method} via ${transport} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
|
|
15800
|
+
);
|
|
15738
15801
|
});
|
|
15739
15802
|
}
|
|
15740
15803
|
bindMachineCommandHandlers(socket) {
|
|
@@ -16989,8 +17052,8 @@ exports.notifyDaemonSessionEvent = notifyDaemonSessionEvent;
|
|
|
16989
17052
|
exports.notifyDaemonSessionStarted = notifyDaemonSessionStarted;
|
|
16990
17053
|
exports.parseExactVersion = parseExactVersion;
|
|
16991
17054
|
exports.parseTerminalHookPayload = parseTerminalHookPayload;
|
|
16992
|
-
exports.projectPath = projectPath;
|
|
16993
17055
|
exports.pushClipboardViaDaemon = pushClipboardViaDaemon;
|
|
17056
|
+
exports.pushFilePreviewViaDaemon = pushFilePreviewViaDaemon;
|
|
16994
17057
|
exports.readLocalHappyAgentCredentials = readLocalHappyAgentCredentials;
|
|
16995
17058
|
exports.readVhTerminal = readVhTerminal;
|
|
16996
17059
|
exports.resolveCliUpdateCheckInterval = resolveCliUpdateCheckInterval;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import { l as logger,
|
|
2
|
+
import { l as logger, g as encodeBase64, j as encrypt, k as decrypt, m as decodeBase64, c as configuration, o as readDaemonState, q as clearDaemonState, s as decryptBlob, t as prepareClipboardText, u as prepareClipboardHistoryText, f as readSettings, r as readPersistedSessions, v as credentialRelayProblem, p as packageJson, x as readTrackedClaudeSessionIds, y as readTrackedCodexThreadIds, z as libsodiumEncryptForPublicKey, A as libsodiumPublicKeyFromSecretKey, B as getRandomBytes, D as redactLogValue } from './limits-uABU-yq3.mjs';
|
|
3
3
|
import { EventEmitter } from 'node:events';
|
|
4
4
|
import { io } from 'socket.io-client';
|
|
5
5
|
import * as z from 'zod';
|
|
@@ -10,9 +10,9 @@ import { spawn as spawn$1, exec, execSync } from 'child_process';
|
|
|
10
10
|
import { promisify } from 'util';
|
|
11
11
|
import { mkdir, writeFile, appendFile, stat, rename, unlink, readdir, readFile } from 'fs/promises';
|
|
12
12
|
import { randomUUID, createHash } from 'crypto';
|
|
13
|
-
import {
|
|
13
|
+
import { resolve, join, sep } from 'path';
|
|
14
14
|
import { spawn } from 'cross-spawn';
|
|
15
|
-
import {
|
|
15
|
+
import { p as projectPath } from './projectPath-CSpqWdxp.mjs';
|
|
16
16
|
import os, { platform } from 'os';
|
|
17
17
|
import { stat as stat$1, readdir as readdir$1, lstat, open, copyFile, unlink as unlink$1, readFile as readFile$1, rename as rename$1, writeFile as writeFile$1 } from 'node:fs/promises';
|
|
18
18
|
import { join as join$1, isAbsolute, resolve as resolve$1 } from 'node:path';
|
|
@@ -1356,10 +1356,38 @@ class RpcHandlerManager {
|
|
|
1356
1356
|
}
|
|
1357
1357
|
}
|
|
1358
1358
|
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1359
|
+
function describeSocketAckDrop(drop) {
|
|
1360
|
+
switch (drop.reason) {
|
|
1361
|
+
case "no-ack":
|
|
1362
|
+
return "no ack callback on the frame (re-delivered after a transport close?); response dropped";
|
|
1363
|
+
case "handler-threw":
|
|
1364
|
+
return `handler threw: ${drop.error instanceof Error ? drop.error.message : String(drop.error)}`;
|
|
1365
|
+
case "ack-threw":
|
|
1366
|
+
return `ack callback threw: ${drop.error instanceof Error ? drop.error.message : String(drop.error)}`;
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
function safeAck(ack, onDrop) {
|
|
1370
|
+
return (value) => {
|
|
1371
|
+
if (typeof ack !== "function") {
|
|
1372
|
+
onDrop({ reason: "no-ack" });
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
try {
|
|
1376
|
+
ack(value);
|
|
1377
|
+
} catch (error) {
|
|
1378
|
+
onDrop({ reason: "ack-threw", error });
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1382
|
+
async function answerSocketRequest(ack, run, onDrop) {
|
|
1383
|
+
let value;
|
|
1384
|
+
try {
|
|
1385
|
+
value = await run();
|
|
1386
|
+
} catch (error) {
|
|
1387
|
+
onDrop({ reason: "handler-threw", error });
|
|
1388
|
+
return;
|
|
1389
|
+
}
|
|
1390
|
+
safeAck(ack, onDrop)(value);
|
|
1363
1391
|
}
|
|
1364
1392
|
|
|
1365
1393
|
function run$1(args, options) {
|
|
@@ -3052,13 +3080,18 @@ async function notifyDaemonTurnEvent(sessionId, event) {
|
|
|
3052
3080
|
async function stopDaemonHttp() {
|
|
3053
3081
|
await daemonPost("/stop");
|
|
3054
3082
|
}
|
|
3055
|
-
async function pushClipboardViaDaemon(text) {
|
|
3056
|
-
const result = await daemonPost("/clipboard", { text });
|
|
3083
|
+
async function pushClipboardViaDaemon(text, terminalId) {
|
|
3084
|
+
const result = await daemonPost("/clipboard", { text, ...terminalId ? { terminalId } : {} });
|
|
3057
3085
|
if (result?.error && result.delivered === void 0) {
|
|
3058
3086
|
return { delivered: false, error: result.error };
|
|
3059
3087
|
}
|
|
3060
3088
|
return result;
|
|
3061
3089
|
}
|
|
3090
|
+
async function pushFilePreviewViaDaemon(terminalId, path, mode = "file") {
|
|
3091
|
+
const result = await daemonPost("/file-preview", { terminalId, path, mode });
|
|
3092
|
+
if (result?.error) return { delivered: false, error: result.error };
|
|
3093
|
+
return { delivered: result?.delivered === true, ...result?.delivered === true ? {} : { error: "preview was not delivered" } };
|
|
3094
|
+
}
|
|
3062
3095
|
async function setTerminalTitleViaDaemon(terminalId, title, ifAbsent = false) {
|
|
3063
3096
|
const result = await daemonPost("/terminal-title", { terminalId, title, ifAbsent });
|
|
3064
3097
|
if (result?.error) {
|
|
@@ -3259,7 +3292,11 @@ class ApiSessionClient extends EventEmitter {
|
|
|
3259
3292
|
void this.connectSessionRelay();
|
|
3260
3293
|
});
|
|
3261
3294
|
this.socket.on("rpc-request", async (data, callback) => {
|
|
3262
|
-
|
|
3295
|
+
await answerSocketRequest(
|
|
3296
|
+
callback,
|
|
3297
|
+
() => this.rpcHandlerManager.handleRequest(data),
|
|
3298
|
+
(drop) => logger.debug(`[API] RPC ${data?.method} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
|
|
3299
|
+
);
|
|
3263
3300
|
});
|
|
3264
3301
|
this.socket.on("disconnect", (reason) => {
|
|
3265
3302
|
logger.debug(`[API] Socket disconnected: ${reason}`);
|
|
@@ -3695,9 +3732,14 @@ class ApiSessionClient extends EventEmitter {
|
|
|
3695
3732
|
logger.debug(`[API] Session connected to regional relay ${assignment.relayId}`);
|
|
3696
3733
|
});
|
|
3697
3734
|
relaySocket.on("rpc-request", async (data, callback) => {
|
|
3698
|
-
|
|
3735
|
+
await answerSocketRequest(
|
|
3736
|
+
callback,
|
|
3737
|
+
() => this.rpcHandlerManager.handleRequest(data),
|
|
3738
|
+
(drop) => logger.debug(`[API] Relay RPC ${data?.method} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
|
|
3739
|
+
);
|
|
3699
3740
|
});
|
|
3700
|
-
relaySocket.on("session-message-deliver", async (data,
|
|
3741
|
+
relaySocket.on("session-message-deliver", async (data, rawCallback) => {
|
|
3742
|
+
const callback = safeAck(rawCallback, (drop) => logger.debug(`[API] session-message-deliver unanswered \u2014 ${describeSocketAckDrop(drop)}`));
|
|
3701
3743
|
if (data?.sessionId !== this.sessionId || !Array.isArray(data.messages) || data.messages.length === 0 || data.messages.length > 50) {
|
|
3702
3744
|
callback({ ok: false, error: "Invalid session message request" });
|
|
3703
3745
|
return;
|
|
@@ -3998,12 +4040,15 @@ class ApiSessionClient extends EventEmitter {
|
|
|
3998
4040
|
*/
|
|
3999
4041
|
pushClipboard(text) {
|
|
4000
4042
|
const prepared = prepareClipboardText(text);
|
|
4043
|
+
const history = prepareClipboardHistoryText(text);
|
|
4001
4044
|
if (!this.socket.connected) {
|
|
4002
4045
|
return { delivered: false, truncated: prepared.truncated, totalBytes: prepared.totalBytes };
|
|
4003
4046
|
}
|
|
4004
4047
|
this.socket.emit("clipboard-push", {
|
|
4005
4048
|
payload: encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, prepared.text)),
|
|
4006
4049
|
enc: true,
|
|
4050
|
+
historyPayload: encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, history.text)),
|
|
4051
|
+
historyTruncated: history.truncated,
|
|
4007
4052
|
truncated: prepared.truncated,
|
|
4008
4053
|
totalBytes: prepared.totalBytes
|
|
4009
4054
|
});
|
|
@@ -14818,19 +14863,34 @@ class ApiMachineClient {
|
|
|
14818
14863
|
* (terminal-path claude → `very-happy mcp` → daemon /clipboard → here).
|
|
14819
14864
|
* Encrypted with the per-machine key; the server relays without reading.
|
|
14820
14865
|
*/
|
|
14821
|
-
pushClipboard(text) {
|
|
14866
|
+
pushClipboard(text, terminalId) {
|
|
14822
14867
|
const prepared = prepareClipboardText(text);
|
|
14868
|
+
const history = prepareClipboardHistoryText(text);
|
|
14823
14869
|
if (!this.socket?.connected) {
|
|
14824
14870
|
return { delivered: false, truncated: prepared.truncated, totalBytes: prepared.totalBytes, error: "daemon is not connected to the server" };
|
|
14825
14871
|
}
|
|
14826
14872
|
this.socket.emit("clipboard-push", {
|
|
14873
|
+
...terminalId ? { terminalId } : {},
|
|
14827
14874
|
payload: encodeBase64(encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, prepared.text)),
|
|
14828
14875
|
enc: true,
|
|
14876
|
+
historyPayload: encodeBase64(encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, history.text)),
|
|
14877
|
+
historyTruncated: history.truncated,
|
|
14829
14878
|
truncated: prepared.truncated,
|
|
14830
14879
|
totalBytes: prepared.totalBytes
|
|
14831
14880
|
});
|
|
14832
14881
|
return { delivered: true, truncated: prepared.truncated, totalBytes: prepared.totalBytes };
|
|
14833
14882
|
}
|
|
14883
|
+
/** Queue a terminal preview with the machine key. Delivery does not prove a browser opened it. */
|
|
14884
|
+
pushFilePreview(terminalId, path, mode = "file") {
|
|
14885
|
+
if (!this.socket?.connected) return { delivered: false, error: "daemon is not connected to the server" };
|
|
14886
|
+
this.socket.emit("file-preview-push", {
|
|
14887
|
+
terminalId,
|
|
14888
|
+
payload: encodeBase64(encrypt(this.machine.encryptionKey, this.machine.encryptionVariant, path)),
|
|
14889
|
+
enc: true,
|
|
14890
|
+
mode
|
|
14891
|
+
});
|
|
14892
|
+
return { delivered: true };
|
|
14893
|
+
}
|
|
14834
14894
|
/** Encrypt one base64 terminal payload with the per-machine key (same scheme
|
|
14835
14895
|
* as the live output stream) → base64 ciphertext. Used for both live output
|
|
14836
14896
|
* and the open-terminal snapshot/replay payloads. */
|
|
@@ -15712,7 +15772,11 @@ class ApiMachineClient {
|
|
|
15712
15772
|
bindRpcRequestHandler(socket, transport) {
|
|
15713
15773
|
socket.on("rpc-request", async (data, callback) => {
|
|
15714
15774
|
logger.debugLargeJson(`[API MACHINE] Received RPC request via ${transport}:`, data);
|
|
15715
|
-
|
|
15775
|
+
await answerSocketRequest(
|
|
15776
|
+
callback,
|
|
15777
|
+
() => this.rpcHandlerManager.handleRequest(data),
|
|
15778
|
+
(drop) => logger.debug(`[API MACHINE] RPC ${data?.method} via ${transport} unanswered \u2014 ${describeSocketAckDrop(drop)}`)
|
|
15779
|
+
);
|
|
15716
15780
|
});
|
|
15717
15781
|
}
|
|
15718
15782
|
bindMachineCommandHandlers(socket) {
|
|
@@ -16916,4 +16980,4 @@ const RawJSONLinesSchema = z$1.discriminatedUnion("type", [
|
|
|
16916
16980
|
}).passthrough()
|
|
16917
16981
|
]);
|
|
16918
16982
|
|
|
16919
|
-
export { shellescape as $, ApiClient as A, BUILTIN_TODO_SKILL as B, getLocalHappyAgentCredentialPath as C, readLocalHappyAgentCredentials as D, parseExactVersion as E, compareExactVersions as F, extractCompleteLines as G, decideBackfill as H, InvalidateSync as I, parseTerminalHookPayload as J, tmuxArgs as K, scrubTmuxClientEnv as L, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, decideMirrorBinding as N, MIRROR_BACKFILL_LINES_DEFAULT as O, mirrorLineKey as P, mirrorLocalId as Q, RawJSONLinesSchema as R, STREAM_DELTA_MAX_CHARS as S, listDaemonSessions as T, stopDaemonSession as U, detectCLIAvailability as V, detectResumeSupport as W, isDaemonRunningCurrentlyInstalledHappyVersion as X, stopDaemon as Y, TurnActivityTracker as Z, summarizeSpawnSessionForLog as _, ApiSessionClient as a, fetchCliUpdateState as a0, resolveCliUpdateCheckInterval as a1, DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS as a2, cleanupDaemonState as a3, listVhTerminals as a4, isValidTerminalId as a5, readVhTerminal as a6, sendToVhTerminal as a7, ContextUsageSchema as a8, TITLE_PROMPT_PREFIX as a9, BOARD_ANALYZER_PROMPT_PREFIX as aa, startOfflineReconnection as ab, CodexAppServerClient as ac, api as ad, streamKeyOf as b, checkIfDaemonRunningAndCleanupStaleState as c, createEnvelope as d, createBuiltinTodoClient as e,
|
|
16983
|
+
export { shellescape as $, ApiClient as A, BUILTIN_TODO_SKILL as B, getLocalHappyAgentCredentialPath as C, readLocalHappyAgentCredentials as D, parseExactVersion as E, compareExactVersions as F, extractCompleteLines as G, decideBackfill as H, InvalidateSync as I, parseTerminalHookPayload as J, tmuxArgs as K, scrubTmuxClientEnv as L, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, decideMirrorBinding as N, MIRROR_BACKFILL_LINES_DEFAULT as O, mirrorLineKey as P, mirrorLocalId as Q, RawJSONLinesSchema as R, STREAM_DELTA_MAX_CHARS as S, listDaemonSessions as T, stopDaemonSession as U, detectCLIAvailability as V, detectResumeSupport as W, isDaemonRunningCurrentlyInstalledHappyVersion as X, stopDaemon as Y, TurnActivityTracker as Z, summarizeSpawnSessionForLog as _, ApiSessionClient as a, fetchCliUpdateState as a0, resolveCliUpdateCheckInterval as a1, DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS as a2, cleanupDaemonState as a3, listVhTerminals as a4, isValidTerminalId as a5, readVhTerminal as a6, sendToVhTerminal as a7, ContextUsageSchema as a8, TITLE_PROMPT_PREFIX as a9, BOARD_ANALYZER_PROMPT_PREFIX as aa, startOfflineReconnection as ab, CodexAppServerClient as ac, api as ad, streamKeyOf as b, checkIfDaemonRunningAndCleanupStaleState as c, createEnvelope as d, createBuiltinTodoClient as e, pushFilePreviewViaDaemon as f, setTerminalTitleViaDaemon as g, connectionState as h, isValidSessionId as i, BUILTIN_TODO_DISCOVERY as j, errorLogMetadata as k, contentLogMetadata as l, delay as m, notifyDaemonSessionStarted as n, notifyDaemonSessionEvent as o, pushClipboardViaDaemon as p, getProjectPath as q, initializeSandbox as r, spawnDaemonSession as s, AsyncLock as t, notifyDaemonClaudeAuthFailed as u, commandOnPath as v, wrapCommand as w, deriveLocalCliUpdateSummary as x, AGENT_VERSION_SOURCES as y, isClaudeSessionId as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "very-happy-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.143",
|
|
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": [
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
"module": "./dist/index.mjs",
|
|
26
26
|
"types": "./dist/index.d.cts",
|
|
27
27
|
"exports": {
|
|
28
|
+
"./pi-extension": {
|
|
29
|
+
"types": "./dist/piExtension.d.mts",
|
|
30
|
+
"default": "./dist/piExtension.mjs"
|
|
31
|
+
},
|
|
28
32
|
".": {
|
|
29
33
|
"require": {
|
|
30
34
|
"types": "./dist/index.d.cts",
|
|
@@ -113,12 +117,12 @@
|
|
|
113
117
|
"zod": "^4.0.0"
|
|
114
118
|
},
|
|
115
119
|
"optionalDependencies": {
|
|
116
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
117
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
118
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
119
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
120
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
121
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
120
|
+
"very-happy-tools-arm64-darwin": "0.2.143",
|
|
121
|
+
"very-happy-tools-x64-darwin": "0.2.143",
|
|
122
|
+
"very-happy-tools-arm64-linux": "0.2.143",
|
|
123
|
+
"very-happy-tools-x64-linux": "0.2.143",
|
|
124
|
+
"very-happy-tools-arm64-win32": "0.2.143",
|
|
125
|
+
"very-happy-tools-x64-win32": "0.2.143"
|
|
122
126
|
},
|
|
123
127
|
"devDependencies": {
|
|
124
128
|
"@slopus/happy-wire": "workspace:*",
|