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.
Files changed (57) hide show
  1. package/dist/{AcpBackend-CnWSwaHk.cjs → AcpBackend-B8oehrfU.cjs} +2 -2
  2. package/dist/{AcpBackend-CWmjboOm.mjs → AcpBackend-LEgn9vol.mjs} +2 -2
  3. package/dist/{AcpSessionManager-Dxt78rPO.cjs → AcpSessionManager-BomdfyhZ.cjs} +1 -1
  4. package/dist/{AcpSessionManager-CtXoi6PN.mjs → AcpSessionManager-Yfbs5bi2.mjs} +1 -1
  5. package/dist/{agentGuidance-Do7cQka3.mjs → agentGuidance-BU4hxm8M.mjs} +1 -1
  6. package/dist/{agentGuidance-B9ENxSaS.cjs → agentGuidance-CJSl54ua.cjs} +1 -1
  7. package/dist/codex/happyMcpStdioBridge.cjs +2 -2
  8. package/dist/codex/happyMcpStdioBridge.mjs +2 -2
  9. package/dist/{config-Dn7nAHcA.cjs → config-CfqWoHmO.cjs} +5 -4
  10. package/dist/{config-DY57frJF.mjs → config-euZ_K5Lo.mjs} +5 -4
  11. package/dist/{index-BSVgut_Y.cjs → index-BREtikhm.cjs} +5 -4
  12. package/dist/{index-3STVDtNO.cjs → index-Bj68y6ee.cjs} +12 -40
  13. package/dist/{index-ChWePQEd.cjs → index-C510dSUn.cjs} +188 -132
  14. package/dist/{index-C55sW8E9.mjs → index-DoiG88oX.mjs} +169 -114
  15. package/dist/{index-DhfgAB8K.mjs → index-PM_SsRpw.mjs} +5 -4
  16. package/dist/{index-Dz6FgNFg.mjs → index-ZOMC8Gzn.mjs} +11 -39
  17. package/dist/index.cjs +7 -6
  18. package/dist/index.mjs +7 -6
  19. package/dist/installPiTools-BKnXjrVu.cjs +82 -0
  20. package/dist/installPiTools-C-Lxv4Bt.mjs +77 -0
  21. package/dist/{installTerminalHooks-zmtIrf3E.mjs → installTerminalHooks-BGVQqbgq.mjs} +8 -7
  22. package/dist/{installTerminalHooks--jkP17uE.cjs → installTerminalHooks-C_jraM1j.cjs} +9 -8
  23. package/dist/lib.cjs +3 -2
  24. package/dist/lib.d.cts +6 -1
  25. package/dist/lib.d.mts +6 -1
  26. package/dist/lib.mjs +3 -2
  27. package/dist/{limits-DbLWXlJm.cjs → limits-B3oVgqBJ.cjs} +29 -10
  28. package/dist/{limits-DT5Yk_UH.mjs → limits-uABU-yq3.mjs} +29 -11
  29. package/dist/{mcp-Bzy-X9kI.mjs → mcp-CfbTQXyh.mjs} +28 -14
  30. package/dist/{mcp-kE0n1dBF.cjs → mcp-G-3lL_KH.cjs} +29 -15
  31. package/dist/piExtension.d.mts +17 -0
  32. package/dist/piExtension.mjs +84 -0
  33. package/dist/piRuntime-BE6iYQwU.mjs +37 -0
  34. package/dist/piRuntime-CWE-1W-y.cjs +39 -0
  35. package/dist/piTerminal-Dyc_9pGP.cjs +132 -0
  36. package/dist/piTerminal-rqKn1_Zy.mjs +129 -0
  37. package/dist/projectPath-CSpqWdxp.mjs +10 -0
  38. package/dist/projectPath-ChLhdOyt.cjs +13 -0
  39. package/dist/{runGemini-BmdhYEzM.mjs → runGemini-BMlXIaTL.mjs} +8 -7
  40. package/dist/{runGemini-CxUz95A1.cjs → runGemini-C6qMFzcn.cjs} +9 -8
  41. package/dist/{runOpenClaw-RLIFJx61.cjs → runOpenClaw-C2_aCP7v.cjs} +6 -5
  42. package/dist/{runOpenClaw-CYpO3Vv8.mjs → runOpenClaw-CoO5Vp3S.mjs} +6 -5
  43. package/dist/{send-DT04hV8o.mjs → send-CBrJylJc.mjs} +5 -4
  44. package/dist/{send-BGcCrMUT.cjs → send-DGVwmB-p.cjs} +5 -4
  45. package/dist/{sessions-DDWTq2AG.mjs → sessions-DbLubh2N.mjs} +7 -6
  46. package/dist/{sessions-Jt9lrcrG.cjs → sessions-DyQXMN-8.cjs} +7 -6
  47. package/dist/{spawn-CdZgvthE.cjs → spawn-DIyFOn3W.cjs} +5 -4
  48. package/dist/{spawn-Ca0A70dX.mjs → spawn-wkkxEGdF.mjs} +5 -4
  49. package/dist/{teams-CzK1zg0m.mjs → teams-BTyVFK3P.mjs} +5 -4
  50. package/dist/{teams-DfVwVZ4x.cjs → teams-QOkGFjkJ.cjs} +5 -4
  51. package/dist/terminalToolContext-CFeGeaNm.mjs +7 -0
  52. package/dist/terminalToolContext-DoV9Gs7K.cjs +9 -0
  53. package/dist/{todo-4WhOom8k.mjs → todo-DoLkqdBe.mjs} +4 -3
  54. package/dist/{todo-D9nFaYpQ.cjs → todo-Du6pjwx_.cjs} +4 -3
  55. package/dist/{types-Bk3W89Z3.cjs → types-6__wqmmP.cjs} +80 -17
  56. package/dist/{types-CLosaeZT.mjs → types-BG4gFjLL.mjs} +79 -15
  57. package/package.json +11 -7
