very-happy-cli 0.2.77 → 0.2.79
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-CsLnh1So.cjs → AcpBackend-BuxJntPo.cjs} +1 -1
- package/dist/{AcpBackend-BFFC77vV.mjs → AcpBackend-DPcRh_3n.mjs} +1 -1
- package/dist/{AcpSessionManager--CixPN-p.cjs → AcpSessionManager-BOZPQZUQ.cjs} +1 -1
- package/dist/{AcpSessionManager-CU5vsxgF.mjs → AcpSessionManager-DVGWPtBC.mjs} +1 -1
- package/dist/{config-pv17N6Kg.cjs → config-DB0v5eoc.cjs} +2 -2
- package/dist/{config-CRFTYuTN.mjs → config-T7eM_8eT.mjs} +2 -2
- package/dist/{index-Dcv1RKe8.cjs → index-BGvGqzc1.cjs} +252 -73
- package/dist/{index-BkvUwyIU.mjs → index-CuLe9SB7.mjs} +5 -5
- package/dist/{index-C1OnwMx0.cjs → index-D_ZjCYNI.cjs} +4 -4
- package/dist/{index-DOb57EGb.mjs → index-HYOkniru.mjs} +249 -70
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{installTerminalHooks-YyT3fv6w.cjs → installTerminalHooks-CAViJyYh.cjs} +2 -2
- package/dist/{installTerminalHooks-IXvZMGJq.mjs → installTerminalHooks-CPKThY28.mjs} +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +11 -2
- package/dist/lib.d.mts +11 -2
- package/dist/lib.mjs +1 -1
- package/dist/{mcp-CsKnmeE5.cjs → mcp-DhQcmKO7.cjs} +2 -2
- package/dist/{mcp-B-GdhlKD.mjs → mcp-DhUA22wj.mjs} +2 -2
- package/dist/{runGemini-D0lddF43.mjs → runGemini-BVxviS8T.mjs} +4 -4
- package/dist/{runGemini-DuUdmlVZ.cjs → runGemini-CfWCL9K7.cjs} +4 -4
- package/dist/{runOpenClaw-BiwwYnYf.mjs → runOpenClaw-DVTaZJtj.mjs} +3 -3
- package/dist/{runOpenClaw-DEMCYSoD.cjs → runOpenClaw-kSy7Os3C.cjs} +3 -3
- package/dist/{send-DM8oqJFp.mjs → send-DjjJQXJt.mjs} +2 -2
- package/dist/{send-DijSXAMp.cjs → send-jzwPToBN.cjs} +2 -2
- package/dist/{spawn-nISXbZD5.mjs → spawn-DBpgsEkS.mjs} +2 -2
- package/dist/{spawn-De3b5Hsu.cjs → spawn-DFnYIiKP.cjs} +2 -2
- package/dist/{types-D2qSKjsO.mjs → types-BRDN6zN2.mjs} +92 -14
- package/dist/{types-NwtcBgfS.cjs → types-Dy7P_1bh.cjs} +93 -15
- package/package.json +7 -7
|
@@ -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.79";
|
|
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.79",
|
|
168
|
+
"very-happy-tools-x64-darwin": "0.2.79",
|
|
169
|
+
"very-happy-tools-arm64-linux": "0.2.79",
|
|
170
|
+
"very-happy-tools-x64-linux": "0.2.79",
|
|
171
|
+
"very-happy-tools-arm64-win32": "0.2.79",
|
|
172
|
+
"very-happy-tools-x64-win32": "0.2.79"
|
|
173
173
|
};
|
|
174
174
|
var devDependencies = {
|
|
175
175
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -694,6 +694,9 @@ const sessionTurnUsageSchema = z__namespace.object({
|
|
|
694
694
|
const sessionTurnEndEventSchema = z__namespace.object({
|
|
695
695
|
t: z__namespace.literal("turn-end"),
|
|
696
696
|
status: sessionTurnEndStatusSchema,
|
|
697
|
+
// Human-readable SDK failure detail. Optional for backward compatibility;
|
|
698
|
+
// successful and cancelled turns normally omit it.
|
|
699
|
+
error: z__namespace.string().optional(),
|
|
697
700
|
// Optional per-turn metadata sourced from the SDK result message. Present
|
|
698
701
|
// only on turns ended by a result event; absent on lazily-closed turns.
|
|
699
702
|
costUsd: z__namespace.number().optional(),
|
|
@@ -960,6 +963,9 @@ const CliUpdateStateSchema = z.z.object({
|
|
|
960
963
|
const WebTerminalListItemSchema = z.z.object({
|
|
961
964
|
id: z.z.string(),
|
|
962
965
|
title: z.z.string().optional(),
|
|
966
|
+
/** New daemons always send an array (including []); absence identifies an
|
|
967
|
+
* old daemon that cannot persist terminal tags. */
|
|
968
|
+
tags: z.z.array(z.z.string()).optional(),
|
|
963
969
|
cwd: z.z.string().optional(),
|
|
964
970
|
createdAt: z.z.number().optional(),
|
|
965
971
|
activityAt: z.z.number().optional(),
|
|
@@ -1474,7 +1480,7 @@ class RpcHandlerManager {
|
|
|
1474
1480
|
}
|
|
1475
1481
|
}
|
|
1476
1482
|
|
|
1477
|
-
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-
|
|
1483
|
+
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-Dy7P_1bh.cjs', document.baseURI).href))));
|
|
1478
1484
|
function projectPath() {
|
|
1479
1485
|
const path = path$1.resolve(__dirname$1, "..");
|
|
1480
1486
|
return path;
|
|
@@ -2466,12 +2472,14 @@ function closeTurn(state, status, envelopes, meta) {
|
|
|
2466
2472
|
envelopes.push(createEnvelope("agent", {
|
|
2467
2473
|
t: "turn-end",
|
|
2468
2474
|
status,
|
|
2475
|
+
...meta?.error ? { error: meta.error } : {},
|
|
2469
2476
|
...typeof meta?.costUsd === "number" ? { costUsd: meta.costUsd } : {},
|
|
2470
2477
|
...typeof meta?.durationMs === "number" ? { durationMs: meta.durationMs } : {},
|
|
2471
2478
|
...typeof meta?.numTurns === "number" ? { numTurns: meta.numTurns } : {},
|
|
2472
2479
|
...meta?.usage ? { usage: meta.usage } : {}
|
|
2473
2480
|
}, { turn: state.currentTurnId }));
|
|
2474
2481
|
state.currentTurnId = null;
|
|
2482
|
+
state.pendingAssistantError = void 0;
|
|
2475
2483
|
clearSubagentTracking(state);
|
|
2476
2484
|
}
|
|
2477
2485
|
function toolTitle(name, input) {
|
|
@@ -2492,9 +2500,9 @@ function toToolArgs(input) {
|
|
|
2492
2500
|
}
|
|
2493
2501
|
return { input };
|
|
2494
2502
|
}
|
|
2495
|
-
function closeClaudeTurnWithStatus(state, status) {
|
|
2503
|
+
function closeClaudeTurnWithStatus(state, status, meta) {
|
|
2496
2504
|
const envelopes = [];
|
|
2497
|
-
closeTurn(state, status, envelopes);
|
|
2505
|
+
closeTurn(state, status, envelopes, meta);
|
|
2498
2506
|
return {
|
|
2499
2507
|
currentTurnId: state.currentTurnId,
|
|
2500
2508
|
envelopes
|
|
@@ -2535,6 +2543,10 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
|
|
|
2535
2543
|
};
|
|
2536
2544
|
}
|
|
2537
2545
|
if (message.type === "assistant") {
|
|
2546
|
+
const assistantError = message.error;
|
|
2547
|
+
if (!message.isSidechain && typeof assistantError === "string" && assistantError.trim()) {
|
|
2548
|
+
state.pendingAssistantError = assistantError.trim();
|
|
2549
|
+
}
|
|
2538
2550
|
const turnId = ensureTurn(state, envelopes);
|
|
2539
2551
|
maybeEmitSubagentStart(state, turnId, subagent, envelopes);
|
|
2540
2552
|
const usage = pickAssistantUsage(message);
|
|
@@ -2656,6 +2668,10 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
|
|
|
2656
2668
|
if (message.type === "result") {
|
|
2657
2669
|
const raw = message;
|
|
2658
2670
|
const status = raw.is_error === true ? "failed" : "completed";
|
|
2671
|
+
const error = status === "failed" ? raw.errors?.filter((item) => typeof item === "string" && item.trim()).join("\n") || state.pendingAssistantError || raw.subtype || "Claude turn failed" : void 0;
|
|
2672
|
+
if (status === "failed" && !state.currentTurnId) {
|
|
2673
|
+
ensureTurn(state, envelopes);
|
|
2674
|
+
}
|
|
2659
2675
|
const usage = raw.usage && typeof raw.usage.input_tokens === "number" && typeof raw.usage.output_tokens === "number" ? {
|
|
2660
2676
|
input_tokens: raw.usage.input_tokens,
|
|
2661
2677
|
output_tokens: raw.usage.output_tokens,
|
|
@@ -2663,6 +2679,7 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
|
|
|
2663
2679
|
...typeof raw.usage.cache_read_input_tokens === "number" ? { cache_read_input_tokens: raw.usage.cache_read_input_tokens } : {}
|
|
2664
2680
|
} : void 0;
|
|
2665
2681
|
closeTurn(state, status, envelopes, {
|
|
2682
|
+
error,
|
|
2666
2683
|
costUsd: typeof raw.total_cost_usd === "number" ? raw.total_cost_usd : void 0,
|
|
2667
2684
|
durationMs: typeof raw.duration_ms === "number" ? raw.duration_ms : void 0,
|
|
2668
2685
|
numTurns: typeof raw.num_turns === "number" ? raw.num_turns : void 0,
|
|
@@ -3398,9 +3415,9 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
3398
3415
|
}));
|
|
3399
3416
|
}
|
|
3400
3417
|
}
|
|
3401
|
-
closeClaudeSessionTurn(status = "completed") {
|
|
3418
|
+
closeClaudeSessionTurn(status = "completed", meta) {
|
|
3402
3419
|
this.emit("turn-ended", status);
|
|
3403
|
-
const mapped = closeClaudeTurnWithStatus(this.claudeSessionProtocolState, status);
|
|
3420
|
+
const mapped = closeClaudeTurnWithStatus(this.claudeSessionProtocolState, status, meta);
|
|
3404
3421
|
this.claudeSessionProtocolState.currentTurnId = mapped.currentTurnId;
|
|
3405
3422
|
for (const envelope of mapped.envelopes) {
|
|
3406
3423
|
this.sendSessionProtocolMessage(envelope);
|
|
@@ -9808,6 +9825,7 @@ function terminalListSignature(items) {
|
|
|
9808
9825
|
const canon = [...items].sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0).map((t) => [
|
|
9809
9826
|
t.id,
|
|
9810
9827
|
t.title ?? "",
|
|
9828
|
+
t.tags ?? [],
|
|
9811
9829
|
t.cwd ?? "",
|
|
9812
9830
|
t.createdAt ?? 0,
|
|
9813
9831
|
Math.floor((t.activityAt ?? 0) / ACTIVITY_SIGNATURE_BUCKET_MS),
|
|
@@ -9841,6 +9859,7 @@ const LIST_SESSIONS_FORMAT = [
|
|
|
9841
9859
|
"#{pane_current_path}",
|
|
9842
9860
|
"#{@vh_title}",
|
|
9843
9861
|
"#{@vh_title_manual}",
|
|
9862
|
+
"#{@vh_tags}",
|
|
9844
9863
|
// B-121: the control-mode client has no `pty.process`, so the agent-state
|
|
9845
9864
|
// fast path lost its live `#{pane_current_command}` equivalent. Carry it in
|
|
9846
9865
|
// the ONE list-sessions call the tracker already makes — the value goes
|
|
@@ -9855,8 +9874,8 @@ const LIST_SESSIONS_FORMAT = [
|
|
|
9855
9874
|
function parseSessionListLine(line) {
|
|
9856
9875
|
if (!line) return void 0;
|
|
9857
9876
|
const parts = line.split(LIST_FIELD_SEP);
|
|
9858
|
-
if (parts.length <
|
|
9859
|
-
const [name, created, activity, cwd, vhTitle, manual, paneCommand] = parts;
|
|
9877
|
+
if (parts.length < 9) return void 0;
|
|
9878
|
+
const [name, created, activity, cwd, vhTitle, manual, vhTags, paneCommand] = parts;
|
|
9860
9879
|
if (!name) return void 0;
|
|
9861
9880
|
return {
|
|
9862
9881
|
name,
|
|
@@ -9865,12 +9884,40 @@ function parseSessionListLine(line) {
|
|
|
9865
9884
|
cwd: cwd || void 0,
|
|
9866
9885
|
vhTitle: vhTitle.trim() || void 0,
|
|
9867
9886
|
manual: manual.trim().length > 0,
|
|
9887
|
+
tags: parseTerminalTags(vhTags),
|
|
9868
9888
|
paneCurrentCommand: paneCommand.trim() || void 0,
|
|
9869
9889
|
// pane_title is last, so anything after field 8 is title content that
|
|
9870
9890
|
// contained the separator — rejoin it rather than dropping it.
|
|
9871
|
-
paneTitle: parts.slice(
|
|
9891
|
+
paneTitle: parts.slice(8).join(LIST_FIELD_SEP) || void 0
|
|
9872
9892
|
};
|
|
9873
9893
|
}
|
|
9894
|
+
const TERMINAL_TAG_MAX_COUNT = 64;
|
|
9895
|
+
const TERMINAL_TAG_MAX_LENGTH = 24;
|
|
9896
|
+
const TERMINAL_TAGS_MAX_BYTES = 4096;
|
|
9897
|
+
function validateTerminalTags(value) {
|
|
9898
|
+
if (!Array.isArray(value) || value.length > TERMINAL_TAG_MAX_COUNT) return void 0;
|
|
9899
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9900
|
+
const out = [];
|
|
9901
|
+
for (const valueTag of value) {
|
|
9902
|
+
if (typeof valueTag !== "string") return void 0;
|
|
9903
|
+
const tag = valueTag.trim().replace(/^#+/, "").trim().replace(/\s+/g, "-").slice(0, TERMINAL_TAG_MAX_LENGTH);
|
|
9904
|
+
if (!tag || tag !== valueTag) return void 0;
|
|
9905
|
+
const key = tag.toLowerCase();
|
|
9906
|
+
if (seen.has(key)) return void 0;
|
|
9907
|
+
seen.add(key);
|
|
9908
|
+
out.push(tag);
|
|
9909
|
+
}
|
|
9910
|
+
if (Buffer.byteLength(JSON.stringify(out), "utf8") > TERMINAL_TAGS_MAX_BYTES) return void 0;
|
|
9911
|
+
return out;
|
|
9912
|
+
}
|
|
9913
|
+
function parseTerminalTags(raw) {
|
|
9914
|
+
if (typeof raw !== "string" || !raw.trim()) return [];
|
|
9915
|
+
try {
|
|
9916
|
+
return validateTerminalTags(JSON.parse(raw)) ?? [];
|
|
9917
|
+
} catch {
|
|
9918
|
+
return [];
|
|
9919
|
+
}
|
|
9920
|
+
}
|
|
9874
9921
|
function classifyPane(currentCommand, tail) {
|
|
9875
9922
|
const cmd = (currentCommand || "").trim().replace(/^-/, "").toLowerCase();
|
|
9876
9923
|
const isShell = SHELL_COMMANDS.has(cmd);
|
|
@@ -11303,6 +11350,8 @@ class WebTerminalManager {
|
|
|
11303
11350
|
out.push({
|
|
11304
11351
|
id,
|
|
11305
11352
|
title,
|
|
11353
|
+
// Always include [] so Web can feature-detect tag support.
|
|
11354
|
+
tags: s.tags,
|
|
11306
11355
|
cwd: s.cwd,
|
|
11307
11356
|
createdAt: s.created,
|
|
11308
11357
|
// tmux last-activity (epoch s) → ms; optional so old daemons
|
|
@@ -11480,6 +11529,25 @@ class WebTerminalManager {
|
|
|
11480
11529
|
return false;
|
|
11481
11530
|
}
|
|
11482
11531
|
}
|
|
11532
|
+
/** Persist terminal tags in tmux, parallel to @vh_title. */
|
|
11533
|
+
setTags(terminalId, tags) {
|
|
11534
|
+
if (!isTmuxAvailable()) return false;
|
|
11535
|
+
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(terminalId)) return false;
|
|
11536
|
+
const valid = validateTerminalTags(tags);
|
|
11537
|
+
if (!valid) return false;
|
|
11538
|
+
const name = `vh-${terminalId}`;
|
|
11539
|
+
try {
|
|
11540
|
+
const r = node_child_process.spawnSync("tmux", ["set-option", "-t", name, "@vh_tags", JSON.stringify(valid)], {
|
|
11541
|
+
stdio: "ignore",
|
|
11542
|
+
env: ptyEnv()
|
|
11543
|
+
});
|
|
11544
|
+
if (r.status !== 0) return false;
|
|
11545
|
+
this.kickListRefresh();
|
|
11546
|
+
return true;
|
|
11547
|
+
} catch {
|
|
11548
|
+
return false;
|
|
11549
|
+
}
|
|
11550
|
+
}
|
|
11483
11551
|
}
|
|
11484
11552
|
|
|
11485
11553
|
const TMUX_TIMEOUT_MS = 3e3;
|
|
@@ -13428,6 +13496,16 @@ class ApiMachineClient {
|
|
|
13428
13496
|
}
|
|
13429
13497
|
return { type: "success" };
|
|
13430
13498
|
});
|
|
13499
|
+
this.rpcHandlerManager.registerHandler("set-terminal-tags", async (params) => {
|
|
13500
|
+
const { terminalId, tags } = params || {};
|
|
13501
|
+
if (!terminalId || !Array.isArray(tags)) {
|
|
13502
|
+
throw new Error("terminalId and tags are required");
|
|
13503
|
+
}
|
|
13504
|
+
if (!this.webTerminal.setTags(terminalId, tags)) {
|
|
13505
|
+
throw new Error("Failed to set terminal tags (invalid tags, tmux unavailable, or session gone)");
|
|
13506
|
+
}
|
|
13507
|
+
return { type: "success" };
|
|
13508
|
+
});
|
|
13431
13509
|
this.rpcHandlerManager.registerHandler("stop-session", (params) => {
|
|
13432
13510
|
const { sessionId } = params || {};
|
|
13433
13511
|
if (!sessionId) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "very-happy-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.79",
|
|
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.79",
|
|
117
|
+
"very-happy-tools-x64-darwin": "0.2.79",
|
|
118
|
+
"very-happy-tools-arm64-linux": "0.2.79",
|
|
119
|
+
"very-happy-tools-x64-linux": "0.2.79",
|
|
120
|
+
"very-happy-tools-arm64-win32": "0.2.79",
|
|
121
|
+
"very-happy-tools-x64-win32": "0.2.79"
|
|
122
122
|
},
|
|
123
123
|
"devDependencies": {
|
|
124
124
|
"@slopus/happy-wire": "workspace:*",
|