very-happy-cli 0.2.90 → 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-BV4wSnJ3.mjs → AcpBackend-B5RRlzLU.mjs} +1 -1
  2. package/dist/{AcpBackend-CnYZFdd0.cjs → AcpBackend-GqveWg8u.cjs} +1 -1
  3. package/dist/{AcpSessionManager-Cyne6Rmg.mjs → AcpSessionManager-Ij1pI5Ex.mjs} +1 -1
  4. package/dist/{AcpSessionManager-BPBdrrME.cjs → AcpSessionManager-YcrSZwvq.cjs} +1 -1
  5. package/dist/{config-CgXitj0f.cjs → config-C4NCw7Dz.cjs} +2 -2
  6. package/dist/{config-BEdyyciP.mjs → config-ra8iKxdU.mjs} +2 -2
  7. package/dist/{index-B1wTVXjt.cjs → index-C1HIm7NY.cjs} +4 -4
  8. package/dist/{index-Dfu5uvjk.mjs → index-CB5H7YI6.mjs} +5 -5
  9. package/dist/{index-4YmVbx7j.cjs → index-FkXJNwiy.cjs} +87 -31
  10. package/dist/{index-an09rejO.mjs → index-UCYD5Wk3.mjs} +84 -28
  11. package/dist/index.cjs +2 -2
  12. package/dist/index.mjs +2 -2
  13. package/dist/{installTerminalHooks-DDpVxk8-.cjs → installTerminalHooks-CoK5wNcA.cjs} +2 -2
  14. package/dist/{installTerminalHooks-C-OgZr5k.mjs → installTerminalHooks-TkkGzzbI.mjs} +2 -2
  15. package/dist/lib.cjs +1 -1
  16. package/dist/lib.d.cts +34 -0
  17. package/dist/lib.d.mts +34 -0
  18. package/dist/lib.mjs +1 -1
  19. package/dist/{mcp-Du-N0qlK.mjs → mcp-C3MiqObi.mjs} +2 -2
  20. package/dist/{mcp-B6Nq-RUL.cjs → mcp-DcRvswVI.cjs} +2 -2
  21. package/dist/{runGemini-DBr_TiTL.mjs → runGemini-BbC0uwUj.mjs} +4 -4
  22. package/dist/{runGemini-ChG7cGMC.cjs → runGemini-Dnvd2gWq.cjs} +4 -4
  23. package/dist/{runOpenClaw-Cbde8t92.mjs → runOpenClaw--nbqTW3K.mjs} +3 -3
  24. package/dist/{runOpenClaw-D2jtVgpC.cjs → runOpenClaw-CnuTBNQW.cjs} +3 -3
  25. package/dist/{send-BHliX59m.mjs → send-9nJxn09Y.mjs} +2 -2
  26. package/dist/{send-Bjen1TUE.cjs → send-DkKOPatx.cjs} +2 -2
  27. package/dist/{spawn-JxaPHAoP.mjs → spawn-CRW4ioms.mjs} +2 -2
  28. package/dist/{spawn-CH1Rq-LW.cjs → spawn-DE7WhS8Y.cjs} +2 -2
  29. package/dist/{types-DS3i_5LV.mjs → types-BKyjG23_.mjs} +251 -15
  30. package/dist/{types-BNGeiP1C.cjs → types-ClDADuxP.cjs} +252 -16
  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.90";
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.90",
168
- "very-happy-tools-x64-darwin": "0.2.90",
169
- "very-happy-tools-arm64-linux": "0.2.90",
170
- "very-happy-tools-x64-linux": "0.2.90",
171
- "very-happy-tools-arm64-win32": "0.2.90",
172
- "very-happy-tools-x64-win32": "0.2.90"
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-BNGeiP1C.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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "very-happy-cli",
3
- "version": "0.2.90",
3
+ "version": "0.2.91",
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.90",
117
- "very-happy-tools-x64-darwin": "0.2.90",
118
- "very-happy-tools-arm64-linux": "0.2.90",
119
- "very-happy-tools-x64-linux": "0.2.90",
120
- "very-happy-tools-arm64-win32": "0.2.90",
121
- "very-happy-tools-x64-win32": "0.2.90"
116
+ "very-happy-tools-arm64-darwin": "0.2.91",
117
+ "very-happy-tools-x64-darwin": "0.2.91",
118
+ "very-happy-tools-arm64-linux": "0.2.91",
119
+ "very-happy-tools-x64-linux": "0.2.91",
120
+ "very-happy-tools-arm64-win32": "0.2.91",
121
+ "very-happy-tools-x64-win32": "0.2.91"
122
122
  },
123
123
  "devDependencies": {
124
124
  "@slopus/happy-wire": "workspace:*",