package/dist/index.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  require('chalk');
4
- require('./index-ChWePQEd.cjs');
5
- require('./limits-DbLWXlJm.cjs');
4
+ require('./index-C510dSUn.cjs');
5
+ require('./limits-B3oVgqBJ.cjs');
6
6
  require('zod');
7
- require('./types-Bk3W89Z3.cjs');
7
+ require('./types-6__wqmmP.cjs');
8
8
  require('node:child_process');
9
9
  require('node:os');
10
10
  require('node:crypto');
@@ -12,7 +12,10 @@ require('cross-spawn');
12
12
  require('node:path');
13
13
  require('node:readline');
14
14
  require('node:fs');
15
- require('./agentGuidance-B9ENxSaS.cjs');
15
+ require('./projectPath-ChLhdOyt.cjs');
16
+ require('path');
17
+ require('url');
18
+ require('./agentGuidance-CJSl54ua.cjs');
16
19
  require('node:fs/promises');
17
20
  require('fs/promises');
18
21
  require('ink');
@@ -26,7 +29,6 @@ require('os');
26
29
  require('child_process');
27
30
  require('@paralleldrive/cuid2');
28
31
  require('fs');
29
- require('path');
30
32
  require('@anthropic-ai/sandbox-runtime');
31
33
  require('expo-server-sdk');
32
34
  require('crypto');
@@ -45,6 +47,5 @@ require('util');
45
47
  require('inquirer');
46
48
  require('node:url');
47
49
  require('node:readline/promises');
48
- require('url');
49
50
  require('node-pty');
50
51
 
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import 'chalk';
2
- import './index-C55sW8E9.mjs';
3
- import './limits-DT5Yk_UH.mjs';
2
+ import './index-DoiG88oX.mjs';
3
+ import './limits-uABU-yq3.mjs';
4
4
  import 'zod';
5
- import './types-CLosaeZT.mjs';
5
+ import './types-BG4gFjLL.mjs';
6
6
  import 'node:child_process';
7
7
  import 'node:os';
8
8
  import 'node:crypto';
@@ -10,7 +10,10 @@ import 'cross-spawn';
10
10
  import 'node:path';
11
11
  import 'node:readline';
12
12
  import 'node:fs';
13
- import './agentGuidance-Do7cQka3.mjs';
13
+ import './projectPath-CSpqWdxp.mjs';
14
+ import 'path';
15
+ import 'url';
16
+ import './agentGuidance-BU4hxm8M.mjs';
14
17
  import 'node:fs/promises';
15
18
  import 'fs/promises';
16
19
  import 'ink';
@@ -24,7 +27,6 @@ import 'os';
24
27
  import 'child_process';
25
28
  import '@paralleldrive/cuid2';
26
29
  import 'fs';
27
- import 'path';
28
30
  import '@anthropic-ai/sandbox-runtime';
29
31
  import 'expo-server-sdk';
30
32
  import 'crypto';
@@ -43,5 +45,4 @@ import 'util';
43
45
  import 'inquirer';
44
46
  import 'node:url';
45
47
  import 'node:readline/promises';
46
- import 'url';
47
48
  import 'node-pty';
