@drisp/cli 0.5.7 → 0.5.10

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.
@@ -373,6 +373,21 @@ var RULES = {
373
373
  defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
374
374
  canBlock: false
375
375
  },
376
+ "instructions.loaded": {
377
+ expectsDecision: false,
378
+ defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
379
+ canBlock: false
380
+ },
381
+ "worktree.create": {
382
+ expectsDecision: false,
383
+ defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
384
+ canBlock: false
385
+ },
386
+ "worktree.remove": {
387
+ expectsDecision: false,
388
+ defaultTimeoutMs: DEFAULT_TIMEOUT_MS,
389
+ canBlock: false
390
+ },
376
391
  "elicitation.request": {
377
392
  expectsDecision: true,
378
393
  defaultTimeoutMs: PERMISSION_TIMEOUT_MS,
@@ -629,6 +644,32 @@ function translateClaudeEnvelope(envelope) {
629
644
  file_path: payload["file_path"]
630
645
  }
631
646
  };
647
+ case "InstructionsLoaded":
648
+ return {
649
+ kind: "instructions.loaded",
650
+ data: {
651
+ file_path: payload["file_path"],
652
+ memory_type: payload["memory_type"],
653
+ load_reason: payload["load_reason"],
654
+ globs: Array.isArray(payload["globs"]) ? payload["globs"] : void 0,
655
+ trigger_file_path: payload["trigger_file_path"],
656
+ parent_file_path: payload["parent_file_path"]
657
+ }
658
+ };
659
+ case "WorktreeCreate":
660
+ return {
661
+ kind: "worktree.create",
662
+ data: {
663
+ worktree_path: payload["worktree_path"]
664
+ }
665
+ };
666
+ case "WorktreeRemove":
667
+ return {
668
+ kind: "worktree.remove",
669
+ data: {
670
+ worktree_path: payload["worktree_path"]
671
+ }
672
+ };
632
673
  case "Elicitation":
633
674
  return {
634
675
  kind: "elicitation.request",
@@ -5208,16 +5249,21 @@ function translateServerRequest(msg) {
5208
5249
  networkContext: params.networkApprovalContext && typeof params.networkApprovalContext === "object" ? {
5209
5250
  host: params.networkApprovalContext.host,
5210
5251
  protocol: params.networkApprovalContext.protocol
5211
- } : void 0
5252
+ } : void 0,
5253
+ toolUseId: params.itemId
5212
5254
  }
5213
5255
  );
5214
5256
  }
5215
5257
  case FILE_CHANGE_REQUEST_APPROVAL: {
5216
5258
  const params = msg.params;
5217
- return permissionRequestEvent("Edit", {
5218
- reason: params.reason,
5219
- grantRoot: params.grantRoot
5220
- });
5259
+ return permissionRequestEvent(
5260
+ "Edit",
5261
+ {
5262
+ reason: params.reason,
5263
+ grantRoot: params.grantRoot
5264
+ },
5265
+ { toolUseId: params.itemId }
5266
+ );
5221
5267
  }
