@drisp/cli 0.4.2 → 0.4.4

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/cli.js CHANGED
@@ -34,8 +34,9 @@ import {
34
34
  getGlyphs,
35
35
  getMostRecentAthenaSession,
36
36
  getSessionMeta,
37
- handleEvent,
38
37
  hintGlyphs,
38
+ ingestRuntimeDecision,
39
+ ingestRuntimeEvent,
39
40
  isScopedPermissionsRequest,
40
41
  isSubagentTool,
41
42
  isSupportedGatewayUrl,
@@ -69,7 +70,7 @@ import {
69
70
  todoGlyphSet,
70
71
  writeGatewayClientConfig,
71
72
  wsClientOptionsForEndpoint
72
- } from "./chunk-WHELLVBL.js";
73
+ } from "./chunk-JAPBSL7D.js";
73
74
  import {
74
75
  generateId as generateId2
75
76
  } from "./chunk-BTKQ67RE.js";
@@ -128,7 +129,7 @@ import {
128
129
  useWorkflowSessionController,
129
130
  writeGlobalConfig,
130
131
  writeProjectConfig
131
- } from "./chunk-GE6PPB6Z.js";
132
+ } from "./chunk-5VK2ZMVV.js";
132
133
 
133
134
  // src/app/entry/cli.tsx
134
135
  import { render } from "ink";