@@ -0,0 +1,82 @@
1
+ 'use strict';
2
+
3
+ var promises = require('node:fs/promises');
4
+ var os = require('node:os');
5
+ var path = require('node:path');
6
+ var node_url = require('node:url');
7
+ var node_crypto = require('node:crypto');
8
+ var projectPath = require('./projectPath-ChLhdOyt.cjs');
9
+ require('path');
10
+ require('url');
11
+
12
+ const HEADER = "// Managed by Very Happy: native Pi terminal tools.\n";
13
+ const PI_TOOLS_HELP = `very-happy install-pi-tools - enable tools in native Pi
14
+
15
+ Usage:
16
+ very-happy install-pi-tools
17
+ very-happy install-pi-tools --remove
18
+
19
+ Installs one extension in ~/.pi/agent/extensions (or $PI_CODING_AGENT_DIR/extensions).
20
+ Then run pi directly inside a Very Happy terminal, or /reload an existing Pi.
21
+ It provides change_title, copy_to_clipboard and open_preview through that terminal's
22
+ daemon. Outside a Very Happy terminal it does nothing. Pi settings and other
23
+ extensions are preserved. Managed Pi uses its existing session tools instead.`;
24
+ function piToolsLoader(extensionPath) {
25
+ return `${HEADER}export { default } from ${JSON.stringify(node_url.pathToFileURL(extensionPath).href)};
26
+ `;
27
+ }
28
+ function isOwnedLoader(content) {
29
+ if (!content.startsWith(HEADER)) return false;
30
+ const match = /^export \{ default \} from ("[^\n]+");\n$/.exec(content.slice(HEADER.length));
31
+ if (!match) return false;
32
+ try {
33
+ return new URL(JSON.parse(match[1])).protocol === "file:";
34
+ } catch {
35
+ return false;
36
+ }
37
+ }
38
+ async function installPiTools(remove = false) {
39
+ const agentDir = process.env.PI_CODING_AGENT_DIR?.replace(/^~(?=\/|$)/, os.homedir()) || path.join(os.homedir(), ".pi", "agent");
40
+ const target = path.resolve(agentDir, "extensions", "very-happy-terminal-tools.js");
41
+ try {
42
+ const stat = await promises.lstat(target);
43
+ if (!stat.isFile() || !isOwnedLoader(await promises.readFile(target, "utf8"))) {
44
+ throw new Error(`Refusing to overwrite or remove a custom extension: ${target}`);
45
+ }
46
+ } catch (error) {
47
+ if (error.code !== "ENOENT") throw error;
48
+ if (remove) return target;
49
+ }
50
+ if (remove) {
51
+ await promises.unlink(target);
52
+ return target;
53
+ }
54
+ const content = piToolsLoader(path.resolve(projectPath.projectPath(), "dist/piExtension.mjs"));
55
+ await promises.mkdir(path.dirname(target), { recursive: true, mode: 448 });
56
+ const temporary = `${target}.${node_crypto.randomUUID()}.new`;
57
+ try {
58
+ await promises.writeFile(temporary, content, { flag: "wx", mode: 384 });
59
+ await promises.rename(temporary, target);
60
+ } finally {
61
+ await promises.unlink(temporary).catch((error) => {
62
+ if (error.code !== "ENOENT") throw error;
63
+ });
64
+ }
65
+ return target;
66
+ }
67
+ async function handleInstallPiTools(args) {
68
+ if (args.includes("--help") || args.includes("-h")) {
69
+ console.log(PI_TOOLS_HELP);
70
+ return;
71
+ }
72
+ if (args.some((arg) => arg !== "--remove")) throw new Error("Unknown install-pi-tools option");
73
+ const remove = args.includes("--remove");
74
+ const target = await installPiTools(remove);
75
+ console.log(`${remove ? "Removed" : "Installed"} Very Happy Pi tools: ${target}`);
76
+ if (!remove) console.log("Run pi inside a Very Happy terminal, or use /reload in an existing Pi session.");
77
+ }
78
+
79
+ exports.PI_TOOLS_HELP = PI_TOOLS_HELP;
80
+ exports.handleInstallPiTools = handleInstallPiTools;
81
+ exports.installPiTools = installPiTools;
82
+ exports.piToolsLoader = piToolsLoader;
@@ -0,0 +1,77 @@
1
+ import { lstat, readFile, unlink, mkdir, writeFile, rename } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { join, resolve, dirname } from 'node:path';
4
+ import { pathToFileURL } from 'node:url';
5
+ import { randomUUID } from 'node:crypto';
6
+ import { p as projectPath } from './projectPath-CSpqWdxp.mjs';
7
+ import 'path';
8
+ import 'url';
9
+
10
+ const HEADER = "// Managed by Very Happy: native Pi terminal tools.\n";
11
+ const PI_TOOLS_HELP = `very-happy install-pi-tools - enable tools in native Pi
12
+
13
+ Usage:
14
+ very-happy install-pi-tools
15
+ very-happy install-pi-tools --remove
16
+
17
+ Installs one extension in ~/.pi/agent/extensions (or $PI_CODING_AGENT_DIR/extensions).
18
+ Then run pi directly inside a Very Happy terminal, or /reload an existing Pi.
19
+ It provides change_title, copy_to_clipboard and open_preview through that terminal's
20
+ daemon. Outside a Very Happy terminal it does nothing. Pi settings and other
21
+ extensions are preserved. Managed Pi uses its existing session tools instead.`;
22
+ function piToolsLoader(extensionPath) {
23
+ return `${HEADER}export { default } from ${JSON.stringify(pathToFileURL(extensionPath).href)};
24
+ `;
25
+ }
26
+ function isOwnedLoader(content) {
27
+ if (!content.startsWith(HEADER)) return false;
28
+ const match = /^export \{ default \} from ("[^\n]+");\n$/.exec(content.slice(HEADER.length));
29
+ if (!match) return false;
30
+ try {
31
+ return new URL(JSON.parse(match[1])).protocol === "file:";
32
+ } catch {
33
+ return false;
34
+ }
35
+ }
36
+ async function installPiTools(remove = false) {
37
+ const agentDir = process.env.PI_CODING_AGENT_DIR?.replace(/^~(?=\/|$)/, homedir()) || join(homedir(), ".pi", "agent");
38
+ const target = resolve(agentDir, "extensions", "very-happy-terminal-tools.js");
39
+ try {
40
+ const stat = await lstat(target);
41
+ if (!stat.isFile() || !isOwnedLoader(await readFile(target, "utf8"))) {
42
+ throw new Error(`Refusing to overwrite or remove a custom extension: ${target}`);
43
+ }
44
+ } catch (error) {
45
+ if (error.code !== "ENOENT") throw error;
46
+ if (remove) return target;
47
+ }
48
+ if (remove) {
49
+ await unlink(target);
50
+ return target;
51
+ }
52
+ const content = piToolsLoader(resolve(projectPath(), "dist/piExtension.mjs"));
53
+ await mkdir(dirname(target), { recursive: true, mode: 448 });
54
+ const temporary = `${target}.${randomUUID()}.new`;
55
+ try {
56
+ await writeFile(temporary, content, { flag: "wx", mode: 384 });
57
+ await rename(temporary, target);
58
+ } finally {
59
+ await unlink(temporary).catch((error) => {
60
+ if (error.code !== "ENOENT") throw error;
61
+ });
62
+ }
63
+ return target;
64
+ }
65
+ async function handleInstallPiTools(args) {
66
+ if (args.includes("--help") || args.includes("-h")) {
67
+ console.log(PI_TOOLS_HELP);
68
+ return;
69
+ }
70
+ if (args.some((arg) => arg !== "--remove")) throw new Error("Unknown install-pi-tools option");
71
+ const remove = args.includes("--remove");
72
+ const target = await installPiTools(remove);
73
+ console.log(`${remove ? "Removed" : "Installed"} Very Happy Pi tools: ${target}`);
74
+ if (!remove) console.log("Run pi inside a Very Happy terminal, or use /reload in an existing Pi session.");
75
+ }
76
+
77
+ export { PI_TOOLS_HELP, handleInstallPiTools, installPiTools, piToolsLoader };
@@ -3,13 +3,16 @@ import { join, resolve } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
4
  import { spawnSync } from 'node:child_process';