5222
5268
  case PERMISSIONS_REQUEST_APPROVAL: {
5223
5269
  const params = msg.params;
@@ -6153,15 +6199,34 @@ function createCodexServer(opts) {
6153
6199
  },
6154
6200
  stop() {
6155
6201
  clearPendingApprovals();
6156
- if (loadedAgentConfig) {
6157
- cleanupAgentConfig(loadedAgentConfig.tempDir);
6158
- loadedAgentConfig = null;
6159
- }
6160
- if (manager) {
6161
- manager.removeAllListeners();
6162
- manager.stop().catch(() => {
6163
- });
6164
- manager = null;
6202
+ const managerToStop = manager;
6203
+ const agentConfigToCleanup = loadedAgentConfig;
6204
+ manager = null;
6205
+ loadedAgentConfig = null;
6206
+ if (managerToStop) {
6207
+ managerToStop.removeAllListeners();
6208
+ void (async () => {
6209
+ if (agentConfigToCleanup) {
6210
+ const removalEdits = buildAgentRemovalEdits(
6211
+ agentConfigToCleanup.agentNames
6212
+ );
6213
+ if (removalEdits.length > 0) {
6214
+ try {
6215
+ await managerToStop.sendRequest(CONFIG_BATCH_WRITE, {
6216
+ filePath: `${projectDir}/.codex/config.toml`,
6217
+ edits: removalEdits
6218
+ });
6219
+ } catch (error) {
6220
+ console.error(
6221
+ `[athena:codex] failed to remove agents on stop: ${error instanceof Error ? error.message : String(error)}`
6222
+ );
6223
+ }
6224
+ }
6225
+ cleanupAgentConfig(agentConfigToCleanup.tempDir);
6226
+ }
6227
+ await managerToStop.stop().catch(() => {
6228
+ });
6229
+ })();
6165
6230
  }
6166
6231
  status = "stopped";
6167
6232
  lastError = null;
@@ -7654,6 +7719,12 @@ function generateNeutralTitle(event, g) {
7654
7719
  return truncate(`${g["config.icon"]} cwd \u2192 ${event.data.cwd}`);
7655
7720
  case "file.changed":
7656
7721
  return truncate(`File changed: ${event.data.file_path}`);
7722
+ case "instructions.loaded":
7723
+ return truncate(`Instructions loaded: ${event.data.file_path}`);
7724
+ case "worktree.create":
7725
+ return truncate(`Worktree created: ${event.data.worktree_path}`);
7726
+ case "worktree.remove":
7727
+ return truncate(`Worktree removed: ${event.data.worktree_path}`);
7657
7728
  case "stop.failure":
7658
7729
  return truncate(
7659
7730
  `${g["status.blocked"]} Stop failure: ${event.data.error_type}`
@@ -8104,6 +8175,64 @@ function createRootPlanTracker() {
8104
8175
  };
8105
8176
  }
8106
8177
 
8178
+ // src/core/feed/internals/taskLifecycleTracker.ts
8179
+ function coerceTaskStatus(status) {
8180
+ switch (status) {
8181
+ case "pending":
8182
+ case "in_progress":
8183
+ case "completed":
8184
+ case "failed":
8185
+ return status;
8186
+ default:
8187
+ return null;
8188
+ }
8189
+ }
8190
+ function createTaskLifecycleTracker() {
8191
+ let items = [];
8192
+ return {
8193
+ current() {
8194
+ return items;
8195
+ },
8196
+ upsertCreated({ taskId, subject, description, activeForm }) {
8197
+ const task = {
8198
+ taskId,
8199
+ content: subject,
8200
+ status: "pending",
8201
+ activeForm: activeForm ?? description
8202
+ };
8203
+ const existingIndex = items.findIndex((item) => item.taskId === taskId);
8204
+ if (existingIndex === -1) {
8205
+ items = [...items, task];
8206
+ return;
8207
+ }
8208
+ items = items.map(
8209
+ (item, index) => index === existingIndex ? {
8210
+ ...item,
8211
+ taskId,
8212
+ content: subject,
8213
+ activeForm: task.activeForm ?? item.activeForm
8214
+ } : item
8215
+ );
8216
+ },
8217
+ markCompleted({ taskId, subject }) {
8218
+ const existingIndex = items.findIndex((item) => item.taskId === taskId);
8219
+ if (existingIndex === -1) {
8220
+ if (!subject) return;
8221
+ items = [...items, { taskId, content: subject, status: "completed" }];
8222
+ return;
8223
+ }
8224
+ items = items.map(
8225
+ (item, index) => index === existingIndex ? { ...item, status: "completed" } : item
8226
+ );
8227
+ },
8228
+ updateStatus({ taskId, status }) {
8229
+ items = items.map(
8230
+ (item) => item.taskId === taskId ? { ...item, status } : item
8231
+ );
8232
+ }
8233
+ };
8234
+ }
8235
+
8107
8236
  // src/core/feed/internals/subagentTracker.ts
8108
8237
  function createSubagentTracker() {
8109
8238
  const stack = [];
@@ -8200,6 +8329,7 @@ function createToolProjection(args) {
8200
8329
  runLifecycle,
8201
8330
  toolCorrelation,
8202
8331
  rootPlan,
8332
+ taskLifecycle,
8203
8333
  subagents,
8204
8334
  resolveToolActor
8205
8335
  } = args;
@@ -8299,6 +8429,13 @@ function createToolProjection(args) {
8299
8429
  if (toolName === "TodoWrite" && preEvent.actor_id === "agent:root") {
8300
8430
  rootPlan.set(extractTodoItems(toolInput));
8301
8431
  }
8432
+ if (toolName === "TaskUpdate") {
8433
+ const taskId = readString(toolInput["taskId"], toolInput["task_id"]);
8434
+ const status = coerceTaskStatus(toolInput["status"]);
8435
+ if (taskId && status) {
8436
+ taskLifecycle.updateStatus({ taskId, status });
8437
+ }
8438
+ }
8302
8439
  if (isSubagentTool(toolName)) {
8303
8440
  if (typeof toolInput["description"] === "string") {
8304
8441
  subagents.recordPendingDescription(toolInput["description"]);
@@ -8325,6 +8462,35 @@ function createToolProjection(args) {
8325
8462
  toolUseCause(toolUseId, parentId)
8326
8463
  );
8327
8464
  results.push(postEvent);
8465
+ if (toolName === "TaskCreate") {
8466
+ const response = readObject(data["tool_response"]);
8467
+ const task = readObject(response["task"]);
8468
+ const taskId = readString(task["id"], task["task_id"]);
8469
+ const subject = readString(task["subject"], toolInput["subject"]);
8470
+ if (taskId && subject) {
8471
+ taskLifecycle.upsertCreated({
8472
+ taskId,
8473
+ subject,
8474
+ description: readString(toolInput["description"]),
8475
+ activeForm: readString(toolInput["activeForm"])
8476
+ });
8477
+ }
8478
+ }
8479
+ if (toolName === "TaskUpdate") {
8480
+ const response = readObject(data["tool_response"]);
8481
+ const taskId = readString(
8482
+ response["taskId"],
8483
+ response["task_id"],
8484
+ toolInput["taskId"],
8485
+ toolInput["task_id"]
8486
+ );
8487
+ const status = coerceTaskStatus(
8488
+ readObject(response["statusChange"])["to"] ?? toolInput["status"]
8489
+ );
8490
+ if (taskId && status) {
8491
+ taskLifecycle.updateStatus({ taskId, status });
8492
+ }
8493
+ }
8328
8494
  if (toolName === "WebSearch") {
8329
8495
  results.push(
8330
8496
  webSearchCompleted(event, data, toolUseId, postEvent.event_id)
@@ -8935,6 +9101,59 @@ function createFileConfigProjection(args) {
8935
9101
  );
8936
9102
  return results;
8937
9103
  }
9104
+ if (event.kind === "instructions.loaded") {
9105
+ results.push(
9106
+ collapsed(
9107
+ makeEvent(
9108
+ "instructions.loaded",
9109
+ "info",
9110
+ "system",
9111
+ {
9112
+ file_path: readString(data["file_path"]) ?? "",
9113
+ memory_type: readString(data["memory_type"]),
9114
+ load_reason: readString(data["load_reason"]),
9115
+ globs: Array.isArray(data["globs"]) ? data["globs"] : void 0,
9116
+ trigger_file_path: readString(data["trigger_file_path"]),
9117
+ parent_file_path: readString(data["parent_file_path"])
9118
+ },
9119
+ event
9120
+ )
9121
+ )
9122
+ );
9123
+ return results;
9124
+ }
9125
+ if (event.kind === "worktree.create") {
9126
+ results.push(
9127
+ collapsed(
9128
+ makeEvent(
9129
+ "worktree.create",
9130
+ "info",
9131
+ "system",
9132
+ {
9133
+ worktree_path: readString(data["worktree_path"]) ?? ""
9134
+ },
9135
+ event
9136
+ )
9137
+ )
9138
+ );
9139
+ return results;
9140
+ }
9141
+ if (event.kind === "worktree.remove") {
9142
+ results.push(
9143
+ collapsed(
9144
+ makeEvent(
9145
+ "worktree.remove",
9146
+ "info",
9147
+ "system",
9148
+ {
9149
+ worktree_path: readString(data["worktree_path"]) ?? ""
9150
+ },
9151
+ event
9152
+ )
9153
+ )
9154
+ );
9155
+ return results;
9156
+ }
8938
9157
  return results;
8939
9158
  }
8940
9159
  };
@@ -9203,7 +9422,7 @@ function createRunSessionProjection(args) {
9203
9422
 
9204
9423
  // src/core/feed/internals/statusProjection.ts
9205
9424
  function createStatusProjection(args) {
9206
- const { ensureRunArray, makeEvent } = args;
9425
+ const { ensureRunArray, makeEvent, taskLifecycle } = args;
9207
9426
  return {
9208
9427
  mapStatusEvent(event, data) {
9209
9428
  const results = ensureRunArray(event);
@@ -9223,15 +9442,25 @@ function createStatusProjection(args) {
9223
9442
  return results;
9224
9443
  }
9225
9444
  if (event.kind === "task.created") {
9445
+ const taskId = readString(data["task_id"]) ?? "";
9446
+ const subject = readString(data["task_subject"]) ?? "";
9447
+ const description = readString(data["task_description"]);
9448
+ if (taskId && subject) {
9449
+ taskLifecycle.upsertCreated({
9450
+ taskId,
9451
+ subject,
9452
+ description
9453
+ });
9454
+ }
9226
9455
  results.push(
9227
9456
  makeEvent(
9228
9457
  "task.created",
9229
9458
  "info",
9230
9459
  "system",
9231
9460
  {
9232
- task_id: readString(data["task_id"]) ?? "",
9233
- task_subject: readString(data["task_subject"]) ?? "",
9234
- task_description: readString(data["task_description"]),
9461
+ task_id: taskId,
9462
+ task_subject: subject,
9463
+ task_description: description,
9235
9464
  teammate_name: readString(data["teammate_name"]),
9236
9465
  team_name: readString(data["team_name"])
9237
9466
  },
@@ -9241,14 +9470,17 @@ function createStatusProjection(args) {
9241
9470
  return results;
9242
9471
  }
9243
9472
  if (event.kind === "task.completed") {
9473
+ const taskId = readString(data["task_id"]) ?? "";
9474
+ const subject = readString(data["task_subject"]);
9475
+ if (taskId) taskLifecycle.markCompleted({ taskId, subject });
9244
9476
  results.push(
9245
9477
  makeEvent(
9246
9478
  "task.completed",
9247
9479
  "info",
9248
9480
  "system",
9249
9481
  {
9250
- task_id: readString(data["task_id"]) ?? "",
9251
- task_subject: readString(data["task_subject"]) ?? "",
9482
+ task_id: taskId,
9483
+ task_subject: subject ?? "",
9252
9484
  task_description: readString(data["task_description"]),
9253
9485
  teammate_name: readString(data["teammate_name"]),
9254
9486
  team_name: readString(data["team_name"])
@@ -9299,7 +9531,10 @@ var FILE_CONFIG_EVENT_KINDS = /* @__PURE__ */ new Set([
9299
9531
  "config.change",
9300
9532
  "compact.post",
9301
9533
  "cwd.changed",
9302
- "file.changed"
9534
+ "file.changed",
9535
+ "instructions.loaded",
9536
+ "worktree.create",
9537
+ "worktree.remove"
9303
9538
  ]);
9304
9539
  var STATUS_EVENT_KINDS = /* @__PURE__ */ new Set([
9305
9540
  "teammate.idle",
@@ -9313,6 +9548,7 @@ function createFeedMapper(bootstrap) {
9313
9548
  const transcriptReader = createTranscriptReader();
9314
9549
  const actors = new ActorRegistry();
9315
9550
  const rootPlan = createRootPlanTracker();
9551
+ const taskLifecycle = createTaskLifecycleTracker();
9316
9552
  const subagents = createSubagentTracker();
9317
9553
  function makeEvent(kind, level, actorId, data, runtimeEvent, cause) {
9318
9554
  const s = runLifecycle.allocateSeq();
@@ -9348,6 +9584,40 @@ function createFeedMapper(bootstrap) {
9348
9584
  makeEvent,
9349
9585
  transcriptReader
9350
9586
  );
9587
+ function replayTaskLifecycleToolEvent(e) {
9588
+ if (e.kind !== "tool.pre" && e.kind !== "tool.post") return;
9589
+ const data = e.data;
9590
+ const toolInput = readObject(data.tool_input);
9591
+ if (data.tool_name === "TaskCreate" && e.kind === "tool.post") {
9592
+ const response = readObject(data.tool_response);
9593
+ const task = readObject(response["task"]);
9594
+ const taskId = readString(task["id"], task["task_id"]);
9595
+ const subject = readString(task["subject"], toolInput["subject"]);
9596
+ if (taskId && subject) {
9597
+ taskLifecycle.upsertCreated({
9598
+ taskId,
9599
+ subject,
9600
+ description: readString(toolInput["description"]),
9601
+ activeForm: readString(toolInput["activeForm"])
9602
+ });
9603
+ }
9604
+ }
9605
+ if (data.tool_name === "TaskUpdate") {
9606
+ const response = readObject(data.tool_response);
9607
+ const status = coerceTaskStatus(
9608
+ readObject(response["statusChange"])["to"] ?? toolInput["status"]
9609
+ );
9610
+ const taskId = readString(
9611
+ response["taskId"],
9612
+ response["task_id"],
9613
+ toolInput["taskId"],
9614
+ toolInput["task_id"]
9615
+ );
9616
+ if (taskId && status) {
9617
+ taskLifecycle.updateStatus({ taskId, status });
9618
+ }
9619
+ }
9620
+ }
9351
9621
  if (bootstrap) {
9352
9622
  runLifecycle.restoreFrom(bootstrap);
9353
9623
  for (const e of bootstrap.feedEvents) {
@@ -9356,6 +9626,26 @@ function createFeedMapper(bootstrap) {
9356
9626
  extractTodoItems(e.data.tool_input)
9357
9627
  );
9358
9628
  }
9629
+ replayTaskLifecycleToolEvent(e);
9630
+ if (e.kind === "task.created") {
9631
+ const data = e.data;
9632
+ if (data.task_id && data.task_subject) {
9633
+ taskLifecycle.upsertCreated({
9634
+ taskId: data.task_id,
9635
+ subject: data.task_subject,
9636
+ description: data.task_description
9637
+ });
9638
+ }
9639
+ }
9640
+ if (e.kind === "task.completed") {
9641
+ const data = e.data;
9642
+ if (data.task_id) {
9643
+ taskLifecycle.markCompleted({
9644
+ taskId: data.task_id,
9645
+ subject: data.task_subject
9646
+ });
9647
+ }
9648
+ }
9359
9649
  }
9360
9650
  }
9361
9651
  function closeRunIntoEvent(runtimeEvent, status) {
@@ -9404,6 +9694,7 @@ function createFeedMapper(bootstrap) {
9404
9694
  runLifecycle,
9405
9695
  toolCorrelation,
9406
9696
  rootPlan,
9697
+ taskLifecycle,
9407
9698
  subagents,
9408
9699
  resolveToolActor
9409
9700
  });
@@ -9431,7 +9722,8 @@ function createFeedMapper(bootstrap) {
9431
9722
  });
9432
9723
  const statusProjection = createStatusProjection({
9433
9724
  ensureRunArray,
9434
- makeEvent
9725
+ makeEvent,
9726
+ taskLifecycle
9435
9727
  });
9436
9728
  const currentScope = () => subagents.currentScope();
9437
9729
  const runSessionProjection = createRunSessionProjection({
@@ -9528,7 +9820,7 @@ function createFeedMapper(bootstrap) {
9528
9820
  getSession: () => runLifecycle.getSession(),
9529
9821
  getCurrentRun: () => runLifecycle.getCurrentRun(),
9530
9822
  getActors: () => actors.all(),
9531
- getTasks: () => rootPlan.current(),
9823
+ getTasks: () => [...rootPlan.current(), ...taskLifecycle.current()],
9532
9824
  allocateSeq: () => runLifecycle.allocateSeq()
9533
9825
  };
9534
9826
  }
@@ -10242,72 +10534,3159 @@ function createSessionStore(opts) {
10242
10534
  };
10243
10535
  }
10244
10536
 
10245
- // src/infra/sessions/registry.ts
10246
- import fs18 from "fs";
10247
- import os10 from "os";
10248
- import path15 from "path";
10537
+ // src/infra/sessions/hookAudit.ts
10249
10538
  import Database2 from "better-sqlite3";
10250
- function sessionsDir() {
10251
- return path15.join(os10.homedir(), ".config", "athena", "sessions");
10539
+
10540
+ // src/core/feed/filter.ts
10541
+ var TASK_TOOL_NAMES = /* @__PURE__ */ new Set([
10542
+ "TodoWrite",
10543
+ "TaskCreate",
10544
+ "TaskUpdate",
10545
+ "TaskList",
10546
+ "TaskGet"
10547
+ ]);
10548
+ function isTaskToolEvent(event) {
10549
+ if (event.kind !== "tool.pre" && event.kind !== "tool.post") return false;
10550
+ return TASK_TOOL_NAMES.has(event.data.tool_name);
10252
10551
  }
10253
- function sessionDbPath(sessionId) {
10254
- return path15.join(sessionsDir(), sessionId, "session.db");
10552
+ function shouldExcludeFromFeed(event) {
10553
+ if (isTaskToolEvent(event)) return true;
10554
+ if (event.kind === "todo.update") return true;
10555
+ return false;
10255
10556
  }
10256
- function readSessionFromDb(dbPath) {
10257
- if (!fs18.existsSync(dbPath)) return null;
10258
- let db;
10259
- try {
10260
- db = new Database2(dbPath, { readonly: true });
10261
- const versionRow = db.prepare("SELECT version FROM schema_version").get();
10262
- if (versionRow && versionRow.version > SCHEMA_VERSION) {
10263
- return null;
10557
+
10558
+ // src/core/feed/items.ts
10559
+ function mergeFeedItems(messages, feedEvents) {
10560
+ const messageItems = messages.map((message) => ({
10561
+ type: "message",
10562
+ data: message
10563
+ }));
10564
+ const feedItems = feedEvents.filter((event) => !shouldExcludeFromFeed(event)).map((event) => ({ type: "feed", data: event }));
10565
+ return [...messageItems, ...feedItems].sort((left, right) => {
10566
+ if (left.data.seq !== right.data.seq) return left.data.seq - right.data.seq;
10567
+ if (left.type === "message" && right.type !== "message") return -1;
10568
+ if (left.type !== "message" && right.type === "message") return 1;
10569
+ return 0;
10570
+ });
10571
+ }
10572
+ function buildPostByToolUseId(events) {
10573
+ const map = /* @__PURE__ */ new Map();
10574
+ for (const event of events) {
10575
+ if (event.kind !== "tool.delta" && event.kind !== "tool.post" && event.kind !== "tool.failure") {
10576
+ continue;
10264
10577
  }
10265
- const row = db.prepare("SELECT * FROM session LIMIT 1").get();
10266
- if (!row) return null;
10267
- const adapters = db.prepare("SELECT session_id FROM adapter_sessions ORDER BY started_at").all();
10268
- let firstPrompt;
10269
- if (!row.label && (row.event_count ?? 0) > 0) {
10270
- const promptRow = db.prepare(
10271
- `SELECT json_extract(payload, '$.data.prompt') as prompt FROM runtime_events WHERE hook_name = 'UserPromptSubmit' ORDER BY seq ASC LIMIT 1`
10272
- ).get();
10273
- if (promptRow?.prompt) {
10274
- firstPrompt = promptRow.prompt;
10578
+ const toolUseId = event.data.tool_use_id;
10579
+ if (toolUseId) map.set(toolUseId, event);
10580
+ }
10581
+ return map;
10582
+ }
10583
+
10584
+ // node_modules/ansi-regex/index.js
10585
+ function ansiRegex({ onlyFirst = false } = {}) {
10586
+ const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
10587
+ const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
10588
+ const csi = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";
10589
+ const pattern = `${osc}|${csi}`;
10590
+ return new RegExp(pattern, onlyFirst ? void 0 : "g");
10591
+ }
10592
+
10593
+ // node_modules/strip-ansi/index.js
10594
+ var regex = ansiRegex();
10595
+ function stripAnsi(string) {
10596
+ if (typeof string !== "string") {
10597
+ throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
10598
+ }
10599
+ return string.replace(regex, "");
10600
+ }
10601
+
10602
+ // node_modules/get-east-asian-width/lookup.js
10603
+ function isAmbiguous(x) {
10604
+ return x === 161 || x === 164 || x === 167 || x === 168 || x === 170 || x === 173 || x === 174 || x >= 176 && x <= 180 || x >= 182 && x <= 186 || x >= 188 && x <= 191 || x === 198 || x === 208 || x === 215 || x === 216 || x >= 222 && x <= 225 || x === 230 || x >= 232 && x <= 234 || x === 236 || x === 237 || x === 240 || x === 242 || x === 243 || x >= 247 && x <= 250 || x === 252 || x === 254 || x === 257 || x === 273 || x === 275 || x === 283 || x === 294 || x === 295 || x === 299 || x >= 305 && x <= 307 || x === 312 || x >= 319 && x <= 322 || x === 324 || x >= 328 && x <= 331 || x === 333 || x === 338 || x === 339 || x === 358 || x === 359 || x === 363 || x === 462 || x === 464 || x === 466 || x === 468 || x === 470 || x === 472 || x === 474 || x === 476 || x === 593 || x === 609 || x === 708 || x === 711 || x >= 713 && x <= 715 || x === 717 || x === 720 || x >= 728 && x <= 731 || x === 733 || x === 735 || x >= 768 && x <= 879 || x >= 913 && x <= 929 || x >= 931 && x <= 937 || x >= 945 && x <= 961 || x >= 963 && x <= 969 || x === 1025 || x >= 1040 && x <= 1103 || x === 1105 || x === 8208 || x >= 8211 && x <= 8214 || x === 8216 || x === 8217 || x === 8220 || x === 8221 || x >= 8224 && x <= 8226 || x >= 8228 && x <= 8231 || x === 8240 || x === 8242 || x === 8243 || x === 8245 || x === 8251 || x === 8254 || x === 8308 || x === 8319 || x >= 8321 && x <= 8324 || x === 8364 || x === 8451 || x === 8453 || x === 8457 || x === 8467 || x === 8470 || x === 8481 || x === 8482 || x === 8486 || x === 8491 || x === 8531 || x === 8532 || x >= 8539 && x <= 8542 || x >= 8544 && x <= 8555 || x >= 8560 && x <= 8569 || x === 8585 || x >= 8592 && x <= 8601 || x === 8632 || x === 8633 || x === 8658 || x === 8660 || x === 8679 || x === 8704 || x === 8706 || x === 8707 || x === 8711 || x === 8712 || x === 8715 || x === 8719 || x === 8721 || x === 8725 || x === 8730 || x >= 8733 && x <= 8736 || x === 8739 || x === 8741 || x >= 8743 && x <= 8748 || x === 8750 || x >= 8756 && x <= 8759 || x === 8764 || x === 8765 || x === 8776 || x === 8780 || x === 8786 || x === 8800 || x === 8801 || x >= 8804 && x <= 8807 || x === 8810 || x === 8811 || x === 8814 || x === 8815 || x === 8834 || x === 8835 || x === 8838 || x === 8839 || x === 8853 || x === 8857 || x === 8869 || x === 8895 || x === 8978 || x >= 9312 && x <= 9449 || x >= 9451 && x <= 9547 || x >= 9552 && x <= 9587 || x >= 9600 && x <= 9615 || x >= 9618 && x <= 9621 || x === 9632 || x === 9633 || x >= 9635 && x <= 9641 || x === 9650 || x === 9651 || x === 9654 || x === 9655 || x === 9660 || x === 9661 || x === 9664 || x === 9665 || x >= 9670 && x <= 9672 || x === 9675 || x >= 9678 && x <= 9681 || x >= 9698 && x <= 9701 || x === 9711 || x === 9733 || x === 9734 || x === 9737 || x === 9742 || x === 9743 || x === 9756 || x === 9758 || x === 9792 || x === 9794 || x === 9824 || x === 9825 || x >= 9827 && x <= 9829 || x >= 9831 && x <= 9834 || x === 9836 || x === 9837 || x === 9839 || x === 9886 || x === 9887 || x === 9919 || x >= 9926 && x <= 9933 || x >= 9935 && x <= 9939 || x >= 9941 && x <= 9953 || x === 9955 || x === 9960 || x === 9961 || x >= 9963 && x <= 9969 || x === 9972 || x >= 9974 && x <= 9977 || x === 9979 || x === 9980 || x === 9982 || x === 9983 || x === 10045 || x >= 10102 && x <= 10111 || x >= 11094 && x <= 11097 || x >= 12872 && x <= 12879 || x >= 57344 && x <= 63743 || x >= 65024 && x <= 65039 || x === 65533 || x >= 127232 && x <= 127242 || x >= 127248 && x <= 127277 || x >= 127280 && x <= 127337 || x >= 127344 && x <= 127373 || x === 127375 || x === 127376 || x >= 127387 && x <= 127404 || x >= 917760 && x <= 917999 || x >= 983040 && x <= 1048573 || x >= 1048576 && x <= 1114109;
10605
+ }
10606
+ function isFullWidth(x) {
10607
+ return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
10608
+ }
10609
+ function isWide(x) {
10610
+ return x >= 4352 && x <= 4447 || x === 8986 || x === 8987 || x === 9001 || x === 9002 || x >= 9193 && x <= 9196 || x === 9200 || x === 9203 || x === 9725 || x === 9726 || x === 9748 || x === 9749 || x >= 9776 && x <= 9783 || x >= 9800 && x <= 9811 || x === 9855 || x >= 9866 && x <= 9871 || x === 9875 || x === 9889 || x === 9898 || x === 9899 || x === 9917 || x === 9918 || x === 9924 || x === 9925 || x === 9934 || x === 9940 || x === 9962 || x === 9970 || x === 9971 || x === 9973 || x === 9978 || x === 9981 || x === 9989 || x === 9994 || x === 9995 || x === 10024 || x === 10060 || x === 10062 || x >= 10067 && x <= 10069 || x === 10071 || x >= 10133 && x <= 10135 || x === 10160 || x === 10175 || x === 11035 || x === 11036 || x === 11088 || x === 11093 || x >= 11904 && x <= 11929 || x >= 11931 && x <= 12019 || x >= 12032 && x <= 12245 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12353 && x <= 12438 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12773 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 42124 || x >= 42128 && x <= 42182 || x >= 43360 && x <= 43388 || x >= 44032 && x <= 55203 || x >= 63744 && x <= 64255 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 94176 && x <= 94180 || x >= 94192 && x <= 94198 || x >= 94208 && x <= 101589 || x >= 101631 && x <= 101662 || x >= 101760 && x <= 101874 || x >= 110576 && x <= 110579 || x >= 110581 && x <= 110587 || x === 110589 || x === 110590 || x >= 110592 && x <= 110882 || x === 110898 || x >= 110928 && x <= 110930 || x === 110933 || x >= 110948 && x <= 110951 || x >= 110960 && x <= 111355 || x >= 119552 && x <= 119638 || x >= 119648 && x <= 119670 || x === 126980 || x === 127183 || x === 127374 || x >= 127377 && x <= 127386 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x === 127568 || x === 127569 || x >= 127584 && x <= 127589 || x >= 127744 && x <= 127776 || x >= 127789 && x <= 127797 || x >= 127799 && x <= 127868 || x >= 127870 && x <= 127891 || x >= 127904 && x <= 127946 || x >= 127951 && x <= 127955 || x >= 127968 && x <= 127984 || x === 127988 || x >= 127992 && x <= 128062 || x === 128064 || x >= 128066 && x <= 128252 || x >= 128255 && x <= 128317 || x >= 128331 && x <= 128334 || x >= 128336 && x <= 128359 || x === 128378 || x === 128405 || x === 128406 || x === 128420 || x >= 128507 && x <= 128591 || x >= 128640 && x <= 128709 || x === 128716 || x >= 128720 && x <= 128722 || x >= 128725 && x <= 128728 || x >= 128732 && x <= 128735 || x === 128747 || x === 128748 || x >= 128756 && x <= 128764 || x >= 128992 && x <= 129003 || x === 129008 || x >= 129292 && x <= 129338 || x >= 129340 && x <= 129349 || x >= 129351 && x <= 129535 || x >= 129648 && x <= 129660 || x >= 129664 && x <= 129674 || x >= 129678 && x <= 129734 || x === 129736 || x >= 129741 && x <= 129756 || x >= 129759 && x <= 129770 || x >= 129775 && x <= 129784 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
10611
+ }
10612
+
10613
+ // node_modules/get-east-asian-width/index.js
10614
+ function validate(codePoint) {
10615
+ if (!Number.isSafeInteger(codePoint)) {
10616
+ throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`);
10617
+ }
10618
+ }
10619
+ function eastAsianWidth(codePoint, { ambiguousAsWide = false } = {}) {
10620
+ validate(codePoint);
10621
+ if (isFullWidth(codePoint) || isWide(codePoint) || ambiguousAsWide && isAmbiguous(codePoint)) {
10622
+ return 2;
10623
+ }
10624
+ return 1;
10625
+ }
10626
+
10627
+ // node_modules/string-width/index.js
10628
+ var segmenter = new Intl.Segmenter();
10629
+ var zeroWidthClusterRegex = new RegExp("^(?:\\p{Default_Ignorable_Code_Point}|\\p{Control}|\\p{Format}|\\p{Mark}|\\p{Surrogate})+$", "v");
10630
+ var leadingNonPrintingRegex = new RegExp("^[\\p{Default_Ignorable_Code_Point}\\p{Control}\\p{Format}\\p{Mark}\\p{Surrogate}]+", "v");
10631
+ var rgiEmojiRegex = new RegExp("^\\p{RGI_Emoji}$", "v");
10632
+ function baseVisible(segment) {
10633
+ return segment.replace(leadingNonPrintingRegex, "");
10634
+ }
10635
+ function isZeroWidthCluster(segment) {
10636
+ return zeroWidthClusterRegex.test(segment);
10637
+ }
10638
+ function trailingHalfwidthWidth(segment, eastAsianWidthOptions) {
10639
+ let extra = 0;
10640
+ if (segment.length > 1) {
10641
+ for (const char of segment.slice(1)) {
10642
+ if (char >= "\uFF00" && char <= "\uFFEF") {
10643
+ extra += eastAsianWidth(char.codePointAt(0), eastAsianWidthOptions);
10275
10644
  }
10276
10645
  }
10277
- return rowToAthenaSession(
10278
- row,
10279
- adapters.map((a) => a.session_id),
10280
- firstPrompt
10281
- );
10282
- } catch {
10283
- return null;
10284
- } finally {
10285
- db?.close();
10286
10646
  }
10647
+ return extra;
10287
10648
  }
10288
- function listSessions(projectDir) {
10289
- const dir = sessionsDir();
10290
- if (!fs18.existsSync(dir)) return [];
10291
- const entries = fs18.readdirSync(dir, { withFileTypes: true });
10292
- const sessions = [];
10293
- for (const entry of entries) {
10294
- if (!entry.isDirectory()) continue;
10295
- const dbPath = path15.join(dir, entry.name, "session.db");
10296
- const session = readSessionFromDb(dbPath);
10297
- if (session && (session.eventCount ?? 0) > 0) {
10298
- if (!projectDir || session.projectDir === projectDir) {
10299
- sessions.push(session);
10300
- }
10649
+ function stringWidth(input, options = {}) {
10650
+ if (typeof input !== "string" || input.length === 0) {
10651
+ return 0;
10652
+ }
10653
+ const {
10654
+ ambiguousIsNarrow = true,
10655
+ countAnsiEscapeCodes = false
10656
+ } = options;
10657
+ let string = input;
10658
+ if (!countAnsiEscapeCodes) {
10659
+ string = stripAnsi(string);
10660
+ }
10661
+ if (string.length === 0) {
10662
+ return 0;
10663
+ }
10664
+ let width = 0;
10665
+ const eastAsianWidthOptions = { ambiguousAsWide: !ambiguousIsNarrow };
10666
+ for (const { segment } of segmenter.segment(string)) {
10667
+ if (isZeroWidthCluster(segment)) {
10668
+ continue;
10669
+ }
10670
+ if (rgiEmojiRegex.test(segment)) {
10671
+ width += 2;
10672
+ continue;
10301
10673
  }
10674
+ const codePoint = baseVisible(segment).codePointAt(0);
10675
+ width += eastAsianWidth(codePoint, eastAsianWidthOptions);
10676
+ width += trailingHalfwidthWidth(segment, eastAsianWidthOptions);
10302
10677
  }
10303
- return sessions.sort((a, b) => b.updatedAt - a.updatedAt);
10678
+ return width;
10304
10679
  }
10305
- function getSessionMeta(sessionId) {
10306
- return readSessionFromDb(sessionDbPath(sessionId));
10680
+
10681
+ // node_modules/ansi-styles/index.js
10682
+ var ANSI_BACKGROUND_OFFSET = 10;
10683
+ var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
10684
+ var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
10685
+ var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
10686
+ var styles = {
10687
+ modifier: {
10688
+ reset: [0, 0],
10689
+ // 21 isn't widely supported and 22 does the same thing
10690
+ bold: [1, 22],
10691
+ dim: [2, 22],
10692
+ italic: [3, 23],
10693
+ underline: [4, 24],
10694
+ overline: [53, 55],
10695
+ inverse: [7, 27],
10696
+ hidden: [8, 28],
10697
+ strikethrough: [9, 29]
10698
+ },
10699
+ color: {
10700
+ black: [30, 39],
10701
+ red: [31, 39],
10702
+ green: [32, 39],
10703
+ yellow: [33, 39],
10704
+ blue: [34, 39],
10705
+ magenta: [35, 39],
10706
+ cyan: [36, 39],
10707
+ white: [37, 39],
10708
+ // Bright color
10709
+ blackBright: [90, 39],
10710
+ gray: [90, 39],
10711
+ // Alias of `blackBright`
10712
+ grey: [90, 39],
10713
+ // Alias of `blackBright`
10714
+ redBright: [91, 39],
10715
+ greenBright: [92, 39],
10716
+ yellowBright: [93, 39],
10717
+ blueBright: [94, 39],
10718
+ magentaBright: [95, 39],
10719
+ cyanBright: [96, 39],
10720
+ whiteBright: [97, 39]
10721
+ },
10722
+ bgColor: {
10723
+ bgBlack: [40, 49],
10724
+ bgRed: [41, 49],
10725
+ bgGreen: [42, 49],
10726
+ bgYellow: [43, 49],
10727
+ bgBlue: [44, 49],
10728
+ bgMagenta: [45, 49],
10729
+ bgCyan: [46, 49],
10730
+ bgWhite: [47, 49],
10731
+ // Bright color
10732
+ bgBlackBright: [100, 49],
10733
+ bgGray: [100, 49],
10734
+ // Alias of `bgBlackBright`
10735
+ bgGrey: [100, 49],
10736
+ // Alias of `bgBlackBright`
10737
+ bgRedBright: [101, 49],
10738
+ bgGreenBright: [102, 49],
10739
+ bgYellowBright: [103, 49],
10740
+ bgBlueBright: [104, 49],
10741
+ bgMagentaBright: [105, 49],
10742
+ bgCyanBright: [106, 49],
10743
+ bgWhiteBright: [107, 49]
10744
+ }
10745
+ };
10746
+ var modifierNames = Object.keys(styles.modifier);
10747
+ var foregroundColorNames = Object.keys(styles.color);
10748
+ var backgroundColorNames = Object.keys(styles.bgColor);
10749
+ var colorNames = [...foregroundColorNames, ...backgroundColorNames];
10750
+ function assembleStyles() {
10751
+ const codes = /* @__PURE__ */ new Map();
10752
+ for (const [groupName, group] of Object.entries(styles)) {
10753
+ for (const [styleName, style] of Object.entries(group)) {
10754
+ styles[styleName] = {
10755
+ open: `\x1B[${style[0]}m`,
10756
+ close: `\x1B[${style[1]}m`
10757
+ };
10758
+ group[styleName] = styles[styleName];
10759
+ codes.set(style[0], style[1]);
10760
+ }
10761
+ Object.defineProperty(styles, groupName, {
10762
+ value: group,
10763
+ enumerable: false
10764
+ });
10765
+ }
10766
+ Object.defineProperty(styles, "codes", {
10767
+ value: codes,
10768
+ enumerable: false
10769
+ });
10770
+ styles.color.close = "\x1B[39m";
10771
+ styles.bgColor.close = "\x1B[49m";
10772
+ styles.color.ansi = wrapAnsi16();
10773
+ styles.color.ansi256 = wrapAnsi256();
10774
+ styles.color.ansi16m = wrapAnsi16m();
10775
+ styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
10776
+ styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
10777
+ styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
10778
+ Object.defineProperties(styles, {
10779
+ rgbToAnsi256: {
10780
+ value(red, green, blue) {
10781
+ if (red === green && green === blue) {
10782
+ if (red < 8) {
10783
+ return 16;
10784
+ }
10785
+ if (red > 248) {
10786
+ return 231;
10787
+ }
10788
+ return Math.round((red - 8) / 247 * 24) + 232;
10789
+ }
10790
+ return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
10791
+ },
10792
+ enumerable: false
10793
+ },
10794
+ hexToRgb: {
10795
+ value(hex) {
10796
+ const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
10797
+ if (!matches) {
10798
+ return [0, 0, 0];
10799
+ }
10800
+ let [colorString] = matches;
10801
+ if (colorString.length === 3) {
10802
+ colorString = [...colorString].map((character) => character + character).join("");
10803
+ }
10804
+ const integer = Number.parseInt(colorString, 16);
10805
+ return [
10806
+ /* eslint-disable no-bitwise */
10807
+ integer >> 16 & 255,
10808
+ integer >> 8 & 255,
10809
+ integer & 255
10810
+ /* eslint-enable no-bitwise */
10811
+ ];
10812
+ },
10813
+ enumerable: false
10814
+ },
10815
+ hexToAnsi256: {
10816
+ value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
10817
+ enumerable: false
10818
+ },
10819
+ ansi256ToAnsi: {
10820
+ value(code) {
10821
+ if (code < 8) {
10822
+ return 30 + code;
10823
+ }
10824
+ if (code < 16) {
10825
+ return 90 + (code - 8);
10826
+ }
10827
+ let red;
10828
+ let green;
10829
+ let blue;
10830
+ if (code >= 232) {
10831
+ red = ((code - 232) * 10 + 8) / 255;
10832
+ green = red;
10833
+ blue = red;
10834
+ } else {
10835
+ code -= 16;
10836
+ const remainder = code % 36;
10837
+ red = Math.floor(code / 36) / 5;
10838
+ green = Math.floor(remainder / 6) / 5;
10839
+ blue = remainder % 6 / 5;
10840
+ }
10841
+ const value = Math.max(red, green, blue) * 2;
10842
+ if (value === 0) {
10843
+ return 30;
10844
+ }
10845
+ let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
10846
+ if (value === 2) {
10847
+ result += 60;
10848
+ }
10849
+ return result;
10850
+ },
10851
+ enumerable: false
10852
+ },
10853
+ rgbToAnsi: {
10854
+ value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
10855
+ enumerable: false
10856
+ },
10857
+ hexToAnsi: {
10858
+ value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
10859
+ enumerable: false
10860
+ }
10861
+ });
10862
+ return styles;
10307
10863
  }
10308
- function getMostRecentAthenaSession(projectDir) {
10309
- const sessions = listSessions(projectDir);
10310
- return sessions[0] ?? null;
10864
+ var ansiStyles = assembleStyles();
10865
+ var ansi_styles_default = ansiStyles;
10866
+
10867
+ // node_modules/is-fullwidth-code-point/index.js
10868
+ function isFullwidthCodePoint(codePoint) {
10869
+ if (!Number.isInteger(codePoint)) {
10870
+ return false;
10871
+ }
10872
+ return isFullWidth(codePoint) || isWide(codePoint);
10873
+ }
10874
+
10875
+ // node_modules/slice-ansi/index.js
10876
+ var ESCAPES = /* @__PURE__ */ new Set([27, 155]);
10877
+ var CODE_POINT_0 = "0".codePointAt(0);
10878
+ var CODE_POINT_9 = "9".codePointAt(0);
10879
+ var MAX_ANSI_SEQUENCE_LENGTH = 19;
10880
+ var endCodesSet = /* @__PURE__ */ new Set();
10881
+ var endCodesMap = /* @__PURE__ */ new Map();
10882
+ for (const [start, end] of ansi_styles_default.codes) {
10883
+ endCodesSet.add(ansi_styles_default.color.ansi(end));
10884
+ endCodesMap.set(ansi_styles_default.color.ansi(start), ansi_styles_default.color.ansi(end));
10885
+ }
10886
+ function getEndCode(code) {
10887
+ if (endCodesSet.has(code)) {
10888
+ return code;
10889
+ }
10890
+ if (endCodesMap.has(code)) {
10891
+ return endCodesMap.get(code);
10892
+ }
10893
+ code = code.slice(2);
10894
+ if (code.includes(";")) {
10895
+ code = code[0] + "0";
10896
+ }
10897
+ const returnValue = ansi_styles_default.codes.get(Number.parseInt(code, 10));
10898
+ if (returnValue) {
10899
+ return ansi_styles_default.color.ansi(returnValue);
10900
+ }
10901
+ return ansi_styles_default.reset.open;
10902
+ }
10903
+ function findNumberIndex(string) {
10904
+ for (let index = 0; index < string.length; index++) {
10905
+ const codePoint = string.codePointAt(index);
10906
+ if (codePoint >= CODE_POINT_0 && codePoint <= CODE_POINT_9) {
10907
+ return index;
10908
+ }
10909
+ }
10910
+ return -1;
10911
+ }
10912
+ function parseAnsiCode(string, offset) {
10913
+ string = string.slice(offset, offset + MAX_ANSI_SEQUENCE_LENGTH);
10914
+ const startIndex = findNumberIndex(string);
10915
+ if (startIndex !== -1) {
10916
+ let endIndex = string.indexOf("m", startIndex);
10917
+ if (endIndex === -1) {
10918
+ endIndex = string.length;
10919
+ }
10920
+ return string.slice(0, endIndex + 1);
10921
+ }
10922
+ }
10923
+ function tokenize(string, endCharacter = Number.POSITIVE_INFINITY) {
10924
+ const returnValue = [];
10925
+ let index = 0;
10926
+ let visibleCount = 0;
10927
+ while (index < string.length) {
10928
+ const codePoint = string.codePointAt(index);
10929
+ if (ESCAPES.has(codePoint)) {
10930
+ const code = parseAnsiCode(string, index);
10931
+ if (code) {
10932
+ returnValue.push({
10933
+ type: "ansi",
10934
+ code,
10935
+ endCode: getEndCode(code)
10936
+ });
10937
+ index += code.length;
10938
+ continue;
10939
+ }
10940
+ }
10941
+ const isFullWidth2 = isFullwidthCodePoint(codePoint);
10942
+ const character = String.fromCodePoint(codePoint);
10943
+ returnValue.push({
10944
+ type: "character",
10945
+ value: character,
10946
+ isFullWidth: isFullWidth2
10947
+ });
10948
+ index += character.length;
10949
+ visibleCount += isFullWidth2 ? 2 : character.length;
10950
+ if (visibleCount >= endCharacter) {
10951
+ break;
10952
+ }
10953
+ }
10954
+ return returnValue;
10955
+ }
10956
+ function reduceAnsiCodes(codes) {
10957
+ let returnValue = [];
10958
+ for (const code of codes) {
10959
+ if (code.code === ansi_styles_default.reset.open) {
10960
+ returnValue = [];
10961
+ } else if (endCodesSet.has(code.code)) {
10962
+ returnValue = returnValue.filter((returnValueCode) => returnValueCode.endCode !== code.code);
10963
+ } else {
10964
+ returnValue = returnValue.filter((returnValueCode) => returnValueCode.endCode !== code.endCode);
10965
+ returnValue.push(code);
10966
+ }
10967
+ }
10968
+ return returnValue;
10969
+ }
10970
+ function undoAnsiCodes(codes) {
10971
+ const reduced = reduceAnsiCodes(codes);
10972
+ const endCodes = reduced.map(({ endCode }) => endCode);
10973
+ return endCodes.reverse().join("");
10974
+ }
10975
+ function sliceAnsi(string, start, end) {
10976
+ const tokens = tokenize(string, end);
10977
+ let activeCodes = [];
10978
+ let position = 0;
10979
+ let returnValue = "";
10980
+ let include = false;
10981
+ for (const token of tokens) {
10982
+ if (end !== void 0 && position >= end) {
10983
+ break;
10984
+ }
10985
+ if (token.type === "ansi") {
10986
+ activeCodes.push(token);
10987
+ if (include) {
10988
+ returnValue += token.code;
10989
+ }
10990
+ } else {
10991
+ if (!include && position >= start) {
10992
+ include = true;
10993
+ activeCodes = reduceAnsiCodes(activeCodes);
10994
+ returnValue = activeCodes.map(({ code }) => code).join("");
10995
+ }
10996
+ if (include) {
10997
+ returnValue += token.value;
10998
+ }
10999
+ position += token.isFullWidth ? 2 : token.value.length;
11000
+ }
11001
+ }
11002
+ returnValue += undoAnsiCodes(activeCodes);
11003
+ return returnValue;
11004
+ }
11005
+
11006
+ // src/shared/utils/toolNameParser.ts
11007
+ function extractFriendlyServerName(mcpServer) {
11008
+ const pluginMatch = /^plugin_[^_]+_(.+)$/.exec(mcpServer);
11009
+ if (pluginMatch) {
11010
+ return pluginMatch[1];
11011
+ }
11012
+ return mcpServer;
11013
+ }
11014
+ function parseToolName(toolName) {
11015
+ const match = /^mcp__([^_]+(?:_[^_]+)*)__(.+)$/.exec(toolName);
11016
+ if (match) {
11017
+ const mcpServer = match[1];
11018
+ const mcpAction = match[2];
11019
+ const friendlyServer = extractFriendlyServerName(mcpServer);
11020
+ return {
11021
+ displayName: mcpAction,
11022
+ isMcp: true,
11023
+ mcpServer,
11024
+ mcpAction,
11025
+ serverLabel: `${friendlyServer} (MCP)`
11026
+ };
11027
+ }
11028
+ return {
11029
+ displayName: toolName,
11030
+ isMcp: false
11031
+ };
11032
+ }
11033
+
11034
+ // src/shared/utils/format.ts
11035
+ var SIMPLE_ASCII_RE = /^[\x20-\x7E]*$/;
11036
+ var WIDTH_CACHE_MAX = 2e3;
11037
+ var WIDTH_CACHE_MAX_TEXT_LENGTH = 512;
11038
+ var SPACE_CACHE_MAX = 128;
11039
+ var widthCache = /* @__PURE__ */ new Map();
11040
+ var spaceCache = [""];
11041
+ function cachedStringWidth(text) {
11042
+ if (text.length > WIDTH_CACHE_MAX_TEXT_LENGTH) {
11043
+ return stringWidth(text);
11044
+ }
11045
+ const cached = widthCache.get(text);
11046
+ if (cached !== void 0) {
11047
+ widthCache.delete(text);
11048
+ widthCache.set(text, cached);
11049
+ return cached;
11050
+ }
11051
+ const measured = stringWidth(text);
11052
+ widthCache.set(text, measured);
11053
+ if (widthCache.size > WIDTH_CACHE_MAX) {
11054
+ const oldest = widthCache.keys().next().value;
11055
+ if (oldest !== void 0) {
11056
+ widthCache.delete(oldest);
11057
+ }
11058
+ }
11059
+ return measured;
11060
+ }
11061
+ function spaces(count) {
11062
+ if (count <= 0) return "";
11063
+ if (count < SPACE_CACHE_MAX) {
11064
+ if (count in spaceCache) {
11065
+ return spaceCache[count];
11066
+ }
11067
+ const generated = " ".repeat(count);
11068
+ spaceCache[count] = generated;
11069
+ return generated;
11070
+ }
11071
+ return " ".repeat(count);
11072
+ }
11073
+ function isSimpleAscii(text) {
11074
+ return SIMPLE_ASCII_RE.test(text);
11075
+ }
11076
+ function fitAscii(text, width) {
11077
+ if (width <= 0) return "";
11078
+ const len = text.length;
11079
+ if (len <= width) {
11080
+ const pad = width - len;
11081
+ return pad > 0 ? text + spaces(pad) : text;
11082
+ }
11083
+ if (width <= 3) return text.slice(0, width);
11084
+ return text.slice(0, width - 3) + "...";
11085
+ }
11086
+ function compactText(value, max) {
11087
+ const clean = value.replace(/\s+/g, " ").trim();
11088
+ if (max <= 0) return "";
11089
+ if (isSimpleAscii(clean)) {
11090
+ if (clean.length <= max) return clean;
11091
+ if (max <= 3) return clean.slice(0, max);
11092
+ return clean.slice(0, max - 3) + "...";
11093
+ }
11094
+ const w = cachedStringWidth(clean);
11095
+ if (w <= max) return clean;
11096
+ if (max <= 3) return sliceAnsi(clean, 0, max);
11097
+ return sliceAnsi(clean, 0, max - 3) + "...";
11098
+ }
11099
+ function fit(text, width) {
11100
+ if (isSimpleAscii(text)) {
11101
+ return fitAscii(text, width);
11102
+ }
11103
+ if (width <= 0) return "";
11104
+ const w = cachedStringWidth(text);
11105
+ if (w <= width) {
11106
+ const pad = width - w;
11107
+ return pad > 0 ? text + spaces(pad) : text;
11108
+ }
11109
+ if (width <= 3) return sliceAnsi(text, 0, width);
11110
+ return sliceAnsi(text, 0, width - 3) + "...";
11111
+ }
11112
+ function fitAnsi(text, width) {
11113
+ if (isSimpleAscii(text)) {
11114
+ return fitAscii(text, width);
11115
+ }
11116
+ if (width <= 0) return "";
11117
+ const visualWidth = cachedStringWidth(text);
11118
+ if (visualWidth <= width) {
11119
+ const pad = width - visualWidth;
11120
+ return pad > 0 ? text + spaces(pad) : text;
11121
+ }
11122
+ if (width <= 3) return sliceAnsi(text, 0, width);
11123
+ return sliceAnsi(text, 0, width - 3) + "...";
11124
+ }
11125
+ function centerAnsi(text, width) {
11126
+ if (width <= 0) return "";
11127
+ const visualWidth = cachedStringWidth(text);
11128
+ if (visualWidth >= width) return sliceAnsi(text, 0, width);
11129
+ const left = Math.floor((width - visualWidth) / 2);
11130
+ const right = width - left - visualWidth;
11131
+ return spaces(left) + text + spaces(right);
11132
+ }
11133
+ function formatClock(timestamp) {
11134
+ const d = new Date(timestamp);
11135
+ const hh = String(d.getHours()).padStart(2, "0");
11136
+ const mm = String(d.getMinutes()).padStart(2, "0");
11137
+ return `${hh}:${mm}`;
11138
+ }
11139
+ function formatRunLabel(runId) {
11140
+ if (!runId) return "R-";
11141
+ const direct = runId.match(/^(R\d+)$/i);
11142
+ if (direct) return direct[1].toUpperCase();
11143
+ const tail2 = runId.replace(/[^a-zA-Z0-9]/g, "").slice(-4);
11144
+ return `R${tail2 || "-"}`;
11145
+ }
11146
+ function actorLabel(actorId) {
11147
+ if (actorId === "user") return "USER";
11148
+ if (actorId === "agent:root") return "AGENT";
11149
+ if (actorId === "system") return "SYSTEM";
11150
+ if (actorId.startsWith("subagent:")) {
11151
+ return "SUB-AGENT";
11152
+ }
11153
+ return compactText(actorId.toUpperCase(), 12);
11154
+ }
11155
+ function summarizeValue(value) {
11156
+ if (typeof value === "string") return compactText(JSON.stringify(value), 28);
11157
+ if (typeof value === "number" || typeof value === "boolean") {
11158
+ return String(value);
11159
+ }
11160
+ if (value === null || value === void 0) return String(value);
11161
+ if (Array.isArray(value)) return `[${value.length}]`;
11162
+ if (typeof value === "object") return "{...}";
11163
+ return compactText(String(value), 20);
11164
+ }
11165
+ function summarizeToolInput(input) {
11166
+ const entries = Object.entries(input);
11167
+ const pairs = entries.slice(0, 2).map(([key, value]) => `${key}=${summarizeValue(value)}`);
11168
+ const overflow = entries.length - 2;
11169
+ if (overflow > 0) {
11170
+ pairs.push(`+${overflow}`);
11171
+ }
11172
+ return pairs.join(" ");
11173
+ }
11174
+ function shortenPath(filePath) {
11175
+ const segments = filePath.split("/").filter(Boolean);
11176
+ if (segments.length <= 2) return segments.join("/");
11177
+ return "\u2026/" + segments.slice(-2).join("/");
11178
+ }
11179
+ function compactCommandPaths(cmd) {
11180
+ return cmd.replace(
11181
+ /\/(?:[\w.@-]+\/){2,}[\w.@-]+/g,
11182
+ (match) => shortenPath(match)
11183
+ );
11184
+ }
11185
+ function shortenPathStructured(filePath) {
11186
+ const segments = filePath.split("/").filter(Boolean);
11187
+ if (segments.length === 0) return { prefix: "", filename: filePath };
11188
+ const filename = segments[segments.length - 1];
11189
+ if (segments.length === 1) return { prefix: "", filename };
11190
+ if (segments.length === 2) return { prefix: segments[0] + "/", filename };
11191
+ return { prefix: "\u2026/" + segments[segments.length - 2] + "/", filename };
11192
+ }
11193
+ var filePathExtractor = (input) => shortenPath(String(input.file_path ?? ""));
11194
+ var PRIMARY_INPUT_EXTRACTORS = {
11195
+ Read: filePathExtractor,
11196
+ Write: filePathExtractor,
11197
+ Edit: filePathExtractor,
11198
+ Bash: (input) => compactText(compactCommandPaths(String(input.command ?? "")), 96),
11199
+ Glob: (input) => String(input.pattern ?? ""),
11200
+ Grep: (input) => {
11201
+ const p = `"${String(input.pattern ?? "")}"`;
11202
+ const g = input.glob ? ` ${String(input.glob)}` : "";
11203
+ return p + g;
11204
+ },
11205
+ Task: (input) => compactText(String(input.description ?? ""), 96),
11206
+ Agent: (input) => compactText(String(input.description ?? ""), 96),
11207
+ WebSearch: (input) => `"${String(input.query ?? "")}"`,
11208
+ WebFetch: (input) => compactText(String(input.url ?? ""), 96),
11209
+ Skill: (input) => {
11210
+ const name = String(input.skill ?? "");
11211
+ const colonIdx = name.indexOf(":");
11212
+ return compactText(colonIdx >= 0 ? name.slice(colonIdx + 1) : name, 80);
11213
+ },
11214
+ NotebookEdit: (input) => {
11215
+ const path22 = String(input.notebook_path ?? "");
11216
+ return path22 ? shortenPath(path22) : "";
11217
+ },
11218
+ AskUserQuestion: (input) => {
11219
+ const questions = input.questions;
11220
+ const n = Array.isArray(questions) ? questions.length : 0;
11221
+ return `${n} question${n !== 1 ? "s" : ""}`;
11222
+ }
11223
+ };
11224
+ var eidExtractor = (input) => {
11225
+ const eid = String(input.eid ?? "");
11226
+ return eid ? `eid:${eid.slice(0, 6)}\u2026` : "";
11227
+ };
11228
+ var MCP_INPUT_EXTRACTORS = {
11229
+ navigate: (input) => {
11230
+ const url = String(input.url ?? "");
11231
+ try {
11232
+ const u = new URL(url);
11233
+ return u.hostname.replace(/^www\./, "");
11234
+ } catch {
11235
+ return compactText(url, 96);
11236
+ }
11237
+ },
11238
+ find_elements: (input) => {
11239
+ const parts = [];
11240
+ if (input.kind) parts.push(String(input.kind));
11241
+ if (input.label) parts.push(`"${String(input.label)}"`);
11242
+ if (parts.length === 0 && input.region) parts.push(String(input.region));
11243
+ return parts.join(" ") || "elements";
11244
+ },
11245
+ get_element_details: eidExtractor,
11246
+ click: eidExtractor,
11247
+ type: (input) => {
11248
+ const text = String(input.text ?? "");
11249
+ const eid = input.eid ? String(input.eid).slice(0, 5) + "\u2026" : "";
11250
+ const quoted = `"${compactText(text, 72)}"`;
11251
+ return eid ? `${quoted} \u2192 ${eid}` : quoted;
11252
+ },
11253
+ hover: eidExtractor,
11254
+ select: (input) => {
11255
+ const value = String(input.value ?? "");
11256
+ return value ? `"${compactText(value, 72)}"` : "";
11257
+ },
11258
+ press: (input) => String(input.key ?? ""),
11259
+ scroll_page: (input) => String(input.direction ?? ""),
11260
+ take_screenshot: () => "",
11261
+ close_session: () => "session",
11262
+ close_page: () => ""
11263
+ };
11264
+ function summarizeToolPrimaryInput(toolName, toolInput) {
11265
+ if (toolName in PRIMARY_INPUT_EXTRACTORS) {
11266
+ if (Object.keys(toolInput).length === 0) return "";
11267
+ return PRIMARY_INPUT_EXTRACTORS[toolName](toolInput);
11268
+ }
11269
+ const parsed = parseToolName(toolName);
11270
+ if (parsed.isMcp && parsed.mcpAction) {
11271
+ if (parsed.mcpAction in MCP_INPUT_EXTRACTORS) {
11272
+ return MCP_INPUT_EXTRACTORS[parsed.mcpAction](toolInput);
11273
+ }
11274
+ }
11275
+ if (Object.keys(toolInput).length === 0) return "";
11276
+ return summarizeToolInput(toolInput);
11277
+ }
11278
+ var MAX_INPUT_ROWS = 6;
11279
+ var CURSOR_ON = "\x1B[7m";
11280
+ var CURSOR_OFF = "\x1B[27m";
11281
+ function cursorToVisualPosition(value, cursorOffset, width) {
11282
+ if (width <= 0) return { line: 0, col: cursorOffset, totalLines: 1 };
11283
+ const segments = value.split("\n");
11284
+ let visualLine = 0;
11285
+ let globalOffset = 0;
11286
+ for (let s = 0; s < segments.length; s++) {
11287
+ const seg = segments[s];
11288
+ const segEnd = globalOffset + seg.length;
11289
+ if (cursorOffset <= segEnd) {
11290
+ const posInSeg = cursorOffset - globalOffset;
11291
+ const totalLines2 = visualLine + countSegmentVisualLines(segments, s, width);
11292
+ if (seg.length === 0) {
11293
+ return { line: visualLine, col: 0, totalLines: totalLines2 };
11294
+ }
11295
+ const lineInSeg = Math.min(
11296
+ Math.floor(posInSeg / width),
11297
+ segmentVisualLines(seg.length, width) - 1
11298
+ );
11299
+ const colInLine = posInSeg - lineInSeg * width;
11300
+ return { line: visualLine + lineInSeg, col: colInLine, totalLines: totalLines2 };
11301
+ }
11302
+ visualLine += segmentVisualLines(seg.length, width);
11303
+ globalOffset = segEnd + 1;
11304
+ }
11305
+ const totalLines = wrapText(value, width).length;
11306
+ return { line: Math.max(0, totalLines - 1), col: 0, totalLines };
11307
+ }
11308
+ function segmentVisualLines(segLen, width) {
11309
+ return segLen === 0 ? 1 : Math.ceil(segLen / width);
11310
+ }
11311
+ function countSegmentVisualLines(segments, fromIdx, width) {
11312
+ let count = 0;
11313
+ for (let i = fromIdx; i < segments.length; i++) {
11314
+ count += segmentVisualLines(segments[i].length, width);
11315
+ }
11316
+ return count;
11317
+ }
11318
+ function visualPositionToOffset(value, targetLine, targetCol, width) {
11319
+ if (width <= 0) return targetCol;
11320
+ const segments = value.split("\n");
11321
+ let visualLine = 0;
11322
+ let globalOffset = 0;
11323
+ for (let s = 0; s < segments.length; s++) {
11324
+ const seg = segments[s];
11325
+ const numWrappedLines = segmentVisualLines(seg.length, width);
11326
+ if (targetLine < visualLine + numWrappedLines) {
11327
+ const lineInSeg = targetLine - visualLine;
11328
+ const lineStart = lineInSeg * width;
11329
+ const lineLen = Math.min(width, seg.length - lineStart);
11330
+ return globalOffset + lineStart + Math.min(targetCol, lineLen);
11331
+ }
11332
+ visualLine += numWrappedLines;
11333
+ globalOffset += seg.length + 1;
11334
+ }
11335
+ return value.length;
11336
+ }
11337
+ function renderInputLines(value, cursorOffset, width, showCursor, placeholder) {
11338
+ if (width <= 0) return [""];
11339
+ if (value.length === 0) {
11340
+ if (!showCursor) return [fit(placeholder, width)];
11341
+ const cursor = `${CURSOR_ON} ${CURSOR_OFF}`;
11342
+ return [cursor + fit(placeholder, width - 1)];
11343
+ }
11344
+ if (!showCursor) {
11345
+ const rawLines2 = wrapText(value, width);
11346
+ const visible = rawLines2.slice(0, MAX_INPUT_ROWS);
11347
+ return visible.map((line) => fit(line, width));
11348
+ }
11349
+ const rawLines = wrapText(value, width);
11350
+ const { line: cursorLine, col: cursorCol } = cursorToVisualPosition(
11351
+ value,
11352
+ cursorOffset,
11353
+ width
11354
+ );
11355
+ let viewStart = 0;
11356
+ if (rawLines.length > MAX_INPUT_ROWS) {
11357
+ viewStart = Math.max(
11358
+ 0,
11359
+ Math.min(
11360
+ cursorLine - Math.floor(MAX_INPUT_ROWS / 2),
11361
+ rawLines.length - MAX_INPUT_ROWS
11362
+ )
11363
+ );
11364
+ }
11365
+ const visibleLines = rawLines.slice(viewStart, viewStart + MAX_INPUT_ROWS);
11366
+ return visibleLines.map((line, i) => {
11367
+ const globalIdx = viewStart + i;
11368
+ if (globalIdx === cursorLine) {
11369
+ const before = line.slice(0, cursorCol);
11370
+ const charAtCursor = cursorCol < line.length ? line[cursorCol] : " ";
11371
+ const after = cursorCol < line.length ? line.slice(cursorCol + 1) : "";
11372
+ const rendered = `${before}${CURSOR_ON}${charAtCursor}${CURSOR_OFF}${after}`;
11373
+ return fitAnsi(rendered, width);
11374
+ }
11375
+ return fit(line, width);
11376
+ });
11377
+ }
11378
+ function wrapText(text, width) {
11379
+ if (width <= 0) return [text];
11380
+ const lines = [];
11381
+ for (const segment of text.split("\n")) {
11382
+ if (segment.length === 0) {
11383
+ lines.push("");
11384
+ continue;
11385
+ }
11386
+ for (let i = 0; i < segment.length; i += width) {
11387
+ lines.push(segment.slice(i, i + width));
11388
+ }
11389
+ }
11390
+ return lines;
11391
+ }
11392
+ function computeInputRows(value, width) {
11393
+ if (!value || width <= 0) return 1;
11394
+ return Math.max(1, Math.min(wrapText(value, width).length, MAX_INPUT_ROWS));
11395
+ }
11396
+ function isCommandPrefix(value) {
11397
+ return value.startsWith("/") && !value.includes(" ");
11398
+ }
11399
+
11400
+ // src/shared/utils/toolResponse.ts
11401
+ function isRecord(value) {
11402
+ return typeof value === "object" && value !== null;
11403
+ }
11404
+ function formatToolResponse(response) {
11405
+ if (response == null) return "";
11406
+ if (typeof response === "string") return response.trim();
11407
+ if (Array.isArray(response)) {
11408
+ const parts = [];
11409
+ for (const block of response) {
11410
+ if (!isRecord(block)) continue;
11411
+ if (block["type"] === "image") {
11412
+ parts.push("[image]");
11413
+ } else if (typeof block["text"] === "string") {
11414
+ parts.push(block["text"]);
11415
+ }
11416
+ }
11417
+ if (parts.length > 0) return parts.join("\n").trim();
11418
+ return JSON.stringify(response, null, 2);
11419
+ }
11420
+ if (isRecord(response)) {
11421
+ if (typeof response["text"] === "string" && response["type"] === "text") {
11422
+ return response["text"].trim();
11423
+ }
11424
+ if ("content" in response && response["content"] != null) {
11425
+ return formatToolResponse(response["content"]);
11426
+ }
11427
+ return Object.entries(response).map(([key, val]) => {
11428
+ const valStr = typeof val === "string" ? val : JSON.stringify(val);
11429
+ return ` ${key}: ${valStr}`;
11430
+ }).join("\n");
11431
+ }
11432
+ return String(response);
11433
+ }
11434
+ function isBashToolResponse(response) {
11435
+ return isRecord(response) && typeof response["stdout"] === "string";
11436
+ }
11437
+
11438
+ // src/core/feed/toolSummary.ts
11439
+ function prop(obj, key) {
11440
+ if (typeof obj === "object" && obj !== null) {
11441
+ return obj[key];
11442
+ }
11443
+ return void 0;
11444
+ }
11445
+ function extractFileContent(response) {
11446
+ if (Array.isArray(response)) {
11447
+ for (const block of response) {
11448
+ const fc = prop(prop(block, "file"), "content");
11449
+ if (typeof fc === "string") return fc;
11450
+ const text = prop(block, "text");
11451
+ if (typeof text === "string") return text;
11452
+ }
11453
+ }
11454
+ return void 0;
11455
+ }
11456
+ function summarizeBash(_input, response) {
11457
+ if (isBashToolResponse(response)) {
11458
+ const exitCode = prop(response, "exitCode") ?? 0;
11459
+ const stderr = response.stderr.trim();
11460
+ const firstLine = stderr.split("\n")[0] ?? "";
11461
+ if (stderr && Number(exitCode) !== 0) {
11462
+ return `exit ${exitCode} \u2014 ${firstLine}`;
11463
+ }
11464
+ return `exit ${exitCode}`;
11465
+ }
11466
+ return "";
11467
+ }
11468
+ function summarizeRead(_input, response) {
11469
+ const content = extractFileContent(response);
11470
+ if (content) {
11471
+ const lines = content.split("\n").length;
11472
+ return `${lines} lines`;
11473
+ }
11474
+ return "";
11475
+ }
11476
+ function summarizeEdit(input, _response) {
11477
+ const oldStr = typeof input["old_string"] === "string" ? input["old_string"] : "";
11478
+ const newStr = typeof input["new_string"] === "string" ? input["new_string"] : "";
11479
+ const oldLines = oldStr.split("\n").length;
11480
+ const newLines = newStr.split("\n").length;
11481
+ return `replaced ${oldLines} \u2192 ${newLines} lines`;
11482
+ }
11483
+ function summarizeWrite(_input, _response) {
11484
+ return "";
11485
+ }
11486
+ function summarizeGlob(_input, response) {
11487
+ const filenames = prop(response, "filenames");
11488
+ if (Array.isArray(filenames))
11489
+ return `${filenames.length} ${filenames.length === 1 ? "file" : "files"}`;
11490
+ const numFiles = prop(response, "numFiles");
11491
+ if (typeof numFiles === "number")
11492
+ return `${numFiles} ${numFiles === 1 ? "file" : "files"}`;
11493
+ return "";
11494
+ }
11495
+ function summarizeGrep(_input, response) {
11496
+ if (typeof response === "string") {
11497
+ const matches = response.split("\n").filter(Boolean).length;
11498
+ return `${matches} matches`;
11499
+ }
11500
+ if (typeof response === "object" && response !== null) {
11501
+ const numMatches = prop(response, "numMatches");
11502
+ if (typeof numMatches === "number") return `${numMatches} matches`;
11503
+ const count = prop(response, "count");
11504
+ if (typeof count === "number") return `${count} matches`;
11505
+ }
11506
+ return "";
11507
+ }
11508
+ function summarizeWebSearch(_input, response) {
11509
+ const results = prop(response, "results");
11510
+ if (Array.isArray(results)) {
11511
+ let count = 0;
11512
+ for (const entry of results) {
11513
+ const content = prop(entry, "content");
11514
+ count += Array.isArray(content) ? content.length : 1;
11515
+ }
11516
+ return `${count} results`;
11517
+ }
11518
+ const actionType = prop(response, "type");
11519
+ if (typeof actionType === "string") {
11520
+ return actionType.replace(/_/g, " ");
11521
+ }
11522
+ return "";
11523
+ }
11524
+ function summarizeTask(input, _response) {
11525
+ const agentType = input["subagent_type"] ?? "agent";
11526
+ return String(agentType);
11527
+ }
11528
+ var SUMMARIZERS = {
11529
+ Bash: summarizeBash,
11530
+ Read: summarizeRead,
11531
+ Edit: summarizeEdit,
11532
+ Write: summarizeWrite,
11533
+ Glob: summarizeGlob,
11534
+ Grep: summarizeGrep,
11535
+ WebSearch: summarizeWebSearch,
11536
+ Task: summarizeTask,
11537
+ Agent: summarizeTask
11538
+ };
11539
+ function summarizeFindElements(_input, response) {
11540
+ if (typeof response === "object" && response !== null) {
11541
+ const elements = prop(response, "elements") ?? prop(response, "items");
11542
+ if (Array.isArray(elements)) return `${elements.length} found`;
11543
+ if (Array.isArray(response)) return `${response.length} found`;
11544
+ }
11545
+ return "";
11546
+ }
11547
+ var MCP_SUMMARIZERS = {
11548
+ find_elements: summarizeFindElements
11549
+ };
11550
+ function summarizeToolResult(toolName, toolInput, toolResponse, error) {
11551
+ if (error) {
11552
+ const firstLine = error.split("\n")[0] ?? error;
11553
+ return compactText(firstLine, 160);
11554
+ }
11555
+ if (toolName in SUMMARIZERS) {
11556
+ try {
11557
+ return SUMMARIZERS[toolName](toolInput, toolResponse);
11558
+ } catch {
11559
+ return "";
11560
+ }
11561
+ }
11562
+ const parsed = parseToolName(toolName);
11563
+ if (parsed.isMcp && parsed.mcpAction) {
11564
+ if (parsed.mcpAction in MCP_SUMMARIZERS) {
11565
+ try {
11566
+ return MCP_SUMMARIZERS[parsed.mcpAction](toolInput, toolResponse);
11567
+ } catch {
11568
+ return "";
11569
+ }
11570
+ }
11571
+ }
11572
+ return "";
11573
+ }
11574
+
11575
+ // src/core/feed/verbMap.ts
11576
+ var MCP_VERB_MAP = {
11577
+ navigate: "Navigate",
11578
+ find_elements: "Find",
11579
+ click: "Click",
11580
+ close_session: "Close",
11581
+ close_page: "Close",
11582
+ type: "Type",
11583
+ take_screenshot: "Screenshot",
11584
+ capture_snapshot: "Snapshot",
11585
+ scroll_page: "Scroll",
11586
+ scroll_element_into_view: "Scroll",
11587
+ hover: "Hover",
11588
+ press: "Press",
11589
+ select: "Select",
11590
+ go_back: "Back",
11591
+ go_forward: "Forward",
11592
+ reload: "Reload",
11593
+ list_pages: "Pages",
11594
+ get_element_details: "Inspect",
11595
+ get_form_understanding: "FormScan",
11596
+ get_field_context: "FieldInfo",
11597
+ ping: "Ping",
11598
+ // context7
11599
+ "resolve-library-id": "Resolve",
11600
+ "query-docs": "QueryDocs"
11601
+ };
11602
+ function resolveVerb(toolName, parsed) {
11603
+ if (!parsed.isMcp || !parsed.mcpAction) return toolName;
11604
+ const mapped = MCP_VERB_MAP[parsed.mcpAction];
11605
+ if (mapped) return mapped;
11606
+ const action = parsed.mcpAction;
11607
+ return action.charAt(0).toUpperCase() + action.slice(1).replace(/_/g, " ");
11608
+ }
11609
+
11610
+ // src/core/feed/timeline.ts
11611
+ function opCategory(op) {
11612
+ const dot = op.indexOf(".");
11613
+ return dot >= 0 ? op.slice(0, dot) : op;
11614
+ }
11615
+ function computeDuplicateActors(entries) {
11616
+ for (let i = 0; i < entries.length; i++) {
11617
+ const prev = i > 0 ? entries[i - 1] : void 0;
11618
+ const sameActor = prev !== void 0 && entries[i].actorId === prev.actorId;
11619
+ const isBreak = prev !== void 0 && opCategory(entries[i].opTag) !== opCategory(prev.opTag);
11620
+ entries[i].duplicateActor = sameActor && !isBreak;
11621
+ }
11622
+ }
11623
+ function stripMarkdownInline(text) {
11624
+ return text.replace(/#{1,6}\s+/g, "").replace(/\*\*(.+?)\*\*/g, "$1").replace(/__(.+?)__/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/`(.+?)`/g, "$1").replace(/~~(.+?)~~/g, "$1");
11625
+ }
11626
+ function firstSentence(text) {
11627
+ const nlIdx = text.indexOf("\n");
11628
+ const sentIdx = text.indexOf(". ");
11629
+ const nlEnd = nlIdx === -1 ? Infinity : nlIdx;
11630
+ const sentEnd = sentIdx === -1 ? Infinity : sentIdx + 1;
11631
+ const end = Math.min(nlEnd, sentEnd, text.length);
11632
+ return text.slice(0, end).trim();
11633
+ }
11634
+ function resolveDisplayName(toolName) {
11635
+ const parsed = parseToolName(toolName);
11636
+ if (parsed.isMcp && parsed.mcpServer && parsed.mcpAction) {
11637
+ const friendlyServer = extractFriendlyServerName(parsed.mcpServer);
11638
+ return `[${friendlyServer}] ${parsed.mcpAction}`;
11639
+ }
11640
+ return toolName;
11641
+ }
11642
+ var PATH_TOOLS = /* @__PURE__ */ new Set(["Read", "Write", "Edit", "Glob", "Grep"]);
11643
+ function withMcpServerContext(parsed, primaryInput) {
11644
+ if (!parsed.isMcp || !parsed.mcpServer) return primaryInput;
11645
+ const server = extractFriendlyServerName(parsed.mcpServer);
11646
+ if (!server) return primaryInput;
11647
+ return primaryInput ? `[${server}] ${primaryInput}` : `[${server}]`;
11648
+ }
11649
+ function formatToolSummary(toolName, toolInput, errorSuffix) {
11650
+ const parsed = parseToolName(toolName);
11651
+ const verb = resolveVerb(toolName, parsed);
11652
+ const primaryInput = withMcpServerContext(
11653
+ parsed,
11654
+ summarizeToolPrimaryInput(toolName, toolInput)
11655
+ );
11656
+ const secondary = [primaryInput, errorSuffix].filter(Boolean).join(" ");
11657
+ if (!secondary) {
11658
+ const text2 = compactText(verb, 200);
11659
+ return { text: text2, segments: [{ text: text2, role: "verb" }] };
11660
+ }
11661
+ const full = `${verb} ${secondary}`;
11662
+ const text = compactText(full, 200);
11663
+ const rest = text.slice(verb.length);
11664
+ const baseName = toolName;
11665
+ const filePath = toolInput.file_path ?? toolInput.pattern ?? toolInput.path;
11666
+ if (PATH_TOOLS.has(baseName) && typeof filePath === "string") {
11667
+ const { prefix, filename } = shortenPathStructured(filePath);
11668
+ if (prefix && filename) {
11669
+ const idx = rest.indexOf(prefix);
11670
+ if (idx >= 0) {
11671
+ const beforeFilename = rest.slice(0, idx + prefix.length);
11672
+ const afterFilename = rest.slice(idx + prefix.length + filename.length);
11673
+ return {
11674
+ text,
11675
+ segments: [
11676
+ { text: verb, role: "verb" },
11677
+ { text: beforeFilename, role: "target" },
11678
+ { text: filename, role: "filename" },
11679
+ ...afterFilename ? [{ text: afterFilename, role: "target" }] : []
11680
+ ]
11681
+ };
11682
+ }
11683
+ }
11684
+ }
11685
+ return {
11686
+ text,
11687
+ segments: [
11688
+ { text: verb, role: "verb" },
11689
+ { text: rest, role: "target" }
11690
+ ]
11691
+ };
11692
+ }
11693
+ function formatPermissionSummary(event) {
11694
+ const base = formatToolSummary(event.data.tool_name, event.data.tool_input);
11695
+ const host = event.data.network_context?.host;
11696
+ if (!host) {
11697
+ return base;
11698
+ }
11699
+ const protocol = event.data.network_context?.protocol;
11700
+ const suffix = ` \u2192 ${protocol ? `${protocol} ` : ""}${host}`;
11701
+ const text = compactText(`${base.text}${suffix}`, 200);
11702
+ return {
11703
+ text,
11704
+ segments: [...base.segments, { text: suffix, role: "target" }]
11705
+ };
11706
+ }
11707
+ function formatRunEndSummary(event) {
11708
+ const toolText = `${event.data.counters.tool_uses} tool${event.data.counters.tool_uses === 1 ? "" : "s"}`;
11709
+ const failureCount = event.data.counters.tool_failures;
11710
+ if (failureCount > 0) {
11711
+ return `${event.data.status} \xB7 ${toolText}, ${failureCount} failure${failureCount === 1 ? "" : "s"}`;
11712
+ }
11713
+ return `${event.data.status} \xB7 ${toolText}`;
11714
+ }
11715
+ function harnessSummary(event) {
11716
+ const title = event.display?.title?.trim();
11717
+ if (!title) return void 0;
11718
+ const text = compactText(title, 200);
11719
+ return { text, segments: [{ text, role: "target" }] };
11720
+ }
11721
+ function postOutcome(postEvent) {
11722
+ if (postEvent.kind === "tool.failure") {
11723
+ return summarizeToolResult(
11724
+ postEvent.data.tool_name,
11725
+ postEvent.data.tool_input,
11726
+ void 0,
11727
+ postEvent.data.error
11728
+ );
11729
+ }
11730
+ if (postEvent.kind === "tool.post") {
11731
+ return summarizeToolResult(
11732
+ postEvent.data.tool_name,
11733
+ postEvent.data.tool_input,
11734
+ postEvent.data.tool_response
11735
+ );
11736
+ }
11737
+ return void 0;
11738
+ }
11739
+ function plainSummary(text) {
11740
+ const compact = compactText(text, 200);
11741
+ return { text: compact, segments: [{ text: compact, role: "target" }] };
11742
+ }
11743
+ function dataExpansion(event) {
11744
+ return JSON.stringify(event.data, null, 2);
11745
+ }
11746
+ function rawOrDataExpansion(event) {
11747
+ return JSON.stringify(event.raw ?? event.data, null, 2);
11748
+ }
11749
+ function defaultRenderer(summarize) {
11750
+ return {
11751
+ operation: () => "event",
11752
+ label: () => "Event",
11753
+ detail: () => "\u2500",
11754
+ summary: (event) => plainSummary(summarize(event)),
11755
+ expansion: rawOrDataExpansion
11756
+ };
11757
+ }
11758
+ var sessionStart = {
11759
+ operation: () => "sess.start",
11760
+ label: () => "Sess Start",
11761
+ detail: (event) => event.data.source,
11762
+ summary: (event) => plainSummary(event.data.source),
11763
+ expansion: rawOrDataExpansion
11764
+ };
11765
+ var sessionEnd = {
11766
+ operation: () => "sess.end",
11767
+ label: () => "Sess End",
11768
+ detail: () => "\u2500",
11769
+ summary: (event) => plainSummary(event.data.reason),
11770
+ expansion: rawOrDataExpansion
11771
+ };
11772
+ var runStart = {
11773
+ operation: () => "run.start",
11774
+ label: () => "Run Start",
11775
+ detail: () => "\u2500",
11776
+ summary: (event) => plainSummary(event.data.trigger.prompt_preview || "interactive"),
11777
+ expansion: rawOrDataExpansion
11778
+ };
11779
+ var runEnd = {
11780
+ operation: (event) => {
11781
+ if (event.data.status === "completed") return "run.ok";
11782
+ if (event.data.status === "failed") return "run.fail";
11783
+ return "run.abort";
11784
+ },
11785
+ label: (event) => {
11786
+ if (event.data.status === "completed") return "Run OK";
11787
+ if (event.data.status === "failed") return "Run Fail";
11788
+ return "Run Abort";
11789
+ },
11790
+ detail: () => "\u2500",
11791
+ summary: (event) => plainSummary(formatRunEndSummary(event)),
11792
+ expansion: dataExpansion,
11793
+ isError: (event) => event.data.status !== "completed"
11794
+ };
11795
+ var userPrompt = {
11796
+ operation: () => "prompt",
11797
+ label: () => "User Prompt",
11798
+ detail: () => "\u2500",
11799
+ summary: (event) => plainSummary(event.data.prompt),
11800
+ expansion: rawOrDataExpansion
11801
+ };
11802
+ var planUpdate = {
11803
+ operation: () => "plan.upd",
11804
+ label: () => "Plan Update",
11805
+ detail: () => "plan",
11806
+ summary: (event) => {
11807
+ if (event.data.explanation) return plainSummary(event.data.explanation);
11808
+ if (event.data.plan && event.data.plan.length > 0) {
11809
+ const completed = event.data.plan.filter(
11810
+ (step) => step.status === "completed"
11811
+ ).length;
11812
+ return plainSummary(`${completed}/${event.data.plan.length} steps`);
11813
+ }
11814
+ return plainSummary(event.data.delta || "plan updated");
11815
+ },
11816
+ expansion: dataExpansion
11817
+ };
11818
+ var reasoningSummary = {
11819
+ operation: () => "reason",
11820
+ label: () => "Reasoning",
11821
+ detail: () => "summary",
11822
+ summary: (event) => plainSummary(firstSentence(stripMarkdownInline(event.data.message))),
11823
+ expansion: dataExpansion
11824
+ };
11825
+ var usageUpdate = {
11826
+ operation: () => "usage.upd",
11827
+ label: () => "Usage Update",
11828
+ detail: () => "tokens",
11829
+ summary: (event) => {
11830
+ const total = event.data.usage?.total;
11831
+ const delta = event.data.delta?.total;
11832
+ if (typeof total === "number" && typeof delta === "number") {
11833
+ return plainSummary(
11834
+ `${total.toLocaleString()} total (+${delta.toLocaleString()})`
11835
+ );
11836
+ }
11837
+ if (typeof total === "number") {
11838
+ return plainSummary(`${total.toLocaleString()} total`);
11839
+ }
11840
+ return plainSummary("usage updated");
11841
+ },
11842
+ expansion: dataExpansion
11843
+ };
11844
+ var toolDelta = {
11845
+ operation: () => "tool.call",
11846
+ label: () => "Tool Call",
11847
+ detail: (event) => resolveDisplayName(event.data.tool_name),
11848
+ summary: (event) => formatToolSummary(event.data.tool_name, event.data.tool_input),
11849
+ expansion: (event) => JSON.stringify(
11850
+ { tool: event.data.tool_name, args: event.data.tool_input },
11851
+ null,
11852
+ 2
11853
+ )
11854
+ };
11855
+ var toolPre = {
11856
+ operation: () => "tool.call",
11857
+ label: () => "Tool Call",
11858
+ detail: (event) => resolveDisplayName(event.data.tool_name),
11859
+ summary: (event) => formatToolSummary(event.data.tool_name, event.data.tool_input),
11860
+ expansion: (event) => JSON.stringify(
11861
+ { tool: event.data.tool_name, args: event.data.tool_input },
11862
+ null,
11863
+ 2
11864
+ )
11865
+ };
11866
+ var toolPost = {
11867
+ operation: () => "tool.ok",
11868
+ label: () => "Tool OK",
11869
+ detail: (event) => resolveDisplayName(event.data.tool_name),
11870
+ summary: (event) => formatToolSummary(event.data.tool_name, event.data.tool_input),
11871
+ expansion: (event) => JSON.stringify(
11872
+ {
11873
+ tool: event.data.tool_name,
11874
+ args: event.data.tool_input,
11875
+ result: event.data.tool_response
11876
+ },
11877
+ null,
11878
+ 2
11879
+ )
11880
+ };
11881
+ var toolFailure = {
11882
+ operation: () => "tool.fail",
11883
+ label: () => "Tool Fail",
11884
+ detail: (event) => resolveDisplayName(event.data.tool_name),
11885
+ summary: (event) => formatToolSummary(
11886
+ event.data.tool_name,
11887
+ event.data.tool_input,
11888
+ event.data.error
11889
+ ),
11890
+ expansion: (event) => JSON.stringify(
11891
+ {
11892
+ tool: event.data.tool_name,
11893
+ args: event.data.tool_input,
11894
+ error: event.data.error,
11895
+ interrupt: event.data.is_interrupt
11896
+ },
11897
+ null,
11898
+ 2
11899
+ ),
11900
+ isError: () => true
11901
+ };
11902
+ var permissionRequest = {
11903
+ operation: () => "perm.req",
11904
+ label: () => "Perm Request",
11905
+ detail: (event) => resolveDisplayName(event.data.tool_name),
11906
+ summary: (event) => formatPermissionSummary(event),
11907
+ expansion: (event) => JSON.stringify(
11908
+ {
11909
+ tool: event.data.tool_name,
11910
+ args: event.data.tool_input,
11911
+ suggestions: event.data.permission_suggestions
11912
+ },
11913
+ null,
11914
+ 2
11915
+ )
11916
+ };
11917
+ var permissionDecision = {
11918
+ operation: (event) => `perm.${event.data.decision_type}`,
11919
+ label: (event) => {
11920
+ switch (event.data.decision_type) {
11921
+ case "allow":
11922
+ return "Perm Allow";
11923
+ case "deny":
11924
+ return "Perm Deny";
11925
+ case "ask":
11926
+ return "Perm Ask";
11927
+ case "no_opinion":
11928
+ return "Perm Skip";
11929
+ default:
11930
+ return "Perm Decision";
11931
+ }
11932
+ },
11933
+ detail: () => "\u2500",
11934
+ summary: (event) => {
11935
+ const detail = event.data.decision_type === "deny" ? event.data.message || event.data.reason : event.data.reason;
11936
+ return plainSummary(detail || event.data.decision_type);
11937
+ },
11938
+ expansion: rawOrDataExpansion,
11939
+ isError: (event) => event.data.decision_type === "deny"
11940
+ };
11941
+ var stopRequest = {
11942
+ operation: () => "stop.req",
11943
+ label: () => "Stop Request",
11944
+ detail: () => "\u2500",
11945
+ summary: (event) => plainSummary(
11946
+ event.data.stop_hook_active ? "Stop hook active" : "Stop hook inactive"
11947
+ ),
11948
+ expansion: rawOrDataExpansion
11949
+ };
11950
+ var stopDecision = {
11951
+ operation: (event) => `stop.${event.data.decision_type}`,
11952
+ label: (event) => {
11953
+ switch (event.data.decision_type) {
11954
+ case "block":
11955
+ return "Stop Block";
11956
+ case "allow":
11957
+ return "Stop Allow";
11958
+ case "no_opinion":
11959
+ return "Stop Skip";
11960
+ default:
11961
+ return "Stop Decision";
11962
+ }
11963
+ },
11964
+ detail: () => "\u2500",
11965
+ summary: (event) => plainSummary(event.data.reason || event.data.decision_type),
11966
+ expansion: rawOrDataExpansion,
11967
+ isError: (event) => event.data.decision_type === "block"
11968
+ };
11969
+ var subagentStart = {
11970
+ operation: () => "sub.start",
11971
+ label: () => "Sub Start",
11972
+ detail: (event) => event.data.agent_type,
11973
+ summary: (event) => {
11974
+ const text = compactText(
11975
+ event.data.description?.trim() || `id:${event.data.agent_id}`,
11976
+ 200
11977
+ );
11978
+ return { text, segments: [{ text, role: "target" }] };
11979
+ },
11980
+ expansion: rawOrDataExpansion
11981
+ };
11982
+ var subagentStop = {
11983
+ operation: () => "sub.stop",
11984
+ label: () => "Sub Stop",
11985
+ detail: (event) => event.data.agent_type,
11986
+ summary: (event) => {
11987
+ const text = compactText(
11988
+ event.data.description?.trim() || `id:${event.data.agent_id}`,
11989
+ 200
11990
+ );
11991
+ return { text, segments: [{ text, role: "target" }] };
11992
+ },
11993
+ expansion: dataExpansion
11994
+ };
11995
+ var notification = {
11996
+ operation: () => "notify",
11997
+ label: () => "Notify",
11998
+ detail: () => "\u2500",
11999
+ summary: (event) => plainSummary(stripMarkdownInline(event.data.message)),
12000
+ expansion: rawOrDataExpansion
12001
+ };
12002
+ var runtimeError = {
12003
+ operation: () => "error",
12004
+ label: () => "Error",
12005
+ detail: () => "\u2500",
12006
+ summary: (event) => plainSummary(stripMarkdownInline(event.data.message)),
12007
+ expansion: dataExpansion,
12008
+ isError: () => true
12009
+ };
12010
+ var threadStatus = {
12011
+ operation: () => "thread",
12012
+ label: () => "Thread",
12013
+ detail: (event) => event.data.status_type ?? "status",
12014
+ summary: (event) => plainSummary(event.data.message),
12015
+ expansion: dataExpansion
12016
+ };
12017
+ var turnDiff = {
12018
+ operation: () => "diff",
12019
+ label: () => "Diff",
12020
+ detail: () => "\u2500",
12021
+ summary: (event) => plainSummary(event.data.message),
12022
+ expansion: dataExpansion
12023
+ };
12024
+ var serverRequestResolved = {
12025
+ operation: () => "req.done",
12026
+ label: () => "Request",
12027
+ detail: (event) => event.data.request_id ?? "request",
12028
+ summary: (event) => plainSummary(event.data.message),
12029
+ expansion: dataExpansion
12030
+ };
12031
+ var webSearch = {
12032
+ operation: () => "web.search",
12033
+ label: () => "Web Search",
12034
+ detail: (event) => event.data.action_type ?? event.data.phase,
12035
+ summary: (event) => plainSummary(event.data.message),
12036
+ expansion: dataExpansion
12037
+ };
12038
+ var reviewStatus = {
12039
+ operation: () => "review",
12040
+ label: () => "Review",
12041
+ detail: (event) => event.data.phase,
12042
+ summary: (event) => plainSummary(event.data.message),
12043
+ expansion: dataExpansion
12044
+ };
12045
+ var imageView = {
12046
+ operation: () => "image",
12047
+ label: () => "Image",
12048
+ detail: (event) => event.data.path ?? "image",
12049
+ summary: (event) => plainSummary(event.data.message),
12050
+ expansion: dataExpansion
12051
+ };
12052
+ var contextCompaction = {
12053
+ operation: () => "compact",
12054
+ label: () => "Compaction",
12055
+ detail: (event) => event.data.phase,
12056
+ summary: (event) => plainSummary(event.data.message),
12057
+ expansion: dataExpansion
12058
+ };
12059
+ var mcpProgress = {
12060
+ operation: () => "mcp.prog",
12061
+ label: () => "MCP Progress",
12062
+ detail: () => "\u2500",
12063
+ summary: (event) => plainSummary(event.data.message),
12064
+ expansion: dataExpansion
12065
+ };
12066
+ var terminalInput = {
12067
+ operation: () => "term.in",
12068
+ label: () => "Terminal In",
12069
+ detail: () => "\u2500",
12070
+ summary: (event) => plainSummary(event.data.message),
12071
+ expansion: dataExpansion
12072
+ };
12073
+ var skillsChanged = {
12074
+ operation: () => "skills",
12075
+ label: () => "Skills",
12076
+ detail: () => "\u2500",
12077
+ summary: (event) => plainSummary(event.data.message),
12078
+ expansion: dataExpansion
12079
+ };
12080
+ var skillsLoaded = {
12081
+ operation: () => "skills",
12082
+ label: () => "Skills",
12083
+ detail: () => "\u2500",
12084
+ summary: (event) => plainSummary(event.data.message),
12085
+ expansion: dataExpansion
12086
+ };
12087
+ var compactPre = {
12088
+ operation: () => "compact",
12089
+ label: () => "Compact",
12090
+ detail: () => "\u2500",
12091
+ summary: (event) => plainSummary(event.data.trigger),
12092
+ expansion: dataExpansion
12093
+ };
12094
+ var setup = {
12095
+ operation: () => "setup",
12096
+ label: () => "Setup",
12097
+ detail: () => "\u2500",
12098
+ summary: (event) => plainSummary(event.data.trigger),
12099
+ expansion: rawOrDataExpansion
12100
+ };
12101
+ var unknownHook = {
12102
+ operation: () => "unknown",
12103
+ label: () => "Unknown",
12104
+ detail: () => "\u2500",
12105
+ summary: (event) => plainSummary(event.data.hook_event_name),
12106
+ expansion: rawOrDataExpansion
12107
+ };
12108
+ var todoAdd = {
12109
+ operation: () => "todo.add",
12110
+ label: () => "Todo Add",
12111
+ detail: (event) => (event.data.priority ?? "p1").toUpperCase(),
12112
+ summary: (event) => plainSummary(
12113
+ `${event.data.priority?.toUpperCase() ?? "P1"} ${event.data.text}`
12114
+ ),
12115
+ expansion: rawOrDataExpansion
12116
+ };
12117
+ var todoUpdate = {
12118
+ operation: () => "todo.upd",
12119
+ label: () => "Todo Update",
12120
+ detail: (event) => event.data.todo_id,
12121
+ summary: (event) => {
12122
+ const patchFields = Object.keys(event.data.patch);
12123
+ return plainSummary(
12124
+ `${event.data.todo_id} ${patchFields.length > 0 ? patchFields.join(",") : "update"}`
12125
+ );
12126
+ },
12127
+ expansion: rawOrDataExpansion
12128
+ };
12129
+ var todoDone = {
12130
+ operation: () => "todo.done",
12131
+ label: () => "Todo Done",
12132
+ detail: (event) => event.data.todo_id,
12133
+ summary: (event) => plainSummary(`${event.data.todo_id} ${event.data.reason || "done"}`),
12134
+ expansion: rawOrDataExpansion
12135
+ };
12136
+ var agentMessage = {
12137
+ operation: () => "agent.msg",
12138
+ label: () => "Agent Msg",
12139
+ detail: () => "\u2500",
12140
+ summary: (event) => {
12141
+ const text = compactText(
12142
+ firstSentence(stripMarkdownInline(event.data.message)),
12143
+ 200
12144
+ );
12145
+ return { text, segments: [{ text, role: "plain" }] };
12146
+ },
12147
+ expansion: rawOrDataExpansion
12148
+ };
12149
+ var teammateIdle = {
12150
+ operation: () => "tm.idle",
12151
+ label: () => "Team Idle",
12152
+ detail: () => "\u2500",
12153
+ summary: (event) => plainSummary(`${event.data.teammate_name} idle in ${event.data.team_name}`),
12154
+ expansion: rawOrDataExpansion
12155
+ };
12156
+ var taskCompleted = {
12157
+ operation: () => "task.ok",
12158
+ label: () => "Task OK",
12159
+ detail: () => "\u2500",
12160
+ summary: (event) => plainSummary(event.data.task_subject),
12161
+ expansion: rawOrDataExpansion
12162
+ };
12163
+ var configChange = {
12164
+ operation: () => "cfg.chg",
12165
+ label: () => "Config Chg",
12166
+ detail: (event) => event.data.source,
12167
+ summary: (event) => plainSummary(
12168
+ `${event.data.source}${event.data.file_path ? ` ${event.data.file_path}` : ""}`
12169
+ ),
12170
+ expansion: rawOrDataExpansion
12171
+ };
12172
+ var compactPost = defaultRenderer(
12173
+ (event) => `compacted (${event.data.trigger})`
12174
+ );
12175
+ var taskCreated = defaultRenderer(
12176
+ (event) => event.data.task_subject
12177
+ );
12178
+ var cwdChanged = defaultRenderer(
12179
+ (event) => `cwd \u2192 ${event.data.cwd}`
12180
+ );
12181
+ var fileChanged = defaultRenderer(
12182
+ (event) => `changed ${event.data.file_path}`
12183
+ );
12184
+ var instructionsLoaded = defaultRenderer(
12185
+ (event) => `${event.data.memory_type ?? "instructions"} ${event.data.file_path}`
12186
+ );
12187
+ var worktreeCreate = defaultRenderer(
12188
+ (event) => `created ${event.data.worktree_path}`
12189
+ );
12190
+ var worktreeRemove = defaultRenderer(
12191
+ (event) => `removed ${event.data.worktree_path}`
12192
+ );
12193
+ var stopFailure = defaultRenderer(
12194
+ (event) => `${event.data.error_type}${event.data.error_message ? `: ${event.data.error_message}` : ""}`
12195
+ );
12196
+ var permissionDenied = defaultRenderer(
12197
+ (event) => `${event.data.tool_name}${event.data.reason ? `: ${event.data.reason}` : ""}`
12198
+ );
12199
+ var elicitationRequest = defaultRenderer((event) => `elicitation from ${event.data.mcp_server}`);
12200
+ var elicitationResult = defaultRenderer(
12201
+ (event) => `${event.data.mcp_server} \u2192 ${event.data.action}`
12202
+ );
12203
+ var channelPermissionRelayed = defaultRenderer(
12204
+ (event) => `${event.data.channel_name}: ${event.data.tool_name} (${event.data.channel_request_id})`
12205
+ );
12206
+ var channelPermissionResolved = defaultRenderer(
12207
+ (event) => `${event.data.channel_name} ${event.data.source} ${event.data.tool_name}`
12208
+ );
12209
+ var channelQuestionRelayed = defaultRenderer(
12210
+ (event) => `${event.data.channel_name}: ${event.data.title} (${event.data.channel_request_id})`
12211
+ );
12212
+ var channelQuestionResolved = defaultRenderer(
12213
+ (event) => `${event.data.channel_name || event.data.source} ${event.data.source} ${event.data.title}`
12214
+ );
12215
+ var channelChatInbound = defaultRenderer((event) => `${event.data.channel_name}: ${event.data.content}`);
12216
+ var channelChatOutbound = defaultRenderer(
12217
+ (event) => `${event.data.channel_name} \u2192 ${event.data.target_peer_id}: ${event.data.content}`
12218
+ );
12219
+ var gatewayFunctionInvoked = defaultRenderer(
12220
+ (event) => `fn invoked: ${event.data.function_name} (${event.data.caller_kind})`
12221
+ );
12222
+ var gatewayFunctionCompleted = defaultRenderer(
12223
+ (event) => `fn ok: ${event.data.function_name} ${event.data.duration_ms}ms`
12224
+ );
12225
+ var gatewayFunctionFailed = defaultRenderer(
12226
+ (event) => `fn ${event.data.reason}: ${event.data.function_name} \u2014 ${event.data.error_message}`
12227
+ );
12228
+ var artifactsManifest = defaultRenderer(
12229
+ (event) => {
12230
+ const manifest = event.data.manifest;
12231
+ const count = Array.isArray(manifest.entries) ? manifest.entries.length : 0;
12232
+ return `artifacts manifest (${count} item${count === 1 ? "" : "s"})`;
12233
+ }
12234
+ );
12235
+ var RENDERERS = {
12236
+ "session.start": sessionStart,
12237
+ "session.end": sessionEnd,
12238
+ "run.start": runStart,
12239
+ "run.end": runEnd,
12240
+ "user.prompt": userPrompt,
12241
+ "plan.update": planUpdate,
12242
+ "reasoning.summary": reasoningSummary,
12243
+ "usage.update": usageUpdate,
12244
+ "tool.delta": toolDelta,
12245
+ "tool.pre": toolPre,
12246
+ "tool.post": toolPost,
12247
+ "tool.failure": toolFailure,
12248
+ "permission.request": permissionRequest,
12249
+ "permission.decision": permissionDecision,
12250
+ "stop.request": stopRequest,
12251
+ "stop.decision": stopDecision,
12252
+ "subagent.start": subagentStart,
12253
+ "subagent.stop": subagentStop,
12254
+ notification,
12255
+ "runtime.error": runtimeError,
12256
+ "thread.status": threadStatus,
12257
+ "turn.diff": turnDiff,
12258
+ "server.request.resolved": serverRequestResolved,
12259
+ "web.search": webSearch,
12260
+ "review.status": reviewStatus,
12261
+ "image.view": imageView,
12262
+ "context.compaction": contextCompaction,
12263
+ "mcp.progress": mcpProgress,
12264
+ "terminal.input": terminalInput,
12265
+ "skills.changed": skillsChanged,
12266
+ "skills.loaded": skillsLoaded,
12267
+ "compact.pre": compactPre,
12268
+ "compact.post": compactPost,
12269
+ setup,
12270
+ "unknown.hook": unknownHook,
12271
+ "todo.add": todoAdd,
12272
+ "todo.update": todoUpdate,
12273
+ "todo.done": todoDone,
12274
+ "agent.message": agentMessage,
12275
+ "teammate.idle": teammateIdle,
12276
+ "task.created": taskCreated,
12277
+ "task.completed": taskCompleted,
12278
+ "config.change": configChange,
12279
+ "cwd.changed": cwdChanged,
12280
+ "file.changed": fileChanged,
12281
+ "instructions.loaded": instructionsLoaded,
12282
+ "worktree.create": worktreeCreate,
12283
+ "worktree.remove": worktreeRemove,
12284
+ "stop.failure": stopFailure,
12285
+ "permission.denied": permissionDenied,
12286
+ "elicitation.request": elicitationRequest,
12287
+ "elicitation.result": elicitationResult,
12288
+ "channel.permission.relayed": channelPermissionRelayed,
12289
+ "channel.permission.resolved": channelPermissionResolved,
12290
+ "channel.question.relayed": channelQuestionRelayed,
12291
+ "channel.question.resolved": channelQuestionResolved,
12292
+ "channel.chat.inbound": channelChatInbound,
12293
+ "channel.chat.outbound": channelChatOutbound,
12294
+ "gateway.function.invoked": gatewayFunctionInvoked,
12295
+ "gateway.function.completed": gatewayFunctionCompleted,
12296
+ "gateway.function.failed": gatewayFunctionFailed,
12297
+ "artifacts.manifest": artifactsManifest
12298
+ };
12299
+ function rendererFor(event) {
12300
+ return RENDERERS[event.kind];
12301
+ }
12302
+ function eventOperation(event) {
12303
+ return rendererFor(event).operation(event);
12304
+ }
12305
+ function eventLabel(event) {
12306
+ return rendererFor(event).label(event);
12307
+ }
12308
+ function eventSummary(event) {
12309
+ const harness = harnessSummary(event);
12310
+ if (harness) return harness;
12311
+ return rendererFor(event).summary(event);
12312
+ }
12313
+ function expansionForEvent(event) {
12314
+ return rendererFor(event).expansion(event);
12315
+ }
12316
+ function isEventError(event) {
12317
+ if (event.level === "error") return true;
12318
+ const renderer = rendererFor(event);
12319
+ return renderer.isError?.(event) ?? false;
12320
+ }
12321
+ function isEventExpandable(event) {
12322
+ void event;
12323
+ return true;
12324
+ }
12325
+ var toolPairOk = {
12326
+ operation: () => "tool.ok",
12327
+ label: () => "Tool OK",
12328
+ summary: (pre, post) => buildMergedToolSummary(pre, post)
12329
+ };
12330
+ var toolPairFail = {
12331
+ operation: () => "tool.fail",
12332
+ label: () => "Tool Fail",
12333
+ summary: (pre, post) => buildMergedToolSummary(pre, post)
12334
+ };
12335
+ var TOOL_PAIRS = {
12336
+ "tool.post": toolPairOk,
12337
+ "tool.failure": toolPairFail
12338
+ };
12339
+ function buildMergedToolSummary(event, postEvent) {
12340
+ const harness = harnessSummary(event) ?? harnessSummary(postEvent);
12341
+ if (harness) {
12342
+ return {
12343
+ ...harness,
12344
+ outcome: postOutcome(postEvent),
12345
+ outcomeZero: false
12346
+ };
12347
+ }
12348
+ const toolName = event.data.tool_name;
12349
+ const preInput = event.data.tool_input;
12350
+ const postInput = postEvent.kind === "tool.post" || postEvent.kind === "tool.failure" ? postEvent.data.tool_input : void 0;
12351
+ const toolInput = postInput && Object.keys(preInput).every((k) => preInput[k] == null) ? postInput : preInput;
12352
+ const parsed = parseToolName(toolName);
12353
+ const name = resolveVerb(toolName, parsed);
12354
+ const primaryInput = withMcpServerContext(
12355
+ parsed,
12356
+ summarizeToolPrimaryInput(toolName, toolInput)
12357
+ );
12358
+ let resultText;
12359
+ if (postEvent.kind === "tool.failure") {
12360
+ resultText = summarizeToolResult(
12361
+ toolName,
12362
+ toolInput,
12363
+ void 0,
12364
+ postEvent.data.error
12365
+ );
12366
+ } else if (postEvent.kind === "tool.post") {
12367
+ resultText = summarizeToolResult(
12368
+ toolName,
12369
+ toolInput,
12370
+ postEvent.data.tool_response
12371
+ );
12372
+ } else {
12373
+ return eventSummary(event);
12374
+ }
12375
+ const prefix = primaryInput ? `${name} ${primaryInput}` : name;
12376
+ const prefixText = compactText(prefix, 200);
12377
+ const segments = primaryInput ? [
12378
+ { text: name, role: "verb" },
12379
+ { text: prefixText.slice(name.length), role: "target" }
12380
+ ] : [{ text: prefixText, role: "verb" }];
12381
+ if (!resultText) {
12382
+ return { text: prefixText, segments };
12383
+ }
12384
+ return {
12385
+ text: prefixText,
12386
+ segments,
12387
+ outcome: resultText,
12388
+ outcomeZero: /^0\s/.test(resultText)
12389
+ };
12390
+ }
12391
+ function mergedEventOperation(event, postEvent) {
12392
+ if (!postEvent) return eventOperation(event);
12393
+ const pair = TOOL_PAIRS[postEvent.kind];
12394
+ if (!pair) return eventOperation(event);
12395
+ return pair.operation(event, postEvent);
12396
+ }
12397
+ function mergedEventLabel(event, postEvent) {
12398
+ if (!postEvent) return eventLabel(event);
12399
+ const pair = TOOL_PAIRS[postEvent.kind];
12400
+ if (!pair) return eventLabel(event);
12401
+ return pair.label(event, postEvent);
12402
+ }
12403
+ function mergedEventSummary(event, postEvent) {
12404
+ if (!postEvent) return eventSummary(event);
12405
+ if (event.kind !== "tool.pre" && event.kind !== "permission.request") {
12406
+ return eventSummary(event);
12407
+ }
12408
+ const pair = TOOL_PAIRS[postEvent.kind];
12409
+ if (!pair) return eventSummary(event);
12410
+ return pair.summary(event, postEvent);
12411
+ }
12412
+ var VERBOSE_ONLY_KINDS = /* @__PURE__ */ new Set([
12413
+ "session.start",
12414
+ "session.end",
12415
+ "run.start",
12416
+ "run.end",
12417
+ "unknown.hook",
12418
+ "compact.pre",
12419
+ "config.change",
12420
+ "instructions.loaded",
12421
+ "worktree.create",
12422
+ "worktree.remove",
12423
+ "turn.diff",
12424
+ "usage.update",
12425
+ "reasoning.summary"
12426
+ ]);
12427
+ function toRunStatus(event) {
12428
+ switch (event.data.status) {
12429
+ case "completed":
12430
+ return "SUCCEEDED";
12431
+ case "failed":
12432
+ return "FAILED";
12433
+ case "aborted":
12434
+ return "CANCELLED";
12435
+ }
12436
+ }
12437
+
12438
+ // src/core/feed/toolDisplay.ts
12439
+ function prop2(obj, key) {
12440
+ if (typeof obj === "object" && obj !== null) {
12441
+ return obj[key];
12442
+ }
12443
+ return void 0;
12444
+ }
12445
+ function truncate2(text, max) {
12446
+ if (text.length <= max) return text;
12447
+ if (max <= 3) return text.slice(0, max);
12448
+ return text.slice(0, max - 1) + "\u2026";
12449
+ }
12450
+ function extractDomain(url) {
12451
+ if (typeof url !== "string") return "";
12452
+ try {
12453
+ const u = new URL(url);
12454
+ return u.hostname.replace(/^www\./, "");
12455
+ } catch {
12456
+ return compactText(String(url), 40);
12457
+ }
12458
+ }
12459
+ function filePathSegments(input) {
12460
+ const path22 = prop2(input, "file_path") ?? prop2(input, "notebook_path") ?? "";
12461
+ if (typeof path22 !== "string" || !path22) return [];
12462
+ const { prefix, filename } = shortenPathStructured(path22);
12463
+ if (prefix && filename) {
12464
+ return [
12465
+ { text: prefix, role: "target" },
12466
+ { text: filename, role: "filename" }
12467
+ ];
12468
+ }
12469
+ return [{ text: filename || path22, role: "filename" }];
12470
+ }
12471
+ function grepSegments(input) {
12472
+ const pattern = String(prop2(input, "pattern") ?? "");
12473
+ const glob = prop2(input, "glob");
12474
+ const parts = `"${pattern}"${glob ? ` ${String(glob)}` : ""}`;
12475
+ return [{ text: parts, role: "target" }];
12476
+ }
12477
+ function commandSegments(input) {
12478
+ const cmd = String(prop2(input, "command") ?? "");
12479
+ return [{ text: compactText(compactCommandPaths(cmd), 50), role: "target" }];
12480
+ }
12481
+ function countOutcome(output, label) {
12482
+ if (Array.isArray(output)) {
12483
+ return { text: `${output.length} ${label}`, zero: output.length === 0 };
12484
+ }
12485
+ if (typeof output === "object" && output !== null) {
12486
+ const filenames = prop2(output, "filenames");
12487
+ if (Array.isArray(filenames)) {
12488
+ return {
12489
+ text: `${filenames.length} ${label}`,
12490
+ zero: filenames.length === 0
12491
+ };
12492
+ }
12493
+ const numFiles = prop2(output, "numFiles");
12494
+ if (typeof numFiles === "number") {
12495
+ return { text: `${numFiles} ${label}`, zero: numFiles === 0 };
12496
+ }
12497
+ const numMatches = prop2(output, "numMatches");
12498
+ if (typeof numMatches === "number") {
12499
+ return { text: `${numMatches} ${label}`, zero: numMatches === 0 };
12500
+ }
12501
+ const count = prop2(output, "count");
12502
+ if (typeof count === "number") {
12503
+ return { text: `${count} ${label}`, zero: count === 0 };
12504
+ }
12505
+ }
12506
+ if (typeof output === "string") {
12507
+ const lines = output.split("\n").filter(Boolean).length;
12508
+ return { text: `${lines} ${label}`, zero: lines === 0 };
12509
+ }
12510
+ return void 0;
12511
+ }
12512
+ function exitCodeOutcome(output) {
12513
+ if (isBashToolResponse(output)) {
12514
+ const code = prop2(output, "exitCode") ?? 0;
12515
+ const stderr = output.stderr.trim();
12516
+ const firstLine = stderr.split("\n")[0] ?? "";
12517
+ if (stderr && Number(code) !== 0) {
12518
+ return { text: `exit ${code} \u2014 ${truncate2(firstLine, 30)}`, zero: false };
12519
+ }
12520
+ return { text: `exit ${code}`, zero: false };
12521
+ }
12522
+ return void 0;
12523
+ }
12524
+ function webSearchOutcome(output) {
12525
+ const results = prop2(output, "results");
12526
+ if (Array.isArray(results)) {
12527
+ let count = 0;
12528
+ for (const entry of results) {
12529
+ const content = prop2(entry, "content");
12530
+ count += Array.isArray(content) ? content.length : 1;
12531
+ }
12532
+ return { text: `${count} results`, zero: count === 0 };
12533
+ }
12534
+ const actionType = prop2(output, "type");
12535
+ if (typeof actionType === "string") {
12536
+ return { text: actionType.replace(/_/g, " "), zero: false };
12537
+ }
12538
+ return void 0;
12539
+ }
12540
+ function taskOutputOutcome(output) {
12541
+ if (typeof output === "string" && output.trim()) {
12542
+ return { text: truncate2(output.trim(), 30), zero: false };
12543
+ }
12544
+ return void 0;
12545
+ }
12546
+ function eidExtractor2(input) {
12547
+ const eid = String(prop2(input, "eid") ?? "");
12548
+ return eid ? [{ text: `eid:${eid.slice(0, 6)}\u2026`, role: "target" }] : [];
12549
+ }
12550
+ function eidOrLabelExtractor(input) {
12551
+ const label = prop2(input, "label");
12552
+ if (typeof label === "string" && label) {
12553
+ return [{ text: `"${truncate2(label, 20)}"`, role: "target" }];
12554
+ }
12555
+ return eidExtractor2(input);
12556
+ }
12557
+ function findDetailsExtractor(input) {
12558
+ const parts = [];
12559
+ const kind = prop2(input, "kind");
12560
+ if (kind) parts.push(String(kind));
12561
+ const label = prop2(input, "label");
12562
+ if (label) parts.push(`"${String(label)}"`);
12563
+ if (parts.length === 0) {
12564
+ const region = prop2(input, "region");
12565
+ if (region) parts.push(String(region));
12566
+ }
12567
+ return parts.length > 0 ? [{ text: parts.join(" "), role: "target" }] : [{ text: "elements", role: "target" }];
12568
+ }
12569
+ function typeDetailsExtractor(input) {
12570
+ const text = String(prop2(input, "text") ?? "");
12571
+ const eid = prop2(input, "eid");
12572
+ const quoted = `"${truncate2(text, 30)}"`;
12573
+ if (eid) {
12574
+ return [{ text: `${quoted} \u2192 ${String(eid).slice(0, 5)}\u2026`, role: "target" }];
12575
+ }
12576
+ return [{ text: quoted, role: "target" }];
12577
+ }
12578
+ function scrollDetailsExtractor(input) {
12579
+ const dir = String(prop2(input, "direction") ?? "");
12580
+ const amount = prop2(input, "amount");
12581
+ const text = amount ? `${dir} ${amount}px` : dir;
12582
+ return text ? [{ text, role: "target" }] : [];
12583
+ }
12584
+ function tabRefExtractor(input) {
12585
+ const pageId = prop2(input, "page_id");
12586
+ return pageId ? [{ text: `page:${String(pageId).slice(0, 6)}`, role: "target" }] : [];
12587
+ }
12588
+ function foundCountOutcome(output) {
12589
+ if (Array.isArray(output)) {
12590
+ return { text: `${output.length} found`, zero: output.length === 0 };
12591
+ }
12592
+ if (typeof output === "object" && output !== null) {
12593
+ const elements = prop2(output, "elements") ?? prop2(output, "items");
12594
+ if (Array.isArray(elements)) {
12595
+ return { text: `${elements.length} found`, zero: elements.length === 0 };
12596
+ }
12597
+ }
12598
+ return void 0;
12599
+ }
12600
+ function tabCountOutcome(output) {
12601
+ if (Array.isArray(output)) {
12602
+ return { text: `${output.length} tabs`, zero: output.length === 0 };
12603
+ }
12604
+ const pages = prop2(output, "pages");
12605
+ if (Array.isArray(pages)) {
12606
+ return { text: `${pages.length} tabs`, zero: pages.length === 0 };
12607
+ }
12608
+ return void 0;
12609
+ }
12610
+ function formCountOutcome(output) {
12611
+ const fields = prop2(output, "fields");
12612
+ if (Array.isArray(fields)) {
12613
+ return { text: `${fields.length} fields`, zero: fields.length === 0 };
12614
+ }
12615
+ return void 0;
12616
+ }
12617
+ function pingOutcome(output) {
12618
+ if (output) return { text: "ok", zero: false };
12619
+ return void 0;
12620
+ }
12621
+ var KNOWN_TOOL_DISPLAY = new Map([
12622
+ // ── Core file tools ──
12623
+ [
12624
+ "Read",
12625
+ {
12626
+ display: "Read",
12627
+ extractDetails: filePathSegments,
12628
+ extractOutcome: () => void 0
12629
+ }
12630
+ ],
12631
+ [
12632
+ "Write",
12633
+ {
12634
+ display: "Write",
12635
+ extractDetails: filePathSegments,
12636
+ extractOutcome: () => void 0
12637
+ }
12638
+ ],
12639
+ [
12640
+ "Edit",
12641
+ {
12642
+ display: "Edit",
12643
+ extractDetails: filePathSegments,
12644
+ extractOutcome: () => void 0
12645
+ }
12646
+ ],
12647
+ [
12648
+ "Glob",
12649
+ {
12650
+ display: "Glob",
12651
+ extractDetails: (input) => [
12652
+ { text: String(prop2(input, "pattern") ?? ""), role: "target" }
12653
+ ],
12654
+ extractOutcome: (output) => countOutcome(output, "files")
12655
+ }
12656
+ ],
12657
+ [
12658
+ "Grep",
12659
+ {
12660
+ display: "Grep",
12661
+ extractDetails: grepSegments,
12662
+ extractOutcome: (output) => countOutcome(output, "matches")
12663
+ }
12664
+ ],
12665
+ [
12666
+ "Bash",
12667
+ {
12668
+ display: "Bash",
12669
+ extractDetails: commandSegments,
12670
+ extractOutcome: exitCodeOutcome
12671
+ }
12672
+ ],
12673
+ // ── Web tools ──
12674
+ [
12675
+ "WebFetch",
12676
+ {
12677
+ display: "WebFetch",
12678
+ extractDetails: (input) => [
12679
+ { text: extractDomain(prop2(input, "url")), role: "target" }
12680
+ ],
12681
+ extractOutcome: () => void 0
12682
+ }
12683
+ ],
12684
+ [
12685
+ "WebSearch",
12686
+ {
12687
+ display: "WebSearch",
12688
+ extractDetails: (input) => [
12689
+ {
12690
+ text: truncate2(String(prop2(input, "query") ?? ""), 40),
12691
+ role: "target"
12692
+ }
12693
+ ],
12694
+ extractOutcome: webSearchOutcome
12695
+ }
12696
+ ],
12697
+ [
12698
+ "NotebookEdit",
12699
+ {
12700
+ display: "Notebook",
12701
+ extractDetails: filePathSegments,
12702
+ extractOutcome: () => void 0
12703
+ }
12704
+ ],
12705
+ // ── Agent & task tools ──
12706
+ ...["Task", "Agent"].map(
12707
+ (name) => [
12708
+ name,
12709
+ {
12710
+ display: "Task",
12711
+ extractDetails: (input) => [
12712
+ {
12713
+ text: truncate2(String(prop2(input, "description") ?? ""), 50),
12714
+ role: "plain"
12715
+ }
12716
+ ],
12717
+ extractOutcome: (output) => {
12718
+ const agentType = prop2(output, "subagent_type");
12719
+ return agentType ? { text: String(agentType), zero: false } : void 0;
12720
+ }
12721
+ }
12722
+ ]
12723
+ ),
12724
+ [
12725
+ "TaskOutput",
12726
+ {
12727
+ display: "TaskOut",
12728
+ extractDetails: (input) => [
12729
+ { text: String(prop2(input, "task_id") ?? ""), role: "target" }
12730
+ ],
12731
+ extractOutcome: taskOutputOutcome
12732
+ }
12733
+ ],
12734
+ [
12735
+ "TaskStop",
12736
+ {
12737
+ display: "TaskStop",
12738
+ extractDetails: (input) => [
12739
+ { text: String(prop2(input, "task_id") ?? ""), role: "target" }
12740
+ ],
12741
+ extractOutcome: () => ({ text: "stopped", zero: false })
12742
+ }
12743
+ ],
12744
+ [
12745
+ "TodoWrite",
12746
+ {
12747
+ display: "TodoWrite",
12748
+ extractDetails: (input) => {
12749
+ const todos = prop2(input, "todos");
12750
+ const n = Array.isArray(todos) ? todos.length : 0;
12751
+ return [{ text: `${n} items`, role: "target" }];
12752
+ },
12753
+ extractOutcome: () => void 0
12754
+ }
12755
+ ],
12756
+ // ── Planning & interaction ──
12757
+ [
12758
+ "AskUserQuestion",
12759
+ {
12760
+ display: "AskUser",
12761
+ extractDetails: (input) => {
12762
+ const questions = prop2(input, "questions");
12763
+ const n = Array.isArray(questions) ? questions.length : 0;
12764
+ return [{ text: `${n} question${n !== 1 ? "s" : ""}`, role: "target" }];
12765
+ },
12766
+ extractOutcome: () => void 0
12767
+ }
12768
+ ],
12769
+ [
12770
+ "EnterPlanMode",
12771
+ {
12772
+ display: "PlanMode",
12773
+ extractDetails: () => [],
12774
+ extractOutcome: () => ({ text: "entered", zero: false })
12775
+ }
12776
+ ],
12777
+ [
12778
+ "ExitPlanMode",
12779
+ {
12780
+ display: "PlanMode",
12781
+ extractDetails: () => [],
12782
+ extractOutcome: () => ({ text: "submitted", zero: false })
12783
+ }
12784
+ ],
12785
+ [
12786
+ "EnterWorktree",
12787
+ {
12788
+ display: "Worktree",
12789
+ extractDetails: (input) => [
12790
+ { text: String(prop2(input, "branch") ?? ""), role: "target" }
12791
+ ],
12792
+ extractOutcome: () => ({ text: "created", zero: false })
12793
+ }
12794
+ ],
12795
+ [
12796
+ "ExitWorktree",
12797
+ {
12798
+ display: "Worktree",
12799
+ extractDetails: (input) => [
12800
+ { text: String(prop2(input, "action") ?? ""), role: "target" }
12801
+ ],
12802
+ extractOutcome: () => ({ text: "exited", zero: false })
12803
+ }
12804
+ ],
12805
+ // ── Cron / scheduling ──
12806
+ [
12807
+ "CronCreate",
12808
+ {
12809
+ display: "Cron",
12810
+ extractDetails: (input) => [
12811
+ { text: truncate2(String(prop2(input, "cron") ?? ""), 30), role: "target" }
12812
+ ],
12813
+ extractOutcome: () => ({ text: "created", zero: false })
12814
+ }
12815
+ ],
12816
+ [
12817
+ "CronDelete",
12818
+ {
12819
+ display: "Cron",
12820
+ extractDetails: (input) => [
12821
+ { text: String(prop2(input, "id") ?? ""), role: "target" }
12822
+ ],
12823
+ extractOutcome: () => ({ text: "deleted", zero: false })
12824
+ }
12825
+ ],
12826
+ [
12827
+ "CronList",
12828
+ {
12829
+ display: "Cron",
12830
+ extractDetails: () => [{ text: "list", role: "target" }],
12831
+ extractOutcome: (output) => countOutcome(output, "triggers")
12832
+ }
12833
+ ],
12834
+ // ── Remote triggers ──
12835
+ [
12836
+ "RemoteTrigger",
12837
+ {
12838
+ display: "Trigger",
12839
+ extractDetails: (input) => {
12840
+ const action = String(prop2(input, "action") ?? "");
12841
+ const triggerId = prop2(input, "trigger_id");
12842
+ const text = triggerId ? `${action} ${String(triggerId)}` : action;
12843
+ return [{ text, role: "target" }];
12844
+ },
12845
+ extractOutcome: () => void 0
12846
+ }
12847
+ ],
12848
+ [
12849
+ "Skill",
12850
+ {
12851
+ display: "Skill",
12852
+ extractDetails: (input) => {
12853
+ const name = String(prop2(input, "skill") ?? "");
12854
+ const colonIdx = name.indexOf(":");
12855
+ const display = colonIdx >= 0 ? name.slice(colonIdx + 1) : name;
12856
+ return [{ text: display.replace(/^\//, ""), role: "target" }];
12857
+ },
12858
+ extractOutcome: () => void 0
12859
+ }
12860
+ ]
12861
+ ]);
12862
+ var MCP_VERB_DISPLAY = /* @__PURE__ */ new Map([
12863
+ // ── Navigation ──
12864
+ [
12865
+ "navigate",
12866
+ {
12867
+ display: "Navigate",
12868
+ extractDetails: (i) => [
12869
+ { text: extractDomain(prop2(i, "url")), role: "target" }
12870
+ ],
12871
+ extractOutcome: () => void 0
12872
+ }
12873
+ ],
12874
+ [
12875
+ "reload",
12876
+ {
12877
+ display: "Reload",
12878
+ extractDetails: () => [],
12879
+ extractOutcome: () => void 0
12880
+ }
12881
+ ],
12882
+ [
12883
+ "go_back",
12884
+ {
12885
+ display: "Back",
12886
+ extractDetails: () => [],
12887
+ extractOutcome: () => void 0
12888
+ }
12889
+ ],
12890
+ [
12891
+ "go_forward",
12892
+ {
12893
+ display: "Forward",
12894
+ extractDetails: () => [],
12895
+ extractOutcome: () => void 0
12896
+ }
12897
+ ],
12898
+ // ── Element interaction ──
12899
+ [
12900
+ "find_elements",
12901
+ {
12902
+ display: "Find",
12903
+ extractDetails: findDetailsExtractor,
12904
+ extractOutcome: foundCountOutcome
12905
+ }
12906
+ ],
12907
+ [
12908
+ "click",
12909
+ {
12910
+ display: "Click",
12911
+ extractDetails: eidOrLabelExtractor,
12912
+ extractOutcome: () => void 0
12913
+ }
12914
+ ],
12915
+ [
12916
+ "type",
12917
+ {
12918
+ display: "Type",
12919
+ extractDetails: typeDetailsExtractor,
12920
+ extractOutcome: () => void 0
12921
+ }
12922
+ ],
12923
+ [
12924
+ "press",
12925
+ {
12926
+ display: "Press",
12927
+ extractDetails: (i) => [
12928
+ { text: String(prop2(i, "key") ?? ""), role: "target" }
12929
+ ],
12930
+ extractOutcome: () => void 0
12931
+ }
12932
+ ],
12933
+ [
12934
+ "select",
12935
+ {
12936
+ display: "Select",
12937
+ extractDetails: (i) => [
12938
+ { text: String(prop2(i, "value") ?? ""), role: "target" }
12939
+ ],
12940
+ extractOutcome: () => void 0
12941
+ }
12942
+ ],
12943
+ [
12944
+ "hover",
12945
+ {
12946
+ display: "Hover",
12947
+ extractDetails: eidOrLabelExtractor,
12948
+ extractOutcome: () => void 0
12949
+ }
12950
+ ],
12951
+ // ── Inspection ──
12952
+ [
12953
+ "get_element_details",
12954
+ {
12955
+ display: "Inspect",
12956
+ extractDetails: eidExtractor2,
12957
+ extractOutcome: () => void 0
12958
+ }
12959
+ ],
12960
+ [
12961
+ "take_screenshot",
12962
+ {
12963
+ display: "Screenshot",
12964
+ extractDetails: () => [],
12965
+ extractOutcome: () => ({ text: "captured", zero: false })
12966
+ }
12967
+ ],
12968
+ [
12969
+ "capture_snapshot",
12970
+ {
12971
+ display: "Snapshot",
12972
+ extractDetails: () => [],
12973
+ extractOutcome: () => void 0
12974
+ }
12975
+ ],
12976
+ [
12977
+ "get_form_understanding",
12978
+ {
12979
+ display: "FormScan",
12980
+ extractDetails: () => [],
12981
+ extractOutcome: formCountOutcome
12982
+ }
12983
+ ],
12984
+ [
12985
+ "get_field_context",
12986
+ {
12987
+ display: "FieldCtx",
12988
+ extractDetails: eidExtractor2,
12989
+ extractOutcome: () => void 0
12990
+ }
12991
+ ],
12992
+ // ── Scroll ──
12993
+ [
12994
+ "scroll_page",
12995
+ {
12996
+ display: "Scroll",
12997
+ extractDetails: scrollDetailsExtractor,
12998
+ extractOutcome: () => void 0
12999
+ }
13000
+ ],
13001
+ [
13002
+ "scroll_element_into_view",
13003
+ {
13004
+ display: "ScrollTo",
13005
+ extractDetails: eidExtractor2,
13006
+ extractOutcome: () => void 0
13007
+ }
13008
+ ],
13009
+ // ── Session ──
13010
+ [
13011
+ "close_session",
13012
+ {
13013
+ display: "Close",
13014
+ extractDetails: () => [{ text: "session", role: "target" }],
13015
+ extractOutcome: () => void 0
13016
+ }
13017
+ ],
13018
+ [
13019
+ "close_page",
13020
+ {
13021
+ display: "ClosePage",
13022
+ extractDetails: tabRefExtractor,
13023
+ extractOutcome: () => void 0
13024
+ }
13025
+ ],
13026
+ [
13027
+ "list_pages",
13028
+ {
13029
+ display: "ListPages",
13030
+ extractDetails: () => [],
13031
+ extractOutcome: tabCountOutcome
13032
+ }
13033
+ ],
13034
+ [
13035
+ "ping",
13036
+ {
13037
+ display: "Ping",
13038
+ extractDetails: () => [],
13039
+ extractOutcome: pingOutcome
13040
+ }
13041
+ ],
13042
+ // ── Context7 ──
13043
+ [
13044
+ "resolve-library-id",
13045
+ {
13046
+ display: "Resolve",
13047
+ extractDetails: (i) => [
13048
+ {
13049
+ text: truncate2(String(prop2(i, "libraryName") ?? ""), 30),
13050
+ role: "target"
13051
+ }
13052
+ ],
13053
+ extractOutcome: () => void 0
13054
+ }
13055
+ ],
13056
+ [
13057
+ "query-docs",
13058
+ {
13059
+ display: "QueryDocs",
13060
+ extractDetails: (i) => [
13061
+ {
13062
+ text: truncate2(String(prop2(i, "query") ?? ""), 40),
13063
+ role: "target"
13064
+ }
13065
+ ],
13066
+ extractOutcome: () => void 0
13067
+ }
13068
+ ]
13069
+ ]);
13070
+ function humanizeToolName(raw) {
13071
+ const display = raw.split(/[_-]/).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
13072
+ return display.length > 14 ? display.slice(0, 13) + "\u2026" : display;
13073
+ }
13074
+ function resolveToolColumn(toolName) {
13075
+ const parsed = parseToolName(toolName);
13076
+ const known = KNOWN_TOOL_DISPLAY.get(parsed.displayName);
13077
+ if (known) return known.display;
13078
+ if (parsed.isMcp && parsed.mcpAction) {
13079
+ const mcp = MCP_VERB_DISPLAY.get(parsed.mcpAction);
13080
+ if (mcp) return mcp.display;
13081
+ }
13082
+ return parsed.isMcp && parsed.mcpAction ? humanizeToolName(parsed.mcpAction) : humanizeToolName(parsed.displayName);
13083
+ }
13084
+ function resolveEventToolColumn(event) {
13085
+ switch (event.kind) {
13086
+ case "subagent.start":
13087
+ case "subagent.stop":
13088
+ return event.data.agent_type;
13089
+ case "permission.request":
13090
+ return resolveToolColumn(event.data.tool_name);
13091
+ case "setup":
13092
+ case "session.start":
13093
+ case "session.end":
13094
+ case "run.start":
13095
+ case "run.end":
13096
+ case "user.prompt":
13097
+ case "plan.update":
13098
+ case "reasoning.summary":
13099
+ case "usage.update":
13100
+ case "tool.delta":
13101
+ case "tool.pre":
13102
+ case "tool.post":
13103
+ case "tool.failure":
13104
+ case "permission.decision":
13105
+ case "permission.denied":
13106
+ case "stop.request":
13107
+ case "stop.decision":
13108
+ case "stop.failure":
13109
+ case "notification":
13110
+ case "runtime.error":
13111
+ case "thread.status":
13112
+ case "turn.diff":
13113
+ case "server.request.resolved":
13114
+ case "web.search":
13115
+ case "review.status":
13116
+ case "image.view":
13117
+ case "context.compaction":
13118
+ case "mcp.progress":
13119
+ case "terminal.input":
13120
+ case "skills.changed":
13121
+ case "skills.loaded":
13122
+ case "compact.pre":
13123
+ case "compact.post":
13124
+ case "unknown.hook":
13125
+ case "todo.add":
13126
+ case "todo.update":
13127
+ case "todo.done":
13128
+ case "agent.message":
13129
+ case "teammate.idle":
13130
+ case "task.created":
13131
+ case "task.completed":
13132
+ case "config.change":
13133
+ case "cwd.changed":
13134
+ case "file.changed":
13135
+ case "instructions.loaded":
13136
+ case "worktree.create":
13137
+ case "worktree.remove":
13138
+ case "elicitation.request":
13139
+ case "elicitation.result":
13140
+ case "channel.permission.relayed":
13141
+ case "channel.permission.resolved":
13142
+ case "channel.question.relayed":
13143
+ case "channel.question.resolved":
13144
+ case "channel.chat.inbound":
13145
+ case "channel.chat.outbound":
13146
+ case "gateway.function.invoked":
13147
+ case "gateway.function.completed":
13148
+ case "gateway.function.failed":
13149
+ case "artifacts.manifest":
13150
+ return "";
13151
+ }
13152
+ }
13153
+
13154
+ // src/core/feed/indexedTimeline.ts
13155
+ var MAX_SEARCH_CACHE_SIZE = 8;
13156
+ function subagentActorLabel(_agentType, _agentId) {
13157
+ return "SUB AGENT";
13158
+ }
13159
+ function buildSubagentTypeMap(feedEvents) {
13160
+ const map = /* @__PURE__ */ new Map();
13161
+ updateSubagentTypeMap(map, feedEvents);
13162
+ return map;
13163
+ }
13164
+ function updateSubagentTypeMap(map, feedEvents) {
13165
+ for (const event of feedEvents) {
13166
+ if (event.kind !== "subagent.start" && event.kind !== "subagent.stop") {
13167
+ continue;
13168
+ }
13169
+ const agentId = event.data.agent_id;
13170
+ const agentType = event.data.agent_type;
13171
+ if (!agentId || !agentType || map.has(agentId)) continue;
13172
+ map.set(agentId, agentType);
13173
+ }
13174
+ }
13175
+ function resolveActorLabel(event, subagentTypes) {
13176
+ if (!event.actor_id.startsWith("subagent:")) {
13177
+ return actorLabel(event.actor_id);
13178
+ }
13179
+ const agentId = event.actor_id.slice("subagent:".length);
13180
+ const eventAgentType = event.kind === "subagent.start" || event.kind === "subagent.stop" ? event.data.agent_type : void 0;
13181
+ return subagentActorLabel(
13182
+ eventAgentType || subagentTypes.get(agentId),
13183
+ agentId
13184
+ );
13185
+ }
13186
+ function buildMessageEntry(item, activeRunId, messageCounter) {
13187
+ const summary = compactText(item.content, 200);
13188
+ const details = item.content;
13189
+ return {
13190
+ id: `M${String(messageCounter).padStart(3, "0")}`,
13191
+ ts: item.timestamp.getTime(),
13192
+ runId: activeRunId,
13193
+ op: item.role === "user" ? "User Msg" : "Agent Msg",
13194
+ opTag: item.role === "user" ? "msg.user" : "msg.agent",
13195
+ actor: item.role === "user" ? "USER" : "AGENT",
13196
+ actorId: item.role === "user" ? "user" : "agent:root",
13197
+ toolColumn: "",
13198
+ summary,
13199
+ summarySegments: [{ text: summary, role: "plain" }],
13200
+ searchText: `${summary}
13201
+ ${details}`,
13202
+ error: false,
13203
+ expandable: details.length > 120,
13204
+ details,
13205
+ duplicateActor: false
13206
+ };
13207
+ }
13208
+ function shouldSkipEvent(event, verbose) {
13209
+ if (!verbose && VERBOSE_ONLY_KINDS.has(event.kind)) {
13210
+ return true;
13211
+ }
13212
+ if (!verbose && event.kind === "stop.request" && !event.data.stop_hook_active) {
13213
+ return true;
13214
+ }
13215
+ return false;
13216
+ }
13217
+ function mergedToolUseId(event, postByToolUseId) {
13218
+ if (event.kind !== "tool.post" && event.kind !== "tool.failure" || isSubagentTool(event.data.tool_name) || !postByToolUseId) {
13219
+ return void 0;
13220
+ }
13221
+ const toolUseId = event.data.tool_use_id;
13222
+ if (!toolUseId) return void 0;
13223
+ return postByToolUseId.get(toolUseId) === event ? toolUseId : void 0;
13224
+ }
13225
+ function pairedPostForEvent(event, postByToolUseId) {
13226
+ if (event.kind !== "tool.pre" && event.kind !== "permission.request" || isSubagentTool(event.data.tool_name) || !event.data.tool_use_id) {
13227
+ return void 0;
13228
+ }
13229
+ return postByToolUseId?.get(event.data.tool_use_id);
13230
+ }
13231
+ function pendingToolUpdateUseId(event) {
13232
+ if (event.kind !== "tool.delta" && event.kind !== "tool.post" && event.kind !== "tool.failure") {
13233
+ return void 0;
13234
+ }
13235
+ if (isSubagentTool(event.data.tool_name)) {
13236
+ return void 0;
13237
+ }
13238
+ return event.data.tool_use_id;
13239
+ }
13240
+ function buildEventEntry(event, subagentTypes, pairedPost) {
13241
+ const opTag = pairedPost ? mergedEventOperation(event, pairedPost) : eventOperation(event);
13242
+ const op = pairedPost ? mergedEventLabel(event, pairedPost) : eventLabel(event);
13243
+ const summaryResult = pairedPost ? mergedEventSummary(event, pairedPost) : eventSummary(event);
13244
+ const { text: summary, segments: summarySegments } = summaryResult;
13245
+ const toolColumn = event.kind === "tool.pre" || event.kind === "tool.post" || event.kind === "tool.failure" ? resolveToolColumn(event.data.tool_name) : resolveEventToolColumn(event);
13246
+ return {
13247
+ id: event.event_id,
13248
+ ts: event.ts,
13249
+ runId: event.run_id,
13250
+ op,
13251
+ opTag,
13252
+ actor: resolveActorLabel(event, subagentTypes),
13253
+ actorId: event.actor_id,
13254
+ toolColumn,
13255
+ summary,
13256
+ summarySegments,
13257
+ summaryOutcome: summaryResult.outcome,
13258
+ summaryOutcomeZero: summaryResult.outcomeZero,
13259
+ searchText: summary,
13260
+ error: isEventError(event) || pairedPost?.kind === "tool.failure",
13261
+ expandable: isEventExpandable(event),
13262
+ details: "",
13263
+ feedEvent: event,
13264
+ pairedPostEvent: pairedPost,
13265
+ duplicateActor: false
13266
+ };
13267
+ }
13268
+ function maybeBuildEventEntry(event, subagentTypes, postByToolUseId, verbose) {
13269
+ if (shouldSkipEvent(event, verbose)) return null;
13270
+ if (event.kind === "tool.delta") return null;
13271
+ if (mergedToolUseId(event, postByToolUseId)) {
13272
+ return null;
13273
+ }
13274
+ return buildEventEntry(
13275
+ event,
13276
+ subagentTypes,
13277
+ pairedPostForEvent(event, postByToolUseId)
13278
+ );
13279
+ }
13280
+ function rememberPendingEntry(pendingEntryIndexByToolUseId, entry, index) {
13281
+ const event = entry.feedEvent;
13282
+ if (!event) return;
13283
+ if (event.kind !== "tool.pre" && event.kind !== "permission.request" || isSubagentTool(event.data.tool_name) || !event.data.tool_use_id || entry.pairedPostEvent) {
13284
+ return;
13285
+ }
13286
+ pendingEntryIndexByToolUseId.set(event.data.tool_use_id, index);
13287
+ }
13288
+ function recomputeDuplicateActorAt(entries, index) {
13289
+ const entry = entries[index];
13290
+ if (index === 0) {
13291
+ entry.duplicateActor = false;
13292
+ return;
13293
+ }
13294
+ const prev = entries[index - 1];
13295
+ const sameActor = entry.actorId === prev.actorId;
13296
+ const isBreak = opCategory(entry.opTag) !== opCategory(prev.opTag);
13297
+ entry.duplicateActor = sameActor && !isBreak;
13298
+ }
13299
+ function recomputeDuplicateActorsAround(entries, index) {
13300
+ recomputeDuplicateActorAt(entries, index);
13301
+ if (index + 1 < entries.length) {
13302
+ recomputeDuplicateActorAt(entries, index + 1);
13303
+ }
13304
+ }
13305
+ function sameFeedItemPrefix(previous, next) {
13306
+ if (next.length < previous.length) return false;
13307
+ for (let i = 0; i < previous.length; i++) {
13308
+ const prev = previous[i];
13309
+ const curr = next[i];
13310
+ if (prev.type !== curr.type || prev.data !== curr.data) {
13311
+ return false;
13312
+ }
13313
+ }
13314
+ return true;
13315
+ }
13316
+ function sameFeedEventPrefix(previous, next) {
13317
+ if (next.length < previous.length) return false;
13318
+ for (let i = 0; i < previous.length; i++) {
13319
+ if (previous[i] !== next[i]) {
13320
+ return false;
13321
+ }
13322
+ }
13323
+ return true;
13324
+ }
13325
+ function canAppendIncrementally(previous, feedItems, feedEvents, verbose) {
13326
+ if (!previous) return false;
13327
+ if (previous.verbose !== verbose) return false;
13328
+ return sameFeedItemPrefix(previous.feedItems, feedItems) && sameFeedEventPrefix(previous.feedEvents, feedEvents);
13329
+ }
13330
+ function buildTimelineCache(feedItems, feedEvents, postByToolUseId, verbose) {
13331
+ const entries = [];
13332
+ let activeRunId;
13333
+ let messageCounter = 1;
13334
+ const subagentTypes = buildSubagentTypeMap(feedEvents);
13335
+ const pendingEntryIndexByToolUseId = /* @__PURE__ */ new Map();
13336
+ for (const item of feedItems) {
13337
+ if (item.type === "message") {
13338
+ entries.push(buildMessageEntry(item.data, activeRunId, messageCounter++));
13339
+ continue;
13340
+ }
13341
+ const event = item.data;
13342
+ if (event.kind === "run.start") {
13343
+ activeRunId = event.run_id;
13344
+ }
13345
+ const entry = maybeBuildEventEntry(
13346
+ event,
13347
+ subagentTypes,
13348
+ postByToolUseId,
13349
+ verbose
13350
+ );
13351
+ if (entry) {
13352
+ const index = entries.push(entry) - 1;
13353
+ rememberPendingEntry(pendingEntryIndexByToolUseId, entry, index);
13354
+ }
13355
+ if (event.kind === "run.end") {
13356
+ activeRunId = void 0;
13357
+ }
13358
+ }
13359
+ computeDuplicateActors(entries);
13360
+ return {
13361
+ feedItems,
13362
+ feedEvents,
13363
+ entries,
13364
+ activeRunId,
13365
+ messageCounter,
13366
+ subagentTypes,
13367
+ pendingEntryIndexByToolUseId,
13368
+ verbose
13369
+ };
13370
+ }
13371
+ function appendTimelineCache(previous, feedItems, feedEvents, postByToolUseId) {
13372
+ const entries = previous.entries.slice();
13373
+ const subagentTypes = new Map(previous.subagentTypes);
13374
+ updateSubagentTypeMap(
13375
+ subagentTypes,
13376
+ feedEvents.slice(previous.feedEvents.length)
13377
+ );
13378
+ const pendingEntryIndexByToolUseId = new Map(
13379
+ previous.pendingEntryIndexByToolUseId
13380
+ );
13381
+ let activeRunId = previous.activeRunId;
13382
+ let messageCounter = previous.messageCounter;
13383
+ for (const item of feedItems.slice(previous.feedItems.length)) {
13384
+ if (item.type === "message") {
13385
+ const index = entries.push(
13386
+ buildMessageEntry(item.data, activeRunId, messageCounter++)
13387
+ ) - 1;
13388
+ recomputeDuplicateActorsAround(entries, index);
13389
+ continue;
13390
+ }
13391
+ const event = item.data;
13392
+ if (event.kind === "run.start") {
13393
+ activeRunId = event.run_id;
13394
+ }
13395
+ const resolvedToolUseId = pendingToolUpdateUseId(event);
13396
+ if (resolvedToolUseId) {
13397
+ const pendingIndex = pendingEntryIndexByToolUseId.get(resolvedToolUseId);
13398
+ if (pendingIndex !== void 0) {
13399
+ const pendingEntry = entries[pendingIndex];
13400
+ if (pendingEntry.feedEvent) {
13401
+ entries[pendingIndex] = buildEventEntry(
13402
+ pendingEntry.feedEvent,
13403
+ subagentTypes,
13404
+ event
13405
+ );
13406
+ if (event.kind === "tool.post" || event.kind === "tool.failure") {
13407
+ pendingEntryIndexByToolUseId.delete(resolvedToolUseId);
13408
+ }
13409
+ recomputeDuplicateActorsAround(entries, pendingIndex);
13410
+ }
13411
+ }
13412
+ continue;
13413
+ }
13414
+ const entry = maybeBuildEventEntry(
13415
+ event,
13416
+ subagentTypes,
13417
+ postByToolUseId,
13418
+ previous.verbose
13419
+ );
13420
+ if (entry) {
13421
+ const index = entries.push(entry) - 1;
13422
+ recomputeDuplicateActorsAround(entries, index);
13423
+ rememberPendingEntry(pendingEntryIndexByToolUseId, entry, index);
13424
+ }
13425
+ if (event.kind === "run.end") {
13426
+ activeRunId = void 0;
13427
+ }
13428
+ }
13429
+ return {
13430
+ feedItems,
13431
+ feedEvents,
13432
+ entries,
13433
+ activeRunId,
13434
+ messageCounter,
13435
+ subagentTypes,
13436
+ pendingEntryIndexByToolUseId,
13437
+ verbose: previous.verbose
13438
+ };
13439
+ }
13440
+ var IndexedTimeline = class {
13441
+ cache = null;
13442
+ runIndex = /* @__PURE__ */ new Map();
13443
+ errorPositions = /* @__PURE__ */ new Set();
13444
+ _runSummaryMap = /* @__PURE__ */ new Map();
13445
+ _runSummariesDirty = true;
13446
+ _runSummariesCache = [];
13447
+ _lastFeedEventsLength = 0;
13448
+ searchCache = /* @__PURE__ */ new Map();
13449
+ lastFilteredRef = null;
13450
+ detailCache = /* @__PURE__ */ new WeakMap();
13451
+ searchTextCache = /* @__PURE__ */ new WeakMap();
13452
+ verbose = false;
13453
+ update(feedItems, feedEvents, postByToolUseId, verbose) {
13454
+ this.verbose = verbose;
13455
+ const incremental = canAppendIncrementally(
13456
+ this.cache,
13457
+ feedItems,
13458
+ feedEvents,
13459
+ this.verbose
13460
+ );
13461
+ if (incremental) {
13462
+ this.updateRunSummaries(feedEvents);
13463
+ this.cache = appendTimelineCache(
13464
+ this.cache,
13465
+ feedItems,
13466
+ feedEvents,
13467
+ postByToolUseId
13468
+ );
13469
+ } else {
13470
+ this.rebuildRunSummaries(feedEvents);
13471
+ this.cache = buildTimelineCache(
13472
+ feedItems,
13473
+ feedEvents,
13474
+ postByToolUseId,
13475
+ this.verbose
13476
+ );
13477
+ }
13478
+ this.rebuildIndexes();
13479
+ }
13480
+ getEntries() {
13481
+ return this.cache?.entries ?? [];
13482
+ }
13483
+ getFilteredView(runFilter, errorsOnly) {
13484
+ const entries = this.getEntries();
13485
+ if ((!runFilter || runFilter === "all") && !errorsOnly) {
13486
+ return entries;
13487
+ }
13488
+ let candidateIndices;
13489
+ if (runFilter && runFilter !== "all") {
13490
+ candidateIndices = this.runIndex.get(runFilter) ?? [];
13491
+ } else {
13492
+ candidateIndices = Array.from({ length: entries.length }, (_, i) => i);
13493
+ }
13494
+ if (errorsOnly) {
13495
+ candidateIndices = candidateIndices.filter(
13496
+ (i) => this.errorPositions.has(i)
13497
+ );
13498
+ }
13499
+ return candidateIndices.map((i) => entries[i]);
13500
+ }
13501
+ getSearchMatches(filteredEntries, query) {
13502
+ const q = query.trim().toLowerCase();
13503
+ if (!q) return [];
13504
+ if (filteredEntries !== this.lastFilteredRef) {
13505
+ this.searchCache.clear();
13506
+ this.lastFilteredRef = filteredEntries;
13507
+ }
13508
+ const cached = this.searchCache.get(q);
13509
+ if (cached && cached.lastScanned === filteredEntries.length) {
13510
+ return cached.matches;
13511
+ }
13512
+ const startFrom = cached ? cached.lastScanned : 0;
13513
+ const matches = cached ? [...cached.matches] : [];
13514
+ for (let i = startFrom; i < filteredEntries.length; i++) {
13515
+ const searchText = this.getEntrySearchText(filteredEntries[i]);
13516
+ if (searchText.toLowerCase().includes(q)) {
13517
+ matches.push(i);
13518
+ }
13519
+ }
13520
+ this.searchCache.set(q, { matches, lastScanned: filteredEntries.length });
13521
+ if (this.searchCache.size > MAX_SEARCH_CACHE_SIZE) {
13522
+ const oldest = this.searchCache.keys().next().value;
13523
+ if (oldest !== void 0) {
13524
+ this.searchCache.delete(oldest);
13525
+ }
13526
+ }
13527
+ return matches;
13528
+ }
13529
+ getEntrySearchText(entry) {
13530
+ const cached = this.searchTextCache.get(entry);
13531
+ if (cached !== void 0) return cached;
13532
+ if (!entry.feedEvent) {
13533
+ this.searchTextCache.set(entry, entry.searchText);
13534
+ return entry.searchText;
13535
+ }
13536
+ const details = this.getEntryDetails(entry);
13537
+ const searchText = details ? `${entry.summary}
13538
+ ${details}` : entry.summary;
13539
+ this.searchTextCache.set(entry, searchText);
13540
+ return searchText;
13541
+ }
13542
+ getEntryDetails(entry) {
13543
+ if (entry.details) return entry.details;
13544
+ if (!entry.feedEvent) return entry.summary;
13545
+ const cached = this.detailCache.get(entry);
13546
+ if (cached !== void 0) return cached;
13547
+ const details = isEventExpandable(entry.feedEvent) ? expansionForEvent(entry.feedEvent) : "";
13548
+ this.detailCache.set(entry, details);
13549
+ return details;
13550
+ }
13551
+ getRunSummaries() {
13552
+ if (this._runSummariesDirty) {
13553
+ this._runSummariesCache = Array.from(this._runSummaryMap.values()).sort(
13554
+ (a, b) => a.startedAt - b.startedAt
13555
+ );
13556
+ this._runSummariesDirty = false;
13557
+ }
13558
+ return this._runSummariesCache;
13559
+ }
13560
+ processRunEvent(event) {
13561
+ if (event.kind === "run.start") {
13562
+ this._runSummaryMap.set(event.run_id, {
13563
+ runId: event.run_id,
13564
+ title: compactText(
13565
+ event.data.trigger.prompt_preview || "Untitled run",
13566
+ 46
13567
+ ),
13568
+ status: "RUNNING",
13569
+ startedAt: event.ts
13570
+ });
13571
+ this._runSummariesDirty = true;
13572
+ } else if (event.kind === "run.end") {
13573
+ const existing = this._runSummaryMap.get(event.run_id);
13574
+ if (existing) {
13575
+ existing.status = toRunStatus(event);
13576
+ existing.endedAt = event.ts;
13577
+ } else {
13578
+ this._runSummaryMap.set(event.run_id, {
13579
+ runId: event.run_id,
13580
+ title: "Untitled run",
13581
+ status: toRunStatus(event),
13582
+ startedAt: event.ts,
13583
+ endedAt: event.ts
13584
+ });
13585
+ }
13586
+ this._runSummariesDirty = true;
13587
+ }
13588
+ }
13589
+ rebuildRunSummaries(feedEvents) {
13590
+ this._runSummaryMap.clear();
13591
+ this._runSummariesDirty = true;
13592
+ this._lastFeedEventsLength = 0;
13593
+ this.updateRunSummaries(feedEvents);
13594
+ }
13595
+ updateRunSummaries(feedEvents) {
13596
+ for (let i = this._lastFeedEventsLength; i < feedEvents.length; i++) {
13597
+ this.processRunEvent(feedEvents[i]);
13598
+ }
13599
+ this._lastFeedEventsLength = feedEvents.length;
13600
+ }
13601
+ addToIndex(entry, index) {
13602
+ const runId = entry.runId ?? "__none__";
13603
+ let indices = this.runIndex.get(runId);
13604
+ if (!indices) {
13605
+ indices = [];
13606
+ this.runIndex.set(runId, indices);
13607
+ }
13608
+ indices.push(index);
13609
+ if (entry.error) {
13610
+ this.errorPositions.add(index);
13611
+ }
13612
+ }
13613
+ rebuildIndexes() {
13614
+ this.runIndex.clear();
13615
+ this.errorPositions.clear();
13616
+ this.searchCache.clear();
13617
+ const entries = this.getEntries();
13618
+ for (let i = 0; i < entries.length; i++) {
13619
+ this.addToIndex(entries[i], i);
13620
+ }
13621
+ }
13622
+ };
13623
+
13624
+ // src/infra/sessions/registry.ts
13625
+ import fs18 from "fs";
13626
+ import os10 from "os";
13627
+ import path15 from "path";
13628
+ import Database3 from "better-sqlite3";
13629
+ function sessionsDir() {
13630
+ return path15.join(os10.homedir(), ".config", "athena", "sessions");
13631
+ }
13632
+ function sessionDbPath(sessionId) {
13633
+ return path15.join(sessionsDir(), sessionId, "session.db");
13634
+ }
13635
+ function readSessionFromDb(dbPath) {
13636
+ if (!fs18.existsSync(dbPath)) return null;
13637
+ let db;
13638
+ try {
13639
+ db = new Database3(dbPath, { readonly: true });
13640
+ const versionRow = db.prepare("SELECT version FROM schema_version").get();
13641
+ if (versionRow && versionRow.version > SCHEMA_VERSION) {
13642
+ return null;
13643
+ }
13644
+ const row = db.prepare("SELECT * FROM session LIMIT 1").get();
13645
+ if (!row) return null;
13646
+ const adapters = db.prepare("SELECT session_id FROM adapter_sessions ORDER BY started_at").all();
13647
+ let firstPrompt;
13648
+ if (!row.label && (row.event_count ?? 0) > 0) {
13649
+ const promptRow = db.prepare(
13650
+ `SELECT json_extract(payload, '$.data.prompt') as prompt FROM runtime_events WHERE hook_name = 'UserPromptSubmit' ORDER BY seq ASC LIMIT 1`
13651
+ ).get();
13652
+ if (promptRow?.prompt) {
13653
+ firstPrompt = promptRow.prompt;
13654
+ }
13655
+ }
13656
+ return rowToAthenaSession(
13657
+ row,
13658
+ adapters.map((a) => a.session_id),
13659
+ firstPrompt
13660
+ );
13661
+ } catch {
13662
+ return null;
13663
+ } finally {
13664
+ db?.close();
13665
+ }
13666
+ }
13667
+ function listSessions(projectDir) {
13668
+ const dir = sessionsDir();
13669
+ if (!fs18.existsSync(dir)) return [];
13670
+ const entries = fs18.readdirSync(dir, { withFileTypes: true });
13671
+ const sessions = [];
13672
+ for (const entry of entries) {
13673
+ if (!entry.isDirectory()) continue;
13674
+ const dbPath = path15.join(dir, entry.name, "session.db");
13675
+ const session = readSessionFromDb(dbPath);
13676
+ if (session && (session.eventCount ?? 0) > 0) {
13677
+ if (!projectDir || session.projectDir === projectDir) {
13678
+ sessions.push(session);
13679
+ }
13680
+ }
13681
+ }
13682
+ return sessions.sort((a, b) => b.updatedAt - a.updatedAt);
13683
+ }
13684
+ function getSessionMeta(sessionId) {
13685
+ return readSessionFromDb(sessionDbPath(sessionId));
13686
+ }
13687
+ function getMostRecentAthenaSession(projectDir) {
13688
+ const sessions = listSessions(projectDir);
13689
+ return sessions[0] ?? null;
10311
13690
  }
10312
13691
 
10313
13692
  // src/app/channels/relayAdapter.ts
@@ -10745,7 +14124,7 @@ import path16 from "path";
10745
14124
 
10746
14125
  // src/shared/gateway-protocol/endpoint.ts
10747
14126
  function parseRuntimeEndpoint(value) {
10748
- if (!isRecord(value)) {
14127
+ if (!isRecord2(value)) {
10749
14128
  throw new Error("gateway client config must be an object");
10750
14129
  }
10751
14130
  if (value["mode"] === "local") {
@@ -10790,7 +14169,7 @@ function isSupportedGatewayUrl(url) {
10790
14169
  return false;
10791
14170
  }
10792
14171
  }
10793
- function isRecord(value) {
14172
+ function isRecord2(value) {
10794
14173
  return typeof value === "object" && value !== null && !Array.isArray(value);
10795
14174
  }
10796
14175
 
@@ -11262,7 +14641,7 @@ function sleepOrAbort(ms, signal) {
11262
14641
  }
11263
14642
 
11264
14643
  // src/app/dashboard/dashboardFeedPublisher.ts
11265
- import Database3 from "better-sqlite3";
14644
+ import Database4 from "better-sqlite3";
11266
14645
  function dashboardFeedOutboxPath() {
11267
14646
  return `${ensureDaemonStateDir().dir}/dashboard-feed-outbox.db`;
11268
14647
  }
@@ -11303,7 +14682,7 @@ function makeEnvelope(input) {
11303
14682
  };
11304
14683
  }
11305
14684
  function createDashboardFeedOutbox(options = {}) {
11306
- const db = new Database3(options.dbPath ?? dashboardFeedOutboxPath());
14685
+ const db = new Database4(options.dbPath ?? dashboardFeedOutboxPath());
11307
14686
  initOutboxSchema(db);
11308
14687
  const insert = db.prepare(`
11309
14688
  INSERT OR IGNORE INTO dashboard_feed_outbox (
@@ -13503,7 +16882,7 @@ function createAttachmentReconciler(options) {
13503
16882
  }
13504
16883
 
13505
16884
  // src/app/dashboard/dashboardDecisionInbox.ts
13506
- import Database4 from "better-sqlite3";
16885
+ import Database5 from "better-sqlite3";
13507
16886
  function dashboardDecisionInboxPath() {
13508
16887
  return `${ensureDaemonStateDir().dir}/dashboard-decision-inbox.db`;
13509
16888
  }
@@ -13571,7 +16950,7 @@ function initInboxSchema(db) {
13571
16950
  `);
13572
16951
  }
13573
16952
  function createDashboardDecisionInbox(options = {}) {
13574
- const db = new Database4(options.dbPath ?? dashboardDecisionInboxPath());
16953
+ const db = new Database5(options.dbPath ?? dashboardDecisionInboxPath());
13575
16954
  initInboxSchema(db);
13576
16955
  const upsertUnconsumed = db.prepare(`
13577
16956
  INSERT INTO dashboard_decision_inbox (
@@ -14595,7 +17974,10 @@ export {
14595
17974
  isScopedPermissionsRequest,
14596
17975
  supportsSessionApproval,
14597
17976
  extractPermissionSnapshot,
14598
- isSubagentTool,
17977
+ extractFriendlyServerName,
17978
+ parseToolName,
17979
+ mergeFeedItems,
17980
+ buildPostByToolUseId,
14599
17981
  createFeedMapper,
14600
17982
  ingestRuntimeEvent,
14601
17983
  ingestRuntimeDecision,
@@ -14648,6 +18030,26 @@ export {
14648
18030
  register,
14649
18031
  get,
14650
18032
  getAll,
18033
+ stripAnsi,
18034
+ stringWidth,
18035
+ sliceAnsi,
18036
+ spaces,
18037
+ compactText,
18038
+ fit,
18039
+ fitAnsi,
18040
+ centerAnsi,
18041
+ formatClock,
18042
+ formatRunLabel,
18043
+ cursorToVisualPosition,
18044
+ visualPositionToOffset,
18045
+ renderInputLines,
18046
+ wrapText,
18047
+ computeInputRows,
18048
+ isCommandPrefix,
18049
+ formatToolResponse,
18050
+ isBashToolResponse,
18051
+ resolveToolColumn,
18052
+ IndexedTimeline,
14651
18053
  bootstrapRuntimeConfig,
14652
18054
  EXEC_EXIT_CODE,
14653
18055
  runExec,
@@ -14660,4 +18062,4 @@ export {
14660
18062
  startUdsServer,
14661
18063
  sendUdsRequest
14662
18064
  };
14663
- //# sourceMappingURL=chunk-UKMVFGY2.js.map
18065
+ //# sourceMappingURL=chunk-RN5AVH3D.js.map