@@ -144,7 +145,7 @@ import process6 from "process";
144
145
  import React9, {
145
146
  Profiler,
146
147
  useState as useState18,
147
- useCallback as useCallback18,
148
+ useCallback as useCallback19,
148
149
  useRef as useRef16,
149
150
  useEffect as useEffect14,
150
151
  useMemo as useMemo17
@@ -1726,7 +1727,7 @@ function useFeed(runtime, messages = [], initialAllowedTools, sessionStore, opti
1726
1727
  const [isServerRunning, setIsServerRunning] = useState4(
1727
1728
  () => runtime.getStatus() === "running"
1728
1729
  );
1729
- const [runtimeError, setRuntimeError] = useState4(
1730
+ const [runtimeError2, setRuntimeError] = useState4(
1730
1731
  () => runtime.getLastError()
1731
1732
  );
1732
1733
  const restoredTokens = useMemo3(
@@ -1934,19 +1935,16 @@ function useFeed(runtime, messages = [], initialAllowedTools, sessionStore, opti
1934
1935
  `useFeed permission event relay-enabled id=${runtimeEvent.id} tool=${runtimeEvent.toolName ?? ""}`
1935
1936
  );
1936
1937
  }
1937
- const result = handleEvent(runtimeEvent, controllerCallbacks);
1938
- if (result.handled && result.decision) {
1939
- runtime.sendDecision(runtimeEvent.id, result.decision);
1940
- }
1941
- const newFeedEvents = mapperRef.current.mapEvent(runtimeEvent);
1942
- if (sessionStoreRef.current) {
1943
- try {
1944
- sessionStoreRef.current.recordEvent(runtimeEvent, newFeedEvents);
1945
- } catch (err) {
1946
- sessionStoreRef.current.markDegraded(
1947
- `recordEvent failed: ${err instanceof Error ? err.message : err}`
1948
- );
1938
+ const { feedEvents: newFeedEvents, decision } = ingestRuntimeEvent(
1939
+ runtimeEvent,
1940
+ {
1941
+ mapper: mapperRef.current,
1942
+ store: sessionStoreRef.current,
1943
+ controllerCallbacks
1949
1944
  }
1945
+ );
1946
+ if (decision) {
1947
+ runtime.sendDecision(runtimeEvent.id, decision);
1950
1948
  }
1951
1949
  if (!abortRef.current.signal.aborted && newFeedEvents.length > 0) {
1952
1950
  for (const fe of newFeedEvents) {
@@ -1984,17 +1982,11 @@ function useFeed(runtime, messages = [], initialAllowedTools, sessionStore, opti
1984
1982
  if (decision.intent?.kind === "question_answer" || decision.source === "timeout") {
1985
1983
  dequeueQuestion(eventId);
1986
1984
  }
1987
- const feedEvent = mapperRef.current.mapDecision(eventId, decision);
1985
+ const feedEvent = ingestRuntimeDecision(eventId, decision, {
1986
+ mapper: mapperRef.current,
1987
+ store: sessionStoreRef.current
1988
+ });
1988
1989
  if (feedEvent) {
1989
- if (sessionStoreRef.current) {
1990
- try {
1991
- sessionStoreRef.current.recordFeedEvents([feedEvent]);
1992
- } catch (err) {
1993
- sessionStoreRef.current.markDegraded(
1994
- `recordFeedEvents failed: ${err instanceof Error ? err.message : err}`
1995
- );
1996
- }
1997
- }
1998
1990
  feedStoreRef.current.pushEvents([feedEvent]);
1999
1991
  if (feedEvent.kind === "permission.decision" && feedEvent.cause?.hook_request_id) {
2000
1992
  dequeuePermission(feedEvent.cause.hook_request_id);
@@ -2049,7 +2041,7 @@ function useFeed(runtime, messages = [], initialAllowedTools, sessionStore, opti
2049
2041
  currentRun: mapperRef.current.getCurrentRun(),
2050
2042
  actors: mapperRef.current.getActors(),
2051
2043
  isServerRunning,
2052
- runtimeError,
2044
+ runtimeError: runtimeError2,
2053
2045
  currentPermissionRequest,
2054
2046
  permissionQueueCount: permissionQueue.length,
2055
2047
  resolvePermission,
@@ -5018,31 +5010,7 @@ function useTodoDisplayItems({
5018
5010
  }
5019
5011
 
5020
5012
  // src/ui/hooks/useTimeline.ts
5021
- import { useMemo as useMemo9, useRef as useRef9 } from "react";
5022
-
5023
- // src/core/feed/defaultRender.ts
5024
- var DEFAULT_RENDER = /* @__PURE__ */ new Set([
5025
- "compact.post",
5026
- "task.created",
5027
- "cwd.changed",
5028
- "file.changed",
5029
- "stop.failure",
5030
- "permission.denied",
5031
- "elicitation.request",
5032
- "elicitation.result",
5033
- "channel.permission.relayed",
5034
- "channel.permission.resolved",
5035
- "channel.question.relayed",
5036
- "channel.question.resolved",
5037
- "channel.chat.inbound",
5038
- "channel.chat.outbound",
5039
- "gateway.function.invoked",
5040
- "gateway.function.completed",
5041
- "gateway.function.failed"
5042
- ]);
5043
- function isDefaultRenderKind(k) {
5044
- return DEFAULT_RENDER.has(k);
5045
- }
5013
+ import { useMemo as useMemo9, useRef as useRef9, useCallback as useCallback10 } from "react";
5046
5014
 
5047
5015
  // src/shared/utils/toolResponse.ts
5048
5016
  function isRecord(value) {
@@ -5267,207 +5235,24 @@ function computeDuplicateActors(entries) {
5267
5235
  entries[i].duplicateActor = sameActor && !isBreak;
5268
5236
  }
5269
5237
  }
5270
- function eventOperation(event) {
5271
- if (isDefaultRenderKind(event.kind)) return "event";
5272
- switch (event.kind) {
5273
- case "run.start":
5274
- return "run.start";
5275
- case "run.end":
5276
- if (event.data.status === "completed") return "run.ok";
5277
- if (event.data.status === "failed") return "run.fail";
5278
- return "run.abort";
5279
- case "user.prompt":
5280
- return "prompt";
5281
- case "plan.update":
5282
- return "plan.upd";
5283
- case "reasoning.summary":
5284
- return "reason";
5285
- case "usage.update":
5286
- return "usage.upd";
5287
- case "tool.delta":
5288
- return "tool.call";
5289
- case "tool.pre":
5290
- return "tool.call";
5291
- case "tool.post":
5292
- return "tool.ok";
5293
- case "tool.failure":
5294
- return "tool.fail";
5295
- case "subagent.start":
5296
- return "sub.start";
5297
- case "subagent.stop":
5298
- return "sub.stop";
5299
- case "permission.request":
5300
- return "perm.req";
5301
- case "permission.decision":
5302
- return `perm.${event.data.decision_type}`;
5303
- case "stop.request":
5304
- return "stop.req";
5305
- case "stop.decision":
5306
- return `stop.${event.data.decision_type}`;
5307
- case "session.start":
5308
- return "sess.start";
5309
- case "session.end":
5310
- return "sess.end";
5311
- case "notification":
5312
- return "notify";
5313
- case "runtime.error":
5314
- return "error";
5315
- case "thread.status":
5316
- return "thread";
5317
- case "turn.diff":
5318
- return "diff";
5319
- case "server.request.resolved":
5320
- return "req.done";
5321
- case "web.search":
5322
- return "web.search";
5323
- case "review.status":
5324
- return "review";
5325
- case "image.view":
5326
- return "image";
5327
- case "context.compaction":
5328
- return "compact";
5329
- case "mcp.progress":
5330
- return "mcp.prog";
5331
- case "terminal.input":
5332
- return "term.in";
5333
- case "skills.changed":
5334
- return "skills";
5335
- case "skills.loaded":
5336
- return "skills";
5337
- case "compact.pre":
5338
- return "compact";
5339
- case "setup":
5340
- return "setup";
5341
- case "unknown.hook":
5342
- return "unknown";
5343
- case "todo.add":
5344
- return "todo.add";
5345
- case "todo.update":
5346
- return "todo.upd";
5347
- case "todo.done":
5348
- return "todo.done";
5349
- case "agent.message":
5350
- return "agent.msg";
5351
- case "teammate.idle":
5352
- return "tm.idle";
5353
- case "task.completed":
5354
- return "task.ok";
5355
- case "config.change":
5356
- return "cfg.chg";
5357
- default:
5358
- return "event";
5359
- }
5238
+ function stripMarkdownInline(text) {
5239
+ return text.replace(/#{1,6}\s+/g, "").replace(/\*\*(.+?)\*\*/g, "$1").replace(/__(.+?)__/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/`(.+?)`/g, "$1").replace(/~~(.+?)~~/g, "$1");
5360
5240
  }
5361
- function eventLabel(event) {
5362
- if (isDefaultRenderKind(event.kind)) return "Event";
5363
- switch (event.kind) {
5364
- case "run.start":
5365
- return "Run Start";
5366
- case "run.end":
5367
- if (event.data.status === "completed") return "Run OK";
5368
- if (event.data.status === "failed") return "Run Fail";
5369
- return "Run Abort";
5370
- case "user.prompt":
5371
- return "User Prompt";
5372
- case "plan.update":
5373
- return "Plan Update";
5374
- case "reasoning.summary":
5375
- return "Reasoning";
5376
- case "usage.update":
5377
- return "Usage Update";
5378
- case "tool.delta":
5379
- return "Tool Call";
5380
- case "tool.pre":
5381
- return "Tool Call";
5382
- case "tool.post":
5383
- return "Tool OK";
5384
- case "tool.failure":
5385
- return "Tool Fail";
5386
- case "subagent.start":
5387
- return "Sub Start";
5388
- case "subagent.stop":
5389
- return "Sub Stop";
5390
- case "permission.request":
5391
- return "Perm Request";
5392
- case "permission.decision":
5393
- switch (event.data.decision_type) {
5394
- case "allow":
5395
- return "Perm Allow";
5396
- case "deny":
5397
- return "Perm Deny";
5398
- case "ask":
5399
- return "Perm Ask";
5400
- case "no_opinion":
5401
- return "Perm Skip";
5402
- default:
5403
- return "Perm Decision";
5404
- }
5405
- case "stop.request":
5406
- return "Stop Request";
5407
- case "stop.decision":
5408
- switch (event.data.decision_type) {
5409
- case "block":
5410
- return "Stop Block";
5411
- case "allow":
5412
- return "Stop Allow";
5413
- case "no_opinion":
5414
- return "Stop Skip";
5415
- default:
5416
- return "Stop Decision";
5417
- }
5418
- case "session.start":
5419
- return "Sess Start";
5420
- case "session.end":
5421
- return "Sess End";
5422
- case "notification":
5423
- return "Notify";
5424
- case "runtime.error":
5425
- return "Error";
5426
- case "thread.status":
5427
- return "Thread";
5428
- case "turn.diff":
5429
- return "Diff";
5430
- case "server.request.resolved":
5431
- return "Request";
5432
- case "web.search":
5433
- return "Web Search";
5434
- case "review.status":
5435
- return "Review";
5436
- case "image.view":
5437
- return "Image";
5438
- case "context.compaction":
5439
- return "Compaction";
5440
- case "mcp.progress":
5441
- return "MCP Progress";
5442
- case "terminal.input":
5443
- return "Terminal In";
5444
- case "skills.changed":
5445
- return "Skills";
5446
- case "skills.loaded":
5447
- return "Skills";
5448
- case "compact.pre":
5449
- return "Compact";
5450
- case "setup":
5451
- return "Setup";
5452
- case "unknown.hook":
5453
- return "Unknown";
5454
- case "todo.add":
5455
- return "Todo Add";
5456
- case "todo.update":
5457
- return "Todo Update";
5458
- case "todo.done":
5459
- return "Todo Done";
5460
- case "agent.message":
5461
- return "Agent Msg";
5462
- case "teammate.idle":
5463
- return "Team Idle";
5464
- case "task.completed":
5465
- return "Task OK";
5466
- case "config.change":
5467
- return "Config Chg";
5468
- default:
5469
- return "Event";
5241
+ function firstSentence(text) {
5242
+ const nlIdx = text.indexOf("\n");
5243
+ const sentIdx = text.indexOf(". ");
5244
+ const nlEnd = nlIdx === -1 ? Infinity : nlIdx;
5245
+ const sentEnd = sentIdx === -1 ? Infinity : sentIdx + 1;
5246
+ const end = Math.min(nlEnd, sentEnd, text.length);
5247
+ return text.slice(0, end).trim();
5248
+ }
5249
+ function resolveDisplayName(toolName) {
5250
+ const parsed = parseToolName(toolName);
5251
+ if (parsed.isMcp && parsed.mcpServer && parsed.mcpAction) {
5252
+ const friendlyServer = extractFriendlyServerName(parsed.mcpServer);
5253
+ return `[${friendlyServer}] ${parsed.mcpAction}`;
5470
5254
  }
5255
+ return toolName;
5471
5256
  }
5472
5257
  var PATH_TOOLS = /* @__PURE__ */ new Set(["Read", "Write", "Edit", "Glob", "Grep"]);
5473
5258
  function withMcpServerContext(parsed, primaryInput) {
@@ -5520,89 +5305,6 @@ function formatToolSummary(toolName, toolInput, errorSuffix) {
5520
5305
  ]
5521
5306
  };
5522
5307
  }
5523
- function eventSummary(event) {
5524
- const harness = harnessSummary(event);
5525
- if (harness) return harness;
5526
- switch (event.kind) {
5527
- case "tool.delta":
5528
- case "tool.pre":
5529
- case "tool.post":
5530
- return formatToolSummary(event.data.tool_name, event.data.tool_input);
5531
- case "permission.request":
5532
- return formatPermissionSummary(event);
5533
- case "tool.failure":
5534
- return formatToolSummary(
5535
- event.data.tool_name,
5536
- event.data.tool_input,
5537
- event.data.error
5538
- );
5539
- case "subagent.start":
5540
- case "subagent.stop": {
5541
- const text = compactText(
5542
- event.data.description?.trim() || `id:${event.data.agent_id}`,
5543
- 200
5544
- );
5545
- return { text, segments: [{ text, role: "target" }] };
5546
- }
5547
- case "agent.message": {
5548
- const text = eventSummaryText(event);
5549
- return { text, segments: [{ text, role: "plain" }] };
5550
- }
5551
- case "setup":
5552
- case "session.start":
5553
- case "session.end":
5554
- case "run.start":
5555
- case "run.end":
5556
- case "user.prompt":
5557
- case "plan.update":
5558
- case "reasoning.summary":
5559
- case "usage.update":
5560
- case "permission.decision":
5561
- case "permission.denied":
5562
- case "stop.request":
5563
- case "stop.decision":
5564
- case "stop.failure":
5565
- case "notification":
5566
- case "runtime.error":
5567
- case "thread.status":
5568
- case "turn.diff":
5569
- case "server.request.resolved":
5570
- case "web.search":
5571
- case "review.status":
5572
- case "image.view":
5573
- case "context.compaction":
5574
- case "mcp.progress":
5575
- case "terminal.input":
5576
- case "skills.changed":
5577
- case "skills.loaded":
5578
- case "compact.pre":
5579
- case "compact.post":
5580
- case "unknown.hook":
5581
- case "todo.add":
5582
- case "todo.update":
5583
- case "todo.done":
5584
- case "teammate.idle":
5585
- case "task.created":
5586
- case "task.completed":
5587
- case "config.change":
5588
- case "cwd.changed":
5589
- case "file.changed":
5590
- case "elicitation.request":
5591
- case "elicitation.result":
5592
- case "channel.permission.relayed":
5593
- case "channel.permission.resolved":
5594
- case "channel.question.relayed":
5595
- case "channel.question.resolved":
5596
- case "channel.chat.inbound":
5597
- case "channel.chat.outbound":
5598
- case "gateway.function.invoked":
5599
- case "gateway.function.completed":
5600
- case "gateway.function.failed": {
5601
- const text = eventSummaryText(event);
5602
- return { text, segments: [{ text, role: "target" }] };
5603
- }
5604
- }
5605
- }
5606
5308
  function formatPermissionSummary(event) {
5607
5309
  const base = formatToolSummary(event.data.tool_name, event.data.tool_input);
5608
5310
  const host = event.data.network_context?.host;
@@ -5617,369 +5319,619 @@ function formatPermissionSummary(event) {
5617
5319
  segments: [...base.segments, { text: suffix, role: "target" }]
5618
5320
  };
5619
5321
  }
5620
- function stripMarkdownInline(text) {
5621
- return text.replace(/#{1,6}\s+/g, "").replace(/\*\*(.+?)\*\*/g, "$1").replace(/__(.+?)__/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/`(.+?)`/g, "$1").replace(/~~(.+?)~~/g, "$1");
5322
+ function formatRunEndSummary(event) {
5323
+ const toolText = `${event.data.counters.tool_uses} tool${event.data.counters.tool_uses === 1 ? "" : "s"}`;
5324
+ const failureCount = event.data.counters.tool_failures;
5325
+ if (failureCount > 0) {
5326
+ return `${event.data.status} \xB7 ${toolText}, ${failureCount} failure${failureCount === 1 ? "" : "s"}`;
5327
+ }
5328
+ return `${event.data.status} \xB7 ${toolText}`;
5622
5329
  }
5623
- function firstSentence(text) {
5624
- const nlIdx = text.indexOf("\n");
5625
- const sentIdx = text.indexOf(". ");
5626
- const nlEnd = nlIdx === -1 ? Infinity : nlIdx;
5627
- const sentEnd = sentIdx === -1 ? Infinity : sentIdx + 1;
5628
- const end = Math.min(nlEnd, sentEnd, text.length);
5629
- return text.slice(0, end).trim();
5330
+ function harnessSummary(event) {
5331
+ const title = event.display?.title?.trim();
5332
+ if (!title) return void 0;
5333
+ const text = compactText(title, 200);
5334
+ return { text, segments: [{ text, role: "target" }] };
5630
5335
  }
5631
- function eventSummaryText(event) {
5632
- switch (event.kind) {
5633
- case "run.start":
5634
- return compactText(
5635
- event.data.trigger.prompt_preview || "interactive",
5636
- 200
5637
- );
5638
- case "run.end":
5639
- return compactText(formatRunEndSummary(event), 200);
5640
- case "user.prompt":
5641
- return compactText(event.data.prompt, 200);
5642
- case "plan.update": {
5643
- if (event.data.explanation) {
5644
- return compactText(event.data.explanation, 200);
5645
- }
5646
- if (event.data.plan && event.data.plan.length > 0) {
5647
- const completed = event.data.plan.filter(
5648
- (step) => step.status === "completed"
5649
- ).length;
5650
- return compactText(`${completed}/${event.data.plan.length} steps`, 200);
5651
- }
5652
- return compactText(event.data.delta || "plan updated", 200);
5653
- }
5654
- case "reasoning.summary":
5655
- return compactText(
5656
- firstSentence(stripMarkdownInline(event.data.message)),
5657
- 200
5658
- );
5659
- case "usage.update": {
5660
- const total = event.data.usage?.total;
5661
- const delta = event.data.delta?.total;
5662
- if (typeof total === "number" && typeof delta === "number") {
5663
- return compactText(
5664
- `${total.toLocaleString()} total (+${delta.toLocaleString()})`,
5665
- 200
5666
- );
5667
- }
5668
- if (typeof total === "number") {
5669
- return compactText(`${total.toLocaleString()} total`, 200);
5670
- }
5671
- return compactText("usage updated", 200);
5672
- }
5673
- case "permission.decision": {
5674
- const detail = event.data.decision_type === "deny" ? event.data.message || event.data.reason : event.data.reason;
5675
- return compactText(detail || event.data.decision_type, 200);
5676
- }
5677
- case "stop.request":
5678
- return compactText(
5679
- event.data.stop_hook_active ? "Stop hook active" : "Stop hook inactive",
5680
- 200
5681
- );
5682
- case "stop.decision":
5683
- return compactText(event.data.reason || event.data.decision_type, 200);
5684
- case "session.start":
5685
- return compactText(event.data.source, 200);
5686
- case "session.end":
5687
- return compactText(event.data.reason, 200);
5688
- case "notification":
5689
- return compactText(stripMarkdownInline(event.data.message), 200);
5690
- case "runtime.error":
5691
- return compactText(stripMarkdownInline(event.data.message), 200);
5692
- case "thread.status":
5693
- return compactText(event.data.message, 200);
5694
- case "turn.diff":
5695
- return compactText(event.data.message, 200);
5696
- case "server.request.resolved":
5697
- return compactText(event.data.message, 200);
5698
- case "web.search":
5699
- return compactText(event.data.message, 200);
5700
- case "review.status":
5701
- return compactText(event.data.message, 200);
5702
- case "image.view":
5703
- return compactText(event.data.message, 200);
5704
- case "context.compaction":
5705
- return compactText(event.data.message, 200);
5706
- case "mcp.progress":
5707
- return compactText(event.data.message, 200);
5708
- case "terminal.input":
5709
- return compactText(event.data.message, 200);
5710
- case "skills.changed":
5711
- case "skills.loaded":
5712
- return compactText(event.data.message, 200);
5713
- case "compact.pre":
5714
- return compactText(event.data.trigger, 200);
5715
- case "setup":
5716
- return compactText(event.data.trigger, 200);
5717
- case "unknown.hook":
5718
- return compactText(event.data.hook_event_name, 200);
5719
- case "todo.add":
5720
- return compactText(
5721
- `${event.data.priority?.toUpperCase() ?? "P1"} ${event.data.text}`,
5722
- 200
5723
- );
5724
- case "todo.update": {
5725
- const patchFields = Object.keys(event.data.patch);
5726
- return compactText(
5727
- `${event.data.todo_id} ${patchFields.length > 0 ? patchFields.join(",") : "update"}`,
5728
- 200
5729
- );
5730
- }
5731
- case "todo.done":
5732
- return compactText(
5733
- `${event.data.todo_id} ${event.data.reason || "done"}`,
5734
- 200
5735
- );
5736
- case "agent.message":
5737
- return compactText(
5738
- firstSentence(stripMarkdownInline(event.data.message)),
5739
- 200
5740
- );
5741
- case "teammate.idle":
5742
- return compactText(
5743
- `${event.data.teammate_name} idle in ${event.data.team_name}`,
5744
- 200
5745
- );
5746
- case "task.created":
5747
- case "task.completed":
5748
- return compactText(event.data.task_subject, 200);
5749
- case "config.change":
5750
- return compactText(
5751
- `${event.data.source}${event.data.file_path ? ` ${event.data.file_path}` : ""}`,
5752
- 200
5753
- );
5754
- case "cwd.changed":
5755
- return compactText(`cwd \u2192 ${event.data.cwd}`, 200);
5756
- case "file.changed":
5757
- return compactText(`changed ${event.data.file_path}`, 200);
5758
- case "stop.failure":
5759
- return compactText(
5760
- `${event.data.error_type}${event.data.error_message ? `: ${event.data.error_message}` : ""}`,
5761
- 200
5762
- );
5763
- case "permission.denied":
5764
- return compactText(
5765
- `${event.data.tool_name}${event.data.reason ? `: ${event.data.reason}` : ""}`,
5766
- 200
5767
- );
5768
- case "elicitation.request":
5769
- return compactText(`elicitation from ${event.data.mcp_server}`, 200);
5770
- case "elicitation.result":
5771
- return compactText(
5772
- `${event.data.mcp_server} \u2192 ${event.data.action}`,
5773
- 200
5774
- );
5775
- case "channel.permission.relayed":
5776
- return compactText(
5777
- `${event.data.channel_name}: ${event.data.tool_name} (${event.data.channel_request_id})`,
5778
- 200
5779
- );
5780
- case "channel.permission.resolved":
5781
- return compactText(
5782
- `${event.data.channel_name} ${event.data.source} ${event.data.tool_name}`,
5783
- 200
5784
- );
5785
- case "channel.question.relayed":
5786
- return compactText(
5787
- `${event.data.channel_name}: ${event.data.title} (${event.data.channel_request_id})`,
5788
- 200
5789
- );
5790
- case "channel.question.resolved":
5791
- return compactText(
5792
- `${event.data.channel_name || event.data.source} ${event.data.source} ${event.data.title}`,
5793
- 200
5794
- );
5795
- case "channel.chat.inbound":
5796
- return compactText(
5797
- `${event.data.channel_name}: ${event.data.content}`,
5798
- 200
5799
- );
5800
- case "channel.chat.outbound":
5801
- return compactText(
5802
- `${event.data.channel_name} \u2192 ${event.data.target_peer_id}: ${event.data.content}`,
5803
- 200
5804
- );
5805
- case "gateway.function.invoked":
5806
- return compactText(
5807
- `fn invoked: ${event.data.function_name} (${event.data.caller_kind})`,
5808
- 200
5809
- );
5810
- case "gateway.function.completed":
5811
- return compactText(
5812
- `fn ok: ${event.data.function_name} ${event.data.duration_ms}ms`,
5813
- 200
5814
- );
5815
- case "gateway.function.failed":
5816
- return compactText(
5817
- `fn ${event.data.reason}: ${event.data.function_name} \u2014 ${event.data.error_message}`,
5818
- 200
5819
- );
5820
- case "compact.post":
5821
- return compactText(`compacted (${event.data.trigger})`, 200);
5822
- case "tool.pre":
5823
- case "tool.delta":
5824
- case "tool.post":
5825
- case "tool.failure":
5826
- case "permission.request":
5827
- case "subagent.start":
5828
- case "subagent.stop":
5829
- return compactText("event", 200);
5336
+ function postOutcome(postEvent) {
5337
+ if (postEvent.kind === "tool.failure") {
5338
+ return summarizeToolResult(
5339
+ postEvent.data.tool_name,
5340
+ postEvent.data.tool_input,
5341
+ void 0,
5342
+ postEvent.data.error
5343
+ );
5830
5344
  }
5831
- }
5832
- function formatRunEndSummary(event) {
5833
- const toolText = `${event.data.counters.tool_uses} tool${event.data.counters.tool_uses === 1 ? "" : "s"}`;
5834
- const failureCount = event.data.counters.tool_failures;
5835
- if (failureCount > 0) {
5836
- return `${event.data.status} \xB7 ${toolText}, ${failureCount} failure${failureCount === 1 ? "" : "s"}`;
5345
+ if (postEvent.kind === "tool.post") {
5346
+ return summarizeToolResult(
5347
+ postEvent.data.tool_name,
5348
+ postEvent.data.tool_input,
5349
+ postEvent.data.tool_response
5350
+ );
5837
5351
  }
5838
- return `${event.data.status} \xB7 ${toolText}`;
5352
+ return void 0;
5839
5353
  }
5840
- function expansionForEvent(event) {
5841
- switch (event.kind) {
5842
- case "tool.pre":
5843
- case "tool.delta":
5844
- return JSON.stringify(
5845
- { tool: event.data.tool_name, args: event.data.tool_input },
5846
- null,
5847
- 2
5848
- );
5849
- case "tool.post":
5850
- return JSON.stringify(
5851
- {
5852
- tool: event.data.tool_name,
5853
- args: event.data.tool_input,
5854
- result: event.data.tool_response
5855
- },
5856
- null,
5857
- 2
5858
- );
5859
- case "tool.failure":
5860
- return JSON.stringify(
5861
- {
5862
- tool: event.data.tool_name,
5863
- args: event.data.tool_input,
5864
- error: event.data.error,
5865
- interrupt: event.data.is_interrupt
5866
- },
5867
- null,
5868
- 2
5869
- );
5870
- case "permission.request":
5871
- return JSON.stringify(
5872
- {
5873
- tool: event.data.tool_name,
5874
- args: event.data.tool_input,
5875
- suggestions: event.data.permission_suggestions
5876
- },
5877
- null,
5878
- 2
5879
- );
5880
- case "subagent.stop":
5881
- case "run.end":
5882
- case "plan.update":
5883
- case "reasoning.summary":
5884
- case "usage.update":
5885
- case "runtime.error":
5886
- case "thread.status":
5887
- case "turn.diff":
5888
- case "server.request.resolved":
5889
- case "web.search":
5890
- case "review.status":
5891
- case "image.view":
5892
- case "context.compaction":
5893
- case "mcp.progress":
5894
- case "terminal.input":
5895
- case "skills.changed":
5896
- case "skills.loaded":
5897
- return JSON.stringify(event.data, null, 2);
5898
- case "setup":
5899
- case "session.start":
5900
- case "session.end":
5901
- case "run.start":
5902
- case "user.prompt":
5903
- case "permission.decision":
5904
- case "permission.denied":
5905
- case "stop.request":
5906
- case "stop.decision":
5907
- case "stop.failure":
5908
- case "notification":
5909
- case "subagent.start":
5910
- case "compact.pre":
5911
- case "compact.post":
5912
- case "unknown.hook":
5913
- case "todo.add":
5914
- case "todo.update":
5915
- case "todo.done":
5916
- case "agent.message":
5917
- case "teammate.idle":
5918
- case "task.created":
5919
- case "task.completed":
5920
- case "config.change":
5921
- case "cwd.changed":
5922
- case "file.changed":
5923
- case "elicitation.request":
5924
- case "elicitation.result":
5925
- case "channel.permission.relayed":
5926
- case "channel.permission.resolved":
5927
- case "channel.question.relayed":
5928
- case "channel.question.resolved":
5929
- case "channel.chat.inbound":
5930
- case "channel.chat.outbound":
5931
- case "gateway.function.invoked":
5932
- case "gateway.function.completed":
5933
- case "gateway.function.failed":
5934
- return JSON.stringify(event.raw ?? event.data, null, 2);
5935
- }
5354
+ function plainSummary(text) {
5355
+ const compact = compactText(text, 200);
5356
+ return { text: compact, segments: [{ text: compact, role: "target" }] };
5936
5357
  }
5937
- function isEventError(event) {
5938
- if (event.level === "error") return true;
5939
- if (event.kind === "tool.failure") return true;
5940
- if (event.kind === "runtime.error") return true;
5941
- if (event.kind === "run.end") return event.data.status !== "completed";
5942
- if (event.kind === "permission.decision" && event.data.decision_type === "deny") {
5943
- return true;
5944
- }
5945
- if (event.kind === "stop.decision" && event.data.decision_type === "block") {
5946
- return true;
5947
- }
5948
- return false;
5358
+ function dataExpansion(event) {
5359
+ return JSON.stringify(event.data, null, 2);
5949
5360
  }
5950
- function isEventExpandable(event) {
5951
- void event;
5952
- return true;
5361
+ function rawOrDataExpansion(event) {
5362
+ return JSON.stringify(event.raw ?? event.data, null, 2);
5953
5363
  }
5954
- var VERBOSE_ONLY_KINDS = /* @__PURE__ */ new Set([
5955
- "session.start",
5956
- "session.end",
5957
- "run.start",
5958
- "run.end",
5959
- "unknown.hook",
5960
- "compact.pre",
5961
- "config.change",
5962
- "turn.diff",
5963
- "usage.update",
5964
- "reasoning.summary"
5965
- ]);
5966
- function mergedEventOperation(event, postEvent) {
5967
- if (!postEvent) return eventOperation(event);
5968
- if (postEvent.kind === "tool.failure") return "tool.fail";
5969
- if (postEvent.kind === "tool.post") return "tool.ok";
5970
- return eventOperation(event);
5364
+ function defaultRenderer(summarize2) {
5365
+ return {
5366
+ operation: () => "event",
5367
+ label: () => "Event",
5368
+ detail: () => "\u2500",
5369
+ summary: (event) => plainSummary(summarize2(event)),
5370
+ expansion: rawOrDataExpansion
5371
+ };
5372
+ }
5373
+ var sessionStart = {
5374
+ operation: () => "sess.start",
5375
+ label: () => "Sess Start",
5376
+ detail: (event) => event.data.source,
5377
+ summary: (event) => plainSummary(event.data.source),
5378
+ expansion: rawOrDataExpansion
5379
+ };
5380
+ var sessionEnd = {
5381
+ operation: () => "sess.end",
5382
+ label: () => "Sess End",
5383
+ detail: () => "\u2500",
5384
+ summary: (event) => plainSummary(event.data.reason),
5385
+ expansion: rawOrDataExpansion
5386
+ };
5387
+ var runStart = {
5388
+ operation: () => "run.start",
5389
+ label: () => "Run Start",
5390
+ detail: () => "\u2500",
5391
+ summary: (event) => plainSummary(event.data.trigger.prompt_preview || "interactive"),
5392
+ expansion: rawOrDataExpansion
5393
+ };
5394
+ var runEnd = {
5395
+ operation: (event) => {
5396
+ if (event.data.status === "completed") return "run.ok";
5397
+ if (event.data.status === "failed") return "run.fail";
5398
+ return "run.abort";
5399
+ },
5400
+ label: (event) => {
5401
+ if (event.data.status === "completed") return "Run OK";
5402
+ if (event.data.status === "failed") return "Run Fail";
5403
+ return "Run Abort";
5404
+ },
5405
+ detail: () => "\u2500",
5406
+ summary: (event) => plainSummary(formatRunEndSummary(event)),
5407
+ expansion: dataExpansion,
5408
+ isError: (event) => event.data.status !== "completed"
5409
+ };
5410
+ var userPrompt = {
5411
+ operation: () => "prompt",
5412
+ label: () => "User Prompt",
5413
+ detail: () => "\u2500",
5414
+ summary: (event) => plainSummary(event.data.prompt),
5415
+ expansion: rawOrDataExpansion
5416
+ };
5417
+ var planUpdate = {
5418
+ operation: () => "plan.upd",
5419
+ label: () => "Plan Update",
5420
+ detail: () => "plan",
5421
+ summary: (event) => {
5422
+ if (event.data.explanation) return plainSummary(event.data.explanation);
5423
+ if (event.data.plan && event.data.plan.length > 0) {
5424
+ const completed = event.data.plan.filter(
5425
+ (step) => step.status === "completed"
5426
+ ).length;
5427
+ return plainSummary(`${completed}/${event.data.plan.length} steps`);
5428
+ }
5429
+ return plainSummary(event.data.delta || "plan updated");
5430
+ },
5431
+ expansion: dataExpansion
5432
+ };
5433
+ var reasoningSummary = {
5434
+ operation: () => "reason",
5435
+ label: () => "Reasoning",
5436
+ detail: () => "summary",
5437
+ summary: (event) => plainSummary(firstSentence(stripMarkdownInline(event.data.message))),
5438
+ expansion: dataExpansion
5439
+ };
5440
+ var usageUpdate = {
5441
+ operation: () => "usage.upd",
5442
+ label: () => "Usage Update",
5443
+ detail: () => "tokens",
5444
+ summary: (event) => {
5445
+ const total = event.data.usage?.total;
5446
+ const delta = event.data.delta?.total;
5447
+ if (typeof total === "number" && typeof delta === "number") {
5448
+ return plainSummary(
5449
+ `${total.toLocaleString()} total (+${delta.toLocaleString()})`
5450
+ );
5451
+ }
5452
+ if (typeof total === "number") {
5453
+ return plainSummary(`${total.toLocaleString()} total`);
5454
+ }
5455
+ return plainSummary("usage updated");
5456
+ },
5457
+ expansion: dataExpansion
5458
+ };
5459
+ var toolDelta = {
5460
+ operation: () => "tool.call",
5461
+ label: () => "Tool Call",
5462
+ detail: (event) => resolveDisplayName(event.data.tool_name),
5463
+ summary: (event) => formatToolSummary(event.data.tool_name, event.data.tool_input),
5464
+ expansion: (event) => JSON.stringify(
5465
+ { tool: event.data.tool_name, args: event.data.tool_input },
5466
+ null,
5467
+ 2
5468
+ )
5469
+ };
5470
+ var toolPre = {
5471
+ operation: () => "tool.call",
5472
+ label: () => "Tool Call",
5473
+ detail: (event) => resolveDisplayName(event.data.tool_name),
5474
+ summary: (event) => formatToolSummary(event.data.tool_name, event.data.tool_input),
5475
+ expansion: (event) => JSON.stringify(
5476
+ { tool: event.data.tool_name, args: event.data.tool_input },
5477
+ null,
5478
+ 2
5479
+ )
5480
+ };
5481
+ var toolPost = {
5482
+ operation: () => "tool.ok",
5483
+ label: () => "Tool OK",
5484
+ detail: (event) => resolveDisplayName(event.data.tool_name),
5485
+ summary: (event) => formatToolSummary(event.data.tool_name, event.data.tool_input),
5486
+ expansion: (event) => JSON.stringify(
5487
+ {
5488
+ tool: event.data.tool_name,
5489
+ args: event.data.tool_input,
5490
+ result: event.data.tool_response
5491
+ },
5492
+ null,
5493
+ 2
5494
+ )
5495
+ };
5496
+ var toolFailure = {
5497
+ operation: () => "tool.fail",
5498
+ label: () => "Tool Fail",
5499
+ detail: (event) => resolveDisplayName(event.data.tool_name),
5500
+ summary: (event) => formatToolSummary(
5501
+ event.data.tool_name,
5502
+ event.data.tool_input,
5503
+ event.data.error
5504
+ ),
5505
+ expansion: (event) => JSON.stringify(
5506
+ {
5507
+ tool: event.data.tool_name,
5508
+ args: event.data.tool_input,
5509
+ error: event.data.error,
5510
+ interrupt: event.data.is_interrupt
5511
+ },
5512
+ null,
5513
+ 2
5514
+ ),
5515
+ isError: () => true
5516
+ };
5517
+ var permissionRequest = {
5518
+ operation: () => "perm.req",
5519
+ label: () => "Perm Request",
5520
+ detail: (event) => resolveDisplayName(event.data.tool_name),
5521
+ summary: (event) => formatPermissionSummary(event),
5522
+ expansion: (event) => JSON.stringify(
5523
+ {
5524
+ tool: event.data.tool_name,
5525
+ args: event.data.tool_input,
5526
+ suggestions: event.data.permission_suggestions
5527
+ },
5528
+ null,
5529
+ 2
5530
+ )
5531
+ };
5532
+ var permissionDecision = {
5533
+ operation: (event) => `perm.${event.data.decision_type}`,
5534
+ label: (event) => {
5535
+ switch (event.data.decision_type) {
5536
+ case "allow":
5537
+ return "Perm Allow";
5538
+ case "deny":
5539
+ return "Perm Deny";
5540
+ case "ask":
5541
+ return "Perm Ask";
5542
+ case "no_opinion":
5543
+ return "Perm Skip";
5544
+ default:
5545
+ return "Perm Decision";
5546
+ }
5547
+ },
5548
+ detail: () => "\u2500",
5549
+ summary: (event) => {
5550
+ const detail = event.data.decision_type === "deny" ? event.data.message || event.data.reason : event.data.reason;
5551
+ return plainSummary(detail || event.data.decision_type);
5552
+ },
5553
+ expansion: rawOrDataExpansion,
5554
+ isError: (event) => event.data.decision_type === "deny"
5555
+ };
5556
+ var stopRequest = {
5557
+ operation: () => "stop.req",
5558
+ label: () => "Stop Request",
5559
+ detail: () => "\u2500",
5560
+ summary: (event) => plainSummary(
5561
+ event.data.stop_hook_active ? "Stop hook active" : "Stop hook inactive"
5562
+ ),
5563
+ expansion: rawOrDataExpansion
5564
+ };
5565
+ var stopDecision = {
5566
+ operation: (event) => `stop.${event.data.decision_type}`,
5567
+ label: (event) => {
5568
+ switch (event.data.decision_type) {
5569
+ case "block":
5570
+ return "Stop Block";
5571
+ case "allow":
5572
+ return "Stop Allow";
5573
+ case "no_opinion":
5574
+ return "Stop Skip";
5575
+ default:
5576
+ return "Stop Decision";
5577
+ }
5578
+ },
5579
+ detail: () => "\u2500",
5580
+ summary: (event) => plainSummary(event.data.reason || event.data.decision_type),
5581
+ expansion: rawOrDataExpansion,
5582
+ isError: (event) => event.data.decision_type === "block"
5583
+ };
5584
+ var subagentStart = {
5585
+ operation: () => "sub.start",
5586
+ label: () => "Sub Start",
5587
+ detail: (event) => event.data.agent_type,
5588
+ summary: (event) => {
5589
+ const text = compactText(
5590
+ event.data.description?.trim() || `id:${event.data.agent_id}`,
5591
+ 200
5592
+ );
5593
+ return { text, segments: [{ text, role: "target" }] };
5594
+ },
5595
+ expansion: rawOrDataExpansion
5596
+ };
5597
+ var subagentStop = {
5598
+ operation: () => "sub.stop",
5599
+ label: () => "Sub Stop",
5600
+ detail: (event) => event.data.agent_type,
5601
+ summary: (event) => {
5602
+ const text = compactText(
5603
+ event.data.description?.trim() || `id:${event.data.agent_id}`,
5604
+ 200
5605
+ );
5606
+ return { text, segments: [{ text, role: "target" }] };
5607
+ },
5608
+ expansion: dataExpansion
5609
+ };
5610
+ var notification = {
5611
+ operation: () => "notify",
5612
+ label: () => "Notify",
5613
+ detail: () => "\u2500",
5614
+ summary: (event) => plainSummary(stripMarkdownInline(event.data.message)),
5615
+ expansion: rawOrDataExpansion
5616
+ };
5617
+ var runtimeError = {
5618
+ operation: () => "error",
5619
+ label: () => "Error",
5620
+ detail: () => "\u2500",
5621
+ summary: (event) => plainSummary(stripMarkdownInline(event.data.message)),
5622
+ expansion: dataExpansion,
5623
+ isError: () => true
5624
+ };
5625
+ var threadStatus = {
5626
+ operation: () => "thread",
5627
+ label: () => "Thread",
5628
+ detail: (event) => event.data.status_type ?? "status",
5629
+ summary: (event) => plainSummary(event.data.message),
5630
+ expansion: dataExpansion
5631
+ };
5632
+ var turnDiff = {
5633
+ operation: () => "diff",
5634
+ label: () => "Diff",
5635
+ detail: () => "\u2500",
5636
+ summary: (event) => plainSummary(event.data.message),
5637
+ expansion: dataExpansion
5638
+ };
5639
+ var serverRequestResolved = {
5640
+ operation: () => "req.done",
5641
+ label: () => "Request",
5642
+ detail: (event) => event.data.request_id ?? "request",
5643
+ summary: (event) => plainSummary(event.data.message),
5644
+ expansion: dataExpansion
5645
+ };
5646
+ var webSearch = {
5647
+ operation: () => "web.search",
5648
+ label: () => "Web Search",
5649
+ detail: (event) => event.data.action_type ?? event.data.phase,
5650
+ summary: (event) => plainSummary(event.data.message),
5651
+ expansion: dataExpansion
5652
+ };
5653
+ var reviewStatus = {
5654
+ operation: () => "review",
5655
+ label: () => "Review",
5656
+ detail: (event) => event.data.phase,
5657
+ summary: (event) => plainSummary(event.data.message),
5658
+ expansion: dataExpansion
5659
+ };
5660
+ var imageView = {
5661
+ operation: () => "image",
5662
+ label: () => "Image",
5663
+ detail: (event) => event.data.path ?? "image",
5664
+ summary: (event) => plainSummary(event.data.message),
5665
+ expansion: dataExpansion
5666
+ };
5667
+ var contextCompaction = {
5668
+ operation: () => "compact",
5669
+ label: () => "Compaction",
5670
+ detail: (event) => event.data.phase,
5671
+ summary: (event) => plainSummary(event.data.message),
5672
+ expansion: dataExpansion
5673
+ };
5674
+ var mcpProgress = {
5675
+ operation: () => "mcp.prog",
5676
+ label: () => "MCP Progress",
5677
+ detail: () => "\u2500",
5678
+ summary: (event) => plainSummary(event.data.message),
5679
+ expansion: dataExpansion
5680
+ };
5681
+ var terminalInput = {
5682
+ operation: () => "term.in",
5683
+ label: () => "Terminal In",
5684
+ detail: () => "\u2500",
5685
+ summary: (event) => plainSummary(event.data.message),
5686
+ expansion: dataExpansion
5687
+ };
5688
+ var skillsChanged = {
5689
+ operation: () => "skills",
5690
+ label: () => "Skills",
5691
+ detail: () => "\u2500",
5692
+ summary: (event) => plainSummary(event.data.message),
5693
+ expansion: dataExpansion
5694
+ };
5695
+ var skillsLoaded = {
5696
+ operation: () => "skills",
5697
+ label: () => "Skills",
5698
+ detail: () => "\u2500",
5699
+ summary: (event) => plainSummary(event.data.message),
5700
+ expansion: dataExpansion
5701
+ };
5702
+ var compactPre = {
5703
+ operation: () => "compact",
5704
+ label: () => "Compact",
5705
+ detail: () => "\u2500",
5706
+ summary: (event) => plainSummary(event.data.trigger),
5707
+ expansion: dataExpansion
5708
+ };
5709
+ var setup = {
5710
+ operation: () => "setup",
5711
+ label: () => "Setup",
5712
+ detail: () => "\u2500",
5713
+ summary: (event) => plainSummary(event.data.trigger),
5714
+ expansion: rawOrDataExpansion
5715
+ };
5716
+ var unknownHook = {
5717
+ operation: () => "unknown",
5718
+ label: () => "Unknown",
5719
+ detail: () => "\u2500",
5720
+ summary: (event) => plainSummary(event.data.hook_event_name),
5721
+ expansion: rawOrDataExpansion
5722
+ };
5723
+ var todoAdd = {
5724
+ operation: () => "todo.add",
5725
+ label: () => "Todo Add",
5726
+ detail: (event) => (event.data.priority ?? "p1").toUpperCase(),
5727
+ summary: (event) => plainSummary(
5728
+ `${event.data.priority?.toUpperCase() ?? "P1"} ${event.data.text}`
5729
+ ),
5730
+ expansion: rawOrDataExpansion
5731
+ };
5732
+ var todoUpdate = {
5733
+ operation: () => "todo.upd",
5734
+ label: () => "Todo Update",
5735
+ detail: (event) => event.data.todo_id,
5736
+ summary: (event) => {
5737
+ const patchFields = Object.keys(event.data.patch);
5738
+ return plainSummary(
5739
+ `${event.data.todo_id} ${patchFields.length > 0 ? patchFields.join(",") : "update"}`
5740
+ );
5741
+ },
5742
+ expansion: rawOrDataExpansion
5743
+ };
5744
+ var todoDone = {
5745
+ operation: () => "todo.done",
5746
+ label: () => "Todo Done",
5747
+ detail: (event) => event.data.todo_id,
5748
+ summary: (event) => plainSummary(`${event.data.todo_id} ${event.data.reason || "done"}`),
5749
+ expansion: rawOrDataExpansion
5750
+ };
5751
+ var agentMessage = {
5752
+ operation: () => "agent.msg",
5753
+ label: () => "Agent Msg",
5754
+ detail: () => "\u2500",
5755
+ summary: (event) => {
5756
+ const text = compactText(
5757
+ firstSentence(stripMarkdownInline(event.data.message)),
5758
+ 200
5759
+ );
5760
+ return { text, segments: [{ text, role: "plain" }] };
5761
+ },
5762
+ expansion: rawOrDataExpansion
5763
+ };
5764
+ var teammateIdle = {
5765
+ operation: () => "tm.idle",
5766
+ label: () => "Team Idle",
5767
+ detail: () => "\u2500",
5768
+ summary: (event) => plainSummary(`${event.data.teammate_name} idle in ${event.data.team_name}`),
5769
+ expansion: rawOrDataExpansion
5770
+ };
5771
+ var taskCompleted = {
5772
+ operation: () => "task.ok",
5773
+ label: () => "Task OK",
5774
+ detail: () => "\u2500",
5775
+ summary: (event) => plainSummary(event.data.task_subject),
5776
+ expansion: rawOrDataExpansion
5777
+ };
5778
+ var configChange = {
5779
+ operation: () => "cfg.chg",
5780
+ label: () => "Config Chg",
5781
+ detail: (event) => event.data.source,
5782
+ summary: (event) => plainSummary(
5783
+ `${event.data.source}${event.data.file_path ? ` ${event.data.file_path}` : ""}`
5784
+ ),
5785
+ expansion: rawOrDataExpansion
5786
+ };
5787
+ var compactPost = defaultRenderer(
5788
+ (event) => `compacted (${event.data.trigger})`
5789
+ );
5790
+ var taskCreated = defaultRenderer(
5791
+ (event) => event.data.task_subject
5792
+ );
5793
+ var cwdChanged = defaultRenderer(
5794
+ (event) => `cwd \u2192 ${event.data.cwd}`
5795
+ );
5796
+ var fileChanged = defaultRenderer(
5797
+ (event) => `changed ${event.data.file_path}`
5798
+ );
5799
+ var stopFailure = defaultRenderer(
5800
+ (event) => `${event.data.error_type}${event.data.error_message ? `: ${event.data.error_message}` : ""}`
5801
+ );
5802
+ var permissionDenied = defaultRenderer(
5803
+ (event) => `${event.data.tool_name}${event.data.reason ? `: ${event.data.reason}` : ""}`
5804
+ );
5805
+ var elicitationRequest = defaultRenderer((event) => `elicitation from ${event.data.mcp_server}`);
5806
+ var elicitationResult = defaultRenderer(
5807
+ (event) => `${event.data.mcp_server} \u2192 ${event.data.action}`
5808
+ );
5809
+ var channelPermissionRelayed = defaultRenderer(
5810
+ (event) => `${event.data.channel_name}: ${event.data.tool_name} (${event.data.channel_request_id})`
5811
+ );
5812
+ var channelPermissionResolved = defaultRenderer(
5813
+ (event) => `${event.data.channel_name} ${event.data.source} ${event.data.tool_name}`
5814
+ );
5815
+ var channelQuestionRelayed = defaultRenderer(
5816
+ (event) => `${event.data.channel_name}: ${event.data.title} (${event.data.channel_request_id})`
5817
+ );
5818
+ var channelQuestionResolved = defaultRenderer(
5819
+ (event) => `${event.data.channel_name || event.data.source} ${event.data.source} ${event.data.title}`
5820
+ );
5821
+ var channelChatInbound = defaultRenderer((event) => `${event.data.channel_name}: ${event.data.content}`);
5822
+ var channelChatOutbound = defaultRenderer(
5823
+ (event) => `${event.data.channel_name} \u2192 ${event.data.target_peer_id}: ${event.data.content}`
5824
+ );
5825
+ var gatewayFunctionInvoked = defaultRenderer(
5826
+ (event) => `fn invoked: ${event.data.function_name} (${event.data.caller_kind})`
5827
+ );
5828
+ var gatewayFunctionCompleted = defaultRenderer(
5829
+ (event) => `fn ok: ${event.data.function_name} ${event.data.duration_ms}ms`
5830
+ );
5831
+ var gatewayFunctionFailed = defaultRenderer(
5832
+ (event) => `fn ${event.data.reason}: ${event.data.function_name} \u2014 ${event.data.error_message}`
5833
+ );
5834
+ var RENDERERS = {
5835
+ "session.start": sessionStart,
5836
+ "session.end": sessionEnd,
5837
+ "run.start": runStart,
5838
+ "run.end": runEnd,
5839
+ "user.prompt": userPrompt,
5840
+ "plan.update": planUpdate,
5841
+ "reasoning.summary": reasoningSummary,
5842
+ "usage.update": usageUpdate,
5843
+ "tool.delta": toolDelta,
5844
+ "tool.pre": toolPre,
5845
+ "tool.post": toolPost,
5846
+ "tool.failure": toolFailure,
5847
+ "permission.request": permissionRequest,
5848
+ "permission.decision": permissionDecision,
5849
+ "stop.request": stopRequest,
5850
+ "stop.decision": stopDecision,
5851
+ "subagent.start": subagentStart,
5852
+ "subagent.stop": subagentStop,
5853
+ notification,
5854
+ "runtime.error": runtimeError,
5855
+ "thread.status": threadStatus,
5856
+ "turn.diff": turnDiff,
5857
+ "server.request.resolved": serverRequestResolved,
5858
+ "web.search": webSearch,
5859
+ "review.status": reviewStatus,
5860
+ "image.view": imageView,
5861
+ "context.compaction": contextCompaction,
5862
+ "mcp.progress": mcpProgress,
5863
+ "terminal.input": terminalInput,
5864
+ "skills.changed": skillsChanged,
5865
+ "skills.loaded": skillsLoaded,
5866
+ "compact.pre": compactPre,
5867
+ "compact.post": compactPost,
5868
+ setup,
5869
+ "unknown.hook": unknownHook,
5870
+ "todo.add": todoAdd,
5871
+ "todo.update": todoUpdate,
5872
+ "todo.done": todoDone,
5873
+ "agent.message": agentMessage,
5874
+ "teammate.idle": teammateIdle,
5875
+ "task.created": taskCreated,
5876
+ "task.completed": taskCompleted,
5877
+ "config.change": configChange,
5878
+ "cwd.changed": cwdChanged,
5879
+ "file.changed": fileChanged,
5880
+ "stop.failure": stopFailure,
5881
+ "permission.denied": permissionDenied,
5882
+ "elicitation.request": elicitationRequest,
5883
+ "elicitation.result": elicitationResult,
5884
+ "channel.permission.relayed": channelPermissionRelayed,
5885
+ "channel.permission.resolved": channelPermissionResolved,
5886
+ "channel.question.relayed": channelQuestionRelayed,
5887
+ "channel.question.resolved": channelQuestionResolved,
5888
+ "channel.chat.inbound": channelChatInbound,
5889
+ "channel.chat.outbound": channelChatOutbound,
5890
+ "gateway.function.invoked": gatewayFunctionInvoked,
5891
+ "gateway.function.completed": gatewayFunctionCompleted,
5892
+ "gateway.function.failed": gatewayFunctionFailed
5893
+ };
5894
+ function rendererFor(event) {
5895
+ return RENDERERS[event.kind];
5896
+ }
5897
+ function eventOperation(event) {
5898
+ return rendererFor(event).operation(event);
5971
5899
  }
5972
- function mergedEventLabel(event, postEvent) {
5973
- if (!postEvent) return eventLabel(event);
5974
- if (postEvent.kind === "tool.failure") return "Tool Fail";
5975
- if (postEvent.kind === "tool.post") return "Tool OK";
5976
- return eventLabel(event);
5900
+ function eventLabel(event) {
5901
+ return rendererFor(event).label(event);
5977
5902
  }
5978
- function mergedEventSummary(event, postEvent) {
5979
- if (!postEvent) return eventSummary(event);
5980
- if (event.kind !== "tool.pre" && event.kind !== "permission.request") {
5981
- return eventSummary(event);
5982
- }
5903
+ function eventSummary(event) {
5904
+ const harness = harnessSummary(event);
5905
+ if (harness) return harness;
5906
+ return rendererFor(event).summary(event);
5907
+ }
5908
+ function expansionForEvent(event) {
5909
+ return rendererFor(event).expansion(event);
5910
+ }
5911
+ function isEventError(event) {
5912
+ if (event.level === "error") return true;
5913
+ const renderer = rendererFor(event);
5914
+ return renderer.isError?.(event) ?? false;
5915
+ }
5916
+ function isEventExpandable(event) {
5917
+ void event;
5918
+ return true;
5919
+ }
5920
+ var toolPairOk = {
5921
+ operation: () => "tool.ok",
5922
+ label: () => "Tool OK",
5923
+ summary: (pre, post) => buildMergedToolSummary(pre, post)
5924
+ };
5925
+ var toolPairFail = {
5926
+ operation: () => "tool.fail",
5927
+ label: () => "Tool Fail",
5928
+ summary: (pre, post) => buildMergedToolSummary(pre, post)
5929
+ };
5930
+ var TOOL_PAIRS = {
5931
+ "tool.post": toolPairOk,
5932
+ "tool.failure": toolPairFail
5933
+ };
5934
+ function buildMergedToolSummary(event, postEvent) {
5983
5935
  const harness = harnessSummary(event) ?? harnessSummary(postEvent);
5984
5936
  if (harness) {
5985
5937
  return {
@@ -6006,8 +5958,6 @@ function mergedEventSummary(event, postEvent) {
6006
5958
  void 0,
6007
5959
  postEvent.data.error
6008
5960
  );
6009
- } else if (postEvent.kind === "tool.delta") {
6010
- return eventSummary(event);
6011
5961
  } else if (postEvent.kind === "tool.post") {
6012
5962
  resultText = summarizeToolResult(
6013
5963
  toolName,
@@ -6033,252 +5983,49 @@ function mergedEventSummary(event, postEvent) {
6033
5983
  outcomeZero: /^0\s/.test(resultText)
6034
5984
  };
6035
5985
  }
6036
- function harnessSummary(event) {
6037
- const title = event.display?.title?.trim();
6038
- if (!title) return void 0;
6039
- const text = compactText(title, 200);
6040
- return { text, segments: [{ text, role: "target" }] };
6041
- }
6042
- function postOutcome(postEvent) {
6043
- if (postEvent.kind === "tool.failure") {
6044
- return summarizeToolResult(
6045
- postEvent.data.tool_name,
6046
- postEvent.data.tool_input,
6047
- void 0,
6048
- postEvent.data.error
6049
- );
6050
- }
6051
- if (postEvent.kind === "tool.post") {
6052
- return summarizeToolResult(
6053
- postEvent.data.tool_name,
6054
- postEvent.data.tool_input,
6055
- postEvent.data.tool_response
6056
- );
6057
- }
6058
- return void 0;
6059
- }
6060
- function toRunStatus(event) {
6061
- switch (event.data.status) {
6062
- case "completed":
6063
- return "SUCCEEDED";
6064
- case "failed":
6065
- return "FAILED";
6066
- case "aborted":
6067
- return "CANCELLED";
6068
- }
5986
+ function mergedEventOperation(event, postEvent) {
5987
+ if (!postEvent) return eventOperation(event);
5988
+ const pair = TOOL_PAIRS[postEvent.kind];
5989
+ if (!pair) return eventOperation(event);
5990
+ return pair.operation(event, postEvent);
6069
5991
  }
6070
-
6071
- // src/core/feed/indexedTimeline.ts
6072
- var MAX_SEARCH_CACHE_SIZE = 8;
6073
- var IndexedTimeline = class {
6074
- // Underlying build cache (reuses existing logic from useTimeline.ts)
6075
- cache = null;
6076
- // Secondary indexes (maintained on every update)
6077
- runIndex = /* @__PURE__ */ new Map();
6078
- errorPositions = /* @__PURE__ */ new Set();
6079
- // Run summary tracking (incremental)
6080
- _runSummaryMap = /* @__PURE__ */ new Map();
6081
- _runSummariesDirty = true;
6082
- _runSummariesCache = [];
6083
- _lastFeedEventsLength = 0;
6084
- // Search cache
6085
- searchCache = /* @__PURE__ */ new Map();
6086
- lastFilteredRef = null;
6087
- // Instance-level caches (avoid cross-instance leaks in tests)
6088
- detailCache = /* @__PURE__ */ new WeakMap();
6089
- searchTextCache = /* @__PURE__ */ new WeakMap();
6090
- verbose = false;
6091
- constructor() {
6092
- }
6093
- /**
6094
- * Main update — determines if incremental append is possible,
6095
- * delegates to existing build/append logic, then updates indexes.
6096
- */
6097
- update(feedItems, feedEvents, postByToolUseId, verbose) {
6098
- this.verbose = verbose;
6099
- const incremental = canAppendIncrementally(
6100
- this.cache,
6101
- feedItems,
6102
- feedEvents,
6103
- this.verbose
6104
- );
6105
- if (incremental) {
6106
- this.updateRunSummaries(feedEvents);
6107
- this.cache = appendTimelineCache(
6108
- this.cache,
6109
- feedItems,
6110
- feedEvents,
6111
- postByToolUseId
6112
- );
6113
- } else {
6114
- this.rebuildRunSummaries(feedEvents);
6115
- this.cache = buildTimelineCache(
6116
- feedItems,
6117
- feedEvents,
6118
- postByToolUseId,
6119
- this.verbose
6120
- );
6121
- }
6122
- this.rebuildIndexes();
6123
- }
6124
- getEntries() {
6125
- return this.cache?.entries ?? [];
6126
- }
6127
- /**
6128
- * Index-based filtering — O(k) where k = matching entries.
6129
- * Replaces Array.filter() O(n) on every render.
6130
- */
6131
- getFilteredView(runFilter, errorsOnly) {
6132
- const entries = this.getEntries();
6133
- if ((!runFilter || runFilter === "all") && !errorsOnly) {
6134
- return entries;
6135
- }
6136
- let candidateIndices;
6137
- if (runFilter && runFilter !== "all") {
6138
- candidateIndices = this.runIndex.get(runFilter) ?? [];
6139
- } else {
6140
- candidateIndices = Array.from({ length: entries.length }, (_, i) => i);
6141
- }
6142
- if (errorsOnly) {
6143
- candidateIndices = candidateIndices.filter(
6144
- (i) => this.errorPositions.has(i)
6145
- );
6146
- }
6147
- return candidateIndices.map((i) => entries[i]);
6148
- }
6149
- /**
6150
- * Incremental search — only scans new entries since last call with same query.
6151
- * Returns indices into filteredEntries (not this.entries).
6152
- */
6153
- getSearchMatches(filteredEntries, query) {
6154
- const q = query.trim().toLowerCase();
6155
- if (!q) return [];
6156
- if (filteredEntries !== this.lastFilteredRef) {
6157
- this.searchCache.clear();
6158
- this.lastFilteredRef = filteredEntries;
6159
- }
6160
- const cached = this.searchCache.get(q);
6161
- if (cached && cached.lastScanned === filteredEntries.length) {
6162
- return cached.matches;
6163
- }
6164
- const startFrom = cached ? cached.lastScanned : 0;
6165
- const matches = cached ? [...cached.matches] : [];
6166
- for (let i = startFrom; i < filteredEntries.length; i++) {
6167
- const searchText = this.getEntrySearchText(filteredEntries[i]);
6168
- if (searchText.toLowerCase().includes(q)) {
6169
- matches.push(i);
6170
- }
6171
- }
6172
- this.searchCache.set(q, { matches, lastScanned: filteredEntries.length });
6173
- if (this.searchCache.size > MAX_SEARCH_CACHE_SIZE) {
6174
- const oldest = this.searchCache.keys().next().value;
6175
- if (oldest !== void 0) {
6176
- this.searchCache.delete(oldest);
6177
- }
6178
- }
6179
- return matches;
6180
- }
6181
- // ── Search text helpers ─────────────────────────────────
6182
- getEntrySearchText(entry) {
6183
- const cached = this.searchTextCache.get(entry);
6184
- if (cached !== void 0) return cached;
6185
- if (!entry.feedEvent) {
6186
- this.searchTextCache.set(entry, entry.searchText);
6187
- return entry.searchText;
6188
- }
6189
- const details = this.getEntryDetails(entry);
6190
- const searchText = details ? `${entry.summary}
6191
- ${details}` : entry.summary;
6192
- this.searchTextCache.set(entry, searchText);
6193
- return searchText;
6194
- }
6195
- getEntryDetails(entry) {
6196
- if (entry.details) return entry.details;
6197
- if (!entry.feedEvent) return entry.summary;
6198
- const cached = this.detailCache.get(entry);
6199
- if (cached !== void 0) return cached;
6200
- const details = isEventExpandable(entry.feedEvent) ? expansionForEvent(entry.feedEvent) : "";
6201
- this.detailCache.set(entry, details);
6202
- return details;
6203
- }
6204
- // ── Run summary tracking ─────────────────────────────
6205
- /**
6206
- * Returns sorted run summaries. Cached until a run.start/run.end
6207
- * event invalidates the sorted array.
6208
- */
6209
- getRunSummaries() {
6210
- if (this._runSummariesDirty) {
6211
- this._runSummariesCache = Array.from(this._runSummaryMap.values()).sort(
6212
- (a, b) => a.startedAt - b.startedAt
6213
- );
6214
- this._runSummariesDirty = false;
6215
- }
6216
- return this._runSummariesCache;
6217
- }
6218
- processRunEvent(event) {
6219
- if (event.kind === "run.start") {
6220
- this._runSummaryMap.set(event.run_id, {
6221
- runId: event.run_id,
6222
- title: compactText(
6223
- event.data.trigger.prompt_preview || "Untitled run",
6224
- 46
6225
- ),
6226
- status: "RUNNING",
6227
- startedAt: event.ts
6228
- });
6229
- this._runSummariesDirty = true;
6230
- } else if (event.kind === "run.end") {
6231
- const existing = this._runSummaryMap.get(event.run_id);
6232
- if (existing) {
6233
- existing.status = toRunStatus(event);
6234
- existing.endedAt = event.ts;
6235
- } else {
6236
- this._runSummaryMap.set(event.run_id, {
6237
- runId: event.run_id,
6238
- title: "Untitled run",
6239
- status: toRunStatus(event),
6240
- startedAt: event.ts,
6241
- endedAt: event.ts
6242
- });
6243
- }
6244
- this._runSummariesDirty = true;
6245
- }
6246
- }
6247
- rebuildRunSummaries(feedEvents) {
6248
- this._runSummaryMap.clear();
6249
- this._runSummariesDirty = true;
6250
- this._lastFeedEventsLength = 0;
6251
- this.updateRunSummaries(feedEvents);
6252
- }
6253
- updateRunSummaries(feedEvents) {
6254
- for (let i = this._lastFeedEventsLength; i < feedEvents.length; i++) {
6255
- this.processRunEvent(feedEvents[i]);
6256
- }
6257
- this._lastFeedEventsLength = feedEvents.length;
6258
- }
6259
- // ── Index maintenance ─────────────────────────────────
6260
- addToIndex(entry, index) {
6261
- const runId = entry.runId ?? "__none__";
6262
- let indices = this.runIndex.get(runId);
6263
- if (!indices) {
6264
- indices = [];
6265
- this.runIndex.set(runId, indices);
6266
- }
6267
- indices.push(index);
6268
- if (entry.error) {
6269
- this.errorPositions.add(index);
6270
- }
6271
- }
6272
- rebuildIndexes() {
6273
- this.runIndex.clear();
6274
- this.errorPositions.clear();
6275
- this.searchCache.clear();
6276
- const entries = this.getEntries();
6277
- for (let i = 0; i < entries.length; i++) {
6278
- this.addToIndex(entries[i], i);
6279
- }
5992
+ function mergedEventLabel(event, postEvent) {
5993
+ if (!postEvent) return eventLabel(event);
5994
+ const pair = TOOL_PAIRS[postEvent.kind];
5995
+ if (!pair) return eventLabel(event);
5996
+ return pair.label(event, postEvent);
5997
+ }
5998
+ function mergedEventSummary(event, postEvent) {
5999
+ if (!postEvent) return eventSummary(event);
6000
+ if (event.kind !== "tool.pre" && event.kind !== "permission.request") {
6001
+ return eventSummary(event);
6280
6002
  }
6281
- };
6003
+ const pair = TOOL_PAIRS[postEvent.kind];
6004
+ if (!pair) return eventSummary(event);
6005
+ return pair.summary(event, postEvent);
6006
+ }
6007
+ var VERBOSE_ONLY_KINDS = /* @__PURE__ */ new Set([
6008
+ "session.start",
6009
+ "session.end",
6010
+ "run.start",
6011
+ "run.end",
6012
+ "unknown.hook",
6013
+ "compact.pre",
6014
+ "config.change",
6015
+ "turn.diff",
6016
+ "usage.update",
6017
+ "reasoning.summary"
6018
+ ]);
6019
+ function toRunStatus(event) {
6020
+ switch (event.data.status) {
6021
+ case "completed":
6022
+ return "SUCCEEDED";
6023
+ case "failed":
6024
+ return "FAILED";
6025
+ case "aborted":
6026
+ return "CANCELLED";
6027
+ }
6028
+ }
6282
6029
 
6283
6030
  // src/core/feed/toolDisplay.ts
6284
6031
  function prop2(obj, key) {
@@ -6992,14 +6739,9 @@ function resolveEventToolColumn(event) {
6992
6739
  }
6993
6740
  }
6994
6741
 
6995
- // src/ui/hooks/useTimeline.ts
6996
- var detailCache = /* @__PURE__ */ new WeakMap();
6997
- var searchTextCache = /* @__PURE__ */ new WeakMap();
6998
- var EMPTY_MATCHES = Object.freeze([]);
6999
- var EMPTY_MATCH_SET = Object.freeze(/* @__PURE__ */ new Set());
7000
- function subagentActorLabel(agentType, agentId) {
7001
- void agentType;
7002
- void agentId;
6742
+ // src/core/feed/indexedTimeline.ts
6743
+ var MAX_SEARCH_CACHE_SIZE = 8;
6744
+ function subagentActorLabel(_agentType, _agentId) {
7003
6745
  return "SUB AGENT";
7004
6746
  }
7005
6747
  function buildSubagentTypeMap(feedEvents) {
@@ -7170,7 +6912,7 @@ function sameFeedEventPrefix(previous, next) {
7170
6912
  }
7171
6913
  function canAppendIncrementally(previous, feedItems, feedEvents, verbose) {
7172
6914
  if (!previous) return false;
7173
- if (previous.verbose !== !!verbose) return false;
6915
+ if (previous.verbose !== verbose) return false;
7174
6916
  return sameFeedItemPrefix(previous.feedItems, feedItems) && sameFeedEventPrefix(previous.feedEvents, feedEvents);
7175
6917
  }
7176
6918
  function buildTimelineCache(feedItems, feedEvents, postByToolUseId, verbose) {
@@ -7211,7 +6953,7 @@ function buildTimelineCache(feedItems, feedEvents, postByToolUseId, verbose) {
7211
6953
  messageCounter,
7212
6954
  subagentTypes,
7213
6955
  pendingEntryIndexByToolUseId,
7214
- verbose: !!verbose
6956
+ verbose
7215
6957
  };
7216
6958
  }
7217
6959
  function appendTimelineCache(previous, feedItems, feedEvents, postByToolUseId) {
@@ -7283,28 +7025,193 @@ function appendTimelineCache(previous, feedItems, feedEvents, postByToolUseId) {
7283
7025
  verbose: previous.verbose
7284
7026
  };
7285
7027
  }
7286
- function getTimelineEntryDetails(entry) {
7287
- if (entry.details) return entry.details;
7288
- if (!entry.feedEvent) return entry.summary;
7289
- const cached = detailCache.get(entry);
7290
- if (cached !== void 0) return cached;
7291
- const details = isEventExpandable(entry.feedEvent) ? expansionForEvent(entry.feedEvent) : "";
7292
- detailCache.set(entry, details);
7293
- return details;
7294
- }
7295
- function getTimelineEntrySearchText(entry) {
7296
- const cached = searchTextCache.get(entry);
7297
- if (cached !== void 0) return cached;
7298
- if (!entry.feedEvent) {
7299
- searchTextCache.set(entry, entry.searchText);
7300
- return entry.searchText;
7028
+ var IndexedTimeline = class {
7029
+ cache = null;
7030
+ runIndex = /* @__PURE__ */ new Map();
7031
+ errorPositions = /* @__PURE__ */ new Set();
7032
+ _runSummaryMap = /* @__PURE__ */ new Map();
7033
+ _runSummariesDirty = true;
7034
+ _runSummariesCache = [];
7035
+ _lastFeedEventsLength = 0;
7036
+ searchCache = /* @__PURE__ */ new Map();
7037
+ lastFilteredRef = null;
7038
+ detailCache = /* @__PURE__ */ new WeakMap();
7039
+ searchTextCache = /* @__PURE__ */ new WeakMap();
7040
+ verbose = false;
7041
+ update(feedItems, feedEvents, postByToolUseId, verbose) {
7042
+ this.verbose = verbose;
7043
+ const incremental = canAppendIncrementally(
7044
+ this.cache,
7045
+ feedItems,
7046
+ feedEvents,
7047
+ this.verbose
7048
+ );
7049
+ if (incremental) {
7050
+ this.updateRunSummaries(feedEvents);
7051
+ this.cache = appendTimelineCache(
7052
+ this.cache,
7053
+ feedItems,
7054
+ feedEvents,
7055
+ postByToolUseId
7056
+ );
7057
+ } else {
7058
+ this.rebuildRunSummaries(feedEvents);
7059
+ this.cache = buildTimelineCache(
7060
+ feedItems,
7061
+ feedEvents,
7062
+ postByToolUseId,
7063
+ this.verbose
7064
+ );
7065
+ }
7066
+ this.rebuildIndexes();
7067
+ }
7068
+ getEntries() {
7069
+ return this.cache?.entries ?? [];
7070
+ }
7071
+ getFilteredView(runFilter, errorsOnly) {
7072
+ const entries = this.getEntries();
7073
+ if ((!runFilter || runFilter === "all") && !errorsOnly) {
7074
+ return entries;
7075
+ }
7076
+ let candidateIndices;
7077
+ if (runFilter && runFilter !== "all") {
7078
+ candidateIndices = this.runIndex.get(runFilter) ?? [];
7079
+ } else {
7080
+ candidateIndices = Array.from({ length: entries.length }, (_, i) => i);
7081
+ }
7082
+ if (errorsOnly) {
7083
+ candidateIndices = candidateIndices.filter(
7084
+ (i) => this.errorPositions.has(i)
7085
+ );
7086
+ }
7087
+ return candidateIndices.map((i) => entries[i]);
7088
+ }
7089
+ getSearchMatches(filteredEntries, query) {
7090
+ const q = query.trim().toLowerCase();
7091
+ if (!q) return [];
7092
+ if (filteredEntries !== this.lastFilteredRef) {
7093
+ this.searchCache.clear();
7094
+ this.lastFilteredRef = filteredEntries;
7095
+ }
7096
+ const cached = this.searchCache.get(q);
7097
+ if (cached && cached.lastScanned === filteredEntries.length) {
7098
+ return cached.matches;
7099
+ }
7100
+ const startFrom = cached ? cached.lastScanned : 0;
7101
+ const matches = cached ? [...cached.matches] : [];
7102
+ for (let i = startFrom; i < filteredEntries.length; i++) {
7103
+ const searchText = this.getEntrySearchText(filteredEntries[i]);
7104
+ if (searchText.toLowerCase().includes(q)) {
7105
+ matches.push(i);
7106
+ }
7107
+ }
7108
+ this.searchCache.set(q, { matches, lastScanned: filteredEntries.length });
7109
+ if (this.searchCache.size > MAX_SEARCH_CACHE_SIZE) {
7110
+ const oldest = this.searchCache.keys().next().value;
7111
+ if (oldest !== void 0) {
7112
+ this.searchCache.delete(oldest);
7113
+ }
7114
+ }
7115
+ return matches;
7301
7116
  }
7302
- const details = getTimelineEntryDetails(entry);
7303
- const searchText = details ? `${entry.summary}
7117
+ getEntrySearchText(entry) {
7118
+ const cached = this.searchTextCache.get(entry);
7119
+ if (cached !== void 0) return cached;
7120
+ if (!entry.feedEvent) {
7121
+ this.searchTextCache.set(entry, entry.searchText);
7122
+ return entry.searchText;
7123
+ }
7124
+ const details = this.getEntryDetails(entry);
7125
+ const searchText = details ? `${entry.summary}
7304
7126
  ${details}` : entry.summary;
7305
- searchTextCache.set(entry, searchText);
7306
- return searchText;
7307
- }
7127
+ this.searchTextCache.set(entry, searchText);
7128
+ return searchText;
7129
+ }
7130
+ getEntryDetails(entry) {
7131
+ if (entry.details) return entry.details;
7132
+ if (!entry.feedEvent) return entry.summary;
7133
+ const cached = this.detailCache.get(entry);
7134
+ if (cached !== void 0) return cached;
7135
+ const details = isEventExpandable(entry.feedEvent) ? expansionForEvent(entry.feedEvent) : "";
7136
+ this.detailCache.set(entry, details);
7137
+ return details;
7138
+ }
7139
+ getRunSummaries() {
7140
+ if (this._runSummariesDirty) {
7141
+ this._runSummariesCache = Array.from(this._runSummaryMap.values()).sort(
7142
+ (a, b) => a.startedAt - b.startedAt
7143
+ );
7144
+ this._runSummariesDirty = false;
7145
+ }
7146
+ return this._runSummariesCache;
7147
+ }
7148
+ processRunEvent(event) {
7149
+ if (event.kind === "run.start") {
7150
+ this._runSummaryMap.set(event.run_id, {
7151
+ runId: event.run_id,
7152
+ title: compactText(
7153
+ event.data.trigger.prompt_preview || "Untitled run",
7154
+ 46
7155
+ ),
7156
+ status: "RUNNING",
7157
+ startedAt: event.ts
7158
+ });
7159
+ this._runSummariesDirty = true;
7160
+ } else if (event.kind === "run.end") {
7161
+ const existing = this._runSummaryMap.get(event.run_id);
7162
+ if (existing) {
7163
+ existing.status = toRunStatus(event);
7164
+ existing.endedAt = event.ts;
7165
+ } else {
7166
+ this._runSummaryMap.set(event.run_id, {
7167
+ runId: event.run_id,
7168
+ title: "Untitled run",
7169
+ status: toRunStatus(event),
7170
+ startedAt: event.ts,
7171
+ endedAt: event.ts
7172
+ });
7173
+ }
7174
+ this._runSummariesDirty = true;
7175
+ }
7176
+ }
7177
+ rebuildRunSummaries(feedEvents) {
7178
+ this._runSummaryMap.clear();
7179
+ this._runSummariesDirty = true;
7180
+ this._lastFeedEventsLength = 0;
7181
+ this.updateRunSummaries(feedEvents);
7182
+ }
7183
+ updateRunSummaries(feedEvents) {
7184
+ for (let i = this._lastFeedEventsLength; i < feedEvents.length; i++) {
7185
+ this.processRunEvent(feedEvents[i]);
7186
+ }
7187
+ this._lastFeedEventsLength = feedEvents.length;
7188
+ }
7189
+ addToIndex(entry, index) {
7190
+ const runId = entry.runId ?? "__none__";
7191
+ let indices = this.runIndex.get(runId);
7192
+ if (!indices) {
7193
+ indices = [];
7194
+ this.runIndex.set(runId, indices);
7195
+ }
7196
+ indices.push(index);
7197
+ if (entry.error) {
7198
+ this.errorPositions.add(index);
7199
+ }
7200
+ }
7201
+ rebuildIndexes() {
7202
+ this.runIndex.clear();
7203
+ this.errorPositions.clear();
7204
+ this.searchCache.clear();
7205
+ const entries = this.getEntries();
7206
+ for (let i = 0; i < entries.length; i++) {
7207
+ this.addToIndex(entries[i], i);
7208
+ }
7209
+ }
7210
+ };
7211
+
7212
+ // src/ui/hooks/useTimeline.ts
7213
+ var EMPTY_MATCHES = Object.freeze([]);
7214
+ var EMPTY_MATCH_SET = Object.freeze(/* @__PURE__ */ new Set());
7308
7215
  function useTimeline({
7309
7216
  feedItems,
7310
7217
  feedEvents,
@@ -7362,12 +7269,17 @@ function useTimeline({
7362
7269
  () => searchMatches === EMPTY_MATCHES ? EMPTY_MATCH_SET : new Set(searchMatches),
7363
7270
  [searchMatches]
7364
7271
  );
7272
+ const getEntrySearchText = useCallback10(
7273
+ (entry) => indexedRef.current.getEntrySearchText(entry),
7274
+ []
7275
+ );
7365
7276
  return {
7366
7277
  timelineEntries,
7367
7278
  runSummaries,
7368
7279
  filteredEntries,
7369
7280
  searchMatches,
7370
- searchMatchSet
7281
+ searchMatchSet,
7282
+ getEntrySearchText
7371
7283
  };
7372
7284
  }
7373
7285
 
@@ -7448,7 +7360,7 @@ function useLayout({
7448
7360
 
7449
7361
  // src/ui/hooks/usePager.ts
7450
7362
  import process5 from "process";
7451
- import { useState as useState10, useCallback as useCallback10, useRef as useRef11, useEffect as useEffect9 } from "react";
7363
+ import { useState as useState10, useCallback as useCallback11, useRef as useRef11, useEffect as useEffect9 } from "react";
7452
7364
  import { useInput as useInput11 } from "ink";
7453
7365
 
7454
7366
  // src/shared/utils/clipboard.ts
@@ -7477,6 +7389,30 @@ function getClipboardCommand() {
7477
7389
  return null;
7478
7390
  }
7479
7391
 
7392
+ // src/core/feed/defaultRender.ts
7393
+ var DEFAULT_RENDER = /* @__PURE__ */ new Set([
7394
+ "compact.post",
7395
+ "task.created",
7396
+ "cwd.changed",
7397
+ "file.changed",
7398
+ "stop.failure",
7399
+ "permission.denied",
7400
+ "elicitation.request",
7401
+ "elicitation.result",
7402
+ "channel.permission.relayed",
7403
+ "channel.permission.resolved",
7404
+ "channel.question.relayed",
7405
+ "channel.question.resolved",
7406
+ "channel.chat.inbound",
7407
+ "channel.chat.outbound",
7408
+ "gateway.function.invoked",
7409
+ "gateway.function.completed",
7410
+ "gateway.function.failed"
7411
+ ]);
7412
+ function isDefaultRenderKind(k) {
7413
+ return DEFAULT_RENDER.has(k);
7414
+ }
7415
+
7480
7416
  // src/ui/tooling/toolExtractors.ts
7481
7417
  var EXT_TO_LANGUAGE = {
7482
7418
  ".ts": "typescript",
@@ -8571,13 +8507,13 @@ function usePager({
8571
8507
  const pagerActiveRef = useRef11(false);
8572
8508
  const pagerEntryIdRef = useRef11(null);
8573
8509
  const lastPairedPostRef = useRef11(void 0);
8574
- const clearCopyToastTimer = useCallback10(() => {
8510
+ const clearCopyToastTimer = useCallback11(() => {
8575
8511
  if (copyToastTimerRef.current) {
8576
8512
  clearTimeout(copyToastTimerRef.current);
8577
8513
  copyToastTimerRef.current = null;
8578
8514
  }
8579
8515
  }, []);
8580
- const paintPager = useCallback10(() => {
8516
+ const paintPager = useCallback11(() => {
8581
8517
  const lines = pagerLinesRef.current;
8582
8518
  const scroll = pagerScrollRef.current;
8583
8519
  const contentRows = pagerContentRows();
@@ -8600,7 +8536,7 @@ function usePager({
8600
8536
  margin + source_default.dim(`${pos} \u2191/\u2193 j/k scroll PgUp/PgDn page y copy q exit`)
8601
8537
  );
8602
8538
  }, []);
8603
- const scrollPager = useCallback10(
8539
+ const scrollPager = useCallback11(
8604
8540
  (delta) => {
8605
8541
  const contentRows = pagerContentRows();
8606
8542
  const maxScroll = Math.max(0, pagerLinesRef.current.length - contentRows);
@@ -8612,7 +8548,7 @@ function usePager({
8612
8548
  },
8613
8549
  [paintPager]
8614
8550
  );
8615
- const handleExpandForPager = useCallback10(() => {
8551
+ const handleExpandForPager = useCallback11(() => {
8616
8552
  const entry = displayedEntriesRef.current.find((e) => e.id === feedCursorId);
8617
8553
  if (!entry?.expandable) return;
8618
8554
  pendingPagerEntryRef.current = entry;
@@ -8755,7 +8691,7 @@ function usePager({
8755
8691
  }
8756
8692
 
8757
8693
  // src/ui/hooks/useFrameChrome.ts
8758
- import { useMemo as useMemo10, useCallback as useCallback11 } from "react";
8694
+ import { useMemo as useMemo10, useCallback as useCallback12 } from "react";
8759
8695
 
8760
8696
  // src/ui/layout/buildFrameLines.ts
8761
8697
  function buildHintPairs(pairs) {
@@ -8945,7 +8881,7 @@ function useFrameChrome({
8945
8881
  sectionBorder: `${glyphs.teeLeft}${spliceJunction(hFill, glyphs.cross)}${glyphs.teeRight}`
8946
8882
  };
8947
8883
  }, [glyphs, innerWidth, dividerColumn]);
8948
- const frameLine = useCallback11(
8884
+ const frameLine = useCallback12(
8949
8885
  (content) => `${glyphs.vertical}${fitAnsi(content, innerWidth)}${glyphs.vertical}`,
8950
8886
  [glyphs.vertical, innerWidth]
8951
8887
  );
@@ -11122,24 +11058,24 @@ function renderYankLines(entry, width, theme) {
11122
11058
  }
11123
11059
 
11124
11060
  // src/setup/SetupWizard.tsx
11125
- import { useState as useState14, useCallback as useCallback14, useEffect as useEffect10, useRef as useRef13 } from "react";
11061
+ import { useState as useState14, useCallback as useCallback15, useEffect as useEffect10, useRef as useRef13 } from "react";
11126
11062
  import { Box as Box16, Text as Text22, useInput as useInput13 } from "ink";
11127
11063
 
11128
11064
  // src/setup/useSetupState.ts
11129
- import { useState as useState12, useCallback as useCallback12 } from "react";
11065
+ import { useState as useState12, useCallback as useCallback13 } from "react";
11130
11066
  var TOTAL_STEPS = 2;
11131
11067
  function useSetupState() {
11132
11068
  const [stepIndex, setStepIndex] = useState12(0);
11133
11069
  const [stepState, setStepState] = useState12("selecting");
11134
- const startVerifying = useCallback12(() => setStepState("verifying"), []);
11135
- const markSuccess = useCallback12(() => setStepState("success"), []);
11136
- const markError = useCallback12(() => setStepState("error"), []);
11137
- const retry = useCallback12(() => setStepState("selecting"), []);
11138
- const advance = useCallback12(() => {
11070
+ const startVerifying = useCallback13(() => setStepState("verifying"), []);
11071
+ const markSuccess = useCallback13(() => setStepState("success"), []);
11072
+ const markError = useCallback13(() => setStepState("error"), []);
11073
+ const retry = useCallback13(() => setStepState("selecting"), []);
11074
+ const advance = useCallback13(() => {
11139
11075
  setStepIndex((prev) => prev + 1);
11140
11076
  setStepState("selecting");
11141
11077
  }, []);
11142
- const retreat = useCallback12(() => {
11078
+ const retreat = useCallback13(() => {
11143
11079
  setStepIndex((prev) => Math.max(0, prev - 1));
11144
11080
  setStepState("selecting");
11145
11081
  }, []);
@@ -11193,7 +11129,7 @@ function ThemeStep({ onComplete, onPreview }) {
11193
11129
  }
11194
11130
 
11195
11131
  // src/setup/steps/HarnessStep.tsx
11196
- import { useState as useState13, useCallback as useCallback13 } from "react";
11132
+ import { useState as useState13, useCallback as useCallback14 } from "react";
11197
11133
  import { Box as Box13, Text as Text19 } from "ink";
11198
11134
  import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
11199
11135
  function HarnessStep({ onComplete, onError }) {
@@ -11202,7 +11138,7 @@ function HarnessStep({ onComplete, onError }) {
11202
11138
  const [status, setStatus] = useState13("selecting");
11203
11139
  const [message, setMessage] = useState13("");
11204
11140
  const [checks, setChecks] = useState13([]);
11205
- const renderCheckLine = useCallback13(
11141
+ const renderCheckLine = useCallback14(
11206
11142
  (check) => {
11207
11143
  const glyph = check.status === "pass" ? "\u2713" : check.status === "fail" ? "\u2717" : "!";
11208
11144
  const color = check.status === "pass" ? theme.status.success : check.status === "fail" ? theme.status.error : theme.status.warning;
@@ -11210,7 +11146,7 @@ function HarnessStep({ onComplete, onError }) {
11210
11146
  },
11211
11147
  [theme.status.error, theme.status.success, theme.status.warning]
11212
11148
  );
11213
- const handleSelect = useCallback13(
11149
+ const handleSelect = useCallback14(
11214
11150
  (value) => {
11215
11151
  const capability = capabilities.find(
11216
11152
  (c2) => c2.id === value
@@ -11345,7 +11281,7 @@ function SetupWizard({ onComplete, onThemePreview }) {
11345
11281
  const [writeRetryCount, setWriteRetryCount] = useState14(0);
11346
11282
  const themePreviewRef = useRef13(result.theme);
11347
11283
  const completedRef = useRef13(false);
11348
- const handleThemeComplete = useCallback14(
11284
+ const handleThemeComplete = useCallback15(
11349
11285
  (theme2) => {
11350
11286
  themePreviewRef.current = theme2;
11351
11287
  setResult((prev) => ({ ...prev, theme: theme2 }));
@@ -11354,25 +11290,25 @@ function SetupWizard({ onComplete, onThemePreview }) {
11354
11290
  },
11355
11291
  [markSuccess, onThemePreview]
11356
11292
  );
11357
- const handleThemePreview = useCallback14(
11293
+ const handleThemePreview = useCallback15(
11358
11294
  (nextTheme) => {
11359
11295
  themePreviewRef.current = nextTheme;
11360
11296
  onThemePreview?.(nextTheme);
11361
11297
  },
11362
11298
  [onThemePreview]
11363
11299
  );
11364
- const handleHarnessComplete = useCallback14(
11300
+ const handleHarnessComplete = useCallback15(
11365
11301
  (harness) => {
11366
11302
  setResult((prev) => ({ ...prev, harness }));
11367
11303
  markSuccess();
11368
11304
  },
11369
11305
  [markSuccess]
11370
11306
  );
11371
- const handleHarnessSkip = useCallback14(() => {
11307
+ const handleHarnessSkip = useCallback15(() => {
11372
11308
  setResult((prev) => ({ ...prev, harness: void 0 }));
11373
11309
  markSuccess();
11374
11310
  }, [markSuccess]);
11375
- const handleSkipShortcut = useCallback14(() => {
11311
+ const handleSkipShortcut = useCallback15(() => {
11376
11312
  if (stepState !== "selecting" || isComplete) {
11377
11313
  return;
11378
11314
  }
@@ -11493,7 +11429,7 @@ function SetupWizard({ onComplete, onThemePreview }) {
11493
11429
  }
11494
11430
 
11495
11431
  // src/app/workflow/WorkflowPicker.tsx
11496
- import { useState as useState15, useCallback as useCallback15, useEffect as useEffect11 } from "react";
11432
+ import { useState as useState15, useCallback as useCallback16, useEffect as useEffect11 } from "react";
11497
11433
  import { Box as Box17, Text as Text23, useInput as useInput14, useStdout as useStdout7 } from "ink";
11498
11434
 
11499
11435
  // src/core/workflows/workflowOptions.ts
@@ -11593,7 +11529,7 @@ function WorkflowPicker({
11593
11529
  }
11594
11530
  }
11595
11531
  });
11596
- const handleSelect = useCallback15(
11532
+ const handleSelect = useCallback16(
11597
11533
  (value) => {
11598
11534
  if (value === "default") {
11599
11535
  writeProjectConfig(projectDir, { activeWorkflow: "default" });
@@ -11631,7 +11567,7 @@ function WorkflowPicker({
11631
11567
  },
11632
11568
  [onComplete, projectDir]
11633
11569
  );
11634
- const handleMcpComplete = useCallback15(
11570
+ const handleMcpComplete = useCallback16(
11635
11571
  (choices) => {
11636
11572
  if (phase.type !== "mcp-options") return;
11637
11573
  const { workflowName } = phase;
@@ -11694,7 +11630,7 @@ function WorkflowPicker({
11694
11630
  }
11695
11631
 
11696
11632
  // src/app/modelPreferences/ModelPicker.tsx
11697
- import { useState as useState16, useEffect as useEffect12, useCallback as useCallback16 } from "react";
11633
+ import { useState as useState16, useEffect as useEffect12, useCallback as useCallback17 } from "react";
11698
11634
  import { Box as Box18, Text as Text24, useInput as useInput15, useStdout as useStdout8 } from "ink";
11699
11635
 
11700
11636
  // src/app/modelPreferences/listAvailableModels.ts
@@ -11761,7 +11697,7 @@ function ModelPicker({
11761
11697
  const { stdout } = useStdout8();
11762
11698
  const frameWidth = Math.min(stdout.columns - 4, 72);
11763
11699
  const [phase, setPhase] = useState16({ type: "loading" });
11764
- const loadModels = useCallback16(() => {
11700
+ const loadModels = useCallback17(() => {
11765
11701
  setPhase({ type: "loading" });
11766
11702
  setTimeout(() => {
11767
11703
  void listAvailableModels({ harness, runtime }).then((options) => {
@@ -11793,7 +11729,7 @@ function ModelPicker({
11793
11729
  loadModels();
11794
11730
  }
11795
11731
  });
11796
- const handleSelect = useCallback16(
11732
+ const handleSelect = useCallback17(
11797
11733
  (value) => {
11798
11734
  setPhase({ type: "saving", model: value });
11799
11735
  setTimeout(() => {
@@ -11882,7 +11818,7 @@ function useRuntimeSelectors() {
11882
11818
  const questionQueueCount = useHookContextSelector((v) => v.questionQueueCount);
11883
11819
  const resolveQuestion = useHookContextSelector((v) => v.resolveQuestion);
11884
11820
  const isServerRunning = useHookContextSelector((v) => v.isServerRunning);
11885
- const runtimeError = useHookContextSelector((v) => v.runtimeError);
11821
+ const runtimeError2 = useHookContextSelector((v) => v.runtimeError);
11886
11822
  const postByToolUseId = useHookContextSelector((v) => v.postByToolUseId);
11887
11823
  const allocateSeq = useHookContextSelector((v) => v.allocateSeq);
11888
11824
  const clearEvents = useHookContextSelector((v) => v.clearEvents);
@@ -11907,7 +11843,7 @@ function useRuntimeSelectors() {
11907
11843
  questionQueueCount,
11908
11844
  resolveQuestion,
11909
11845
  isServerRunning,
11910
- runtimeError,
11846
+ runtimeError: runtimeError2,
11911
11847
  postByToolUseId,
11912
11848
  allocateSeq,
11913
11849
  clearEvents,
@@ -11958,16 +11894,16 @@ function useTimelineCurrentRun(currentRun) {
11958
11894
  }
11959
11895
 
11960
11896
  // src/app/shell/useShellInput.ts
11961
- import { useState as useState17, useCallback as useCallback17, useRef as useRef14 } from "react";
11897
+ import { useState as useState17, useCallback as useCallback18, useRef as useRef14 } from "react";
11962
11898
  function deriveInputMode(value) {
11963
11899
  if (value.startsWith("/")) return "command";
11964
11900
  if (value.startsWith(":")) return "search";
11965
11901
  return "normal";
11966
11902
  }
11967
- function findFirstSearchMatch(entries, query, startIndex) {
11903
+ function findFirstSearchMatch(entries, query, startIndex, getEntrySearchText) {
11968
11904
  const q = query.toLowerCase();
11969
11905
  for (let i = startIndex; i < entries.length; i++) {
11970
- if (getTimelineEntrySearchText(entries[i]).toLowerCase().includes(q)) {
11906
+ if (getEntrySearchText(entries[i]).toLowerCase().includes(q)) {
11971
11907
  return i;
11972
11908
  }
11973
11909
  }
@@ -11981,13 +11917,14 @@ function useShellInput({
11981
11917
  submitSearchQuery,
11982
11918
  submitPromptOrSlashCommand,
11983
11919
  displayedEntriesRef,
11920
+ getEntrySearchText,
11984
11921
  getSelectedCommand
11985
11922
  }) {
11986
11923
  const setInputValueRef = useRef14(() => {
11987
11924
  });
11988
11925
  const inputValueRef = useRef14("");
11989
11926
  const [inputRows, setInputRows] = useState17(1);
11990
- const syncInputModeFromValue = useCallback17(
11927
+ const syncInputModeFromValue = useCallback18(
11991
11928
  (value) => {
11992
11929
  const nextMode = deriveInputMode(value);
11993
11930
  setInputMode(nextMode);
@@ -11998,7 +11935,7 @@ function useShellInput({
11998
11935
  [setInputMode, setSearchQuery]
11999
11936
  );
12000
11937
  const inputContentWidthRef = useRef14(1);
12001
- const handleSetValueRef = useCallback17(
11938
+ const handleSetValueRef = useCallback18(
12002
11939
  (setValue) => {
12003
11940
  setInputValueRef.current = (value) => {
12004
11941
  inputValueRef.current = value;
@@ -12009,7 +11946,7 @@ function useShellInput({
12009
11946
  },
12010
11947
  [syncInputModeFromValue]
12011
11948
  );
12012
- const handleInputSubmit = useCallback17(
11949
+ const handleInputSubmit = useCallback18(
12013
11950
  (rawValue) => {
12014
11951
  const trimmed = rawValue.trim();
12015
11952
  if (trimmed) {
@@ -12023,7 +11960,12 @@ function useShellInput({
12023
11960
  }
12024
11961
  } else if (inputMode === "search") {
12025
11962
  const query = trimmed.replace(/^:/, "").trim();
12026
- const firstIdx = query.length > 0 ? findFirstSearchMatch(displayedEntriesRef.current, query, 0) : -1;
11963
+ const firstIdx = query.length > 0 ? findFirstSearchMatch(
11964
+ displayedEntriesRef.current,
11965
+ query,
11966
+ 0,
11967
+ getEntrySearchText
11968
+ ) : -1;
12027
11969
  submitSearchQuery(query, firstIdx >= 0 ? firstIdx : null);
12028
11970
  } else {
12029
11971
  submitPromptOrSlashCommand(trimmed);
@@ -12041,10 +11983,11 @@ function useShellInput({
12041
11983
  getSelectedCommand,
12042
11984
  closeInput,
12043
11985
  submitSearchQuery,
12044
- displayedEntriesRef
11986
+ displayedEntriesRef,
11987
+ getEntrySearchText
12045
11988
  ]
12046
11989
  );
12047
- const handleMainInputChange = useCallback17(
11990
+ const handleMainInputChange = useCallback18(
12048
11991
  (value) => {
12049
11992
  inputValueRef.current = value;
12050
11993
  syncInputModeFromValue(value);
@@ -12850,7 +12793,7 @@ function AppContent({
12850
12793
  const searchQuery = uiState.searchQuery;
12851
12794
  const perfEnabled = isPerfEnabled();
12852
12795
  usePerfRenderLog(perfEnabled, "app.main.content.render");
12853
- const handleSectionProfilerRender = useCallback18(
12796
+ const handleSectionProfilerRender = useCallback19(
12854
12797
  (id, phaseName, actualDuration, baseDuration, startTime, commitTime) => {
12855
12798
  logReactCommit(
12856
12799
  id,
@@ -12884,7 +12827,7 @@ function AppContent({
12884
12827
  isServerRunning,
12885
12828
  recordTokens,
12886
12829
  restoredTokens,
12887
- runtimeError,
12830
+ runtimeError: runtimeError2,
12888
12831
  hookCommandFeed
12889
12832
  } = useRuntimeSelectors();
12890
12833
  const currentSessionId = session?.session_id ?? null;
@@ -12892,7 +12835,7 @@ function AppContent({
12892
12835
  const timelineCurrentRun = useTimelineCurrentRun(currentRun);
12893
12836
  const harnessLabel = detectHarness(harness);
12894
12837
  const shouldTrackClaudeStartup = shouldTrackStartupDiagnostics(harness);
12895
- const onExitTokens = useCallback18(
12838
+ const onExitTokens = useCallback19(
12896
12839
  (tokens) => {
12897
12840
  if (session?.session_id) {
12898
12841
  recordTokens(session.session_id, tokens);
@@ -12900,7 +12843,7 @@ function AppContent({
12900
12843
  },
12901
12844
  [session?.session_id, recordTokens]
12902
12845
  );
12903
- const emitClaudeStartupDiagnostics = useCallback18(
12846
+ const emitClaudeStartupDiagnostics = useCallback19(
12904
12847
  (event) => {
12905
12848
  trackClaudeStartupFailed({
12906
12849
  harness,
@@ -12911,7 +12854,7 @@ function AppContent({
12911
12854
  },
12912
12855
  [harness]
12913
12856
  );
12914
- const onProcessLifecycleEvent = useCallback18(
12857
+ const onProcessLifecycleEvent = useCallback19(
12915
12858
  (event) => {
12916
12859
  const startupAttempt = startupAttemptRef.current;
12917
12860
  const isStartupFailure = shouldTrackClaudeStartup && startupAttempt !== null;
@@ -13029,7 +12972,7 @@ function AppContent({
13029
12972
  if (!current) {
13030
12973
  return current;
13031
12974
  }
13032
- const isActiveHookServerStartupFailure = current.failureStage === "startup_timeout" && !!runtimeError && !isServerRunning && current.message === runtimeError.message;
12975
+ const isActiveHookServerStartupFailure = current.failureStage === "startup_timeout" && !!runtimeError2 && !isServerRunning && current.message === runtimeError2.message;
13033
12976
  if (isActiveHookServerStartupFailure) {
13034
12977
  return current;
13035
12978
  }
@@ -13038,21 +12981,21 @@ function AppContent({
13038
12981
  }
13039
12982
  return null;
13040
12983
  });
13041
- }, [feedEvents.length, isServerRunning, runtimeError]);
12984
+ }, [feedEvents.length, isServerRunning, runtimeError2]);
13042
12985
  useEffect14(() => {
13043
12986
  if (!shouldTrackClaudeStartup || !isTelemetryEnabled()) return;
13044
- if (!runtimeError || isServerRunning) {
12987
+ if (!runtimeError2 || isServerRunning) {
13045
12988
  runtimeStartupDiagnosticsSignatureRef.current = null;
13046
12989
  return;
13047
12990
  }
13048
- const signature = `${runtimeError.code}:${runtimeError.message}`;
12991
+ const signature = `${runtimeError2.code}:${runtimeError2.message}`;
13049
12992
  if (signature === runtimeStartupDiagnosticsSignatureRef.current) {
13050
12993
  return;
13051
12994
  }
13052
12995
  runtimeStartupDiagnosticsSignatureRef.current = signature;
13053
12996
  const diagnosticsEvent = createPendingStartupDiagnosticsEvent({
13054
12997
  failureStage: "startup_timeout",
13055
- message: runtimeError.message,
12998
+ message: runtimeError2.message,
13056
12999
  feedEventCount: feedEvents.length
13057
13000
  });
13058
13001
  if (diagnosticsConsent === true) {
@@ -13065,7 +13008,7 @@ function AppContent({
13065
13008
  emitClaudeStartupDiagnostics,
13066
13009
  feedEvents.length,
13067
13010
  isServerRunning,
13068
- runtimeError,
13011
+ runtimeError2,
13069
13012
  shouldTrackClaudeStartup
13070
13013
  ]);
13071
13014
  useEffect14(() => {
@@ -13080,7 +13023,7 @@ function AppContent({
13080
13023
  return;
13081
13024
  }
13082
13025
  const derivedFailure = deriveStartupTimeoutFailure({
13083
- runtimeError,
13026
+ runtimeError: runtimeError2,
13084
13027
  isServerRunning,
13085
13028
  isHarnessRunning,
13086
13029
  harnessLabel
@@ -13117,10 +13060,10 @@ function AppContent({
13117
13060
  harnessLabel,
13118
13061
  isHarnessRunning,
13119
13062
  isServerRunning,
13120
- runtimeError,
13063
+ runtimeError2,
13121
13064
  shouldTrackClaudeStartup
13122
13065
  ]);
13123
- const addMessage = useCallback18(
13066
+ const addMessage = useCallback19(
13124
13067
  (role, content) => {
13125
13068
  const newMessage = {
13126
13069
  id: generateId(),
@@ -13134,7 +13077,7 @@ function AppContent({
13134
13077
  },
13135
13078
  [allocateSeq]
13136
13079
  );
13137
- const clearScreen = useCallback18(() => {
13080
+ const clearScreen = useCallback19(() => {
13138
13081
  onSessionTelemetrySnapshot(metrics);
13139
13082
  clearEvents();
13140
13083
  process6.stdout.write("\x1B[2J\x1B[3J\x1B[H");
@@ -13148,7 +13091,7 @@ function AppContent({
13148
13091
  postByToolUseId,
13149
13092
  verbose
13150
13093
  });
13151
- const { runSummaries, filteredEntries, searchMatches } = timeline;
13094
+ const { runSummaries, filteredEntries, searchMatches, getEntrySearchText } = timeline;
13152
13095
  const todoPanel = useTodoPanel({
13153
13096
  tasks,
13154
13097
  isWorking: appMode.type === "working",
@@ -13209,7 +13152,7 @@ function AppContent({
13209
13152
  messageEntryLineOffsets: [],
13210
13153
  messageContentRows: 0
13211
13154
  });
13212
- const dispatchUi = useCallback18((action) => {
13155
+ const dispatchUi = useCallback19((action) => {
13213
13156
  setUiState(
13214
13157
  (prev) => reduceSessionUiState(prev, action, uiContextRef.current)
13215
13158
  );
@@ -13221,7 +13164,7 @@ function AppContent({
13221
13164
  previousWorkflowPickerVisibleRef.current = workflowPickerVisible;
13222
13165
  previousModelPickerVisibleRef.current = modelPickerVisible;
13223
13166
  }, [dispatchUi, workflowPickerVisible, modelPickerVisible]);
13224
- const submitPromptOrSlashCommand = useCallback18(
13167
+ const submitPromptOrSlashCommand = useCallback19(
13225
13168
  (value) => {
13226
13169
  if (!value.trim()) return;
13227
13170
  inputHistory.push(value);
@@ -13230,13 +13173,13 @@ function AppContent({
13230
13173
  setPendingStartupDiagnostics(null);
13231
13174
  setStartupFailure(null);
13232
13175
  addMessage("user", result.text);
13233
- if (!isServerRunning && runtimeError) {
13176
+ if (!isServerRunning && runtimeError2) {
13234
13177
  setStartupFailure({
13235
- message: runtimeError.message,
13236
- failureCode: runtimeError.code === "socket_path_too_long" ? "socket_path_too_long" : "hook_server_unavailable"
13178
+ message: runtimeError2.message,
13179
+ failureCode: runtimeError2.code === "socket_path_too_long" ? "socket_path_too_long" : "hook_server_unavailable"
13237
13180
  });
13238
13181
  emitNotification(
13239
- `Athena failed to start ${harnessLabel}: ${runtimeError.message}`,
13182
+ `Athena failed to start ${harnessLabel}: ${runtimeError2.message}`,
13240
13183
  `${harnessLabel} Startup Error`
13241
13184
  );
13242
13185
  return;
@@ -13292,13 +13235,13 @@ function AppContent({
13292
13235
  spawn: (prompt, sessionId2, configOverride) => {
13293
13236
  setPendingStartupDiagnostics(null);
13294
13237
  setStartupFailure(null);
13295
- if (!isServerRunning && runtimeError) {
13238
+ if (!isServerRunning && runtimeError2) {
13296
13239
  setStartupFailure({
13297
- message: runtimeError.message,
13298
- failureCode: runtimeError.code === "socket_path_too_long" ? "socket_path_too_long" : "hook_server_unavailable"
13240
+ message: runtimeError2.message,
13241
+ failureCode: runtimeError2.code === "socket_path_too_long" ? "socket_path_too_long" : "hook_server_unavailable"
13299
13242
  });
13300
13243
  emitNotification(
13301
- `Athena failed to start ${harnessLabel}: ${runtimeError.message}`,
13244
+ `Athena failed to start ${harnessLabel}: ${runtimeError2.message}`,
13302
13245
  `${harnessLabel} Startup Error`
13303
13246
  );
13304
13247
  return Promise.resolve();
@@ -13326,7 +13269,7 @@ function AppContent({
13326
13269
  spawnHarness,
13327
13270
  currentSessionId,
13328
13271
  isServerRunning,
13329
- runtimeError,
13272
+ runtimeError2,
13330
13273
  exit,
13331
13274
  clearScreen,
13332
13275
  onShowSessions,
@@ -13345,7 +13288,7 @@ function AppContent({
13345
13288
  const isHarnessRunningRef = useRef16(isHarnessRunning);
13346
13289
  isHarnessRunningRef.current = isHarnessRunning;
13347
13290
  const submitDispatchAsTurnRef = useRef16(null);
13348
- const submitDispatchAsTurn = useCallback18(
13291
+ const submitDispatchAsTurn = useCallback19(
13349
13292
  (payload) => {
13350
13293
  const text = payload.inbound.text;
13351
13294
  if (text.trim().length === 0) return;
@@ -13438,17 +13381,18 @@ function AppContent({
13438
13381
  submitSearchQuery: (query, firstMatchIndex) => dispatchUi({ type: "submit_search_query", query, firstMatchIndex }),
13439
13382
  submitPromptOrSlashCommand,
13440
13383
  displayedEntriesRef: displayedFeedEntriesRef,
13384
+ getEntrySearchText,
13441
13385
  getSelectedCommand: () => getSelectedCommandRef.current()
13442
13386
  });
13443
13387
  const visualInputRows = Math.max(2, inputRows);
13444
13388
  const shellInputRef = useRef16(null);
13445
13389
  getSelectedCommandRef.current = () => shellInputRef.current?.getSelectedCommand();
13446
13390
  const { back: handleHistoryBack, forward: handleHistoryForward } = inputHistory;
13447
- const stableSetInputValue = useCallback18(
13391
+ const stableSetInputValue = useCallback19(
13448
13392
  (v) => setInputValueRef.current(v),
13449
13393
  [setInputValueRef]
13450
13394
  );
13451
- const stableGetInputValue = useCallback18(() => inputValueRef.current, []);
13395
+ const stableGetInputValue = useCallback19(() => inputValueRef.current, []);
13452
13396
  const provisionalFooterRows = 1;
13453
13397
  const hasMessages = useMemo17(
13454
13398
  () => filteredEntries.some((e) => classifyEntry(e) !== "feed"),
@@ -13631,29 +13575,29 @@ function AppContent({
13631
13575
  runSummaries,
13632
13576
  staticHighWaterMark
13633
13577
  });
13634
- const cycleFocus = useCallback18(
13578
+ const cycleFocus = useCallback19(
13635
13579
  () => dispatchUi({ type: "cycle_focus" }),
13636
13580
  [dispatchUi]
13637
13581
  );
13638
- const handlePermissionDecision = useCallback18(
13582
+ const handlePermissionDecision = useCallback19(
13639
13583
  (decision) => {
13640
13584
  if (!currentPermissionRequest) return;
13641
13585
  resolvePermission(currentPermissionRequest.request_id, decision);
13642
13586
  },
13643
13587
  [currentPermissionRequest, resolvePermission]
13644
13588
  );
13645
- const handleQuestionAnswer = useCallback18(
13589
+ const handleQuestionAnswer = useCallback19(
13646
13590
  (answers) => {
13647
13591
  if (!currentQuestionRequest?.cause?.hook_request_id) return;
13648
13592
  resolveQuestion(currentQuestionRequest.cause.hook_request_id, answers);
13649
13593
  },
13650
13594
  [currentQuestionRequest, resolveQuestion]
13651
13595
  );
13652
- const handleQuestionSkip = useCallback18(() => {
13596
+ const handleQuestionSkip = useCallback19(() => {
13653
13597
  if (!currentQuestionRequest?.cause?.hook_request_id) return;
13654
13598
  resolveQuestion(currentQuestionRequest.cause.hook_request_id, {});
13655
13599
  }, [currentQuestionRequest, resolveQuestion]);
13656
- const handleDiagnosticsDecision = useCallback18(
13600
+ const handleDiagnosticsDecision = useCallback19(
13657
13601
  (decision) => {
13658
13602
  const pending = pendingStartupDiagnostics;
13659
13603
  setPendingStartupDiagnostics(null);
@@ -13705,7 +13649,7 @@ function AppContent({
13705
13649
  }
13706
13650
  }
13707
13651
  });
13708
- const showToast = useCallback18((msg) => {
13652
+ const showToast = useCallback19((msg) => {
13709
13653
  if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
13710
13654
  setToastMessage(msg);
13711
13655
  toastTimerRef.current = setTimeout(() => setToastMessage(null), 1500);
@@ -13715,7 +13659,7 @@ function AppContent({
13715
13659
  if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
13716
13660
  };
13717
13661
  }, []);
13718
- const yankAtCursor = useCallback18(() => {
13662
+ const yankAtCursor = useCallback19(() => {
13719
13663
  const entry = displayedFeedEntriesRef.current.find(
13720
13664
  (e) => e.id === resolvedUiState.feedCursorId
13721
13665
  );
@@ -13724,7 +13668,7 @@ function AppContent({
13724
13668
  copyToClipboard(content);
13725
13669
  showToast("Copied to clipboard!");
13726
13670
  }, [resolvedUiState.feedCursorId, showToast, theme]);
13727
- const yankMessageAtCursor = useCallback18(() => {
13671
+ const yankMessageAtCursor = useCallback19(() => {
13728
13672
  const entry = messageEntries.at(resolvedUiState.messageCursorIndex);
13729
13673
  if (!entry) return;
13730
13674
  const text = messageText(entry);
@@ -13884,7 +13828,7 @@ function AppContent({
13884
13828
  () => source_default.hex(theme.inputPrompt).bold(inputPrefix),
13885
13829
  [inputPrefix, theme.inputPrompt]
13886
13830
  );
13887
- const withBorderEdges = useCallback18(
13831
+ const withBorderEdges = useCallback19(
13888
13832
  (line) => {
13889
13833
  if (line.length < 2) return line;
13890
13834
  const first = line.charAt(0);
@@ -13893,14 +13837,14 @@ function AppContent({
13893
13837
  },
13894
13838
  [border]
13895
13839
  );
13896
- const withSectionEdges = useCallback18(
13840
+ const withSectionEdges = useCallback19(
13897
13841
  (content) => {
13898
13842
  const glyphs = frameGlyphs(useAscii);
13899
13843
  return `${border(glyphs.teeLeft)}${content}${border(glyphs.teeRight)}`;
13900
13844
  },
13901
13845
  [border, useAscii]
13902
13846
  );
13903
- const wrapFrameLine = useCallback18(
13847
+ const wrapFrameLine = useCallback19(
13904
13848
  (line) => withBorderEdges(frameLine(line)),
13905
13849
  [withBorderEdges, frameLine]
13906
13850
  );
@@ -14495,7 +14439,7 @@ function App({
14495
14439
  runtimeState.modelName,
14496
14440
  runtimeState.workflowRef
14497
14441
  ]);
14498
- const handleProfilerRender = useCallback18(
14442
+ const handleProfilerRender = useCallback19(
14499
14443
  (id, phaseName, actualDuration, baseDuration, startTime, commitTime) => {
14500
14444
  logReactCommit(
14501
14445
  id,
@@ -14508,20 +14452,20 @@ function App({
14508
14452
  },
14509
14453
  []
14510
14454
  );
14511
- const handleSessionSelect = useCallback18((sessionId) => {
14455
+ const handleSessionSelect = useCallback19((sessionId) => {
14512
14456
  const meta = getSessionMeta(sessionId);
14513
14457
  const adapterIds = meta?.adapterSessionIds ?? [];
14514
14458
  const lastAdapterId = adapterIds[adapterIds.length - 1];
14515
14459
  setAthenaSessionId(sessionId);
14516
14460
  setPhase({ type: "main", initialSessionId: lastAdapterId });
14517
14461
  }, []);
14518
- const handleSessionCancel = useCallback18(() => {
14462
+ const handleSessionCancel = useCallback19(() => {
14519
14463
  setPhase({ type: "main" });
14520
14464
  }, []);
14521
- const handleShowSessions = useCallback18(() => {
14465
+ const handleShowSessions = useCallback19(() => {
14522
14466
  setPhase({ type: "session-select" });
14523
14467
  }, []);
14524
- const handleShowSetup = useCallback18(() => {
14468
+ const handleShowSetup = useCallback19(() => {
14525
14469
  setPhase({ type: "setup" });
14526
14470
  }, []);
14527
14471
  const [sessions, setSessions] = useState18([]);
@@ -14539,7 +14483,7 @@ function App({
14539
14483
  }, 0);
14540
14484
  return () => clearTimeout(timer);
14541
14485
  }, [projectDir, phase.type]);
14542
- const refreshRuntime = useCallback18(() => {
14486
+ const refreshRuntime = useCallback19(() => {
14543
14487
  try {
14544
14488
  const refreshed = bootstrapRuntimeConfig({
14545
14489
  projectDir,
@@ -14564,7 +14508,7 @@ function App({
14564
14508
  console.error(`Error: ${error.message}`);
14565
14509
  }
14566
14510
  }, [projectDir, pluginFlags, isolationPreset, verbose]);
14567
- const handleSetupComplete = useCallback18(
14511
+ const handleSetupComplete = useCallback19(
14568
14512
  (setupResult) => {
14569
14513
  setActiveTheme(resolveTheme(setupResult.theme));
14570
14514
  refreshRuntime();
@@ -14572,10 +14516,10 @@ function App({
14572
14516
  },
14573
14517
  [refreshRuntime]
14574
14518
  );
14575
- const handleWorkflowSelected = useCallback18(() => {
14519
+ const handleWorkflowSelected = useCallback19(() => {
14576
14520
  refreshRuntime();
14577
14521
  }, [refreshRuntime]);
14578
- const handleModelSelected = useCallback18(() => {
14522
+ const handleModelSelected = useCallback19(() => {
14579
14523
  refreshRuntime();
14580
14524
  }, [refreshRuntime]);
14581
14525
  if (phase.type === "setup") {
@@ -14801,7 +14745,7 @@ var tasksCommand = {
14801
14745
  };
14802
14746
 
14803
14747
  // src/app/commands/builtins/setup.ts
14804
- var setup = {
14748
+ var setup2 = {
14805
14749
  name: "setup",
14806
14750
  description: "Re-run the setup wizard",
14807
14751
  category: "ui",
@@ -14809,7 +14753,7 @@ var setup = {
14809
14753
  ctx.showSetup();
14810
14754
  }
14811
14755
  };
14812
- var setup_default = setup;
14756
+ var setup_default = setup2;
14813
14757
 
14814
14758
  // src/app/commands/builtins/telemetry.ts
14815
14759
  var telemetryCommand = {
@@ -16015,7 +15959,7 @@ var cachedVersion = null;
16015
15959
  function readPackageVersion() {
16016
15960
  if (cachedVersion !== null) return cachedVersion;
16017
15961
  try {
16018
- const injected = "0.4.2";
15962
+ const injected = "0.4.4";
16019
15963
  if (typeof injected === "string" && injected.length > 0) {
16020
15964
  cachedVersion = injected;
16021
15965
  return cachedVersion;
@@ -16137,7 +16081,7 @@ async function runDashboardCommand(input, deps = {}) {
16137
16081
  `dashboard pair: cli version ${packageVersion} is older than the dashboard's required >=${parsed.requiredCliVersion}.`
16138
16082
  );
16139
16083
  logError(
16140
- "dashboard pair: upgrade with `npm i -g @athenaflow/cli` then re-run pair."
16084
+ "dashboard pair: upgrade with `npm i -g @drisp/cli` then re-run pair."
16141
16085
  );
16142
16086
  return 1;
16143
16087
  }
@@ -18473,7 +18417,7 @@ Available commands: ${[...KNOWN_COMMANDS].join(", ")}`
18473
18417
  await exitWith(1);
18474
18418
  return;
18475
18419
  }
18476
- const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-NDWLVIFI.js");
18420
+ const { default: WorkflowInstallWizard } = await import("./WorkflowInstallWizard-2MC5A7W4.js");
18477
18421
  const { waitUntilExit } = render(
18478
18422
  /* @__PURE__ */ jsx25(
18479
18423
  WorkflowInstallWizard,