5
5
  import chalk from 'chalk';
6
- import { p as projectPath } from './types-CLosaeZT.mjs';
7
- import { t as tmuxSupportsSessionEnv } from './index-C55sW8E9.mjs';
6
+ import { p as projectPath } from './projectPath-CSpqWdxp.mjs';
7
+ import { t as tmuxSupportsSessionEnv } from './index-DoiG88oX.mjs';
8
+ import 'path';
9
+ import 'url';
10
+ import 'node:crypto';
11
+ import './types-BG4gFjLL.mjs';
8
12
  import 'axios';
9
- import './limits-DT5Yk_UH.mjs';
13
+ import './limits-uABU-yq3.mjs';
10
14
  import 'node:fs/promises';
11
15
  import 'zod';
12
- import 'node:crypto';
13
16
  import 'tweetnacl';
14
17
  import 'node:util';
15
18
  import 'node:events';
@@ -19,16 +22,14 @@ import 'child_process';
19
22
  import 'util';
20
23
  import 'fs/promises';
21
24
  import 'crypto';
22
- import 'path';
23
25
  import 'cross-spawn';
24
- import 'url';
25
26
  import 'os';
26
27
  import 'node-pty';
27
28
  import 'fs';
28
29
  import 'node:readline';
29
30
  import '@anthropic-ai/sandbox-runtime';
30
31
  import 'expo-server-sdk';
31
- import './agentGuidance-Do7cQka3.mjs';
32
+ import './agentGuidance-BU4hxm8M.mjs';
32
33
  import 'ink';
33
34
  import 'react';
34
35
  import '@anthropic-ai/claude-agent-sdk';
@@ -5,13 +5,16 @@ var path = require('node:path');
5
5
  var os = require('node:os');
6
6
  var node_child_process = require('node:child_process');
7
7
  var chalk = require('chalk');
8
- var api = require('./types-Bk3W89Z3.cjs');
9
- var index = require('./index-ChWePQEd.cjs');
8
+ var projectPath = require('./projectPath-ChLhdOyt.cjs');
9
+ var index = require('./index-C510dSUn.cjs');
10
+ require('path');
11
+ require('url');
12
+ require('node:crypto');
13
+ require('./types-6__wqmmP.cjs');
10
14
  require('axios');
11
- require('./limits-DbLWXlJm.cjs');
15
+ require('./limits-B3oVgqBJ.cjs');
12
16
  require('node:fs/promises');
