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.
Files changed (31) hide show
  1. package/dist/{AcpBackend-DuxcHPyn.mjs → AcpBackend-B5RRlzLU.mjs} +1 -1
  2. package/dist/{AcpBackend-ClEvE-A-.cjs → AcpBackend-GqveWg8u.cjs} +1 -1
  3. package/dist/{AcpSessionManager-CGrA8bTm.mjs → AcpSessionManager-Ij1pI5Ex.mjs} +1 -1
  4. package/dist/{AcpSessionManager-DgbEf8FX.cjs → AcpSessionManager-YcrSZwvq.cjs} +1 -1
  5. package/dist/{config-BZNnPK1L.cjs → config-C4NCw7Dz.cjs} +2 -2
  6. package/dist/{config-CdoGLla8.mjs → config-ra8iKxdU.mjs} +2 -2
  7. package/dist/{index-Bx-UTV3I.cjs → index-C1HIm7NY.cjs} +4 -4
  8. package/dist/{index-BP2wylez.mjs → index-CB5H7YI6.mjs} +5 -5
  9. package/dist/{index-DYDAFqAN.cjs → index-FkXJNwiy.cjs} +141 -39
  10. package/dist/{index-vCgb7QnZ.mjs → index-UCYD5Wk3.mjs} +138 -36
  11. package/dist/index.cjs +2 -2
  12. package/dist/index.mjs +2 -2
  13. package/dist/{installTerminalHooks-T4NE5fmC.cjs → installTerminalHooks-CoK5wNcA.cjs} +2 -2
  14. package/dist/{installTerminalHooks-C7JS6CBM.mjs → installTerminalHooks-TkkGzzbI.mjs} +2 -2
  15. package/dist/lib.cjs +1 -1
  16. package/dist/lib.d.cts +42 -0
  17. package/dist/lib.d.mts +42 -0
  18. package/dist/lib.mjs +1 -1
  19. package/dist/{mcp-B3EgenZh.mjs → mcp-C3MiqObi.mjs} +2 -2
  20. package/dist/{mcp-DgPg5mKa.cjs → mcp-DcRvswVI.cjs} +2 -2
  21. package/dist/{runGemini-B3iv1QRL.mjs → runGemini-BbC0uwUj.mjs} +4 -4
  22. package/dist/{runGemini-xZnGj7jx.cjs → runGemini-Dnvd2gWq.cjs} +4 -4
  23. package/dist/{runOpenClaw-CmM4ZLYi.mjs → runOpenClaw--nbqTW3K.mjs} +3 -3
  24. package/dist/{runOpenClaw-6ZLPeYYZ.cjs → runOpenClaw-CnuTBNQW.cjs} +3 -3
  25. package/dist/{send-M2ax7UGy.mjs → send-9nJxn09Y.mjs} +2 -2
  26. package/dist/{send-S9ibMiAt.cjs → send-DkKOPatx.cjs} +2 -2
  27. package/dist/{spawn-Dx_xnLlg.mjs → spawn-CRW4ioms.mjs} +2 -2
  28. package/dist/{spawn-ie_kfwQe.cjs → spawn-DE7WhS8Y.cjs} +2 -2
  29. package/dist/{types-d_104eQF.mjs → types-BKyjG23_.mjs} +304 -52
  30. package/dist/{types-DLI6sss2.cjs → types-ClDADuxP.cjs} +306 -52
  31. 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.89";
54
+ var version = "0.2.91";
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.89",
168
- "very-happy-tools-x64-darwin": "0.2.89",
169
- "very-happy-tools-arm64-linux": "0.2.89",
170
- "very-happy-tools-x64-linux": "0.2.89",
171
- "very-happy-tools-arm64-win32": "0.2.89",
172
- "very-happy-tools-x64-win32": "0.2.89"
167
+ "very-happy-tools-arm64-darwin": "0.2.91",
168
+ "very-happy-tools-x64-darwin": "0.2.91",
169
+ "very-happy-tools-arm64-linux": "0.2.91",
170
+ "very-happy-tools-x64-linux": "0.2.91",
171
+ "very-happy-tools-arm64-win32": "0.2.91",
172
+ "very-happy-tools-x64-win32": "0.2.91"
173
173
  };
