very-happy-cli 0.2.89 → 0.2.91
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-DuxcHPyn.mjs → AcpBackend-B5RRlzLU.mjs} +1 -1
- package/dist/{AcpBackend-ClEvE-A-.cjs → AcpBackend-GqveWg8u.cjs} +1 -1
- package/dist/{AcpSessionManager-CGrA8bTm.mjs → AcpSessionManager-Ij1pI5Ex.mjs} +1 -1
- package/dist/{AcpSessionManager-DgbEf8FX.cjs → AcpSessionManager-YcrSZwvq.cjs} +1 -1
- package/dist/{config-BZNnPK1L.cjs → config-C4NCw7Dz.cjs} +2 -2
- package/dist/{config-CdoGLla8.mjs → config-ra8iKxdU.mjs} +2 -2
- package/dist/{index-Bx-UTV3I.cjs → index-C1HIm7NY.cjs} +4 -4
- package/dist/{index-BP2wylez.mjs → index-CB5H7YI6.mjs} +5 -5
- package/dist/{index-DYDAFqAN.cjs → index-FkXJNwiy.cjs} +141 -39
- package/dist/{index-vCgb7QnZ.mjs → index-UCYD5Wk3.mjs} +138 -36
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{installTerminalHooks-T4NE5fmC.cjs → installTerminalHooks-CoK5wNcA.cjs} +2 -2
- package/dist/{installTerminalHooks-C7JS6CBM.mjs → installTerminalHooks-TkkGzzbI.mjs} +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +42 -0
- package/dist/lib.d.mts +42 -0
- package/dist/lib.mjs +1 -1
- package/dist/{mcp-B3EgenZh.mjs → mcp-C3MiqObi.mjs} +2 -2
- package/dist/{mcp-DgPg5mKa.cjs → mcp-DcRvswVI.cjs} +2 -2
- package/dist/{runGemini-B3iv1QRL.mjs → runGemini-BbC0uwUj.mjs} +4 -4
- package/dist/{runGemini-xZnGj7jx.cjs → runGemini-Dnvd2gWq.cjs} +4 -4
- package/dist/{runOpenClaw-CmM4ZLYi.mjs → runOpenClaw--nbqTW3K.mjs} +3 -3
- package/dist/{runOpenClaw-6ZLPeYYZ.cjs → runOpenClaw-CnuTBNQW.cjs} +3 -3
- package/dist/{send-M2ax7UGy.mjs → send-9nJxn09Y.mjs} +2 -2
- package/dist/{send-S9ibMiAt.cjs → send-DkKOPatx.cjs} +2 -2
- package/dist/{spawn-Dx_xnLlg.mjs → spawn-CRW4ioms.mjs} +2 -2
- package/dist/{spawn-ie_kfwQe.cjs → spawn-DE7WhS8Y.cjs} +2 -2
- package/dist/{types-d_104eQF.mjs → types-BKyjG23_.mjs} +304 -52
- package/dist/{types-DLI6sss2.cjs → types-ClDADuxP.cjs} +306 -52
- package/package.json +7 -7
|
@@ -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.91";
|
|
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.91",
|
|
146
|
+
"very-happy-tools-x64-darwin": "0.2.91",
|
|
147
|
+
"very-happy-tools-arm64-linux": "0.2.91",
|
|
148
|
+
"very-happy-tools-x64-linux": "0.2.91",
|
|
149
|
+
"very-happy-tools-arm64-win32": "0.2.91",
|
|
150
|
+
"very-happy-tools-x64-win32": "0.2.91"
|
|
151
151
|
};
|
|
152
152
|
var devDependencies = {
|
|
153
153
|
"@slopus/happy-wire": "workspace:*",
|
|
@@ -639,9 +639,27 @@ const sessionToolCallStartEventSchema = z.object({
|
|
|
639
639
|
description: z.string(),
|
|
640
640
|
args: z.record(z.string(), z.unknown())
|
|
641
641
|
});
|
|
642
|
+
const sessionSubagentResultSchema = z.object({
|
|
643
|
+
text: z.string(),
|
|
644
|
+
truncated: z.boolean().optional()
|
|
645
|
+
});
|
|
646
|
+
const sessionSubagentUsageSchema = z.object({
|
|
647
|
+
toolUses: z.number().optional(),
|
|
648
|
+
totalTokens: z.number().optional(),
|
|
649
|
+
durationMs: z.number().optional()
|
|
650
|
+
});
|
|
642
651
|
const sessionToolCallEndEventSchema = z.object({
|
|
643
652
|
t: z.literal("tool-call-end"),
|
|
644
|
-
call: z.string()
|
|
653
|
+
call: z.string(),
|
|
654
|
+
// Foreground Agent/Task completion: the sub-agent's final report + run
|
|
655
|
+
// totals (SDK `tool_use_result`). Absent for ordinary tools and for the
|
|
656
|
+
// background stub ("Async agent launched").
|
|
657
|
+
result: sessionSubagentResultSchema.extend({
|
|
658
|
+
isError: z.boolean().optional(),
|
|
659
|
+
stats: sessionSubagentUsageSchema.extend({
|
|
660
|
+
toolStats: z.record(z.string(), z.unknown()).optional()
|
|
661
|
+
}).optional()
|
|
662
|
+
}).optional()
|
|
645
663
|
});
|
|
646
664
|
const sessionFileEventSchema = z.object({
|
|
647
665
|
t: z.literal("file"),
|
|
@@ -660,7 +678,10 @@ const sessionTurnStartEventSchema = z.object({
|
|
|
660
678
|
});
|
|
661
679
|
const sessionStartEventSchema = z.object({
|
|
662
680
|
t: z.literal("start"),
|
|
663
|
-
title: z.string().optional()
|
|
681
|
+
title: z.string().optional(),
|
|
682
|
+
// B-260-P2: identity from SDK task_started / Agent tool input.
|
|
683
|
+
description: z.string().optional(),
|
|
684
|
+
subagentType: z.string().optional()
|
|
664
685
|
});
|
|
665
686
|
const sessionTurnEndStatusSchema = z.enum(["completed", "failed", "cancelled"]);
|
|
666
687
|
const sessionTurnUsageSchema = z.object({
|
|
@@ -683,7 +704,21 @@ const sessionTurnEndEventSchema = z.object({
|
|
|
683
704
|
usage: sessionTurnUsageSchema.optional()
|
|
684
705
|
});
|
|
685
706
|
const sessionStopEventSchema = z.object({
|
|
686
|
-
t: z.literal("stop")
|
|
707
|
+
t: z.literal("stop"),
|
|
708
|
+
// B-260-P2: from SDK task_notification. A second `stop` for the same
|
|
709
|
+
// subagent may follow carrying `result` once the notification user message
|
|
710
|
+
// (which holds the <result> block) arrives; consumers fold by subagent id.
|
|
711
|
+
status: z.enum(["completed", "failed", "stopped"]).optional(),
|
|
712
|
+
result: sessionSubagentResultSchema.optional(),
|
|
713
|
+
usage: sessionSubagentUsageSchema.optional()
|
|
714
|
+
});
|
|
715
|
+
const sessionProgressEventSchema = z.object({
|
|
716
|
+
t: z.literal("progress"),
|
|
717
|
+
toolUses: z.number(),
|
|
718
|
+
lastTool: z.string().optional(),
|
|
719
|
+
totalTokens: z.number().optional(),
|
|
720
|
+
durationMs: z.number().optional(),
|
|
721
|
+
summary: z.string().optional()
|
|
687
722
|
});
|
|
688
723
|
const sessionEventSchema = z.discriminatedUnion("t", [
|
|
689
724
|
sessionTextEventSchema,
|
|
@@ -694,7 +729,8 @@ const sessionEventSchema = z.discriminatedUnion("t", [
|
|
|
694
729
|
sessionTurnStartEventSchema,
|
|
695
730
|
sessionStartEventSchema,
|
|
696
731
|
sessionTurnEndEventSchema,
|
|
697
|
-
sessionStopEventSchema
|
|
732
|
+
sessionStopEventSchema,
|
|
733
|
+
sessionProgressEventSchema
|
|
698
734
|
]);
|
|
699
735
|
const sessionEnvelopeSchema = z.object({
|
|
700
736
|
id: z.string(),
|
|
@@ -725,7 +761,14 @@ const sessionEnvelopeSchema = z.object({
|
|
|
725
761
|
path: ["role"]
|
|
726
762
|
});
|
|
727
763
|
}
|
|
728
|
-
if (
|
|
764
|
+
if (envelope.ev.t === "progress" && !envelope.subagent) {
|
|
765
|
+
ctx.addIssue({
|
|
766
|
+
code: z.ZodIssueCode.custom,
|
|
767
|
+
message: "progress events must carry a subagent",
|
|
768
|
+
path: ["subagent"]
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
if ((envelope.ev.t === "start" || envelope.ev.t === "stop" || envelope.ev.t === "progress") && envelope.role !== "agent") {
|
|
729
772
|
ctx.addIssue({
|
|
730
773
|
code: z.ZodIssueCode.custom,
|
|
731
774
|
message: `${envelope.ev.t} events must use role "agent"`,
|
|
@@ -2149,6 +2192,69 @@ function shouldReconnect() {
|
|
|
2149
2192
|
return true;
|
|
2150
2193
|
}
|
|
2151
2194
|
|
|
2195
|
+
const SUBAGENT_RESULT_MAX_CHARS = 16384;
|
|
2196
|
+
const SUBAGENT_PROGRESS_MIN_INTERVAL_MS = 5e3;
|
|
2197
|
+
function capSubagentText(text, max = SUBAGENT_RESULT_MAX_CHARS) {
|
|
2198
|
+
const trimmed = text.trim();
|
|
2199
|
+
if (trimmed.length <= max) return { text: trimmed };
|
|
2200
|
+
return { text: trimmed.slice(0, max), truncated: true };
|
|
2201
|
+
}
|
|
2202
|
+
function toolUseResultToText(toolUseResult) {
|
|
2203
|
+
if (!toolUseResult || typeof toolUseResult !== "object") return null;
|
|
2204
|
+
const content = toolUseResult.content;
|
|
2205
|
+
if (typeof content === "string") return content;
|
|
2206
|
+
if (!Array.isArray(content)) return null;
|
|
2207
|
+
const parts = [];
|
|
2208
|
+
for (const block of content) {
|
|
2209
|
+
if (block && typeof block === "object" && block.type === "text" && typeof block.text === "string") {
|
|
2210
|
+
parts.push(block.text);
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
return parts.length > 0 ? parts.join("\n") : null;
|
|
2214
|
+
}
|
|
2215
|
+
function toolUseResultStatus(toolUseResult) {
|
|
2216
|
+
if (!toolUseResult || typeof toolUseResult !== "object") return "unknown";
|
|
2217
|
+
const status = toolUseResult.status;
|
|
2218
|
+
if (status === "async_launched") return "async_launched";
|
|
2219
|
+
if (status === "completed") return "completed";
|
|
2220
|
+
return "unknown";
|
|
2221
|
+
}
|
|
2222
|
+
function toolUseResultStats(toolUseResult) {
|
|
2223
|
+
if (!toolUseResult || typeof toolUseResult !== "object") return void 0;
|
|
2224
|
+
const r = toolUseResult;
|
|
2225
|
+
const stats = {};
|
|
2226
|
+
if (typeof r.totalToolUseCount === "number") stats.toolUses = r.totalToolUseCount;
|
|
2227
|
+
if (typeof r.totalTokens === "number") stats.totalTokens = r.totalTokens;
|
|
2228
|
+
if (typeof r.totalDurationMs === "number") stats.durationMs = r.totalDurationMs;
|
|
2229
|
+
if (r.toolStats && typeof r.toolStats === "object") stats.toolStats = r.toolStats;
|
|
2230
|
+
return Object.keys(stats).length > 0 ? stats : void 0;
|
|
2231
|
+
}
|
|
2232
|
+
function parseTaskNotificationText(text) {
|
|
2233
|
+
if (!/<task-notification>/i.test(text)) return null;
|
|
2234
|
+
const pick = (tag) => text.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`, "i"))?.[1] ?? null;
|
|
2235
|
+
const rawStatus = pick("status")?.trim().toLowerCase() ?? null;
|
|
2236
|
+
const status = rawStatus === "completed" || rawStatus === "failed" || rawStatus === "stopped" ? rawStatus : null;
|
|
2237
|
+
let resultText = pick("result");
|
|
2238
|
+
let result = null;
|
|
2239
|
+
if (resultText !== null) {
|
|
2240
|
+
resultText = resultText.replace(/^\s*\[harness:[^\]]*\]\s*/i, "").replace(/<usage>[\s\S]*?<\/usage>/gi, "").trim();
|
|
2241
|
+
if (resultText.length > 0) result = capSubagentText(resultText);
|
|
2242
|
+
}
|
|
2243
|
+
return {
|
|
2244
|
+
toolUseId: pick("tool-use-id")?.trim() || null,
|
|
2245
|
+
taskId: pick("task-id")?.trim() || null,
|
|
2246
|
+
status,
|
|
2247
|
+
summary: pick("summary")?.trim() || null,
|
|
2248
|
+
result
|
|
2249
|
+
};
|
|
2250
|
+
}
|
|
2251
|
+
function shouldEmitProgress(previous, toolUses, now) {
|
|
2252
|
+
if (!previous) return true;
|
|
2253
|
+
if (previous.lastToolUses === toolUses) return false;
|
|
2254
|
+
return now - previous.lastAt >= SUBAGENT_PROGRESS_MIN_INTERVAL_MS;
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
const SUBAGENT_BUFFER_MAX_MESSAGES = 100;
|
|
2152
2258
|
function isSubagentTool(name) {
|
|
2153
2259
|
return name === "Task" || name === "Agent";
|
|
2154
2260
|
}
|
|
@@ -2217,6 +2323,7 @@ function bufferSubagentMessage(state, subagent, message) {
|
|
|
2217
2323
|
const buffer = getBufferedSubagentMessages(state);
|
|
2218
2324
|
const queue = buffer.get(subagent) ?? [];
|
|
2219
2325
|
queue.push(message);
|
|
2326
|
+
while (queue.length > SUBAGENT_BUFFER_MAX_MESSAGES) queue.shift();
|
|
2220
2327
|
buffer.set(subagent, queue);
|
|
2221
2328
|
}
|
|
2222
2329
|
function consumeBufferedSubagentMessages(state, subagent) {
|
|
@@ -2237,6 +2344,31 @@ function getActiveSubagents(state) {
|
|
|
2237
2344
|
}
|
|
2238
2345
|
return state.activeSubagents;
|
|
2239
2346
|
}
|
|
2347
|
+
function getAgentToolCalls(state) {
|
|
2348
|
+
if (!state.agentToolCalls) state.agentToolCalls = /* @__PURE__ */ new Set();
|
|
2349
|
+
return state.agentToolCalls;
|
|
2350
|
+
}
|
|
2351
|
+
function getSubagentMeta(state) {
|
|
2352
|
+
if (!state.subagentMeta) state.subagentMeta = /* @__PURE__ */ new Map();
|
|
2353
|
+
return state.subagentMeta;
|
|
2354
|
+
}
|
|
2355
|
+
function getStubSubagents(state) {
|
|
2356
|
+
if (!state.stubSubagents) state.stubSubagents = /* @__PURE__ */ new Set();
|
|
2357
|
+
return state.stubSubagents;
|
|
2358
|
+
}
|
|
2359
|
+
function getProgressThrottle(state) {
|
|
2360
|
+
if (!state.progressThrottle) state.progressThrottle = /* @__PURE__ */ new Map();
|
|
2361
|
+
return state.progressThrottle;
|
|
2362
|
+
}
|
|
2363
|
+
function nowOf(state) {
|
|
2364
|
+
return state.now ? state.now() : Date.now();
|
|
2365
|
+
}
|
|
2366
|
+
function rememberSubagentMeta(state, subagent, meta) {
|
|
2367
|
+
const existing = getSubagentMeta(state).get(subagent) ?? {};
|
|
2368
|
+
const description = typeof meta.description === "string" && meta.description.trim() ? meta.description.trim() : existing.description;
|
|
2369
|
+
const subagentType = typeof meta.subagentType === "string" && meta.subagentType.trim() ? meta.subagentType.trim() : existing.subagentType;
|
|
2370
|
+
getSubagentMeta(state).set(subagent, { ...description ? { description } : {}, ...subagentType ? { subagentType } : {} });
|
|
2371
|
+
}
|
|
2240
2372
|
function pickAssistantUsage(message) {
|
|
2241
2373
|
if (message.type !== "assistant") return void 0;
|
|
2242
2374
|
const usage = message.message?.usage;
|
|
@@ -2413,13 +2545,26 @@ function maybeEmitSubagentStart(state, turn, subagent, envelopes) {
|
|
|
2413
2545
|
return;
|
|
2414
2546
|
}
|
|
2415
2547
|
const title = getSubagentTitles(state).get(subagent);
|
|
2548
|
+
const meta = getSubagentMeta(state).get(subagent);
|
|
2416
2549
|
envelopes.push(createEnvelope("agent", {
|
|
2417
2550
|
t: "start",
|
|
2418
|
-
...title ? { title } : {}
|
|
2551
|
+
...title ? { title } : {},
|
|
2552
|
+
...meta?.description ? { description: meta.description } : {},
|
|
2553
|
+
...meta?.subagentType ? { subagentType: meta.subagentType } : {}
|
|
2419
2554
|
}, { turn, subagent }));
|
|
2420
2555
|
started.add(subagent);
|
|
2421
2556
|
getActiveSubagents(state).add(subagent);
|
|
2422
2557
|
}
|
|
2558
|
+
function emitSubagentStopWithStatus(state, turn, subagent, envelopes, payload) {
|
|
2559
|
+
envelopes.push(createEnvelope("agent", {
|
|
2560
|
+
t: "stop",
|
|
2561
|
+
...payload.status ? { status: payload.status } : {},
|
|
2562
|
+
...payload.result ? { result: payload.result } : {},
|
|
2563
|
+
...payload.usage ? { usage: payload.usage } : {}
|
|
2564
|
+
}, { ...turn ? { turn } : {}, subagent }));
|
|
2565
|
+
getActiveSubagents(state).delete(subagent);
|
|
2566
|
+
getStartedSubagents(state).delete(subagent);
|
|
2567
|
+
}
|
|
2423
2568
|
function maybeEmitSubagentStop(state, turn, subagent, envelopes) {
|
|
2424
2569
|
const active = getActiveSubagents(state);
|
|
2425
2570
|
if (!active.has(subagent)) {
|
|
@@ -2431,8 +2576,6 @@ function maybeEmitSubagentStop(state, turn, subagent, envelopes) {
|
|
|
2431
2576
|
function clearSubagentTracking(state) {
|
|
2432
2577
|
getUuidToProviderSubagent(state).clear();
|
|
2433
2578
|
getTaskPromptToSubagents(state).clear();
|
|
2434
|
-
getProviderSubagentToSessionSubagent(state).clear();
|
|
2435
|
-
getSubagentTitles(state).clear();
|
|
2436
2579
|
getBufferedSubagentMessages(state).clear();
|
|
2437
2580
|
getHiddenParentToolCalls(state).clear();
|
|
2438
2581
|
getStartedSubagents(state).clear();
|
|
@@ -2493,6 +2636,58 @@ function closeClaudeTurnWithStatus(state, status, meta) {
|
|
|
2493
2636
|
function mapClaudeLogMessageToSessionEnvelopes(message, state) {
|
|
2494
2637
|
return mapClaudeLogMessageToSessionEnvelopesInternal(message, state);
|
|
2495
2638
|
}
|
|
2639
|
+
function mapTaskLifecycleSystemMessage(message, state, envelopes) {
|
|
2640
|
+
const raw = message;
|
|
2641
|
+
const subtype = typeof raw.subtype === "string" ? raw.subtype : "";
|
|
2642
|
+
if (!subtype.startsWith("task_")) return;
|
|
2643
|
+
if (raw.skip_transcript === true) return;
|
|
2644
|
+
const toolUseId = typeof raw.tool_use_id === "string" && raw.tool_use_id.length > 0 ? raw.tool_use_id : null;
|
|
2645
|
+
if (!toolUseId || !getAgentToolCalls(state).has(toolUseId)) return;
|
|
2646
|
+
const subagent = ensureSessionSubagentIdForProviderSubagent(state, toolUseId);
|
|
2647
|
+
const usage = raw.usage && typeof raw.usage === "object" ? {
|
|
2648
|
+
...typeof raw.usage.tool_uses === "number" ? { toolUses: raw.usage.tool_uses } : {},
|
|
2649
|
+
...typeof raw.usage.total_tokens === "number" ? { totalTokens: raw.usage.total_tokens } : {},
|
|
2650
|
+
...typeof raw.usage.duration_ms === "number" ? { durationMs: raw.usage.duration_ms } : {}
|
|
2651
|
+
} : void 0;
|
|
2652
|
+
if (subtype === "task_started") {
|
|
2653
|
+
rememberSubagentMeta(state, subagent, { description: raw.description, subagentType: raw.subagent_type });
|
|
2654
|
+
const turn = ensureTurn(state, envelopes);
|
|
2655
|
+
getStartedSubagents(state).delete(subagent);
|
|
2656
|
+
maybeEmitSubagentStart(state, turn, subagent, envelopes);
|
|
2657
|
+
return;
|
|
2658
|
+
}
|
|
2659
|
+
if (subtype === "task_progress") {
|
|
2660
|
+
const toolUses = typeof raw.usage?.tool_uses === "number" ? raw.usage.tool_uses : 0;
|
|
2661
|
+
const throttle = getProgressThrottle(state);
|
|
2662
|
+
const now = nowOf(state);
|
|
2663
|
+
if (!shouldEmitProgress(throttle.get(subagent), toolUses, now)) return;
|
|
2664
|
+
throttle.set(subagent, { lastAt: now, lastToolUses: toolUses });
|
|
2665
|
+
const turn = ensureTurn(state, envelopes);
|
|
2666
|
+
maybeEmitSubagentStart(state, turn, subagent, envelopes);
|
|
2667
|
+
envelopes.push(createEnvelope("agent", {
|
|
2668
|
+
t: "progress",
|
|
2669
|
+
toolUses,
|
|
2670
|
+
...typeof raw.last_tool_name === "string" && raw.last_tool_name ? { lastTool: raw.last_tool_name } : {},
|
|
2671
|
+
...usage?.totalTokens !== void 0 ? { totalTokens: usage.totalTokens } : {},
|
|
2672
|
+
...usage?.durationMs !== void 0 ? { durationMs: usage.durationMs } : {},
|
|
2673
|
+
...typeof raw.summary === "string" && raw.summary.trim() ? { summary: raw.summary.trim() } : {}
|
|
2674
|
+
}, { turn, subagent }));
|
|
2675
|
+
return;
|
|
2676
|
+
}
|
|
2677
|
+
if (subtype === "task_notification") {
|
|
2678
|
+
const status = raw.status === "completed" || raw.status === "failed" || raw.status === "stopped" ? raw.status : "completed";
|
|
2679
|
+
emitSubagentStopWithStatus(state, state.currentTurnId ?? void 0, subagent, envelopes, {
|
|
2680
|
+
status,
|
|
2681
|
+
...usage ? { usage } : {}
|
|
2682
|
+
});
|
|
2683
|
+
getStubSubagents(state).delete(subagent);
|
|
2684
|
+
getProgressThrottle(state).delete(subagent);
|
|
2685
|
+
return;
|
|
2686
|
+
}
|
|
2687
|
+
if (subtype === "task_updated" && raw.patch?.is_backgrounded === true) {
|
|
2688
|
+
getStubSubagents(state).add(subagent);
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2496
2691
|
function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
|
|
2497
2692
|
const envelopes = [];
|
|
2498
2693
|
const claudeUuid = pickUuid(message);
|
|
@@ -2513,6 +2708,7 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
|
|
|
2513
2708
|
};
|
|
2514
2709
|
}
|
|
2515
2710
|
if (message.type === "system") {
|
|
2711
|
+
mapTaskLifecycleSystemMessage(message, state, envelopes);
|
|
2516
2712
|
return {
|
|
2517
2713
|
currentTurnId: state.currentTurnId,
|
|
2518
2714
|
envelopes
|
|
@@ -2554,6 +2750,9 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
|
|
|
2554
2750
|
queueTaskPromptSubagent(state, prompt, call);
|
|
2555
2751
|
}
|
|
2556
2752
|
setSubagentTitle(state, sessionSubagentForCall, pickTaskTitle(block.input) ?? prompt);
|
|
2753
|
+
getAgentToolCalls(state).add(call);
|
|
2754
|
+
const input = block.input ?? {};
|
|
2755
|
+
rememberSubagentMeta(state, sessionSubagentForCall, { description: input.description, subagentType: input.subagent_type });
|
|
2557
2756
|
}
|
|
2558
2757
|
if (shouldHideParentToolCall(name)) {
|
|
2559
2758
|
getHiddenParentToolCalls(state).add(call);
|
|
@@ -2598,6 +2797,18 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
|
|
|
2598
2797
|
maybeEmitSubagentStart(state, turnId2, subagent, envelopes);
|
|
2599
2798
|
envelopes.push(createEnvelope("agent", { t: "text", text: message.message.content }, { turn: turnId2, subagent, claudeUuid }));
|
|
2600
2799
|
} else {
|
|
2800
|
+
const origin = message.origin;
|
|
2801
|
+
if (origin?.kind === "task-notification" || /<task-notification>/i.test(message.message.content)) {
|
|
2802
|
+
const fields = parseTaskNotificationText(message.message.content);
|
|
2803
|
+
const providerId = fields?.toolUseId ?? null;
|
|
2804
|
+
const subagentForNotification = providerId && getAgentToolCalls(state).has(providerId) ? getSessionSubagentIdForProviderSubagent(state, providerId) : void 0;
|
|
2805
|
+
if (fields && subagentForNotification && (fields.result || fields.status)) {
|
|
2806
|
+
emitSubagentStopWithStatus(state, state.currentTurnId ?? void 0, subagentForNotification, envelopes, {
|
|
2807
|
+
...fields.status ? { status: fields.status } : {},
|
|
2808
|
+
...fields.result ? { result: fields.result } : {}
|
|
2809
|
+
});
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2601
2812
|
closeTurn(state, "completed", envelopes);
|
|
2602
2813
|
envelopes.push(createEnvelope("user", { t: "text", text: message.message.content }, { claudeUuid }));
|
|
2603
2814
|
}
|
|
@@ -2628,6 +2839,31 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
|
|
|
2628
2839
|
getHiddenParentToolCalls(state).delete(block.tool_use_id);
|
|
2629
2840
|
continue;
|
|
2630
2841
|
}
|
|
2842
|
+
if (sessionSubagentForToolResult && getAgentToolCalls(state).has(block.tool_use_id)) {
|
|
2843
|
+
const toolUseResult = message.tool_use_result;
|
|
2844
|
+
const resultStatus = toolUseResultStatus(toolUseResult);
|
|
2845
|
+
if (resultStatus === "async_launched") {
|
|
2846
|
+
getStubSubagents(state).add(sessionSubagentForToolResult);
|
|
2847
|
+
envelopes.push(createEnvelope("agent", { t: "tool-call-end", call: block.tool_use_id }, { turn: turnId, subagent }));
|
|
2848
|
+
continue;
|
|
2849
|
+
}
|
|
2850
|
+
if (resultStatus === "completed") {
|
|
2851
|
+
const text = toolUseResultToText(toolUseResult);
|
|
2852
|
+
const stats = toolUseResultStats(toolUseResult);
|
|
2853
|
+
const result = text ? capSubagentText(text) : void 0;
|
|
2854
|
+
emitSubagentStopWithStatus(state, turnId, sessionSubagentForToolResult, envelopes, {
|
|
2855
|
+
status: "completed",
|
|
2856
|
+
...result ? { result } : {},
|
|
2857
|
+
...stats ? { usage: { toolUses: stats.toolUses, totalTokens: stats.totalTokens, durationMs: stats.durationMs } } : {}
|
|
2858
|
+
});
|
|
2859
|
+
envelopes.push(createEnvelope("agent", {
|
|
2860
|
+
t: "tool-call-end",
|
|
2861
|
+
call: block.tool_use_id,
|
|
2862
|
+
...result ? { result: { ...result, ...stats ? { stats } : {} } } : {}
|
|
2863
|
+
}, { turn: turnId, subagent }));
|
|
2864
|
+
continue;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2631
2867
|
if (sessionSubagentForToolResult) {
|
|
2632
2868
|
maybeEmitSubagentStop(state, turnId, sessionSubagentForToolResult, envelopes);
|
|
2633
2869
|
}
|
|
@@ -8807,6 +9043,20 @@ function previewAscii(line) {
|
|
|
8807
9043
|
return line.length > 80 ? `${out}\u2026` : out;
|
|
8808
9044
|
}
|
|
8809
9045
|
|
|
9046
|
+
const VH_TMUX_SOCKET_ENV = "VH_TMUX_SOCKET";
|
|
9047
|
+
function tmuxSocketFlags(env = process.env) {
|
|
9048
|
+
const socket = env[VH_TMUX_SOCKET_ENV];
|
|
9049
|
+
return socket ? ["-S", socket] : [];
|
|
9050
|
+
}
|
|
9051
|
+
function tmuxArgs(args, env = process.env) {
|
|
9052
|
+
return [...tmuxSocketFlags(env), ...args];
|
|
9053
|
+
}
|
|
9054
|
+
function scrubTmuxClientEnv(env) {
|
|
9055
|
+
delete env.TMUX;
|
|
9056
|
+
delete env.TMUX_PANE;
|
|
9057
|
+
return env;
|
|
9058
|
+
}
|
|
9059
|
+
|
|
8810
9060
|
const CONTROL_CLIENT_KILL_GRACE_MS = 2e3;
|
|
8811
9061
|
const CONTROL_COMMAND_TIMEOUT_MS = 1e4;
|
|
8812
9062
|
function isSafeControlCommand(command) {
|
|
@@ -8816,7 +9066,7 @@ class ControlClient {
|
|
|
8816
9066
|
constructor(tmuxSession, env, handlers) {
|
|
8817
9067
|
this.tmuxSession = tmuxSession;
|
|
8818
9068
|
this.handlers = handlers;
|
|
8819
|
-
this.child = spawn$2("tmux", ["-C", "attach-session", "-t", `=${tmuxSession}:`], {
|
|
9069
|
+
this.child = spawn$2("tmux", tmuxArgs(["-C", "attach-session", "-t", `=${tmuxSession}:`], env), {
|
|
8820
9070
|
stdio: ["pipe", "pipe", "pipe"],
|
|
8821
9071
|
env
|
|
8822
9072
|
});
|
|
@@ -9968,7 +10218,7 @@ let tmuxAvailableCache = null;
|
|
|
9968
10218
|
function isTmuxAvailable() {
|
|
9969
10219
|
if (tmuxAvailableCache !== null) return tmuxAvailableCache;
|
|
9970
10220
|
try {
|
|
9971
|
-
const r = spawnSync("tmux", ["-V"], { stdio: "ignore", env: ptyEnv() });
|
|
10221
|
+
const r = spawnSync("tmux", tmuxArgs(["-V"]), { stdio: "ignore", env: ptyEnv() });
|
|
9972
10222
|
tmuxAvailableCache = r.status === 0;
|
|
9973
10223
|
} catch {
|
|
9974
10224
|
tmuxAvailableCache = false;
|
|
@@ -9979,7 +10229,7 @@ let tmuxEnvFlagCache = null;
|
|
|
9979
10229
|
function tmuxSupportsEnvFlag() {
|
|
9980
10230
|
if (tmuxEnvFlagCache !== null) return tmuxEnvFlagCache;
|
|
9981
10231
|
try {
|
|
9982
|
-
const r = spawnSync("tmux", ["-V"], { encoding: "utf8", env: ptyEnv() });
|
|
10232
|
+
const r = spawnSync("tmux", tmuxArgs(["-V"]), { encoding: "utf8", env: ptyEnv() });
|
|
9983
10233
|
tmuxEnvFlagCache = r.status === 0 && tmuxSupportsNewSessionEnv(r.stdout || "");
|
|
9984
10234
|
} catch {
|
|
9985
10235
|
tmuxEnvFlagCache = false;
|
|
@@ -10023,6 +10273,7 @@ function ptyEnv() {
|
|
|
10023
10273
|
for (const [k, v] of Object.entries(process.env)) {
|
|
10024
10274
|
if (typeof v === "string") env[k] = v;
|
|
10025
10275
|
}
|
|
10276
|
+
scrubTmuxClientEnv(env);
|
|
10026
10277
|
const local = `${os$1.homedir()}/.local/bin`;
|
|
10027
10278
|
if (!(env.PATH || "").split(":").includes(local)) {
|
|
10028
10279
|
env.PATH = `${local}:${env.PATH || ""}`;
|
|
@@ -10678,7 +10929,7 @@ class WebTerminalManager {
|
|
|
10678
10929
|
const name = `vh-${plan.terminalId}`;
|
|
10679
10930
|
const exists = spawnSync(
|
|
10680
10931
|
"tmux",
|
|
10681
|
-
["has-session", "-t", `=${name}:`],
|
|
10932
|
+
tmuxArgs(["has-session", "-t", `=${name}:`]),
|
|
10682
10933
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
|
|
10683
10934
|
).status === 0;
|
|
10684
10935
|
if (exists) return false;
|
|
@@ -10692,12 +10943,12 @@ class WebTerminalManager {
|
|
|
10692
10943
|
] : [];
|
|
10693
10944
|
const created = spawnSync(
|
|
10694
10945
|
"tmux",
|
|
10695
|
-
tmuxNewSessionArgs(name, 120, 30, plan.cwd, envFlags, defaultShell()),
|
|
10946
|
+
tmuxArgs(tmuxNewSessionArgs(name, 120, 30, plan.cwd, envFlags, defaultShell())),
|
|
10696
10947
|
{ stdio: "ignore", timeout: TMUX_CREATE_TIMEOUT_MS, env }
|
|
10697
10948
|
);
|
|
10698
10949
|
const live = created.status === 0 && spawnSync(
|
|
10699
10950
|
"tmux",
|
|
10700
|
-
["has-session", "-t", `=${name}:`],
|
|
10951
|
+
tmuxArgs(["has-session", "-t", `=${name}:`]),
|
|
10701
10952
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
|
|
10702
10953
|
).status === 0;
|
|
10703
10954
|
if (!live) {
|
|
@@ -10707,12 +10958,12 @@ class WebTerminalManager {
|
|
|
10707
10958
|
if (plan.title) {
|
|
10708
10959
|
spawnSync(
|
|
10709
10960
|
"tmux",
|
|
10710
|
-
["set-option", "-t", `=${name}:`, "@vh_title", plan.title],
|
|
10961
|
+
tmuxArgs(["set-option", "-t", `=${name}:`, "@vh_title", plan.title]),
|
|
10711
10962
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
|
|
10712
10963
|
);
|
|
10713
10964
|
}
|
|
10714
10965
|
for (const argv of startupInjectionArgs(name, plan.command)) {
|
|
10715
|
-
spawnSync("tmux", argv, { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
|
|
10966
|
+
spawnSync("tmux", tmuxArgs(argv), { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
|
|
10716
10967
|
}
|
|
10717
10968
|
logger.info(`[WEB TERMINAL] auto-restored ${plan.terminalId} in ${plan.cwd}`);
|
|
10718
10969
|
return true;
|
|
@@ -10844,14 +11095,14 @@ class WebTerminalManager {
|
|
|
10844
11095
|
if (opts.attachOnly || opts.resub) {
|
|
10845
11096
|
const alive = isTmuxAvailable() && spawnSync(
|
|
10846
11097
|
"tmux",
|
|
10847
|
-
["has-session", "-t", `=vh-${id}:`],
|
|
11098
|
+
tmuxArgs(["has-session", "-t", `=vh-${id}:`]),
|
|
10848
11099
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
10849
11100
|
).status === 0;
|
|
10850
11101
|
if (!alive) throw new Error("terminal-gone");
|
|
10851
11102
|
} else if (this.tombstones[id]) {
|
|
10852
11103
|
const alive = isTmuxAvailable() && spawnSync(
|
|
10853
11104
|
"tmux",
|
|
10854
|
-
["has-session", "-t", `=vh-${id}:`],
|
|
11105
|
+
tmuxArgs(["has-session", "-t", `=vh-${id}:`]),
|
|
10855
11106
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
10856
11107
|
).status === 0;
|
|
10857
11108
|
if (!alive) {
|
|
@@ -10880,7 +11131,7 @@ class WebTerminalManager {
|
|
|
10880
11131
|
try {
|
|
10881
11132
|
const created = spawnSync(
|
|
10882
11133
|
"tmux",
|
|
10883
|
-
tmuxNewSessionArgs(tmuxSession, cols, rows, cwd, envFlags, defaultShell()),
|
|
11134
|
+
tmuxArgs(tmuxNewSessionArgs(tmuxSession, cols, rows, cwd, envFlags, defaultShell())),
|
|
10884
11135
|
{ stdio: "ignore", timeout: TMUX_CREATE_TIMEOUT_MS, env }
|
|
10885
11136
|
);
|
|
10886
11137
|
createdNew = created.status === 0;
|
|
@@ -10912,7 +11163,7 @@ class WebTerminalManager {
|
|
|
10912
11163
|
];
|
|
10913
11164
|
for (const a of optArgs) {
|
|
10914
11165
|
try {
|
|
10915
|
-
spawnSync("tmux", a, { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
|
|
11166
|
+
spawnSync("tmux", tmuxArgs(a), { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
|
|
10916
11167
|
} catch {
|
|
10917
11168
|
}
|
|
10918
11169
|
}
|
|
@@ -10921,7 +11172,7 @@ class WebTerminalManager {
|
|
|
10921
11172
|
if (startup) {
|
|
10922
11173
|
try {
|
|
10923
11174
|
for (const a of startupInjectionArgs(tmuxSession, startup)) {
|
|
10924
|
-
spawnSync("tmux", a, { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
|
|
11175
|
+
spawnSync("tmux", tmuxArgs(a), { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
|
|
10925
11176
|
}
|
|
10926
11177
|
logger.debug(`[WEB TERMINAL] injected startup command into new session ${tmuxSession}`);
|
|
10927
11178
|
} catch {
|
|
@@ -10931,13 +11182,13 @@ class WebTerminalManager {
|
|
|
10931
11182
|
if (!attachOnly && !createdNew) {
|
|
10932
11183
|
const alive = spawnSync(
|
|
10933
11184
|
"tmux",
|
|
10934
|
-
["has-session", "-t", `=${tmuxSession}:`],
|
|
11185
|
+
tmuxArgs(["has-session", "-t", `=${tmuxSession}:`]),
|
|
10935
11186
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
|
|
10936
11187
|
).status === 0;
|
|
10937
11188
|
if (shouldUseDirectPtyFallback(attachOnly, createdNew, alive)) {
|
|
10938
11189
|
const retry = spawnSync(
|
|
10939
11190
|
"tmux",
|
|
10940
|
-
tmuxNewSessionArgs(tmuxSession, cols, rows, cwd, envFlags, defaultShell()),
|
|
11191
|
+
tmuxArgs(tmuxNewSessionArgs(tmuxSession, cols, rows, cwd, envFlags, defaultShell())),
|
|
10941
11192
|
{ stdio: "ignore", timeout: TMUX_CREATE_TIMEOUT_MS, env }
|
|
10942
11193
|
);
|
|
10943
11194
|
createdNew = retry.status === 0;
|
|
@@ -10946,7 +11197,7 @@ class WebTerminalManager {
|
|
|
10946
11197
|
if (startup) {
|
|
10947
11198
|
for (const a of startupInjectionArgs(tmuxSession, startup)) {
|
|
10948
11199
|
try {
|
|
10949
|
-
spawnSync("tmux", a, { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
|
|
11200
|
+
spawnSync("tmux", tmuxArgs(a), { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
|
|
10950
11201
|
} catch {
|
|
10951
11202
|
}
|
|
10952
11203
|
}
|
|
@@ -10957,7 +11208,7 @@ class WebTerminalManager {
|
|
|
10957
11208
|
if (!attachOnly && !createdNew) {
|
|
10958
11209
|
const alive = spawnSync(
|
|
10959
11210
|
"tmux",
|
|
10960
|
-
["has-session", "-t", `=${tmuxSession}:`],
|
|
11211
|
+
tmuxArgs(["has-session", "-t", `=${tmuxSession}:`]),
|
|
10961
11212
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
|
|
10962
11213
|
).status === 0;
|
|
10963
11214
|
if (!alive) {
|
|
@@ -11284,8 +11535,8 @@ class WebTerminalManager {
|
|
|
11284
11535
|
killSession(terminalId) {
|
|
11285
11536
|
const info = this.lastSeenInfo.get(terminalId) ?? this.listSessions().find((t) => t.id === terminalId);
|
|
11286
11537
|
const target = `=vh-${terminalId}:`;
|
|
11287
|
-
const killed = spawnSync("tmux", ["kill-session", "-t", target], { stdio: "ignore", env: ptyEnv() });
|
|
11288
|
-
const verified = spawnSync("tmux", ["has-session", "-t", target], { stdio: "ignore", env: ptyEnv() });
|
|
11538
|
+
const killed = spawnSync("tmux", tmuxArgs(["kill-session", "-t", target]), { stdio: "ignore", env: ptyEnv() });
|
|
11539
|
+
const verified = spawnSync("tmux", tmuxArgs(["has-session", "-t", target]), { stdio: "ignore", env: ptyEnv() });
|
|
11289
11540
|
if (!tmuxKillVerified(killed, verified)) {
|
|
11290
11541
|
logger.debug(`[WEB TERMINAL] failed to verify tmux session removal ${target}`);
|
|
11291
11542
|
return false;
|
|
@@ -11346,7 +11597,7 @@ class WebTerminalManager {
|
|
|
11346
11597
|
const env = ptyEnv();
|
|
11347
11598
|
const r = spawnSync(
|
|
11348
11599
|
"tmux",
|
|
11349
|
-
["list-sessions", "-F", LIST_SESSIONS_FORMAT],
|
|
11600
|
+
tmuxArgs(["list-sessions", "-F", LIST_SESSIONS_FORMAT]),
|
|
11350
11601
|
{ encoding: "utf8", env }
|
|
11351
11602
|
);
|
|
11352
11603
|
if (r.status !== 0 || !r.stdout) return [];
|
|
@@ -11362,7 +11613,7 @@ class WebTerminalManager {
|
|
|
11362
11613
|
try {
|
|
11363
11614
|
const w = spawnSync(
|
|
11364
11615
|
"tmux",
|
|
11365
|
-
["set-option", "-t", `=${s.name}:`, "@vh_title", auto],
|
|
11616
|
+
tmuxArgs(["set-option", "-t", `=${s.name}:`, "@vh_title", auto]),
|
|
11366
11617
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
|
|
11367
11618
|
);
|
|
11368
11619
|
if (w.status === 0) title = auto;
|
|
@@ -11413,13 +11664,13 @@ class WebTerminalManager {
|
|
|
11413
11664
|
try {
|
|
11414
11665
|
const cmd = spawnSync(
|
|
11415
11666
|
"tmux",
|
|
11416
|
-
["display-message", "-p", "-t", sessionName, "#{pane_current_command}"],
|
|
11667
|
+
tmuxArgs(["display-message", "-p", "-t", sessionName, "#{pane_current_command}"]),
|
|
11417
11668
|
{ encoding: "utf8", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11418
11669
|
);
|
|
11419
11670
|
if (cmd.status !== 0 || typeof cmd.stdout !== "string") return void 0;
|
|
11420
11671
|
const cap = spawnSync(
|
|
11421
11672
|
"tmux",
|
|
11422
|
-
["capture-pane", "-p", "-t", sessionName, "-S", "-40"],
|
|
11673
|
+
tmuxArgs(["capture-pane", "-p", "-t", sessionName, "-S", "-40"]),
|
|
11423
11674
|
{ encoding: "utf8", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11424
11675
|
);
|
|
11425
11676
|
if (cap.status !== 0 || typeof cap.stdout !== "string") return void 0;
|
|
@@ -11446,7 +11697,7 @@ class WebTerminalManager {
|
|
|
11446
11697
|
try {
|
|
11447
11698
|
const probe = spawnSync(
|
|
11448
11699
|
"tmux",
|
|
11449
|
-
["display-message", "-p", "-t", name, "#{pane_in_mode} #{alternate_on} #{mouse_any_flag} #{pane_width} #{pane_height} #{pane_current_command}"],
|
|
11700
|
+
tmuxArgs(["display-message", "-p", "-t", name, "#{pane_in_mode} #{alternate_on} #{mouse_any_flag} #{pane_width} #{pane_height} #{pane_current_command}"]),
|
|
11450
11701
|
{ encoding: "utf8", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11451
11702
|
);
|
|
11452
11703
|
if (probe.status !== 0 || typeof probe.stdout !== "string") return;
|
|
@@ -11464,7 +11715,7 @@ class WebTerminalManager {
|
|
|
11464
11715
|
const hex = sgrWheelHexBytes(action.dir, action.count, Number(paneW) || 80, Number(paneH) || 24);
|
|
11465
11716
|
spawnSync(
|
|
11466
11717
|
"tmux",
|
|
11467
|
-
["send-keys", "-t", name, "-H", ...hex],
|
|
11718
|
+
tmuxArgs(["send-keys", "-t", name, "-H", ...hex]),
|
|
11468
11719
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11469
11720
|
);
|
|
11470
11721
|
return;
|
|
@@ -11472,7 +11723,7 @@ class WebTerminalManager {
|
|
|
11472
11723
|
if (action.kind === "page-keys") {
|
|
11473
11724
|
spawnSync(
|
|
11474
11725
|
"tmux",
|
|
11475
|
-
["send-keys", "-t", name, "-N", String(action.count), action.key],
|
|
11726
|
+
tmuxArgs(["send-keys", "-t", name, "-N", String(action.count), action.key]),
|
|
11476
11727
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11477
11728
|
);
|
|
11478
11729
|
return;
|
|
@@ -11480,19 +11731,19 @@ class WebTerminalManager {
|
|
|
11480
11731
|
if (action.kind === "keys") {
|
|
11481
11732
|
spawnSync(
|
|
11482
11733
|
"tmux",
|
|
11483
|
-
["send-keys", "-t", name, "-N", String(action.count), action.key],
|
|
11734
|
+
tmuxArgs(["send-keys", "-t", name, "-N", String(action.count), action.key]),
|
|
11484
11735
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11485
11736
|
);
|
|
11486
11737
|
return;
|
|
11487
11738
|
}
|
|
11488
11739
|
spawnSync(
|
|
11489
11740
|
"tmux",
|
|
11490
|
-
["copy-mode", "-e", "-t", name],
|
|
11741
|
+
tmuxArgs(["copy-mode", "-e", "-t", name]),
|
|
11491
11742
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11492
11743
|
);
|
|
11493
11744
|
spawnSync(
|
|
11494
11745
|
"tmux",
|
|
11495
|
-
[
|
|
11746
|
+
tmuxArgs([
|
|
11496
11747
|
"send-keys",
|
|
11497
11748
|
"-X",
|
|
11498
11749
|
"-t",
|
|
@@ -11500,7 +11751,7 @@ class WebTerminalManager {
|
|
|
11500
11751
|
"-N",
|
|
11501
11752
|
String(action.count),
|
|
11502
11753
|
action.dir === "up" ? "scroll-up" : "scroll-down"
|
|
11503
|
-
],
|
|
11754
|
+
]),
|
|
11504
11755
|
{ stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
|
|
11505
11756
|
);
|
|
11506
11757
|
} catch {
|
|
@@ -11534,14 +11785,14 @@ class WebTerminalManager {
|
|
|
11534
11785
|
const name = `vh-${terminalId}`;
|
|
11535
11786
|
try {
|
|
11536
11787
|
if (ifAbsent) {
|
|
11537
|
-
const cur = spawnSync("tmux", ["show-options", "-t", name, "-v", "@vh_title"], { encoding: "utf8", env: ptyEnv() });
|
|
11788
|
+
const cur = spawnSync("tmux", tmuxArgs(["show-options", "-t", name, "-v", "@vh_title"]), { encoding: "utf8", env: ptyEnv() });
|
|
11538
11789
|
if (cur.status === 0 && cur.stdout && cur.stdout.trim()) return true;
|
|
11539
11790
|
}
|
|
11540
|
-
const r = spawnSync("tmux", ["set-option", "-t", name, "@vh_title", title], { stdio: "ignore", env: ptyEnv() });
|
|
11791
|
+
const r = spawnSync("tmux", tmuxArgs(["set-option", "-t", name, "@vh_title", title]), { stdio: "ignore", env: ptyEnv() });
|
|
11541
11792
|
if (r.status !== 0) return false;
|
|
11542
11793
|
if (!ifAbsent) {
|
|
11543
11794
|
try {
|
|
11544
|
-
spawnSync("tmux", ["set-option", "-t", name, "@vh_title_manual", "1"], { stdio: "ignore", env: ptyEnv() });
|
|
11795
|
+
spawnSync("tmux", tmuxArgs(["set-option", "-t", name, "@vh_title_manual", "1"]), { stdio: "ignore", env: ptyEnv() });
|
|
11545
11796
|
} catch {
|
|
11546
11797
|
}
|
|
11547
11798
|
}
|
|
@@ -11559,7 +11810,7 @@ class WebTerminalManager {
|
|
|
11559
11810
|
if (!valid) return false;
|
|
11560
11811
|
const name = `vh-${terminalId}`;
|
|
11561
11812
|
try {
|
|
11562
|
-
const r = spawnSync("tmux", ["set-option", "-t", name, "@vh_tags", JSON.stringify(valid)], {
|
|
11813
|
+
const r = spawnSync("tmux", tmuxArgs(["set-option", "-t", name, "@vh_tags", JSON.stringify(valid)]), {
|
|
11563
11814
|
stdio: "ignore",
|
|
11564
11815
|
env: ptyEnv()
|
|
11565
11816
|
});
|
|
@@ -11591,10 +11842,11 @@ function parseVhTerminals(stdout, hostname = os$1.hostname()) {
|
|
|
11591
11842
|
}
|
|
11592
11843
|
function runTmux(args, input) {
|
|
11593
11844
|
try {
|
|
11594
|
-
const r = spawnSync("tmux", args, {
|
|
11845
|
+
const r = spawnSync("tmux", tmuxArgs(args), {
|
|
11595
11846
|
encoding: "utf8",
|
|
11596
11847
|
timeout: TMUX_TIMEOUT_MS,
|
|
11597
|
-
input
|
|
11848
|
+
input,
|
|
11849
|
+
env: scrubTmuxClientEnv({ ...process.env })
|
|
11598
11850
|
});
|
|
11599
11851
|
if (r.error) return { ok: false, stdout: "", error: r.error.message };
|
|
11600
11852
|
if (r.status !== 0) return { ok: false, stdout: r.stdout ?? "", error: (r.stderr || `tmux exited with ${r.status}`).trim() };
|
|
@@ -15149,4 +15401,4 @@ const RawJSONLinesSchema = z$1.discriminatedUnion("type", [
|
|
|
15149
15401
|
}).passthrough()
|
|
15150
15402
|
]);
|
|
15151
15403
|
|
|
15152
|
-
export {
|
|
15404
|
+
export { detectCLIAvailability as $, ApiClient as A, deriveLocalCliUpdateSummary as B, updateSettings as C, encodeBase64Url as D, decodeBase64 as E, writeCredentialsLegacy as F, writeCredentialsDataKey as G, readCredentialsForConfiguredRelay as H, InvalidateSync as I, encrypt as J, getLocalHappyAgentCredentialPath as K, readLocalHappyAgentCredentials as L, MAX_CHAT_ATTACHMENT_SOURCE_BYTES as M, decryptWithDataKey as N, decryptLegacy as O, extractCompleteLines as P, decideBackfill as Q, RawJSONLinesSchema as R, parseTerminalHookPayload as S, tmuxArgs as T, scrubTmuxClientEnv as U, decideMirrorBinding as V, persistSession as W, MIRROR_BACKFILL_LINES_DEFAULT as X, mirrorLineKey as Y, mirrorLocalId as Z, detectResumeSupport as _, ApiSessionClient as a, acquireDaemonLock as a0, summarizeSpawnSessionForLog as a1, deletePersistedSessions as a2, decrypt as a3, writeDaemonState as a4, fetchCliUpdateState as a5, resolveCliUpdateCheckInterval as a6, DEFAULT_CLI_UPDATE_CHECK_INTERVAL_MS as a7, releaseDaemonLock as a8, isValidSessionId as a9, listVhTerminals as aa, isValidTerminalId as ab, readVhTerminal as ac, sendToVhTerminal as ad, startOfflineReconnection as ae, clearCredentials as af, clearMachineId as ag, SandboxConfigSchema as ah, CodexAppServerClient as ai, getLatestDaemonLog as aj, persistence as ak, api as al, createEnvelope as b, configuration as c, contentLogMetadata as d, errorLogMetadata as e, packageJson as f, delay as g, connectionState as h, readSettings as i, encodeBase64 as j, ensurePrivateDirectorySync as k, logger as l, hardenPrivateFileSync as m, readDaemonState as n, clearDaemonState as o, projectPath as p, getProjectPath as q, readPersistedSessions as r, initializeSandbox as s, wrapCommand as t, AsyncLock as u, ensurePrivateDirectory as v, writePrivateFileSync as w, hardenPrivateFile as x, readCredentials as y, credentialRelayProblem as z };
|