13
17
  require('zod');
14
- require('node:crypto');
15
18
  require('tweetnacl');
16
19
  require('node:util');
17
20
  require('node:events');
@@ -21,16 +24,14 @@ require('child_process');
21
24
  require('util');
22
25
  require('fs/promises');
23
26
  require('crypto');
24
- require('path');
25
27
  require('cross-spawn');
26
- require('url');
27
28
  require('os');
28
29
  require('node-pty');
29
30
  require('fs');
30
31
  require('node:readline');
31
32
  require('@anthropic-ai/sandbox-runtime');
32
33
  require('expo-server-sdk');
33
- require('./agentGuidance-B9ENxSaS.cjs');
34
+ require('./agentGuidance-CJSl54ua.cjs');
34
35
  require('ink');
35
36
  require('react');
36
37
  require('@anthropic-ai/claude-agent-sdk');
@@ -152,7 +153,7 @@ function claudeSettingsPath() {
152
153
  return path.join(configDir, "settings.json");
153
154
  }
154
155
  function terminalMirrorHookCommand() {
155
- const script = path.resolve(api.projectPath(), "scripts", TERMINAL_MIRROR_FORWARDER_BASENAME);
156
+ const script = path.resolve(projectPath.projectPath(), "scripts", TERMINAL_MIRROR_FORWARDER_BASENAME);
156
157
  return `[ -f "${script}" ] && node "${script}" || true`;
157
158
  }