174
174
  var devDependencies = {
175
175
  "@slopus/happy-wire": "workspace:*",
@@ -661,9 +661,27 @@ const sessionToolCallStartEventSchema = z__namespace.object({
661
661
  description: z__namespace.string(),
662
662
  args: z__namespace.record(z__namespace.string(), z__namespace.unknown())
663
663
  });
664
+ const sessionSubagentResultSchema = z__namespace.object({
665
+ text: z__namespace.string(),
666
+ truncated: z__namespace.boolean().optional()
667
+ });
668
+ const sessionSubagentUsageSchema = z__namespace.object({
669
+ toolUses: z__namespace.number().optional(),
670
+ totalTokens: z__namespace.number().optional(),
671
+ durationMs: z__namespace.number().optional()
672
+ });
664
673
  const sessionToolCallEndEventSchema = z__namespace.object({
665
674
  t: z__namespace.literal("tool-call-end"),
666
- call: z__namespace.string()
675
+ call: z__namespace.string(),
676
+ // Foreground Agent/Task completion: the sub-agent's final report + run
677
+ // totals (SDK `tool_use_result`). Absent for ordinary tools and for the
678
+ // background stub ("Async agent launched").
679
+ result: sessionSubagentResultSchema.extend({
680
+ isError: z__namespace.boolean().optional(),
681
+ stats: sessionSubagentUsageSchema.extend({
682
+ toolStats: z__namespace.record(z__namespace.string(), z__namespace.unknown()).optional()
683
+ }).optional()
684
+ }).optional()
667
685
  });
668
686
  const sessionFileEventSchema = z__namespace.object({
669
687
  t: z__namespace.literal("file"),
@@ -682,7 +700,10 @@ const sessionTurnStartEventSchema = z__namespace.object({
682
700
  });
683
701
  const sessionStartEventSchema = z__namespace.object({
684
702
  t: z__namespace.literal("start"),
685
- title: z__namespace.string().optional()
703
+ title: z__namespace.string().optional(),
704
+ // B-260-P2: identity from SDK task_started / Agent tool input.
705
+ description: z__namespace.string().optional(),
706
+ subagentType: z__namespace.string().optional()
686
707
  });
687
708
  const sessionTurnEndStatusSchema = z__namespace.enum(["completed", "failed", "cancelled"]);
688
709
  const sessionTurnUsageSchema = z__namespace.object({
@@ -705,7 +726,21 @@ const sessionTurnEndEventSchema = z__namespace.object({
705
726
  usage: sessionTurnUsageSchema.optional()
706
727
  });
707
728
  const sessionStopEventSchema = z__namespace.object({
708
- t: z__namespace.literal("stop")
729
+ t: z__namespace.literal("stop"),
730
+ // B-260-P2: from SDK task_notification. A second `stop` for the same
731
+ // subagent may follow carrying `result` once the notification user message
732
+ // (which holds the <result> block) arrives; consumers fold by subagent id.
733
+ status: z__namespace.enum(["completed", "failed", "stopped"]).optional(),
734
+ result: sessionSubagentResultSchema.optional(),
735
+ usage: sessionSubagentUsageSchema.optional()
736
+ });
737
+ const sessionProgressEventSchema = z__namespace.object({
738
+ t: z__namespace.literal("progress"),
739
+ toolUses: z__namespace.number(),
740
+ lastTool: z__namespace.string().optional(),
741
+ totalTokens: z__namespace.number().optional(),
742
+ durationMs: z__namespace.number().optional(),
743
+ summary: z__namespace.string().optional()
709
744
  });
710
745
  const sessionEventSchema = z__namespace.discriminatedUnion("t", [
711
746
  sessionTextEventSchema,
@@ -716,7 +751,8 @@ const sessionEventSchema = z__namespace.discriminatedUnion("t", [
716
751
  sessionTurnStartEventSchema,
717
752
  sessionStartEventSchema,
718
753
  sessionTurnEndEventSchema,
719
- sessionStopEventSchema
754
+ sessionStopEventSchema,
755
+ sessionProgressEventSchema
720
756
  ]);
721
757
  const sessionEnvelopeSchema = z__namespace.object({
722
758
  id: z__namespace.string(),
@@ -747,7 +783,14 @@ const sessionEnvelopeSchema = z__namespace.object({
747
783
  path: ["role"]
748
784
  });
749
785
  }
750
- if ((envelope.ev.t === "start" || envelope.ev.t === "stop") && envelope.role !== "agent") {
786
+ if (envelope.ev.t === "progress" && !envelope.subagent) {
787
+ ctx.addIssue({
788
+ code: z__namespace.ZodIssueCode.custom,
789
+ message: "progress events must carry a subagent",
790
+ path: ["subagent"]
791
+ });
792
+ }
793
+ if ((envelope.ev.t === "start" || envelope.ev.t === "stop" || envelope.ev.t === "progress") && envelope.role !== "agent") {
751
794
  ctx.addIssue({
752
795
  code: z__namespace.ZodIssueCode.custom,
753
796
  message: `${envelope.ev.t} events must use role "agent"`,
@@ -1484,7 +1527,7 @@ class RpcHandlerManager {
1484
1527
  }
1485
1528
  }
1486
1529
 
1487
- 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-DLI6sss2.cjs', document.baseURI).href))));
1530
+ 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-ClDADuxP.cjs', document.baseURI).href))));
1488
1531
  function projectPath() {
1489
1532
  const path = path$1.resolve(__dirname$1, "..");
1490
1533
  return path;
@@ -2171,6 +2214,69 @@ function shouldReconnect() {
2171
2214
  return true;
2172
2215
  }
2173
2216
 
2217
+ const SUBAGENT_RESULT_MAX_CHARS = 16384;
2218
+ const SUBAGENT_PROGRESS_MIN_INTERVAL_MS = 5e3;
2219
+ function capSubagentText(text, max = SUBAGENT_RESULT_MAX_CHARS) {
2220
+ const trimmed = text.trim();
2221
+ if (trimmed.length <= max) return { text: trimmed };
2222
+ return { text: trimmed.slice(0, max), truncated: true };
2223
+ }
2224
+ function toolUseResultToText(toolUseResult) {
2225
+ if (!toolUseResult || typeof toolUseResult !== "object") return null;
2226
+ const content = toolUseResult.content;
2227
+ if (typeof content === "string") return content;
2228
+ if (!Array.isArray(content)) return null;
2229
+ const parts = [];
2230
+ for (const block of content) {
2231
+ if (block && typeof block === "object" && block.type === "text" && typeof block.text === "string") {
2232
+ parts.push(block.text);
2233
+ }
2234
+ }
2235
+ return parts.length > 0 ? parts.join("\n") : null;
2236
+ }
2237
+ function toolUseResultStatus(toolUseResult) {
2238
+ if (!toolUseResult || typeof toolUseResult !== "object") return "unknown";
2239
+ const status = toolUseResult.status;
2240
+ if (status === "async_launched") return "async_launched";
2241
+ if (status === "completed") return "completed";
2242
+ return "unknown";
2243
+ }
2244
+ function toolUseResultStats(toolUseResult) {
2245
+ if (!toolUseResult || typeof toolUseResult !== "object") return void 0;
2246
+ const r = toolUseResult;
2247
+ const stats = {};
2248
+ if (typeof r.totalToolUseCount === "number") stats.toolUses = r.totalToolUseCount;
2249
+ if (typeof r.totalTokens === "number") stats.totalTokens = r.totalTokens;
2250
+ if (typeof r.totalDurationMs === "number") stats.durationMs = r.totalDurationMs;
2251
+ if (r.toolStats && typeof r.toolStats === "object") stats.toolStats = r.toolStats;
2252
+ return Object.keys(stats).length > 0 ? stats : void 0;
2253
+ }
2254
+ function parseTaskNotificationText(text) {
2255
+ if (!/<task-notification>/i.test(text)) return null;
2256
+ const pick = (tag) => text.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`, "i"))?.[1] ?? null;
2257
+ const rawStatus = pick("status")?.trim().toLowerCase() ?? null;
2258
+ const status = rawStatus === "completed" || rawStatus === "failed" || rawStatus === "stopped" ? rawStatus : null;
2259
+ let resultText = pick("result");
2260
+ let result = null;
2261
+ if (resultText !== null) {
2262
+ resultText = resultText.replace(/^\s*\[harness:[^\]]*\]\s*/i, "").replace(/<usage>[\s\S]*?<\/usage>/gi, "").trim();
2263
+ if (resultText.length > 0) result = capSubagentText(resultText);
2264
+ }
2265
+ return {
2266
+ toolUseId: pick("tool-use-id")?.trim() || null,
2267
+ taskId: pick("task-id")?.trim() || null,
2268
+ status,
2269
+ summary: pick("summary")?.trim() || null,
2270
+ result
2271
+ };
2272
+ }
2273
+ function shouldEmitProgress(previous, toolUses, now) {
2274
+ if (!previous) return true;
2275
+ if (previous.lastToolUses === toolUses) return false;
2276
+ return now - previous.lastAt >= SUBAGENT_PROGRESS_MIN_INTERVAL_MS;
2277
+ }
2278
+
2279
+ const SUBAGENT_BUFFER_MAX_MESSAGES = 100;
2174
2280
  function isSubagentTool(name) {
2175
2281
  return name === "Task" || name === "Agent";
2176
2282
  }
@@ -2239,6 +2345,7 @@ function bufferSubagentMessage(state, subagent, message) {
2239
2345
  const buffer = getBufferedSubagentMessages(state);
2240
2346
  const queue = buffer.get(subagent) ?? [];
2241
2347
  queue.push(message);
2348
+ while (queue.length > SUBAGENT_BUFFER_MAX_MESSAGES) queue.shift();
2242
2349
  buffer.set(subagent, queue);
2243
2350
  }
2244
2351
  function consumeBufferedSubagentMessages(state, subagent) {
@@ -2259,6 +2366,31 @@ function getActiveSubagents(state) {
2259
2366
  }
2260
2367
  return state.activeSubagents;
2261
2368
  }
2369
+ function getAgentToolCalls(state) {
2370
+ if (!state.agentToolCalls) state.agentToolCalls = /* @__PURE__ */ new Set();
2371
+ return state.agentToolCalls;
2372
+ }
2373
+ function getSubagentMeta(state) {
2374
+ if (!state.subagentMeta) state.subagentMeta = /* @__PURE__ */ new Map();
2375
+ return state.subagentMeta;
2376
+ }
2377
+ function getStubSubagents(state) {
2378
+ if (!state.stubSubagents) state.stubSubagents = /* @__PURE__ */ new Set();
2379
+ return state.stubSubagents;
2380
+ }
2381
+ function getProgressThrottle(state) {
2382
+ if (!state.progressThrottle) state.progressThrottle = /* @__PURE__ */ new Map();
2383
+ return state.progressThrottle;
2384
+ }
2385
+ function nowOf(state) {
2386
+ return state.now ? state.now() : Date.now();
2387
+ }
2388
+ function rememberSubagentMeta(state, subagent, meta) {
2389
+ const existing = getSubagentMeta(state).get(subagent) ?? {};
2390
+ const description = typeof meta.description === "string" && meta.description.trim() ? meta.description.trim() : existing.description;
2391
+ const subagentType = typeof meta.subagentType === "string" && meta.subagentType.trim() ? meta.subagentType.trim() : existing.subagentType;
2392
+ getSubagentMeta(state).set(subagent, { ...description ? { description } : {}, ...subagentType ? { subagentType } : {} });
2393
+ }
2262
2394
  function pickAssistantUsage(message) {
2263
2395
  if (message.type !== "assistant") return void 0;
2264
2396
  const usage = message.message?.usage;
@@ -2435,13 +2567,26 @@ function maybeEmitSubagentStart(state, turn, subagent, envelopes) {
2435
2567
  return;
2436
2568
  }
2437
2569
  const title = getSubagentTitles(state).get(subagent);
2570
+ const meta = getSubagentMeta(state).get(subagent);
2438
2571
  envelopes.push(createEnvelope("agent", {
2439
2572
  t: "start",
2440
- ...title ? { title } : {}
2573
+ ...title ? { title } : {},
2574
+ ...meta?.description ? { description: meta.description } : {},
2575
+ ...meta?.subagentType ? { subagentType: meta.subagentType } : {}
2441
2576
  }, { turn, subagent }));
2442
2577
  started.add(subagent);
2443
2578
  getActiveSubagents(state).add(subagent);
2444
2579
  }
2580
+ function emitSubagentStopWithStatus(state, turn, subagent, envelopes, payload) {
2581
+ envelopes.push(createEnvelope("agent", {
2582
+ t: "stop",
2583
+ ...payload.status ? { status: payload.status } : {},
2584
+ ...payload.result ? { result: payload.result } : {},
2585
+ ...payload.usage ? { usage: payload.usage } : {}
2586
+ }, { ...turn ? { turn } : {}, subagent }));
2587
+ getActiveSubagents(state).delete(subagent);
2588
+ getStartedSubagents(state).delete(subagent);
2589
+ }
2445
2590
  function maybeEmitSubagentStop(state, turn, subagent, envelopes) {
2446
2591
  const active = getActiveSubagents(state);
2447
2592
  if (!active.has(subagent)) {
@@ -2453,8 +2598,6 @@ function maybeEmitSubagentStop(state, turn, subagent, envelopes) {
2453
2598
  function clearSubagentTracking(state) {
2454
2599
  getUuidToProviderSubagent(state).clear();
2455
2600
  getTaskPromptToSubagents(state).clear();
2456
- getProviderSubagentToSessionSubagent(state).clear();
2457
- getSubagentTitles(state).clear();
2458
2601
  getBufferedSubagentMessages(state).clear();
2459
2602
  getHiddenParentToolCalls(state).clear();
2460
2603
  getStartedSubagents(state).clear();
@@ -2515,6 +2658,58 @@ function closeClaudeTurnWithStatus(state, status, meta) {
2515
2658
  function mapClaudeLogMessageToSessionEnvelopes(message, state) {
2516
2659
  return mapClaudeLogMessageToSessionEnvelopesInternal(message, state);
2517
2660
  }
2661
+ function mapTaskLifecycleSystemMessage(message, state, envelopes) {
2662
+ const raw = message;
2663
+ const subtype = typeof raw.subtype === "string" ? raw.subtype : "";
2664
+ if (!subtype.startsWith("task_")) return;
2665
+ if (raw.skip_transcript === true) return;
2666
+ const toolUseId = typeof raw.tool_use_id === "string" && raw.tool_use_id.length > 0 ? raw.tool_use_id : null;
2667
+ if (!toolUseId || !getAgentToolCalls(state).has(toolUseId)) return;
2668
+ const subagent = ensureSessionSubagentIdForProviderSubagent(state, toolUseId);
2669
+ const usage = raw.usage && typeof raw.usage === "object" ? {
2670
+ ...typeof raw.usage.tool_uses === "number" ? { toolUses: raw.usage.tool_uses } : {},
2671
+ ...typeof raw.usage.total_tokens === "number" ? { totalTokens: raw.usage.total_tokens } : {},
2672
+ ...typeof raw.usage.duration_ms === "number" ? { durationMs: raw.usage.duration_ms } : {}
2673
+ } : void 0;
2674
+ if (subtype === "task_started") {
2675
+ rememberSubagentMeta(state, subagent, { description: raw.description, subagentType: raw.subagent_type });
2676
+ const turn = ensureTurn(state, envelopes);
2677
+ getStartedSubagents(state).delete(subagent);
2678
+ maybeEmitSubagentStart(state, turn, subagent, envelopes);
2679
+ return;
2680
+ }
2681
+ if (subtype === "task_progress") {
2682
+ const toolUses = typeof raw.usage?.tool_uses === "number" ? raw.usage.tool_uses : 0;
2683
+ const throttle = getProgressThrottle(state);
2684
+ const now = nowOf(state);
2685
+ if (!shouldEmitProgress(throttle.get(subagent), toolUses, now)) return;
2686
+ throttle.set(subagent, { lastAt: now, lastToolUses: toolUses });
2687
+ const turn = ensureTurn(state, envelopes);
2688
+ maybeEmitSubagentStart(state, turn, subagent, envelopes);
2689
+ envelopes.push(createEnvelope("agent", {
2690
+ t: "progress",
2691
+ toolUses,
2692
+ ...typeof raw.last_tool_name === "string" && raw.last_tool_name ? { lastTool: raw.last_tool_name } : {},
2693
+ ...usage?.totalTokens !== void 0 ? { totalTokens: usage.totalTokens } : {},
2694
+ ...usage?.durationMs !== void 0 ? { durationMs: usage.durationMs } : {},
2695
+ ...typeof raw.summary === "string" && raw.summary.trim() ? { summary: raw.summary.trim() } : {}
2696
+ }, { turn, subagent }));
2697
+ return;
2698
+ }
2699
+ if (subtype === "task_notification") {
2700
+ const status = raw.status === "completed" || raw.status === "failed" || raw.status === "stopped" ? raw.status : "completed";
2701
+ emitSubagentStopWithStatus(state, state.currentTurnId ?? void 0, subagent, envelopes, {
2702
+ status,
2703
+ ...usage ? { usage } : {}
2704
+ });
2705
+ getStubSubagents(state).delete(subagent);
2706
+ getProgressThrottle(state).delete(subagent);
2707
+ return;
2708
+ }
2709
+ if (subtype === "task_updated" && raw.patch?.is_backgrounded === true) {
2710
+ getStubSubagents(state).add(subagent);
2711
+ }
2712
+ }
2518
2713
  function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
2519
2714
  const envelopes = [];
2520
2715
  const claudeUuid = pickUuid(message);
@@ -2535,6 +2730,7 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
2535
2730
  };
2536
2731
  }
2537
2732
  if (message.type === "system") {
2733
+ mapTaskLifecycleSystemMessage(message, state, envelopes);
2538
2734
  return {
2539
2735
  currentTurnId: state.currentTurnId,
2540
2736
  envelopes
@@ -2576,6 +2772,9 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
2576
2772
  queueTaskPromptSubagent(state, prompt, call);
2577
2773
  }
2578
2774
  setSubagentTitle(state, sessionSubagentForCall, pickTaskTitle(block.input) ?? prompt);
2775
+ getAgentToolCalls(state).add(call);
2776
+ const input = block.input ?? {};
2777
+ rememberSubagentMeta(state, sessionSubagentForCall, { description: input.description, subagentType: input.subagent_type });
2579
2778
  }
2580
2779
  if (shouldHideParentToolCall(name)) {
2581
2780
  getHiddenParentToolCalls(state).add(call);
@@ -2620,6 +2819,18 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
2620
2819
  maybeEmitSubagentStart(state, turnId2, subagent, envelopes);
2621
2820
  envelopes.push(createEnvelope("agent", { t: "text", text: message.message.content }, { turn: turnId2, subagent, claudeUuid }));
2622
2821
  } else {
2822
+ const origin = message.origin;
2823
+ if (origin?.kind === "task-notification" || /<task-notification>/i.test(message.message.content)) {
2824
+ const fields = parseTaskNotificationText(message.message.content);
2825
+ const providerId = fields?.toolUseId ?? null;
2826
+ const subagentForNotification = providerId && getAgentToolCalls(state).has(providerId) ? getSessionSubagentIdForProviderSubagent(state, providerId) : void 0;
2827
+ if (fields && subagentForNotification && (fields.result || fields.status)) {
2828
+ emitSubagentStopWithStatus(state, state.currentTurnId ?? void 0, subagentForNotification, envelopes, {
2829
+ ...fields.status ? { status: fields.status } : {},
2830
+ ...fields.result ? { result: fields.result } : {}
2831
+ });
2832
+ }
2833
+ }
2623
2834
  closeTurn(state, "completed", envelopes);
2624
2835
  envelopes.push(createEnvelope("user", { t: "text", text: message.message.content }, { claudeUuid }));
2625
2836
  }
@@ -2650,6 +2861,31 @@ function mapClaudeLogMessageToSessionEnvelopesInternal(message, state) {
2650
2861
  getHiddenParentToolCalls(state).delete(block.tool_use_id);
2651
2862
  continue;
2652
2863
  }
2864
+ if (sessionSubagentForToolResult && getAgentToolCalls(state).has(block.tool_use_id)) {
2865
+ const toolUseResult = message.tool_use_result;
2866
+ const resultStatus = toolUseResultStatus(toolUseResult);
2867
+ if (resultStatus === "async_launched") {
2868
+ getStubSubagents(state).add(sessionSubagentForToolResult);
2869
+ envelopes.push(createEnvelope("agent", { t: "tool-call-end", call: block.tool_use_id }, { turn: turnId, subagent }));
2870
+ continue;
2871
+ }
2872
+ if (resultStatus === "completed") {
2873
+ const text = toolUseResultToText(toolUseResult);
2874
+ const stats = toolUseResultStats(toolUseResult);
2875
+ const result = text ? capSubagentText(text) : void 0;
2876
+ emitSubagentStopWithStatus(state, turnId, sessionSubagentForToolResult, envelopes, {
2877
+ status: "completed",
2878
+ ...result ? { result } : {},
2879
+ ...stats ? { usage: { toolUses: stats.toolUses, totalTokens: stats.totalTokens, durationMs: stats.durationMs } } : {}
2880
+ });
2881
+ envelopes.push(createEnvelope("agent", {
2882
+ t: "tool-call-end",
2883
+ call: block.tool_use_id,
2884
+ ...result ? { result: { ...result, ...stats ? { stats } : {} } } : {}
2885
+ }, { turn: turnId, subagent }));
2886
+ continue;
2887
+ }
2888
+ }
2653
2889
  if (sessionSubagentForToolResult) {
2654
2890
  maybeEmitSubagentStop(state, turnId, sessionSubagentForToolResult, envelopes);
2655
2891
  }
@@ -8829,6 +9065,20 @@ function previewAscii(line) {
8829
9065
  return line.length > 80 ? `${out}\u2026` : out;
8830
9066
  }
8831
9067
 
9068
+ const VH_TMUX_SOCKET_ENV = "VH_TMUX_SOCKET";
9069
+ function tmuxSocketFlags(env = process.env) {
9070
+ const socket = env[VH_TMUX_SOCKET_ENV];
9071
+ return socket ? ["-S", socket] : [];
9072
+ }
9073
+ function tmuxArgs(args, env = process.env) {
9074
+ return [...tmuxSocketFlags(env), ...args];
9075
+ }
9076
+ function scrubTmuxClientEnv(env) {
9077
+ delete env.TMUX;
9078
+ delete env.TMUX_PANE;
9079
+ return env;
9080
+ }
9081
+
8832
9082
  const CONTROL_CLIENT_KILL_GRACE_MS = 2e3;
8833
9083
  const CONTROL_COMMAND_TIMEOUT_MS = 1e4;
8834
9084
  function isSafeControlCommand(command) {
@@ -8838,7 +9088,7 @@ class ControlClient {
8838
9088
  constructor(tmuxSession, env, handlers) {
8839
9089
  this.tmuxSession = tmuxSession;
8840
9090
  this.handlers = handlers;
8841
- this.child = node_child_process.spawn("tmux", ["-C", "attach-session", "-t", `=${tmuxSession}:`], {
9091
+ this.child = node_child_process.spawn("tmux", tmuxArgs(["-C", "attach-session", "-t", `=${tmuxSession}:`], env), {
8842
9092
  stdio: ["pipe", "pipe", "pipe"],
8843
9093
  env
8844
9094
  });
@@ -9990,7 +10240,7 @@ let tmuxAvailableCache = null;
9990
10240
  function isTmuxAvailable() {
9991
10241
  if (tmuxAvailableCache !== null) return tmuxAvailableCache;
9992
10242
  try {
9993
- const r = node_child_process.spawnSync("tmux", ["-V"], { stdio: "ignore", env: ptyEnv() });
10243
+ const r = node_child_process.spawnSync("tmux", tmuxArgs(["-V"]), { stdio: "ignore", env: ptyEnv() });
9994
10244
  tmuxAvailableCache = r.status === 0;
9995
10245
  } catch {
9996
10246
  tmuxAvailableCache = false;
@@ -10001,7 +10251,7 @@ let tmuxEnvFlagCache = null;
10001
10251
  function tmuxSupportsEnvFlag() {
10002
10252
  if (tmuxEnvFlagCache !== null) return tmuxEnvFlagCache;
10003
10253
  try {
10004
- const r = node_child_process.spawnSync("tmux", ["-V"], { encoding: "utf8", env: ptyEnv() });
10254
+ const r = node_child_process.spawnSync("tmux", tmuxArgs(["-V"]), { encoding: "utf8", env: ptyEnv() });
10005
10255
  tmuxEnvFlagCache = r.status === 0 && tmuxSupportsNewSessionEnv(r.stdout || "");
10006
10256
  } catch {
10007
10257
  tmuxEnvFlagCache = false;
@@ -10045,6 +10295,7 @@ function ptyEnv() {
10045
10295
  for (const [k, v] of Object.entries(process.env)) {
10046
10296
  if (typeof v === "string") env[k] = v;
10047
10297
  }
10298
+ scrubTmuxClientEnv(env);
10048
10299
  const local = `${os.homedir()}/.local/bin`;
10049
10300
  if (!(env.PATH || "").split(":").includes(local)) {
10050
10301
  env.PATH = `${local}:${env.PATH || ""}`;
@@ -10700,7 +10951,7 @@ class WebTerminalManager {
10700
10951
  const name = `vh-${plan.terminalId}`;
10701
10952
  const exists = node_child_process.spawnSync(
10702
10953
  "tmux",
10703
- ["has-session", "-t", `=${name}:`],
10954
+ tmuxArgs(["has-session", "-t", `=${name}:`]),
10704
10955
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
10705
10956
  ).status === 0;
10706
10957
  if (exists) return false;
@@ -10714,12 +10965,12 @@ class WebTerminalManager {
10714
10965
  ] : [];
10715
10966
  const created = node_child_process.spawnSync(
10716
10967
  "tmux",
10717
- tmuxNewSessionArgs(name, 120, 30, plan.cwd, envFlags, defaultShell()),
10968
+ tmuxArgs(tmuxNewSessionArgs(name, 120, 30, plan.cwd, envFlags, defaultShell())),
10718
10969
  { stdio: "ignore", timeout: TMUX_CREATE_TIMEOUT_MS, env }
10719
10970
  );
10720
10971
  const live = created.status === 0 && node_child_process.spawnSync(
10721
10972
  "tmux",
10722
- ["has-session", "-t", `=${name}:`],
10973
+ tmuxArgs(["has-session", "-t", `=${name}:`]),
10723
10974
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
10724
10975
  ).status === 0;
10725
10976
  if (!live) {
@@ -10729,12 +10980,12 @@ class WebTerminalManager {
10729
10980
  if (plan.title) {
10730
10981
  node_child_process.spawnSync(
10731
10982
  "tmux",
10732
- ["set-option", "-t", `=${name}:`, "@vh_title", plan.title],
10983
+ tmuxArgs(["set-option", "-t", `=${name}:`, "@vh_title", plan.title]),
10733
10984
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
10734
10985
  );
10735
10986
  }
10736
10987
  for (const argv of startupInjectionArgs(name, plan.command)) {
10737
- node_child_process.spawnSync("tmux", argv, { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
10988
+ node_child_process.spawnSync("tmux", tmuxArgs(argv), { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
10738
10989
  }
10739
10990
  logger.info(`[WEB TERMINAL] auto-restored ${plan.terminalId} in ${plan.cwd}`);
10740
10991
  return true;
@@ -10866,14 +11117,14 @@ class WebTerminalManager {
10866
11117
  if (opts.attachOnly || opts.resub) {
10867
11118
  const alive = isTmuxAvailable() && node_child_process.spawnSync(
10868
11119
  "tmux",
10869
- ["has-session", "-t", `=vh-${id}:`],
11120
+ tmuxArgs(["has-session", "-t", `=vh-${id}:`]),
10870
11121
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
10871
11122
  ).status === 0;
10872
11123
  if (!alive) throw new Error("terminal-gone");
10873
11124
  } else if (this.tombstones[id]) {
10874
11125
  const alive = isTmuxAvailable() && node_child_process.spawnSync(
10875
11126
  "tmux",
10876
- ["has-session", "-t", `=vh-${id}:`],
11127
+ tmuxArgs(["has-session", "-t", `=vh-${id}:`]),
10877
11128
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
10878
11129
  ).status === 0;
10879
11130
  if (!alive) {
@@ -10902,7 +11153,7 @@ class WebTerminalManager {
10902
11153
  try {
10903
11154
  const created = node_child_process.spawnSync(
10904
11155
  "tmux",
10905
- tmuxNewSessionArgs(tmuxSession, cols, rows, cwd, envFlags, defaultShell()),
11156
+ tmuxArgs(tmuxNewSessionArgs(tmuxSession, cols, rows, cwd, envFlags, defaultShell())),
10906
11157
  { stdio: "ignore", timeout: TMUX_CREATE_TIMEOUT_MS, env }
10907
11158
  );
10908
11159
  createdNew = created.status === 0;
@@ -10934,7 +11185,7 @@ class WebTerminalManager {
10934
11185
  ];
10935
11186
  for (const a of optArgs) {
10936
11187
  try {
10937
- node_child_process.spawnSync("tmux", a, { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
11188
+ node_child_process.spawnSync("tmux", tmuxArgs(a), { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
10938
11189
  } catch {
10939
11190
  }
10940
11191
  }
@@ -10943,7 +11194,7 @@ class WebTerminalManager {
10943
11194
  if (startup) {
10944
11195
  try {
10945
11196
  for (const a of startupInjectionArgs(tmuxSession, startup)) {
10946
- node_child_process.spawnSync("tmux", a, { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
11197
+ node_child_process.spawnSync("tmux", tmuxArgs(a), { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
10947
11198
  }
10948
11199
  logger.debug(`[WEB TERMINAL] injected startup command into new session ${tmuxSession}`);
10949
11200
  } catch {
@@ -10953,13 +11204,13 @@ class WebTerminalManager {
10953
11204
  if (!attachOnly && !createdNew) {
10954
11205
  const alive = node_child_process.spawnSync(
10955
11206
  "tmux",
10956
- ["has-session", "-t", `=${tmuxSession}:`],
11207
+ tmuxArgs(["has-session", "-t", `=${tmuxSession}:`]),
10957
11208
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
10958
11209
  ).status === 0;
10959
11210
  if (shouldUseDirectPtyFallback(attachOnly, createdNew, alive)) {
10960
11211
  const retry = node_child_process.spawnSync(
10961
11212
  "tmux",
10962
- tmuxNewSessionArgs(tmuxSession, cols, rows, cwd, envFlags, defaultShell()),
11213
+ tmuxArgs(tmuxNewSessionArgs(tmuxSession, cols, rows, cwd, envFlags, defaultShell())),
10963
11214
  { stdio: "ignore", timeout: TMUX_CREATE_TIMEOUT_MS, env }
10964
11215
  );
10965
11216
  createdNew = retry.status === 0;
@@ -10968,7 +11219,7 @@ class WebTerminalManager {
10968
11219
  if (startup) {
10969
11220
  for (const a of startupInjectionArgs(tmuxSession, startup)) {
10970
11221
  try {
10971
- node_child_process.spawnSync("tmux", a, { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
11222
+ node_child_process.spawnSync("tmux", tmuxArgs(a), { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env });
10972
11223
  } catch {
10973
11224
  }
10974
11225
  }
@@ -10979,7 +11230,7 @@ class WebTerminalManager {
10979
11230
  if (!attachOnly && !createdNew) {
10980
11231
  const alive = node_child_process.spawnSync(
10981
11232
  "tmux",
10982
- ["has-session", "-t", `=${tmuxSession}:`],
11233
+ tmuxArgs(["has-session", "-t", `=${tmuxSession}:`]),
10983
11234
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
10984
11235
  ).status === 0;
10985
11236
  if (!alive) {
@@ -11306,8 +11557,8 @@ class WebTerminalManager {
11306
11557
  killSession(terminalId) {
11307
11558
  const info = this.lastSeenInfo.get(terminalId) ?? this.listSessions().find((t) => t.id === terminalId);
11308
11559
  const target = `=vh-${terminalId}:`;
11309
- const killed = node_child_process.spawnSync("tmux", ["kill-session", "-t", target], { stdio: "ignore", env: ptyEnv() });
11310
- const verified = node_child_process.spawnSync("tmux", ["has-session", "-t", target], { stdio: "ignore", env: ptyEnv() });
11560
+ const killed = node_child_process.spawnSync("tmux", tmuxArgs(["kill-session", "-t", target]), { stdio: "ignore", env: ptyEnv() });
11561
+ const verified = node_child_process.spawnSync("tmux", tmuxArgs(["has-session", "-t", target]), { stdio: "ignore", env: ptyEnv() });
11311
11562
  if (!tmuxKillVerified(killed, verified)) {
11312
11563
  logger.debug(`[WEB TERMINAL] failed to verify tmux session removal ${target}`);
11313
11564
  return false;
@@ -11368,7 +11619,7 @@ class WebTerminalManager {
11368
11619
  const env = ptyEnv();
11369
11620
  const r = node_child_process.spawnSync(
11370
11621
  "tmux",
11371
- ["list-sessions", "-F", LIST_SESSIONS_FORMAT],
11622
+ tmuxArgs(["list-sessions", "-F", LIST_SESSIONS_FORMAT]),
11372
11623
  { encoding: "utf8", env }
11373
11624
  );
11374
11625
  if (r.status !== 0 || !r.stdout) return [];
@@ -11384,7 +11635,7 @@ class WebTerminalManager {
11384
11635
  try {
11385
11636
  const w = node_child_process.spawnSync(
11386
11637
  "tmux",
11387
- ["set-option", "-t", `=${s.name}:`, "@vh_title", auto],
11638
+ tmuxArgs(["set-option", "-t", `=${s.name}:`, "@vh_title", auto]),
11388
11639
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env }
11389
11640
  );
11390
11641
  if (w.status === 0) title = auto;
@@ -11435,13 +11686,13 @@ class WebTerminalManager {
11435
11686
  try {
11436
11687
  const cmd = node_child_process.spawnSync(
11437
11688
  "tmux",
11438
- ["display-message", "-p", "-t", sessionName, "#{pane_current_command}"],
11689
+ tmuxArgs(["display-message", "-p", "-t", sessionName, "#{pane_current_command}"]),
11439
11690
  { encoding: "utf8", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
11440
11691
  );
11441
11692
  if (cmd.status !== 0 || typeof cmd.stdout !== "string") return void 0;
11442
11693
  const cap = node_child_process.spawnSync(
11443
11694
  "tmux",
11444
- ["capture-pane", "-p", "-t", sessionName, "-S", "-40"],
11695
+ tmuxArgs(["capture-pane", "-p", "-t", sessionName, "-S", "-40"]),
11445
11696
  { encoding: "utf8", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
11446
11697
  );
11447
11698
  if (cap.status !== 0 || typeof cap.stdout !== "string") return void 0;
@@ -11468,7 +11719,7 @@ class WebTerminalManager {
11468
11719
  try {
11469
11720
  const probe = node_child_process.spawnSync(
11470
11721
  "tmux",
11471
- ["display-message", "-p", "-t", name, "#{pane_in_mode} #{alternate_on} #{mouse_any_flag} #{pane_width} #{pane_height} #{pane_current_command}"],
11722
+ tmuxArgs(["display-message", "-p", "-t", name, "#{pane_in_mode} #{alternate_on} #{mouse_any_flag} #{pane_width} #{pane_height} #{pane_current_command}"]),
11472
11723
  { encoding: "utf8", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
11473
11724
  );
11474
11725
  if (probe.status !== 0 || typeof probe.stdout !== "string") return;
@@ -11486,7 +11737,7 @@ class WebTerminalManager {
11486
11737
  const hex = sgrWheelHexBytes(action.dir, action.count, Number(paneW) || 80, Number(paneH) || 24);
11487
11738
  node_child_process.spawnSync(
11488
11739
  "tmux",
11489
- ["send-keys", "-t", name, "-H", ...hex],
11740
+ tmuxArgs(["send-keys", "-t", name, "-H", ...hex]),
11490
11741
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
11491
11742
  );
11492
11743
  return;
@@ -11494,7 +11745,7 @@ class WebTerminalManager {
11494
11745
  if (action.kind === "page-keys") {
11495
11746
  node_child_process.spawnSync(
11496
11747
  "tmux",
11497
- ["send-keys", "-t", name, "-N", String(action.count), action.key],
11748
+ tmuxArgs(["send-keys", "-t", name, "-N", String(action.count), action.key]),
11498
11749
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
11499
11750
  );
11500
11751
  return;
@@ -11502,19 +11753,19 @@ class WebTerminalManager {
11502
11753
  if (action.kind === "keys") {
11503
11754
  node_child_process.spawnSync(
11504
11755
  "tmux",
11505
- ["send-keys", "-t", name, "-N", String(action.count), action.key],
11756
+ tmuxArgs(["send-keys", "-t", name, "-N", String(action.count), action.key]),
11506
11757
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
11507
11758
  );
11508
11759
  return;
11509
11760
  }
11510
11761
  node_child_process.spawnSync(
11511
11762
  "tmux",
11512
- ["copy-mode", "-e", "-t", name],
11763
+ tmuxArgs(["copy-mode", "-e", "-t", name]),
11513
11764
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
11514
11765
  );
11515
11766
  node_child_process.spawnSync(
11516
11767
  "tmux",
11517
- [
11768
+ tmuxArgs([
11518
11769
  "send-keys",
11519
11770
  "-X",
11520
11771
  "-t",
@@ -11522,7 +11773,7 @@ class WebTerminalManager {
11522
11773
  "-N",
11523
11774
  String(action.count),
11524
11775
  action.dir === "up" ? "scroll-up" : "scroll-down"
11525
- ],
11776
+ ]),
11526
11777
  { stdio: "ignore", timeout: TMUX_PROBE_TIMEOUT_MS, env: ptyEnv() }
11527
11778
  );
11528
11779
  } catch {
@@ -11556,14 +11807,14 @@ class WebTerminalManager {
11556
11807
  const name = `vh-${terminalId}`;
11557
11808
  try {
11558
11809
  if (ifAbsent) {
11559
- const cur = node_child_process.spawnSync("tmux", ["show-options", "-t", name, "-v", "@vh_title"], { encoding: "utf8", env: ptyEnv() });
11810
+ const cur = node_child_process.spawnSync("tmux", tmuxArgs(["show-options", "-t", name, "-v", "@vh_title"]), { encoding: "utf8", env: ptyEnv() });
11560
11811
  if (cur.status === 0 && cur.stdout && cur.stdout.trim()) return true;
11561
11812
  }
11562
- const r = node_child_process.spawnSync("tmux", ["set-option", "-t", name, "@vh_title", title], { stdio: "ignore", env: ptyEnv() });
11813
+ const r = node_child_process.spawnSync("tmux", tmuxArgs(["set-option", "-t", name, "@vh_title", title]), { stdio: "ignore", env: ptyEnv() });
11563
11814
  if (r.status !== 0) return false;
11564
11815
  if (!ifAbsent) {
11565
11816
  try {
11566
- node_child_process.spawnSync("tmux", ["set-option", "-t", name, "@vh_title_manual", "1"], { stdio: "ignore", env: ptyEnv() });
11817
+ node_child_process.spawnSync("tmux", tmuxArgs(["set-option", "-t", name, "@vh_title_manual", "1"]), { stdio: "ignore", env: ptyEnv() });
11567
11818
  } catch {
11568
11819
  }
11569
11820
  }
@@ -11581,7 +11832,7 @@ class WebTerminalManager {
11581
11832
  if (!valid) return false;
11582
11833
  const name = `vh-${terminalId}`;
11583
11834
  try {
11584
- const r = node_child_process.spawnSync("tmux", ["set-option", "-t", name, "@vh_tags", JSON.stringify(valid)], {
11835
+ const r = node_child_process.spawnSync("tmux", tmuxArgs(["set-option", "-t", name, "@vh_tags", JSON.stringify(valid)]), {
11585
11836
  stdio: "ignore",
11586
11837
  env: ptyEnv()
11587
11838
  });
@@ -11613,10 +11864,11 @@ function parseVhTerminals(stdout, hostname = os.hostname()) {
11613
11864
  }
11614
11865
  function runTmux(args, input) {
11615
11866
  try {
11616
- const r = node_child_process.spawnSync("tmux", args, {
11867
+ const r = node_child_process.spawnSync("tmux", tmuxArgs(args), {
11617
11868
  encoding: "utf8",
11618
11869
  timeout: TMUX_TIMEOUT_MS,
11619
- input
11870
+ input,
11871
+ env: scrubTmuxClientEnv({ ...process.env })
11620
11872
  });
11621
11873
  if (r.error) return { ok: false, stdout: "", error: r.error.message };
11622
11874
  if (r.status !== 0) return { ok: false, stdout: r.stdout ?? "", error: (r.stderr || `tmux exited with ${r.status}`).trim() };
@@ -15236,9 +15488,11 @@ exports.readSettings = readSettings;
15236
15488
  exports.readVhTerminal = readVhTerminal;
15237
15489
  exports.releaseDaemonLock = releaseDaemonLock;
15238
15490
  exports.resolveCliUpdateCheckInterval = resolveCliUpdateCheckInterval;
15491
+ exports.scrubTmuxClientEnv = scrubTmuxClientEnv;
15239
15492
  exports.sendToVhTerminal = sendToVhTerminal;
15240
15493
  exports.startOfflineReconnection = startOfflineReconnection;
15241
15494
  exports.summarizeSpawnSessionForLog = summarizeSpawnSessionForLog;
15495
+ exports.tmuxArgs = tmuxArgs;
15242
15496
  exports.updateSettings = updateSettings;
15243
15497
  exports.wrapCommand = wrapCommand;
15244
15498
  exports.writeCredentialsDataKey = writeCredentialsDataKey;