very-happy-cli 0.2.116 → 0.2.118
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-CfKPvoTU.mjs → AcpBackend-Bk9b823B.mjs} +116 -12
- package/dist/{AcpBackend-CauAQpC1.cjs → AcpBackend-p_KNJkHc.cjs} +116 -12
- package/dist/{AcpSessionManager-CA6xeET_.cjs → AcpSessionManager-B9FTbpGQ.cjs} +15 -2
- package/dist/{AcpSessionManager-BQ6pBRW4.mjs → AcpSessionManager-CDvqVHKf.mjs} +15 -2
- package/dist/{config-BpR_CwZu.mjs → config-CIpgmGLR.mjs} +2 -2
- package/dist/{config-BoteFn-v.cjs → config-CkUn1dI4.cjs} +2 -2
- package/dist/{index-C45xN8s0.mjs → index-B6cpyG_G.mjs} +78 -8
- package/dist/{index-D7azxfcs.mjs → index-BUVQf9PI.mjs} +2 -2
- package/dist/{index-4jiUeiUz.cjs → index-BXOXRblP.cjs} +513 -47
- package/dist/{index-DWmhmji9.cjs → index-BzgtwTxC.cjs} +77 -7
- package/dist/{index-lX1UliOs.cjs → index-CxjX8DGz.cjs} +2 -2
- package/dist/{index-Dq-eFp89.mjs → index-DIXjhnV1.mjs} +502 -45
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{installTerminalHooks-k3TrBHD0.mjs → installTerminalHooks-BAa6LaQQ.mjs} +2 -2
- package/dist/{installTerminalHooks-DnaFkrTF.cjs → installTerminalHooks-lXQa6bQU.cjs} +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +43 -1
- package/dist/lib.d.mts +43 -1
- package/dist/lib.mjs +1 -1
- package/dist/{mcp-DSpEpM_2.cjs → mcp-DMD7FxBI.cjs} +62 -16
- package/dist/{mcp-DRePTOap.mjs → mcp-Dwc299mU.mjs} +62 -17
- package/dist/{runGemini-_9-a7duU.mjs → runGemini-BaxGXE9w.mjs} +4 -4
- package/dist/{runGemini-IWHyBq0A.cjs → runGemini-Bj4Egq7j.cjs} +4 -4
- package/dist/{runOpenClaw-0myYIz1U.cjs → runOpenClaw-BJhSvXYy.cjs} +3 -3
- package/dist/{runOpenClaw-Boq6LQ9a.mjs → runOpenClaw-BwJhbIKU.mjs} +3 -3
- package/dist/{send-CwWvFfay.cjs → send-BWGUkWhi.cjs} +2 -2
- package/dist/{send-Cyo6mgMl.mjs → send-DX13svrS.mjs} +2 -2
- package/dist/sessions-CGhpBNqn.cjs +322 -0
- package/dist/sessions-L7O3ypda.mjs +317 -0
- package/dist/{spawn-DQ6FTUK9.cjs → spawn-CbY233Eg.cjs} +6 -7
- package/dist/{spawn-CU0DMauA.mjs → spawn-DPDWZdoW.mjs} +3 -4
- package/dist/{types-Ds0SiQ1D.mjs → types-BtuOM9lw.mjs} +52 -19
- package/dist/{types-C5kEpkcZ.cjs → types-ClvvHves.cjs} +54 -19
- package/package.json +7 -7
- package/dist/sessions-CbzqYiAy.cjs +0 -204
- package/dist/sessions-lvfTH_ql.mjs +0 -200
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
var chalk = require('chalk');
|
|
4
4
|
var node_fs = require('node:fs');
|
|
5
5
|
var path = require('node:path');
|
|
6
|
-
var index = require('./index-
|
|
7
|
-
var persistence = require('./types-
|
|
6
|
+
var index = require('./index-BXOXRblP.cjs');
|
|
7
|
+
var persistence = require('./types-ClvvHves.cjs');
|
|
8
8
|
require('node:os');
|
|
9
9
|
require('node:crypto');
|
|
10
10
|
require('cross-spawn');
|
|
@@ -48,7 +48,6 @@ require('node:util');
|
|
|
48
48
|
require('url');
|
|
49
49
|
require('node-pty');
|
|
50
50
|
|
|
51
|
-
const SPAWN_AGENTS = ["claude", "codex", "gemini", "openclaw"];
|
|
52
51
|
function parseEnvAssignment(raw) {
|
|
53
52
|
const eq = raw.indexOf("=");
|
|
54
53
|
if (eq <= 0) throw new Error(`--env expects KEY=VALUE, got: ${raw}`);
|
|
@@ -89,8 +88,8 @@ function parseSpawnArgs(args) {
|
|
|
89
88
|
} else if (arg === "--agent") {
|
|
90
89
|
const value = args[++i];
|
|
91
90
|
if (value === void 0) throw new Error("--agent requires a value");
|
|
92
|
-
if (!SPAWN_AGENTS.includes(value)) {
|
|
93
|
-
throw new Error(`--agent must be one of: ${SPAWN_AGENTS.join(", ")}`);
|
|
91
|
+
if (!index.SPAWN_AGENTS.includes(value)) {
|
|
92
|
+
throw new Error(`--agent must be one of: ${index.SPAWN_AGENTS.join(", ")}`);
|
|
94
93
|
}
|
|
95
94
|
options.agent = value;
|
|
96
95
|
} else if (arg === "--env") {
|
|
@@ -134,7 +133,7 @@ ${chalk.bold("Options:")}
|
|
|
134
133
|
to approve \u2014 if nothing is watching, it just hangs.
|
|
135
134
|
Unattended dispatchers want bypassPermissions.
|
|
136
135
|
--agent <name> Backend to run: claude (default), codex, gemini,
|
|
137
|
-
openclaw.
|
|
136
|
+
openclaw, pi (needs pi-acp on the daemon's PATH).
|
|
138
137
|
--env KEY=VALUE Extra environment for the session process. Repeatable.
|
|
139
138
|
\${VAR} is expanded against the daemon's environment;
|
|
140
139
|
an unresolved reference fails the spawn.
|
|
@@ -257,8 +256,8 @@ async function handleSpawnCommand(args) {
|
|
|
257
256
|
process.exit(0);
|
|
258
257
|
}
|
|
259
258
|
|
|
259
|
+
exports.SPAWN_AGENTS = index.SPAWN_AGENTS;
|
|
260
260
|
exports.sessionWebUrl = index.sessionWebUrl;
|
|
261
|
-
exports.SPAWN_AGENTS = SPAWN_AGENTS;
|
|
262
261
|
exports.handleSpawnCommand = handleSpawnCommand;
|
|
263
262
|
exports.parseEnvAssignment = parseEnvAssignment;
|
|
264
263
|
exports.parseSpawnArgs = parseSpawnArgs;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { readFileSync, statSync } from 'node:fs';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
|
-
import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, i as isValidSpawnOrigin, b as sanitizeSpawnPermissionMode, A as ALLOWED_SPAWN_PERMISSION_MODES, w as waitForSessionKey, d as sendUserMessage } from './index-
|
|
5
|
-
import { l as logger } from './types-
|
|
4
|
+
import { c as checkIfDaemonRunningAndCleanupStaleState, s as spawnDaemonSession, a as sessionWebUrl, i as isValidSpawnOrigin, b as sanitizeSpawnPermissionMode, A as ALLOWED_SPAWN_PERMISSION_MODES, S as SPAWN_AGENTS, w as waitForSessionKey, d as sendUserMessage } from './index-DIXjhnV1.mjs';
|
|
5
|
+
import { l as logger } from './types-BtuOM9lw.mjs';
|
|
6
6
|
import 'node:os';
|
|
7
7
|
import 'node:crypto';
|
|
8
8
|
import 'cross-spawn';
|
|
@@ -46,7 +46,6 @@ import 'node:util';
|
|
|
46
46
|
import 'url';
|
|
47
47
|
import 'node-pty';
|
|
48
48
|
|
|
49
|
-
const SPAWN_AGENTS = ["claude", "codex", "gemini", "openclaw"];
|
|
50
49
|
function parseEnvAssignment(raw) {
|
|
51
50
|
const eq = raw.indexOf("=");
|
|
52
51
|
if (eq <= 0) throw new Error(`--env expects KEY=VALUE, got: ${raw}`);
|
|
@@ -132,7 +131,7 @@ ${chalk.bold("Options:")}
|
|
|
132
131
|
to approve \u2014 if nothing is watching, it just hangs.
|
|
133
132
|
Unattended dispatchers want bypassPermissions.
|
|
134
133
|
--agent <name> Backend to run: claude (default), codex, gemini,
|
|
135
|
-
openclaw.
|
|
134
|
+
openclaw, pi (needs pi-acp on the daemon's PATH).
|
|
136
135
|
--env KEY=VALUE Extra environment for the session process. Repeatable.
|
|
137
136
|
\${VAR} is expanded against the daemon's environment;
|
|
138
137
|
an unresolved reference fails the spawn.
|
|
@@ -29,7 +29,7 @@ import { SandboxManager } from '@anthropic-ai/sandbox-runtime';
|
|
|
29
29
|
import { Expo } from 'expo-server-sdk';
|
|
30
30
|
|
|
31
31
|
var name = "very-happy-cli";
|
|
32
|
-
var version = "0.2.
|
|
32
|
+
var version = "0.2.118";
|
|
33
33
|
var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
|
|
34
34
|
var author = "Kirill Dubovitskiy";
|
|
35
35
|
var contributors = [
|
|
@@ -142,12 +142,12 @@ var dependencies = {
|
|
|
142
142
|
zod: "^4.0.0"
|
|
143
143
|
};
|
|
144
144
|
var optionalDependencies = {
|
|
145
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
146
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
147
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
148
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
149
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
150
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
145
|
+
"very-happy-tools-arm64-darwin": "0.2.118",
|
|
146
|
+
"very-happy-tools-x64-darwin": "0.2.118",
|
|
147
|
+
"very-happy-tools-arm64-linux": "0.2.118",
|
|
148
|
+
"very-happy-tools-x64-linux": "0.2.118",
|
|
149
|
+
"very-happy-tools-arm64-win32": "0.2.118",
|
|
150
|
+
"very-happy-tools-x64-win32": "0.2.118"
|
|
151
151
|
};
|
|
152
152
|
var devDependencies = {
|
|
153
153
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -1017,6 +1017,8 @@ z$1.object({
|
|
|
1017
1017
|
codex: z$1.boolean(),
|
|
1018
1018
|
gemini: z$1.boolean(),
|
|
1019
1019
|
openclaw: z$1.boolean(),
|
|
1020
|
+
pi: z$1.boolean().optional(),
|
|
1021
|
+
// absent on daemons that predate the pi runner
|
|
1020
1022
|
detectedAt: z$1.number()
|
|
1021
1023
|
}).optional(),
|
|
1022
1024
|
resumeSupport: z$1.object({
|
|
@@ -1048,6 +1050,9 @@ const CliUpdateStateSchema = z$1.object({
|
|
|
1048
1050
|
recommendedVersion: z$1.string().nullable(),
|
|
1049
1051
|
minimumVersion: z$1.string().nullable(),
|
|
1050
1052
|
status: z$1.enum(["current", "available", "required"]),
|
|
1053
|
+
/** B-351: the version this machine may install by itself. Pinned separately
|
|
1054
|
+
* from `recommendedVersion`; null means no unattended install. */
|
|
1055
|
+
autoUpdateVersion: z$1.string().nullable().optional(),
|
|
1051
1056
|
checkedAt: z$1.number(),
|
|
1052
1057
|
/**
|
|
1053
1058
|
* B-321: a new bundle is on disk but refused to run, so the daemon is still
|
|
@@ -4212,6 +4217,7 @@ function deriveCliUpdateState(currentVersion, policy) {
|
|
|
4212
4217
|
if (!parseExactVersion(currentVersion)) return null;
|
|
4213
4218
|
const recommended = policy.recommendedVersion && parseExactVersion(policy.recommendedVersion) ? policy.recommendedVersion.replace(/^v/, "") : null;
|
|
4214
4219
|
const minimum = policy.minimumVersion && parseExactVersion(policy.minimumVersion) ? policy.minimumVersion.replace(/^v/, "") : null;
|
|
4220
|
+
const autoUpdate = policy.autoUpdateVersion && parseExactVersion(policy.autoUpdateVersion) ? policy.autoUpdateVersion.replace(/^v/, "") : null;
|
|
4215
4221
|
if (!recommended && !minimum) return null;
|
|
4216
4222
|
const belowMinimum = minimum ? compareExactVersions(currentVersion, minimum) === -1 : false;
|
|
4217
4223
|
const belowRecommended = recommended ? compareExactVersions(currentVersion, recommended) === -1 : false;
|
|
@@ -4220,6 +4226,7 @@ function deriveCliUpdateState(currentVersion, policy) {
|
|
|
4220
4226
|
recommendedVersion: recommended ? parseExactVersion(recommended).exact : null,
|
|
4221
4227
|
minimumVersion: minimum ? parseExactVersion(minimum).exact : null,
|
|
4222
4228
|
status: belowMinimum ? "required" : belowRecommended ? "available" : "current",
|
|
4229
|
+
autoUpdateVersion: autoUpdate ? parseExactVersion(autoUpdate).exact : null,
|
|
4223
4230
|
checkedAt: policy.checkedAt
|
|
4224
4231
|
};
|
|
4225
4232
|
}
|
|
@@ -4255,9 +4262,11 @@ async function fetchCliUpdateState(serverUrl, currentVersion, fetcher = fetch, t
|
|
|
4255
4262
|
if (!["configured", "registry", "unavailable"].includes(String(raw.source))) return null;
|
|
4256
4263
|
if (raw.recommendedVersion !== null && raw.recommendedVersion !== void 0 && typeof raw.recommendedVersion !== "string") return null;
|
|
4257
4264
|
if (raw.minimumVersion !== null && raw.minimumVersion !== void 0 && typeof raw.minimumVersion !== "string") return null;
|
|
4265
|
+
if (raw.autoUpdateVersion !== null && raw.autoUpdateVersion !== void 0 && typeof raw.autoUpdateVersion !== "string") return null;
|
|
4258
4266
|
return deriveCliUpdateState(currentVersion, {
|
|
4259
4267
|
recommendedVersion: raw.recommendedVersion ?? null,
|
|
4260
4268
|
minimumVersion: raw.minimumVersion ?? null,
|
|
4269
|
+
autoUpdateVersion: raw.autoUpdateVersion ?? null,
|
|
4261
4270
|
checkedAt: raw.checkedAt,
|
|
4262
4271
|
source: raw.source
|
|
4263
4272
|
});
|
|
@@ -12731,6 +12740,19 @@ function commandExists(command) {
|
|
|
12731
12740
|
return false;
|
|
12732
12741
|
}
|
|
12733
12742
|
}
|
|
12743
|
+
function commandExistsWindows(name) {
|
|
12744
|
+
try {
|
|
12745
|
+
execSync(`powershell -NoProfile -Command "Get-Command ${name} -ErrorAction SilentlyContinue"`, { stdio: "ignore", windowsHide: true });
|
|
12746
|
+
return true;
|
|
12747
|
+
} catch {
|
|
12748
|
+
return false;
|
|
12749
|
+
}
|
|
12750
|
+
}
|
|
12751
|
+
const SAFE_COMMAND_NAME = /^[A-Za-z0-9._-]+$/;
|
|
12752
|
+
function commandOnPath(name) {
|
|
12753
|
+
if (!SAFE_COMMAND_NAME.test(name)) return false;
|
|
12754
|
+
return os.platform() === "win32" ? commandExistsWindows(name) : commandExists(name);
|
|
12755
|
+
}
|
|
12734
12756
|
function detectPosix() {
|
|
12735
12757
|
const claude = commandExists("claude");
|
|
12736
12758
|
const codex = commandExists("codex");
|
|
@@ -12739,17 +12761,11 @@ function detectPosix() {
|
|
|
12739
12761
|
const openclawConfig = existsSync$1(join$1(os.homedir(), ".openclaw", "openclaw.json"));
|
|
12740
12762
|
const openclawEnv = !!process.env.OPENCLAW_GATEWAY_URL;
|
|
12741
12763
|
const openclaw = openclawCommand || openclawConfig || openclawEnv;
|
|
12742
|
-
|
|
12764
|
+
const pi = commandExists("pi") && commandExists("pi-acp");
|
|
12765
|
+
return { claude, codex, gemini, openclaw, pi, detectedAt: Date.now() };
|
|
12743
12766
|
}
|
|
12744
12767
|
function detectWindows() {
|
|
12745
|
-
const checkCommand =
|
|
12746
|
-
try {
|
|
12747
|
-
execSync(`powershell -NoProfile -Command "Get-Command ${name} -ErrorAction SilentlyContinue"`, { stdio: "ignore", windowsHide: true });
|
|
12748
|
-
return true;
|
|
12749
|
-
} catch {
|
|
12750
|
-
return false;
|
|
12751
|
-
}
|
|
12752
|
-
};
|
|
12768
|
+
const checkCommand = commandExistsWindows;
|
|
12753
12769
|
const claude = checkCommand("claude");
|
|
12754
12770
|
const codex = checkCommand("codex");
|
|
12755
12771
|
const gemini = checkCommand("gemini");
|
|
@@ -12757,7 +12773,8 @@ function detectWindows() {
|
|
|
12757
12773
|
const openclawConfig = existsSync$1(join$1(process.env.USERPROFILE || os.homedir(), ".openclaw", "openclaw.json"));
|
|
12758
12774
|
const openclawEnv = !!process.env.OPENCLAW_GATEWAY_URL;
|
|
12759
12775
|
const openclaw = openclawCommand || openclawConfig || openclawEnv;
|
|
12760
|
-
|
|
12776
|
+
const pi = checkCommand("pi") && checkCommand("pi-acp");
|
|
12777
|
+
return { claude, codex, gemini, openclaw, pi, detectedAt: Date.now() };
|
|
12761
12778
|
}
|
|
12762
12779
|
|
|
12763
12780
|
const AgentCredentialsSchema = z$1.object({
|
|
@@ -14566,6 +14583,22 @@ class ApiMachineClient {
|
|
|
14566
14583
|
event: n.event
|
|
14567
14584
|
});
|
|
14568
14585
|
});
|
|
14586
|
+
/**
|
|
14587
|
+
* The CLI availability last advertised in machine metadata (re-probed by
|
|
14588
|
+
* the keep-alive). Null until the first keep-alive tick; the daemon falls
|
|
14589
|
+
* back to its startup probe then.
|
|
14590
|
+
*/
|
|
14591
|
+
getCLIAvailability() {
|
|
14592
|
+
return this.lastKnownCLIAvailability;
|
|
14593
|
+
}
|
|
14594
|
+
/**
|
|
14595
|
+
* Title a web terminal from inside it (`very-happy mcp` change_title →
|
|
14596
|
+
* daemon /terminal-title → here). Same tmux truthfulness as the
|
|
14597
|
+
* `set-terminal-title` RPC.
|
|
14598
|
+
*/
|
|
14599
|
+
setTerminalTitle(terminalId, title, ifAbsent) {
|
|
14600
|
+
return this.webTerminal.setTitle(terminalId, title, ifAbsent);
|
|
14601
|
+
}
|
|
14569
14602
|
/**
|
|
14570
14603
|
* Push text to the clipboard of every web client the user has open
|
|
14571
14604
|
* (terminal-path claude → `very-happy mcp` → daemon /clipboard → here).
|
|
@@ -15374,7 +15407,7 @@ class ApiMachineClient {
|
|
|
15374
15407
|
const prev = this.lastKnownCLIAvailability;
|
|
15375
15408
|
const newResumeSupport = detectResumeSupport();
|
|
15376
15409
|
const prevResume = this.lastKnownResumeSupport;
|
|
15377
|
-
const cliAvailabilityChanged = !prev || prev.claude !== newAvailability.claude || prev.codex !== newAvailability.codex || prev.gemini !== newAvailability.gemini || prev.openclaw !== newAvailability.openclaw;
|
|
15410
|
+
const cliAvailabilityChanged = !prev || prev.claude !== newAvailability.claude || prev.codex !== newAvailability.codex || prev.gemini !== newAvailability.gemini || prev.openclaw !== newAvailability.openclaw || prev.pi !== newAvailability.pi;
|
|
15378
15411
|
const resumeSupportChanged = !prevResume || prevResume.rpcAvailable !== newResumeSupport.rpcAvailable || prevResume.happyAgentAuthenticated !== newResumeSupport.happyAgentAuthenticated;
|
|
15379
15412
|
if (cliAvailabilityChanged || resumeSupportChanged) {
|
|
15380
15413
|
this.lastKnownCLIAvailability = newAvailability;
|
|
@@ -16597,4 +16630,4 @@ const RawJSONLinesSchema = z$1.discriminatedUnion("type", [
|
|
|
16597
16630
|
}).passthrough()
|
|
16598
16631
|
]);
|
|
16599
16632
|
|
|
16600
|
-
export {
|
|
16633
|
+
export { MIRROR_BACKFILL_LINES_DEFAULT as $, ApiClient as A, readCredentials as B, credentialRelayProblem as C, deriveLocalCliUpdateSummary as D, updateSettings as E, encodeBase64Url as F, decodeBase64 as G, writeCredentialsLegacy as H, InvalidateSync as I, writeCredentialsDataKey as J, readCredentialsForConfiguredRelay as K, encrypt as L, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, isClaudeSessionId as N, getLocalHappyAgentCredentialPath as O, readLocalHappyAgentCredentials as P, decryptWithDataKey as Q, RawJSONLinesSchema as R, STREAM_DELTA_MAX_CHARS as S, decryptLegacy as T, compareExactVersions as U, extractCompleteLines as V, decideBackfill as W, parseTerminalHookPayload as X, tmuxArgs as Y, scrubTmuxClientEnv as Z, decideMirrorBinding as _, ApiSessionClient as a, persistSession as a0, mirrorLineKey as a1, mirrorLocalId as a2, detectCLIAvailability as a3, detectResumeSupport as a4, acquireDaemonLock as a5, summarizeSpawnSessionForLog as a6, deletePersistedSessions as a7, shellescape as a8, decrypt as a9, writeDaemonState as aa, writeSettings as ab, fetchCliUpdateState as ac, resolveCliUpdateCheckInterval as ad, DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS as ae, releaseDaemonLock as af, listVhTerminals as ag, isValidTerminalId as ah, readVhTerminal as ai, sendToVhTerminal as aj, TITLE_PROMPT_PREFIX as ak, BOARD_ANALYZER_PROMPT_PREFIX as al, startOfflineReconnection as am, clearCredentials as an, clearMachineId as ao, SandboxConfigSchema as ap, CodexAppServerClient as aq, getLatestDaemonLog as ar, persistence as as, api as at, createEnvelope as b, configuration as c, connectionState as d, readSettings as e, encodeBase64 as f, contentLogMetadata as g, errorLogMetadata as h, isValidSessionId as i, packageJson as j, delay as k, logger as l, ensurePrivateDirectorySync as m, hardenPrivateFileSync as n, readDaemonState as o, projectPath as p, clearDaemonState as q, readPersistedSessions as r, getProjectPath as s, initializeSandbox as t, wrapCommand as u, AsyncLock as v, writePrivateFileSync as w, ensurePrivateDirectory as x, hardenPrivateFile as y, commandOnPath as z };
|
|
@@ -51,7 +51,7 @@ var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
|
51
51
|
var pty__namespace = /*#__PURE__*/_interopNamespaceDefault(pty);
|
|
52
52
|
|
|
53
53
|
var name = "very-happy-cli";
|
|
54
|
-
var version = "0.2.
|
|
54
|
+
var version = "0.2.118";
|
|
55
55
|
var description = "Remote multi-agent workspace CLI with deep Claude integration, native terminal streaming, and self-hosting.";
|
|
56
56
|
var author = "Kirill Dubovitskiy";
|
|
57
57
|
var contributors = [
|
|
@@ -164,12 +164,12 @@ var dependencies = {
|
|
|
164
164
|
zod: "^4.0.0"
|
|
165
165
|
};
|
|
166
166
|
var optionalDependencies = {
|
|
167
|
-
"very-happy-tools-arm64-darwin": "0.2.
|
|
168
|
-
"very-happy-tools-x64-darwin": "0.2.
|
|
169
|
-
"very-happy-tools-arm64-linux": "0.2.
|
|
170
|
-
"very-happy-tools-x64-linux": "0.2.
|
|
171
|
-
"very-happy-tools-arm64-win32": "0.2.
|
|
172
|
-
"very-happy-tools-x64-win32": "0.2.
|
|
167
|
+
"very-happy-tools-arm64-darwin": "0.2.118",
|
|
168
|
+
"very-happy-tools-x64-darwin": "0.2.118",
|
|
169
|
+
"very-happy-tools-arm64-linux": "0.2.118",
|
|
170
|
+
"very-happy-tools-x64-linux": "0.2.118",
|
|
171
|
+
"very-happy-tools-arm64-win32": "0.2.118",
|
|
172
|
+
"very-happy-tools-x64-win32": "0.2.118"
|
|
173
173
|
};
|
|
174
174
|
var devDependencies = {
|
|
175
175
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -1039,6 +1039,8 @@ z.z.object({
|
|
|
1039
1039
|
codex: z.z.boolean(),
|
|
1040
1040
|
gemini: z.z.boolean(),
|
|
1041
1041
|
openclaw: z.z.boolean(),
|
|
1042
|
+
pi: z.z.boolean().optional(),
|
|
1043
|
+
// absent on daemons that predate the pi runner
|
|
1042
1044
|
detectedAt: z.z.number()
|
|
1043
1045
|
}).optional(),
|
|
1044
1046
|
resumeSupport: z.z.object({
|
|
@@ -1070,6 +1072,9 @@ const CliUpdateStateSchema = z.z.object({
|
|
|
1070
1072
|
recommendedVersion: z.z.string().nullable(),
|
|
1071
1073
|
minimumVersion: z.z.string().nullable(),
|
|
1072
1074
|
status: z.z.enum(["current", "available", "required"]),
|
|
1075
|
+
/** B-351: the version this machine may install by itself. Pinned separately
|
|
1076
|
+
* from `recommendedVersion`; null means no unattended install. */
|
|
1077
|
+
autoUpdateVersion: z.z.string().nullable().optional(),
|
|
1073
1078
|
checkedAt: z.z.number(),
|
|
1074
1079
|
/**
|
|
1075
1080
|
* B-321: a new bundle is on disk but refused to run, so the daemon is still
|
|
@@ -1680,7 +1685,7 @@ class RpcHandlerManager {
|
|
|
1680
1685
|
}
|
|
1681
1686
|
}
|
|
1682
1687
|
|
|
1683
|
-
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-
|
|
1688
|
+
const __dirname$1 = path$1.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('types-ClvvHves.cjs', document.baseURI).href))));
|
|
1684
1689
|
function projectPath() {
|
|
1685
1690
|
const path = path$1.resolve(__dirname$1, "..");
|
|
1686
1691
|
return path;
|
|
@@ -4234,6 +4239,7 @@ function deriveCliUpdateState(currentVersion, policy) {
|
|
|
4234
4239
|
if (!parseExactVersion(currentVersion)) return null;
|
|
4235
4240
|
const recommended = policy.recommendedVersion && parseExactVersion(policy.recommendedVersion) ? policy.recommendedVersion.replace(/^v/, "") : null;
|
|
4236
4241
|
const minimum = policy.minimumVersion && parseExactVersion(policy.minimumVersion) ? policy.minimumVersion.replace(/^v/, "") : null;
|
|
4242
|
+
const autoUpdate = policy.autoUpdateVersion && parseExactVersion(policy.autoUpdateVersion) ? policy.autoUpdateVersion.replace(/^v/, "") : null;
|
|
4237
4243
|
if (!recommended && !minimum) return null;
|
|
4238
4244
|
const belowMinimum = minimum ? compareExactVersions(currentVersion, minimum) === -1 : false;
|
|
4239
4245
|
const belowRecommended = recommended ? compareExactVersions(currentVersion, recommended) === -1 : false;
|
|
@@ -4242,6 +4248,7 @@ function deriveCliUpdateState(currentVersion, policy) {
|
|
|
4242
4248
|
recommendedVersion: recommended ? parseExactVersion(recommended).exact : null,
|
|
4243
4249
|
minimumVersion: minimum ? parseExactVersion(minimum).exact : null,
|
|
4244
4250
|
status: belowMinimum ? "required" : belowRecommended ? "available" : "current",
|
|
4251
|
+
autoUpdateVersion: autoUpdate ? parseExactVersion(autoUpdate).exact : null,
|
|
4245
4252
|
checkedAt: policy.checkedAt
|
|
4246
4253
|
};
|
|
4247
4254
|
}
|
|
@@ -4277,9 +4284,11 @@ async function fetchCliUpdateState(serverUrl, currentVersion, fetcher = fetch, t
|
|
|
4277
4284
|
if (!["configured", "registry", "unavailable"].includes(String(raw.source))) return null;
|
|
4278
4285
|
if (raw.recommendedVersion !== null && raw.recommendedVersion !== void 0 && typeof raw.recommendedVersion !== "string") return null;
|
|
4279
4286
|
if (raw.minimumVersion !== null && raw.minimumVersion !== void 0 && typeof raw.minimumVersion !== "string") return null;
|
|
4287
|
+
if (raw.autoUpdateVersion !== null && raw.autoUpdateVersion !== void 0 && typeof raw.autoUpdateVersion !== "string") return null;
|
|
4280
4288
|
return deriveCliUpdateState(currentVersion, {
|
|
4281
4289
|
recommendedVersion: raw.recommendedVersion ?? null,
|
|
4282
4290
|
minimumVersion: raw.minimumVersion ?? null,
|
|
4291
|
+
autoUpdateVersion: raw.autoUpdateVersion ?? null,
|
|
4283
4292
|
checkedAt: raw.checkedAt,
|
|
4284
4293
|
source: raw.source
|
|
4285
4294
|
});
|
|
@@ -12753,6 +12762,19 @@ function commandExists(command) {
|
|
|
12753
12762
|
return false;
|
|
12754
12763
|
}
|
|
12755
12764
|
}
|
|
12765
|
+
function commandExistsWindows(name) {
|
|
12766
|
+
try {
|
|
12767
|
+
child_process.execSync(`powershell -NoProfile -Command "Get-Command ${name} -ErrorAction SilentlyContinue"`, { stdio: "ignore", windowsHide: true });
|
|
12768
|
+
return true;
|
|
12769
|
+
} catch {
|
|
12770
|
+
return false;
|
|
12771
|
+
}
|
|
12772
|
+
}
|
|
12773
|
+
const SAFE_COMMAND_NAME = /^[A-Za-z0-9._-]+$/;
|
|
12774
|
+
function commandOnPath(name) {
|
|
12775
|
+
if (!SAFE_COMMAND_NAME.test(name)) return false;
|
|
12776
|
+
return os$1.platform() === "win32" ? commandExistsWindows(name) : commandExists(name);
|
|
12777
|
+
}
|
|
12756
12778
|
function detectPosix() {
|
|
12757
12779
|
const claude = commandExists("claude");
|
|
12758
12780
|
const codex = commandExists("codex");
|
|
@@ -12761,17 +12783,11 @@ function detectPosix() {
|
|
|
12761
12783
|
const openclawConfig = fs$1.existsSync(path$1.join(os$1.homedir(), ".openclaw", "openclaw.json"));
|
|
12762
12784
|
const openclawEnv = !!process.env.OPENCLAW_GATEWAY_URL;
|
|
12763
12785
|
const openclaw = openclawCommand || openclawConfig || openclawEnv;
|
|
12764
|
-
|
|
12786
|
+
const pi = commandExists("pi") && commandExists("pi-acp");
|
|
12787
|
+
return { claude, codex, gemini, openclaw, pi, detectedAt: Date.now() };
|
|
12765
12788
|
}
|
|
12766
12789
|
function detectWindows() {
|
|
12767
|
-
const checkCommand =
|
|
12768
|
-
try {
|
|
12769
|
-
child_process.execSync(`powershell -NoProfile -Command "Get-Command ${name} -ErrorAction SilentlyContinue"`, { stdio: "ignore", windowsHide: true });
|
|
12770
|
-
return true;
|
|
12771
|
-
} catch {
|
|
12772
|
-
return false;
|
|
12773
|
-
}
|
|
12774
|
-
};
|
|
12790
|
+
const checkCommand = commandExistsWindows;
|
|
12775
12791
|
const claude = checkCommand("claude");
|
|
12776
12792
|
const codex = checkCommand("codex");
|
|
12777
12793
|
const gemini = checkCommand("gemini");
|
|
@@ -12779,7 +12795,8 @@ function detectWindows() {
|
|
|
12779
12795
|
const openclawConfig = fs$1.existsSync(path$1.join(process.env.USERPROFILE || os$1.homedir(), ".openclaw", "openclaw.json"));
|
|
12780
12796
|
const openclawEnv = !!process.env.OPENCLAW_GATEWAY_URL;
|
|
12781
12797
|
const openclaw = openclawCommand || openclawConfig || openclawEnv;
|
|
12782
|
-
|
|
12798
|
+
const pi = checkCommand("pi") && checkCommand("pi-acp");
|
|
12799
|
+
return { claude, codex, gemini, openclaw, pi, detectedAt: Date.now() };
|
|
12783
12800
|
}
|
|
12784
12801
|
|
|
12785
12802
|
const AgentCredentialsSchema = z.z.object({
|
|
@@ -14588,6 +14605,22 @@ class ApiMachineClient {
|
|
|
14588
14605
|
event: n.event
|
|
14589
14606
|
});
|
|
14590
14607
|
});
|
|
14608
|
+
/**
|
|
14609
|
+
* The CLI availability last advertised in machine metadata (re-probed by
|
|
14610
|
+
* the keep-alive). Null until the first keep-alive tick; the daemon falls
|
|
14611
|
+
* back to its startup probe then.
|
|
14612
|
+
*/
|
|
14613
|
+
getCLIAvailability() {
|
|
14614
|
+
return this.lastKnownCLIAvailability;
|
|
14615
|
+
}
|
|
14616
|
+
/**
|
|
14617
|
+
* Title a web terminal from inside it (`very-happy mcp` change_title →
|
|
14618
|
+
* daemon /terminal-title → here). Same tmux truthfulness as the
|
|
14619
|
+
* `set-terminal-title` RPC.
|
|
14620
|
+
*/
|
|
14621
|
+
setTerminalTitle(terminalId, title, ifAbsent) {
|
|
14622
|
+
return this.webTerminal.setTitle(terminalId, title, ifAbsent);
|
|
14623
|
+
}
|
|
14591
14624
|
/**
|
|
14592
14625
|
* Push text to the clipboard of every web client the user has open
|
|
14593
14626
|
* (terminal-path claude → `very-happy mcp` → daemon /clipboard → here).
|
|
@@ -15396,7 +15429,7 @@ class ApiMachineClient {
|
|
|
15396
15429
|
const prev = this.lastKnownCLIAvailability;
|
|
15397
15430
|
const newResumeSupport = detectResumeSupport();
|
|
15398
15431
|
const prevResume = this.lastKnownResumeSupport;
|
|
15399
|
-
const cliAvailabilityChanged = !prev || prev.claude !== newAvailability.claude || prev.codex !== newAvailability.codex || prev.gemini !== newAvailability.gemini || prev.openclaw !== newAvailability.openclaw;
|
|
15432
|
+
const cliAvailabilityChanged = !prev || prev.claude !== newAvailability.claude || prev.codex !== newAvailability.codex || prev.gemini !== newAvailability.gemini || prev.openclaw !== newAvailability.openclaw || prev.pi !== newAvailability.pi;
|
|
15400
15433
|
const resumeSupportChanged = !prevResume || prevResume.rpcAvailable !== newResumeSupport.rpcAvailable || prevResume.happyAgentAuthenticated !== newResumeSupport.happyAgentAuthenticated;
|
|
15401
15434
|
if (cliAvailabilityChanged || resumeSupportChanged) {
|
|
15402
15435
|
this.lastKnownCLIAvailability = newAvailability;
|
|
@@ -16637,6 +16670,8 @@ exports.api = api;
|
|
|
16637
16670
|
exports.clearCredentials = clearCredentials;
|
|
16638
16671
|
exports.clearDaemonState = clearDaemonState;
|
|
16639
16672
|
exports.clearMachineId = clearMachineId;
|
|
16673
|
+
exports.commandOnPath = commandOnPath;
|
|
16674
|
+
exports.compareExactVersions = compareExactVersions;
|
|
16640
16675
|
exports.configuration = configuration;
|
|
16641
16676
|
exports.connectionState = connectionState;
|
|
16642
16677
|
exports.contentLogMetadata = contentLogMetadata;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "very-happy-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.118",
|
|
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": [
|
|
@@ -113,12 +113,12 @@
|
|
|
113
113
|
"zod": "^4.0.0"
|
|
114
114
|
},
|
|
115
115
|
"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.
|
|
116
|
+
"very-happy-tools-arm64-darwin": "0.2.118",
|
|
117
|
+
"very-happy-tools-x64-darwin": "0.2.118",
|
|
118
|
+
"very-happy-tools-arm64-linux": "0.2.118",
|
|
119
|
+
"very-happy-tools-x64-linux": "0.2.118",
|
|
120
|
+
"very-happy-tools-arm64-win32": "0.2.118",
|
|
121
|
+
"very-happy-tools-x64-win32": "0.2.118"
|
|
122
122
|
},
|
|
123
123
|
"devDependencies": {
|
|
124
124
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chalk = require('chalk');
|
|
4
|
-
var index = require('./index-4jiUeiUz.cjs');
|
|
5
|
-
var persistence = require('./types-C5kEpkcZ.cjs');
|
|
6
|
-
require('node:os');
|
|
7
|
-
require('node:crypto');
|
|
8
|
-
require('cross-spawn');
|
|
9
|
-
require('node:path');
|
|
10
|
-
require('node:readline');
|
|
11
|
-
require('node:fs');
|
|
12
|
-
require('./agentGuidance-BifkGXdE.cjs');
|
|
13
|
-
require('node:fs/promises');
|
|
14
|
-
require('fs/promises');
|
|
15
|
-
require('ink');
|
|
16
|
-
require('react');
|
|
17
|
-
require('@anthropic-ai/claude-agent-sdk');
|
|
18
|
-
require('axios');
|
|
19
|
-
require('node:events');
|
|
20
|
-
require('socket.io-client');
|
|
21
|
-
require('tweetnacl');
|
|
22
|
-
require('os');
|
|
23
|
-
require('child_process');
|
|
24
|
-
require('@paralleldrive/cuid2');
|
|
25
|
-
require('node:child_process');
|
|
26
|
-
require('fs');
|
|
27
|
-
require('path');
|
|
28
|
-
require('@anthropic-ai/sandbox-runtime');
|
|
29
|
-
require('expo-server-sdk');
|
|
30
|
-
require('crypto');
|
|
31
|
-
require('ps-list');
|
|
32
|
-
require('tmp');
|
|
33
|
-
require('open');
|
|
34
|
-
require('fastify');
|
|
35
|
-
require('zod');
|
|
36
|
-
require('fastify-type-provider-zod');
|
|
37
|
-
require('node:module');
|
|
38
|
-
require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
39
|
-
require('node:http');
|
|
40
|
-
require('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
41
|
-
require('./limits-KdWKmwtH.cjs');
|
|
42
|
-
require('http');
|
|
43
|
-
require('util');
|
|
44
|
-
require('inquirer');
|
|
45
|
-
require('node:url');
|
|
46
|
-
require('node:readline/promises');
|
|
47
|
-
require('node:util');
|
|
48
|
-
require('url');
|
|
49
|
-
require('node-pty');
|
|
50
|
-
|
|
51
|
-
const ACTIONS_NEEDING_ID = /* @__PURE__ */ new Set(["read", "stop", "archive"]);
|
|
52
|
-
function parseSessionsArgs(args) {
|
|
53
|
-
const options = { action: "help", json: false };
|
|
54
|
-
let actionSeen = false;
|
|
55
|
-
const positionals = [];
|
|
56
|
-
for (let i = 0; i < args.length; i++) {
|
|
57
|
-
const arg = args[i];
|
|
58
|
-
if (arg === "--help" || arg === "-h") {
|
|
59
|
-
return { action: "help", json: false };
|
|
60
|
-
} else if (arg === "--json") {
|
|
61
|
-
options.json = true;
|
|
62
|
-
} else if (arg === "--tag") {
|
|
63
|
-
const value = args[++i];
|
|
64
|
-
if (value === void 0) throw new Error("--tag requires a value");
|
|
65
|
-
options.tag = value;
|
|
66
|
-
} else if (arg === "--limit") {
|
|
67
|
-
const value = args[++i];
|
|
68
|
-
if (value === void 0) throw new Error("--limit requires a value");
|
|
69
|
-
const parsed = Number(value);
|
|
70
|
-
if (!Number.isInteger(parsed) || parsed < 1) throw new Error("--limit must be a positive integer");
|
|
71
|
-
options.limit = parsed;
|
|
72
|
-
} else if (arg.startsWith("-")) {
|
|
73
|
-
throw new Error(`Unknown argument: ${arg}`);
|
|
74
|
-
} else if (!actionSeen) {
|
|
75
|
-
if (arg !== "list" && arg !== "read" && arg !== "stop" && arg !== "archive") {
|
|
76
|
-
throw new Error(`Unknown action: ${arg} (expected list, read, stop or archive)`);
|
|
77
|
-
}
|
|
78
|
-
options.action = arg;
|
|
79
|
-
actionSeen = true;
|
|
80
|
-
} else {
|
|
81
|
-
positionals.push(arg);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (!actionSeen) return { action: "help", json: false };
|
|
85
|
-
if (positionals.length > 1) throw new Error(`Unexpected extra argument: ${positionals[1]}`);
|
|
86
|
-
if (ACTIONS_NEEDING_ID.has(options.action)) {
|
|
87
|
-
const id = positionals[0];
|
|
88
|
-
if (id === void 0) throw new Error(`${options.action} requires a session id`);
|
|
89
|
-
if (!persistence.isValidSessionId(id)) throw new Error(`Invalid session id: ${id}`);
|
|
90
|
-
options.sessionId = id;
|
|
91
|
-
} else if (positionals.length > 0) {
|
|
92
|
-
throw new Error(`Unexpected argument: ${positionals[0]}`);
|
|
93
|
-
}
|
|
94
|
-
if (options.action !== "list" && options.tag !== void 0) {
|
|
95
|
-
throw new Error("--tag only applies to `sessions list`");
|
|
96
|
-
}
|
|
97
|
-
return options;
|
|
98
|
-
}
|
|
99
|
-
const SESSIONS_HELP = `
|
|
100
|
-
${chalk.bold("very-happy sessions")} - Inspect and control sessions on this machine (for automation)
|
|
101
|
-
|
|
102
|
-
${chalk.bold("Usage:")}
|
|
103
|
-
very-happy sessions list [--tag <name>] [--limit <n>] [--json]
|
|
104
|
-
very-happy sessions read <id> [--limit <n>] [--json]
|
|
105
|
-
very-happy sessions stop <id> [--json]
|
|
106
|
-
very-happy sessions archive <id> [--json]
|
|
107
|
-
|
|
108
|
-
${chalk.bold("Actions:")}
|
|
109
|
-
list Running sessions plus recently seen ones, newest first.
|
|
110
|
-
read The tail of a session as a role-tagged transcript.
|
|
111
|
-
stop SIGTERM the session's process via the local daemon.
|
|
112
|
-
archive Mark the session inactive server-side (it stays resumable).
|
|
113
|
-
|
|
114
|
-
${chalk.bold("Options:")}
|
|
115
|
-
--tag <name> list only: keep sessions carrying this origin tag (see
|
|
116
|
-
\`spawn --spawned-by\`).
|
|
117
|
-
--limit <n> list: how many NOT-running sessions to include (default ${index.DEFAULT_RECENT_LIMIT};
|
|
118
|
-
running ones are never cut). read: how many messages
|
|
119
|
-
(default 20, max ${index.MAX_READ_LIMIT}).
|
|
120
|
-
--json Machine-readable output.
|
|
121
|
-
-h, --help Show this help
|
|
122
|
-
|
|
123
|
-
${chalk.bold("Scope:")}
|
|
124
|
-
This machine only. Reads need the session key from ~/.happy/sessions.json,
|
|
125
|
-
which exists for sessions this machine's daemon spawned and is pruned after
|
|
126
|
-
14 days. A session on another machine cannot be read or stopped from here.
|
|
127
|
-
|
|
128
|
-
${chalk.bold("Exit codes:")}
|
|
129
|
-
0 success
|
|
130
|
-
1 bad arguments, unknown session, no local key, or the operation failed
|
|
131
|
-
(including \`stop\` on a session the daemon is not running)
|
|
132
|
-
`;
|
|
133
|
-
function formatSummaryLine(summary) {
|
|
134
|
-
const parts = [summary.id, summary.live ? "[running]" : "[not running]"];
|
|
135
|
-
if (summary.title) parts.push(`title="${summary.title}"`);
|
|
136
|
-
if (summary.flavor) parts.push(`agent=${summary.flavor}`);
|
|
137
|
-
if (summary.tags?.length) parts.push(`tags=${summary.tags.join(",")}`);
|
|
138
|
-
if (summary.variant) parts.push(`variant=${summary.variant}`);
|
|
139
|
-
if (summary.cwd) parts.push(`cwd=${summary.cwd}`);
|
|
140
|
-
if (summary.pid !== void 0) parts.push(`pid=${summary.pid}`);
|
|
141
|
-
parts.push(summary.url);
|
|
142
|
-
return parts.join(" ");
|
|
143
|
-
}
|
|
144
|
-
async function handleSessionsCommand(args) {
|
|
145
|
-
let options;
|
|
146
|
-
try {
|
|
147
|
-
options = parseSessionsArgs(args);
|
|
148
|
-
} catch (error) {
|
|
149
|
-
console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
150
|
-
console.error(`Run ${chalk.cyan("very-happy sessions --help")} for usage.`);
|
|
151
|
-
process.exit(1);
|
|
152
|
-
}
|
|
153
|
-
if (options.action === "help") {
|
|
154
|
-
console.log(SESSIONS_HELP);
|
|
155
|
-
process.exit(0);
|
|
156
|
-
}
|
|
157
|
-
try {
|
|
158
|
-
if (options.action === "list") {
|
|
159
|
-
const sessions = await index.listSessions({ tag: options.tag, recentLimit: options.limit });
|
|
160
|
-
if (options.json) {
|
|
161
|
-
console.log(JSON.stringify({ sessions }));
|
|
162
|
-
} else if (sessions.length === 0) {
|
|
163
|
-
console.log(options.tag ? `No sessions tagged "${options.tag}" on this machine.` : "No sessions found on this machine.");
|
|
164
|
-
} else {
|
|
165
|
-
for (const summary of sessions) console.log(formatSummaryLine(summary));
|
|
166
|
-
}
|
|
167
|
-
process.exit(0);
|
|
168
|
-
}
|
|
169
|
-
const sessionId = options.sessionId;
|
|
170
|
-
if (options.action === "read") {
|
|
171
|
-
const result = await index.readSessionTranscript(sessionId, options.limit ?? 20);
|
|
172
|
-
if (options.json) {
|
|
173
|
-
console.log(JSON.stringify(result));
|
|
174
|
-
} else {
|
|
175
|
-
console.log(formatSummaryLine(result.summary));
|
|
176
|
-
console.log(`--- last ${result.messageCount} message(s) ---`);
|
|
177
|
-
console.log(result.transcript.length > 0 ? result.transcript : "(no readable conversation content in this range)");
|
|
178
|
-
}
|
|
179
|
-
process.exit(0);
|
|
180
|
-
}
|
|
181
|
-
if (options.action === "stop") {
|
|
182
|
-
const stopped = await index.stopSession(sessionId);
|
|
183
|
-
if (!stopped) {
|
|
184
|
-
if (options.json) console.log(JSON.stringify({ sessionId, stopped: false }));
|
|
185
|
-
console.error(chalk.red("Error:"), `Session ${sessionId} is not among the daemon's running sessions.`);
|
|
186
|
-
process.exit(1);
|
|
187
|
-
}
|
|
188
|
-
if (options.json) console.log(JSON.stringify({ sessionId, stopped: true }));
|
|
189
|
-
else console.log(`Stopped ${sessionId}`);
|
|
190
|
-
process.exit(0);
|
|
191
|
-
}
|
|
192
|
-
await index.archiveSession(sessionId);
|
|
193
|
-
if (options.json) console.log(JSON.stringify({ sessionId, archived: true }));
|
|
194
|
-
else console.log(`Archived ${sessionId}`);
|
|
195
|
-
process.exit(0);
|
|
196
|
-
} catch (error) {
|
|
197
|
-
console.error(chalk.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
198
|
-
process.exit(1);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
exports.SESSIONS_HELP = SESSIONS_HELP;
|
|
203
|
-
exports.handleSessionsCommand = handleSessionsCommand;
|
|
204
|
-
exports.parseSessionsArgs = parseSessionsArgs;
|