158
159
  async function installTerminalHooks(opts = {}) {
package/dist/lib.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var api = require('./types-Bk3W89Z3.cjs');
4
- var persistence = require('./limits-DbLWXlJm.cjs');
3
+ var api = require('./types-6__wqmmP.cjs');
4
+ var persistence = require('./limits-B3oVgqBJ.cjs');
5
5
  require('axios');
6
6
  require('node:events');
7
7
  require('socket.io-client');
@@ -14,6 +14,7 @@ require('fs/promises');
14
14
  require('crypto');
15
15
  require('path');
16
16
  require('cross-spawn');
17
+ require('./projectPath-ChLhdOyt.cjs');
17
18
  require('url');
18
19
  require('os');
19
20
  require('node:fs/promises');
package/dist/lib.d.cts CHANGED
@@ -1360,12 +1360,17 @@ declare class ApiMachineClient {
1360
1360
  * (terminal-path claude → `very-happy mcp` → daemon /clipboard → here).
1361
1361
  * Encrypted with the per-machine key; the server relays without reading.
1362
1362
  */
1363
- pushClipboard(text: string): {
1363
+ pushClipboard(text: string, terminalId?: string): {
1364
1364
  delivered: boolean;
1365
1365
  truncated: boolean;
1366
1366
  totalBytes: number;
1367
1367
  error?: string;
1368
1368
  };
1369
+ /** Queue a terminal preview with the machine key. Delivery does not prove a browser opened it. */
1370
+ pushFilePreview(terminalId: string, path: string, mode?: 'file' | 'diff'): {
1371
+ delivered: boolean;
1372
+ error?: string;
1373
+ };
1369
1374
  /** Encrypt one base64 terminal payload with the per-machine key (same scheme
1370
1375
  * as the live output stream) → base64 ciphertext. Used for both live output
1371
1376
  * and the open-terminal snapshot/replay payloads. */
package/dist/lib.d.mts CHANGED
@@ -1360,12 +1360,17 @@ declare class ApiMachineClient {
1360
1360
  * (terminal-path claude → `very-happy mcp` → daemon /clipboard → here).
1361
1361
  * Encrypted with the per-machine key; the server relays without reading.
1362
1362
  */
1363
- pushClipboard(text: string): {
1363
+ pushClipboard(text: string, terminalId?: string): {
1364
1364
  delivered: boolean;
1365
1365
  truncated: boolean;
1366
1366
  totalBytes: number;
1367
1367
  error?: string;
1368
1368
  };
1369
+ /** Queue a terminal preview with the machine key. Delivery does not prove a browser opened it. */
1370
+ pushFilePreview(terminalId: string, path: string, mode?: 'file' | 'diff'): {
1371
+ delivered: boolean;
1372
+ error?: string;
1373
+ };
1369
1374
  /** Encrypt one base64 terminal payload with the per-machine key (same scheme
1370
1375
  * as the live output stream) → base64 ciphertext. Used for both live output
1371
1376
  * and the open-terminal snapshot/replay payloads. */
package/dist/lib.mjs CHANGED
@@ -1,5 +1,5 @@
1
- export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema } from './types-CLosaeZT.mjs';
2
- export { c as configuration, l as logger } from './limits-DT5Yk_UH.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, R as RawJSONLinesSchema } from './types-BG4gFjLL.mjs';
2
+ export { c as configuration, l as logger } from './limits-uABU-yq3.mjs';
3
3
  import 'axios';
4
4
  import 'node:events';
5
5
  import 'socket.io-client';
@@ -12,6 +12,7 @@ import 'fs/promises';
12
12
  import 'crypto';
13
13
  import 'path';
14
14
  import 'cross-spawn';
15
+ import './projectPath-CSpqWdxp.mjs';
15
16
  import 'url';
16
17
  import 'os';
17
18
  import 'node:fs/promises';
@@ -30,7 +30,7 @@ function _interopNamespaceDefault(e) {
30
30
  var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
31
31
 
32
32
  var name = "very-happy-cli";
33
- var version = "0.2.141";
33
+ var version = "0.2.143";
34
34
  var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
35
35
  var author = "Kirill Dubovitskiy";
36
36
  var contributors = [
@@ -55,6 +55,10 @@ var main = "./dist/index.cjs";
55
55
  var module$1 = "./dist/index.mjs";
56
56
  var types = "./dist/index.d.cts";
57
57
  var exports$1 = {
58
+ "./pi-extension": {
59
+ types: "./dist/piExtension.d.mts",
60
+ "default": "./dist/piExtension.mjs"
61
+ },
58
62
  ".": {
59
63
  require: {
60
64
  types: "./dist/index.d.cts",
@@ -143,12 +147,12 @@ var dependencies = {
143
147
  zod: "^4.0.0"
144
148
  };
145
149
  var optionalDependencies = {
146
- "very-happy-tools-arm64-darwin": "0.2.141",
147
- "very-happy-tools-x64-darwin": "0.2.141",
148
- "very-happy-tools-arm64-linux": "0.2.141",
149
- "very-happy-tools-x64-linux": "0.2.141",
150
- "very-happy-tools-arm64-win32": "0.2.141",
151
- "very-happy-tools-x64-win32": "0.2.141"
150
+ "very-happy-tools-arm64-darwin": "0.2.143",
151
+ "very-happy-tools-x64-darwin": "0.2.143",
152
+ "very-happy-tools-arm64-linux": "0.2.143",
153
+ "very-happy-tools-x64-linux": "0.2.143",
154
+ "very-happy-tools-arm64-win32": "0.2.143",
155
+ "very-happy-tools-x64-win32": "0.2.143"
152
156
  };
153
157
  var devDependencies = {
154
158
  "@slopus/happy-wire": "workspace:*",
@@ -1145,15 +1149,16 @@ var persistence = /*#__PURE__*/Object.freeze({
1145
1149
  });
1146
1150
 
1147
1151
  const CLIPBOARD_MAX_BYTES = 256 * 1024;
1152
+ const CLIPBOARD_HISTORY_MAX_BYTES = 32 * 1024;
1148
1153
  const CLIPBOARD_TOOL_NAME = "copy_to_clipboard";
1149
1154
  const CLIPBOARD_TOOL_TITLE = "Copy to User Clipboard";
1150
1155
  const CLIPBOARD_TOOL_DESCRIPTION = `Copy text to the clipboard of the device the user is currently viewing this session from (their web browser, possibly a phone). Use this whenever the user wants a piece of text handed to them \u2014 not only when they literally say "clipboard". Trigger phrases include: "copy X", "copy that for me", "give me X", "send me X", "I need X on my phone", "\u590D\u5236\u7ED9\u6211", "\u628A X \u590D\u5236\u4E00\u4E0B", "\u53D1\u6211", "\u7ED9\u6211\u4E00\u4EFD", "\u590D\u5236\u5230\u526A\u5207\u677F/\u526A\u8D34\u677F". Typical payloads: command output, code snippets, tokens/keys, URLs, file contents, commit messages. The text is delivered to every device where the user has the web client open. Payloads larger than ${CLIPBOARD_MAX_BYTES / 1024}KB are truncated.`;
1151
- function prepareClipboardText(input) {
1156
+ function prepareClipboardText(input, maxBytes = CLIPBOARD_MAX_BYTES) {
1152
1157
  const totalBytes = Buffer.byteLength(input, "utf8");
1153
- if (totalBytes <= CLIPBOARD_MAX_BYTES) {
1158
+ if (totalBytes <= maxBytes) {
1154
1159
  return { text: input, truncated: false, totalBytes };
1155
1160
  }
1156
- const sliced = Buffer.from(input, "utf8").subarray(0, CLIPBOARD_MAX_BYTES).toString("utf8");
1161
+ const sliced = Buffer.from(input, "utf8").subarray(0, maxBytes).toString("utf8");
1157
1162
  let text = sliced;
1158
1163
  if (text.endsWith("\uFFFD")) {
1159
1164
  text = text.slice(0, -1);
@@ -1164,6 +1169,19 @@ function prepareClipboardText(input) {
1164
1169
  }
1165
1170
  return { text, truncated: true, totalBytes };
1166
1171
  }
1172
+ function prepareClipboardHistoryText(input) {
1173
+ const prepared = prepareClipboardText(input, CLIPBOARD_HISTORY_MAX_BYTES);
1174
+ if (Buffer.byteLength(JSON.stringify(prepared.text), "utf8") <= CLIPBOARD_HISTORY_MAX_BYTES + 2) return prepared;
1175
+ let encodedBytes = 0;
1176
+ let text = "";
1177
+ for (const character of prepared.text) {
1178
+ const cost = Buffer.byteLength(JSON.stringify(character), "utf8") - 2;
1179
+ if (encodedBytes + cost > CLIPBOARD_HISTORY_MAX_BYTES) break;
1180
+ encodedBytes += cost;
1181
+ text += character;
1182
+ }
1183
+ return { text, truncated: true, totalBytes: prepared.totalBytes };
1184
+ }
1167
1185
 
1168
1186
  exports.CLIPBOARD_MAX_BYTES = CLIPBOARD_MAX_BYTES;
1169
1187
  exports.CLIPBOARD_TOOL_DESCRIPTION = CLIPBOARD_TOOL_DESCRIPTION;
@@ -1198,6 +1216,7 @@ exports.normalizeHttpEndpoint = normalizeHttpEndpoint;
1198
1216
  exports.packageJson = packageJson;
1199
1217
  exports.persistSession = persistSession;
1200
1218
  exports.persistence = persistence;
1219
+ exports.prepareClipboardHistoryText = prepareClipboardHistoryText;
1201
1220
  exports.prepareClipboardText = prepareClipboardText;
1202
1221
  exports.readCredentials = readCredentials;
1203
1222
  exports.readCredentialsForConfiguredRelay = readCredentialsForConfiguredRelay;
@@ -9,7 +9,7 @@ import chalk from 'chalk';
9
9
  import { inspect } from 'node:util';
10
10
 
11
11
  var name = "very-happy-cli";
12
- var version = "0.2.141";
12
+ var version = "0.2.143";
13
13
  var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
14
14
  var author = "Kirill Dubovitskiy";
15
15
  var contributors = [
@@ -34,6 +34,10 @@ var main = "./dist/index.cjs";
34
34
  var module$1 = "./dist/index.mjs";
35
35
  var types = "./dist/index.d.cts";
36
36
  var exports$1 = {
37
+ "./pi-extension": {
38
+ types: "./dist/piExtension.d.mts",
39
+ "default": "./dist/piExtension.mjs"
40
+ },
37
41
  ".": {
38
42
  require: {
39
43
  types: "./dist/index.d.cts",
@@ -122,12 +126,12 @@ var dependencies = {
122
126
  zod: "^4.0.0"
123
127
  };
124
128
  var optionalDependencies = {
125
- "very-happy-tools-arm64-darwin": "0.2.141",
126
- "very-happy-tools-x64-darwin": "0.2.141",
127
- "very-happy-tools-arm64-linux": "0.2.141",
128
- "very-happy-tools-x64-linux": "0.2.141",
129
- "very-happy-tools-arm64-win32": "0.2.141",
130
- "very-happy-tools-x64-win32": "0.2.141"
129
+ "very-happy-tools-arm64-darwin": "0.2.143",
130
+ "very-happy-tools-x64-darwin": "0.2.143",
131
+ "very-happy-tools-arm64-linux": "0.2.143",
132
+ "very-happy-tools-x64-linux": "0.2.143",
133
+ "very-happy-tools-arm64-win32": "0.2.143",
134
+ "very-happy-tools-x64-win32": "0.2.143"
131
135
  };
132
136
  var devDependencies = {
133
137
  "@slopus/happy-wire": "workspace:*",
@@ -1124,15 +1128,16 @@ var persistence = /*#__PURE__*/Object.freeze({
1124
1128
  });
1125
1129
 
1126
1130
  const CLIPBOARD_MAX_BYTES = 256 * 1024;
1131
+ const CLIPBOARD_HISTORY_MAX_BYTES = 32 * 1024;
1127
1132
  const CLIPBOARD_TOOL_NAME = "copy_to_clipboard";
1128
1133
  const CLIPBOARD_TOOL_TITLE = "Copy to User Clipboard";
1129
1134
  const CLIPBOARD_TOOL_DESCRIPTION = `Copy text to the clipboard of the device the user is currently viewing this session from (their web browser, possibly a phone). Use this whenever the user wants a piece of text handed to them \u2014 not only when they literally say "clipboard". Trigger phrases include: "copy X", "copy that for me", "give me X", "send me X", "I need X on my phone", "\u590D\u5236\u7ED9\u6211", "\u628A X \u590D\u5236\u4E00\u4E0B", "\u53D1\u6211", "\u7ED9\u6211\u4E00\u4EFD", "\u590D\u5236\u5230\u526A\u5207\u677F/\u526A\u8D34\u677F". Typical payloads: command output, code snippets, tokens/keys, URLs, file contents, commit messages. The text is delivered to every device where the user has the web client open. Payloads larger than ${CLIPBOARD_MAX_BYTES / 1024}KB are truncated.`;
1130
- function prepareClipboardText(input) {
1135
+ function prepareClipboardText(input, maxBytes = CLIPBOARD_MAX_BYTES) {
1131
1136
  const totalBytes = Buffer.byteLength(input, "utf8");
1132
- if (totalBytes <= CLIPBOARD_MAX_BYTES) {
1137
+ if (totalBytes <= maxBytes) {
1133
1138
  return { text: input, truncated: false, totalBytes };
1134
1139
  }
1135
- const sliced = Buffer.from(input, "utf8").subarray(0, CLIPBOARD_MAX_BYTES).toString("utf8");
1140
+ const sliced = Buffer.from(input, "utf8").subarray(0, maxBytes).toString("utf8");
1136
1141
  let text = sliced;
1137
1142
  if (text.endsWith("\uFFFD")) {
1138
1143
  text = text.slice(0, -1);
@@ -1143,5 +1148,18 @@ function prepareClipboardText(input) {
1143
1148
  }
1144
1149
  return { text, truncated: true, totalBytes };
1145
1150
  }
1151
+ function prepareClipboardHistoryText(input) {
1152
+ const prepared = prepareClipboardText(input, CLIPBOARD_HISTORY_MAX_BYTES);
1153
+ if (Buffer.byteLength(JSON.stringify(prepared.text), "utf8") <= CLIPBOARD_HISTORY_MAX_BYTES + 2) return prepared;
1154
+ let encodedBytes = 0;
1155
+ let text = "";
1156
+ for (const character of prepared.text) {
1157
+ const cost = Buffer.byteLength(JSON.stringify(character), "utf8") - 2;
1158
+ if (encodedBytes + cost > CLIPBOARD_HISTORY_MAX_BYTES) break;
1159
+ encodedBytes += cost;
1160
+ text += character;
1161
+ }
1162
+ return { text, truncated: true, totalBytes: prepared.totalBytes };
1163
+ }
1146
1164
 
1147
- export { getRandomBytes as A, redactLogValue as B, CLIPBOARD_TOOL_NAME as C, ensurePrivateDirectory as D, hardenPrivateFile as E, readCredentials as F, readSettingsOutcome as G, updateSettings as H, encodeBase64Url as I, writeCredentialsLegacy as J, writeCredentialsDataKey as K, decryptWithDataKey as L, decryptLegacy as M, persistSession as N, acquireDaemonLock as O, deletePersistedSessions as P, writeDaemonState as Q, writeSettings as R, releaseDaemonLock as S, clearCredentials as T, clearMachineId as U, SandboxConfigSchema as V, getLatestDaemonLog as W, persistence as X, CLIPBOARD_TOOL_TITLE as a, CLIPBOARD_TOOL_DESCRIPTION as b, configuration as c, readCredentialsForConfiguredRelay as d, CLIPBOARD_MAX_BYTES as e, ensurePrivateDirectorySync as f, readSettings as g, hardenPrivateFileSync as h, encodeBase64 as i, encrypt as j, decrypt as k, logger as l, decodeBase64 as m, normalizeHttpEndpoint as n, readDaemonState as o, packageJson as p, clearDaemonState as q, readPersistedSessions as r, decryptBlob as s, prepareClipboardText as t, credentialRelayProblem as u, readTrackedClaudeSessionIds as v, writePrivateFileSync as w, readTrackedCodexThreadIds as x, libsodiumEncryptForPublicKey as y, libsodiumPublicKeyFromSecretKey as z };
1165
+ export { libsodiumPublicKeyFromSecretKey as A, getRandomBytes as B, CLIPBOARD_TOOL_NAME as C, redactLogValue as D, ensurePrivateDirectory as E, hardenPrivateFile as F, readCredentials as G, readSettingsOutcome as H, updateSettings as I, encodeBase64Url as J, writeCredentialsLegacy as K, writeCredentialsDataKey as L, decryptWithDataKey as M, decryptLegacy as N, persistSession as O, acquireDaemonLock as P, deletePersistedSessions as Q, writeDaemonState as R, writeSettings as S, releaseDaemonLock as T, clearCredentials as U, clearMachineId as V, SandboxConfigSchema as W, getLatestDaemonLog as X, persistence as Y, CLIPBOARD_TOOL_TITLE as a, CLIPBOARD_TOOL_DESCRIPTION as b, configuration as c, readCredentialsForConfiguredRelay as d, CLIPBOARD_MAX_BYTES as e, readSettings as f, encodeBase64 as g, ensurePrivateDirectorySync as h, hardenPrivateFileSync as i, encrypt as j, decrypt as k, logger as l, decodeBase64 as m, normalizeHttpEndpoint as n, readDaemonState as o, packageJson as p, clearDaemonState as q, readPersistedSessions as r, decryptBlob as s, prepareClipboardText as t, prepareClipboardHistoryText as u, credentialRelayProblem as v, writePrivateFileSync as w, readTrackedClaudeSessionIds as x, readTrackedCodexThreadIds as y, libsodiumEncryptForPublicKey as z };