@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.
package/dist/cli.js CHANGED
@@ -8,11 +8,16 @@ import {
8
8
  EXEC_EXIT_CODE,
9
9
  GatewayUnauthorizedError,
10
10
  GatewayUnreachableError,
11
+ IndexedTimeline,
11
12
  PORTABLE_PROVIDER_ENV_VARS,
12
13
  bootstrapRuntimeConfig,
13
14
  buildApiKeyHelperSettings,
15
+ buildPostByToolUseId,
14
16
  buildProbeConfigs,
17
+ centerAnsi,
15
18
  classifyFailure,
19
+ compactText,
20
+ computeInputRows,
16
21
  connect,
17
22
  createDashboardDecisionInbox,
18
23
  createFeedMapper,
@@ -23,10 +28,17 @@ import {
23
28
  createSessionStore,
24
29
  createWsClientTransport,
25
30
  credentialHelperKey,
31
+ cursorToVisualPosition,
26
32
  daemonStatePaths,
27
33
  detectClaudeVersion,
34
+ extractFriendlyServerName,
28
35
  extractPermissionSnapshot,
36
+ fit,
37
+ fitAnsi,
38
+ formatClock,
29
39
  formatProbeCommand,
40
+ formatRunLabel,
41
+ formatToolResponse,
30
42
  frameGlyphs,
31
43
  generateHookSettings,
32
44
  generateId,
@@ -38,8 +50,9 @@ import {
38
50
  hintGlyphs,
39
51
  ingestRuntimeDecision,
40
52
  ingestRuntimeEvent,
53
+ isBashToolResponse,
54
+ isCommandPrefix,
41
55
  isScopedPermissionsRequest,
42
- isSubagentTool,
43
56
  isSupportedGatewayUrl,
44
57
  listHarnessAdapters,
45
58
  listHarnessCapabilities,
@@ -47,7 +60,9 @@ import {
47
60
  lookupAllCredentials,
48
61
  lookupCredential,
49
62
  makeSkippedProbe,
63
+ mergeFeedItems,
50
64
  messageGlyphs,
65
+ parseToolName,
51
66
  probeSkipReason,
52
67
  processRegistry,
53
68
  progressGlyphs,
@@ -57,24 +72,32 @@ import {
57
72
  register,
58
73
  registerCleanupOnExit,
59
74
  removeAttachmentMirror,
75
+ renderInputLines,
60
76
  resolveClaudeBinary,
61
77
  resolveClaudeSettingsSurfacePaths,
62
78
  resolveHarnessAdapter,
63
79
  resolveHookForwarderCommand,
64
80
  resolveRuntimeAuthOverlay,
81
+ resolveToolColumn,
65
82
  runClaudeAuthStatus,
66
83
  runDashboardRuntimeDaemon,
67
84
  runExec,
68
85
  runProbe,
69
86
  sendUdsRequest,
70
87
  sessionsDir,
88
+ sliceAnsi,
89
+ spaces,
71
90
  startSessionBridge,
91
+ stringWidth,
92
+ stripAnsi,
72
93
  supportsSessionApproval,
73
94
  todoGlyphSet,
95
+ visualPositionToOffset,
96
+ wrapText,
74
97
  writeAttachmentMirror,
75
98
  writeGatewayClientConfig,
76
99
  wsClientOptionsForEndpoint
77
- } from "./chunk-UKMVFGY2.js";
100
+ } from "./chunk-RN5AVH3D.js";
78
101
  import {
79
102
  generateId as generateId2
80
103
  } from "./chunk-BTKQ67RE.js";
@@ -160,34 +183,6 @@ import { Box as Box19, Text as Text25, useApp, useInput as useInput17, useStdout
160
183
  import { useCallback, useMemo } from "react";
161
184
  import { Box as Box2, Text as Text2, useInput as useInput2, useStdout } from "ink";
162
185
 
163
- // src/shared/utils/toolNameParser.ts
164
- function extractFriendlyServerName(mcpServer) {
165
- const pluginMatch = /^plugin_[^_]+_(.+)$/.exec(mcpServer);
166
- if (pluginMatch) {
167
- return pluginMatch[1];
168
- }
169
- return mcpServer;
170
- }
171
- function parseToolName(toolName) {
172
- const match = /^mcp__([^_]+(?:_[^_]+)*)__(.+)$/.exec(toolName);
173
- if (match) {
174
- const mcpServer = match[1];
175
- const mcpAction = match[2];
176
- const friendlyServer = extractFriendlyServerName(mcpServer);
177
- return {
178
- displayName: mcpAction,
179
- isMcp: true,
180
- mcpServer,
181
- mcpAction,
182
- serverLabel: `${friendlyServer} (MCP)`
183
- };
184
- }
185
- return {
186
- displayName: toolName,
187
- isMcp: false
188
- };
189
- }
190
-
191
186
  // src/ui/components/OptionList.tsx
192
187
  import { useState } from "react";
193
188
  import { Box, Text, useInput } from "ink";
@@ -840,50 +835,6 @@ import {
840
835
  useSyncExternalStore
841
836
  } from "react";
842
837
 
843
- // src/core/feed/filter.ts
844
- var TASK_TOOL_NAMES = /* @__PURE__ */ new Set([
845
- "TodoWrite",
846
- "TaskCreate",
847
- "TaskUpdate",
848
- "TaskList",
849
- "TaskGet"
850
- ]);
851
- function isTaskToolEvent(event) {
852
- if (event.kind !== "tool.pre" && event.kind !== "tool.post") return false;
853
- return TASK_TOOL_NAMES.has(event.data.tool_name);
854
- }
855
- function shouldExcludeFromFeed(event) {
856
- if (isTaskToolEvent(event)) return true;
857
- if (event.kind === "todo.update") return true;
858
- return false;
859
- }
860
-
861
- // src/core/feed/items.ts
862
- function mergeFeedItems(messages, feedEvents) {
863
- const messageItems = messages.map((message) => ({
864
- type: "message",
865
- data: message
866
- }));
867
- const feedItems = feedEvents.filter((event) => !shouldExcludeFromFeed(event)).map((event) => ({ type: "feed", data: event }));
868
- return [...messageItems, ...feedItems].sort((left, right) => {
869
- if (left.data.seq !== right.data.seq) return left.data.seq - right.data.seq;
870
- if (left.type === "message" && right.type !== "message") return -1;
871
- if (left.type !== "message" && right.type === "message") return 1;
872
- return 0;
873
- });
874
- }
875
- function buildPostByToolUseId(events) {
876
- const map = /* @__PURE__ */ new Map();
877
- for (const event of events) {
878
- if (event.kind !== "tool.delta" && event.kind !== "tool.post" && event.kind !== "tool.failure") {
879
- continue;
880
- }
881
- const toolUseId = event.data.tool_use_id;
882
- if (toolUseId) map.set(toolUseId, event);
883
- }
884
- return map;
885
- }
886
-
887
838
  // src/shared/utils/perf.ts
888
839
  import fs from "fs";
889
840
  import path from "path";
@@ -1731,7 +1682,7 @@ function useFeed(runtime, messages = [], initialAllowedTools, sessionStore, opti
1731
1682
  const [isServerRunning, setIsServerRunning] = useState4(
1732
1683
  () => runtime.getStatus() === "running"
1733
1684
  );
1734
- const [runtimeError2, setRuntimeError] = useState4(
1685
+ const [runtimeError, setRuntimeError] = useState4(
1735
1686
  () => runtime.getLastError()
1736
1687
  );
1737
1688
  const restoredTokens = useMemo3(
@@ -2118,7 +2069,7 @@ function useFeed(runtime, messages = [], initialAllowedTools, sessionStore, opti
2118
2069
  currentRun: mapperRef.current.getCurrentRun(),
2119
2070
  actors: mapperRef.current.getActors(),
2120
2071
  isServerRunning,
2121
- runtimeError: runtimeError2,
2072
+ runtimeError,
2122
2073
  currentPermissionRequest,
2123
2074
  permissionQueueCount: permissionQueue.length,
2124
2075
  resolvePermission,
@@ -2962,896 +2913,108 @@ var chalk = createChalk();
2962
2913
  var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
2963
2914
  var source_default = chalk;
2964
2915
 
2965
- // node_modules/ansi-regex/index.js
2966
- function ansiRegex({ onlyFirst = false } = {}) {
2967
- const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
2968
- const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
2969
- const csi = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";
2970
- const pattern = `${osc}|${csi}`;
2971
- return new RegExp(pattern, onlyFirst ? void 0 : "g");
2972
- }
2973
-
2974
- // node_modules/strip-ansi/index.js
2975
- var regex = ansiRegex();
2976
- function stripAnsi(string) {
2977
- if (typeof string !== "string") {
2978
- throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
2979
- }
2980
- return string.replace(regex, "");
2981
- }
2916
+ // src/ui/hooks/useTextInput.ts
2917
+ import { useReducer, useCallback as useCallback6, useEffect as useEffect5, useRef as useRef4 } from "react";
2918
+ import { useInput as useInput6, useStdin } from "ink";
2982
2919
 
2983
- // node_modules/get-east-asian-width/lookup.js
2984
- function isAmbiguous(x) {
2985
- 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;
2986
- }
2987
- function isFullWidth(x) {
2988
- return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
2989
- }
2990
- function isWide(x) {
2991
- 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;
2920
+ // src/ui/hooks/usePanelMouseWheel.ts
2921
+ import process4 from "process";
2922
+ import { useEffect as useEffect4 } from "react";
2923
+ var ENABLE_MOUSE_TRACKING = "\x1B[?1000h\x1B[?1006h";
2924
+ var DISABLE_MOUSE_TRACKING = "\x1B[?1006l\x1B[?1000l";
2925
+ var PANEL_MOUSE_SCROLL_LINES = 3;
2926
+ function contains(rect, col, row) {
2927
+ return col >= rect.left && col <= rect.right && row >= rect.top && row <= rect.bottom;
2992
2928
  }
2993
-
2994
- // node_modules/get-east-asian-width/index.js
2995
- function validate(codePoint) {
2996
- if (!Number.isSafeInteger(codePoint)) {
2997
- throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`);
2929
+ function parseSgrWheelEvents(data) {
2930
+ const sgrMouseRe = /\x1B\[<(64|65);(\d+);(\d+)[Mm]/g;
2931
+ const events = [];
2932
+ let match;
2933
+ while ((match = sgrMouseRe.exec(data)) !== null) {
2934
+ events.push({
2935
+ direction: match[1] === "64" ? "up" : "down",
2936
+ col: Number.parseInt(match[2], 10),
2937
+ row: Number.parseInt(match[3], 10)
2938
+ });
2998
2939
  }
2940
+ return events;
2999
2941
  }
3000
- function eastAsianWidth(codePoint, { ambiguousAsWide = false } = {}) {
3001
- validate(codePoint);
3002
- if (isFullWidth(codePoint) || isWide(codePoint) || ambiguousAsWide && isAmbiguous(codePoint)) {
3003
- return 2;
3004
- }
3005
- return 1;
2942
+ function looksLikeMouseEscapeSequence(input) {
2943
+ if (input.length === 0) return false;
2944
+ if (parseSgrWheelEvents(input).length > 0) return true;
2945
+ return /^\[<\d+;\d+;\d+[Mm]$/.test(input) || /^\d+;\d+;\d+[Mm]$/.test(input);
3006
2946
  }
3007
-
3008
- // node_modules/string-width/index.js
3009
- var segmenter = new Intl.Segmenter();
3010
- var zeroWidthClusterRegex = new RegExp("^(?:\\p{Default_Ignorable_Code_Point}|\\p{Control}|\\p{Format}|\\p{Mark}|\\p{Surrogate})+$", "v");
3011
- var leadingNonPrintingRegex = new RegExp("^[\\p{Default_Ignorable_Code_Point}\\p{Control}\\p{Format}\\p{Mark}\\p{Surrogate}]+", "v");
3012
- var rgiEmojiRegex = new RegExp("^\\p{RGI_Emoji}$", "v");
3013
- function baseVisible(segment) {
3014
- return segment.replace(leadingNonPrintingRegex, "");
3015
- }
3016
- function isZeroWidthCluster(segment) {
3017
- return zeroWidthClusterRegex.test(segment);
3018
- }
3019
- function trailingHalfwidthWidth(segment, eastAsianWidthOptions) {
3020
- let extra = 0;
3021
- if (segment.length > 1) {
3022
- for (const char of segment.slice(1)) {
3023
- if (char >= "\uFF00" && char <= "\uFFEF") {
3024
- extra += eastAsianWidth(char.codePointAt(0), eastAsianWidthOptions);
3025
- }
3026
- }
2947
+ function parseSgrClickEvents(data) {
2948
+ const sgrMouseRe = /\x1B\[<0;(\d+);(\d+)M/g;
2949
+ const events = [];
2950
+ let match;
2951
+ while ((match = sgrMouseRe.exec(data)) !== null) {
2952
+ events.push({
2953
+ button: "left",
2954
+ col: Number.parseInt(match[1], 10),
2955
+ row: Number.parseInt(match[2], 10)
2956
+ });
3027
2957
  }
3028
- return extra;
2958
+ return events;
3029
2959
  }
3030
- function stringWidth(input, options = {}) {
3031
- if (typeof input !== "string" || input.length === 0) {
3032
- return 0;
2960
+ function resolvePanelTarget(rects, col, row) {
2961
+ if (rects.input && contains(rects.input, col, row)) {
2962
+ return "input";
3033
2963
  }
3034
- const {
3035
- ambiguousIsNarrow = true,
3036
- countAnsiEscapeCodes = false
3037
- } = options;
3038
- let string = input;
3039
- if (!countAnsiEscapeCodes) {
3040
- string = stripAnsi(string);
3041
- }
3042
- if (string.length === 0) {
3043
- return 0;
2964
+ if (rects.messages && contains(rects.messages, col, row)) {
2965
+ return "messages";
3044
2966
  }
3045
- let width = 0;
3046
- const eastAsianWidthOptions = { ambiguousAsWide: !ambiguousIsNarrow };
3047
- for (const { segment } of segmenter.segment(string)) {
3048
- if (isZeroWidthCluster(segment)) {
3049
- continue;
3050
- }
3051
- if (rgiEmojiRegex.test(segment)) {
3052
- width += 2;
3053
- continue;
3054
- }
3055
- const codePoint = baseVisible(segment).codePointAt(0);
3056
- width += eastAsianWidth(codePoint, eastAsianWidthOptions);
3057
- width += trailingHalfwidthWidth(segment, eastAsianWidthOptions);
2967
+ if (contains(rects.feed, col, row)) {
2968
+ return "feed";
3058
2969
  }
3059
- return width;
2970
+ return null;
3060
2971
  }
3061
-
3062
- // node_modules/ansi-styles/index.js
3063
- var ANSI_BACKGROUND_OFFSET2 = 10;
3064
- var wrapAnsi162 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
3065
- var wrapAnsi2562 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
3066
- var wrapAnsi16m2 = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
3067
- var styles3 = {
3068
- modifier: {
3069
- reset: [0, 0],
3070
- // 21 isn't widely supported and 22 does the same thing
3071
- bold: [1, 22],
3072
- dim: [2, 22],
3073
- italic: [3, 23],
3074
- underline: [4, 24],
3075
- overline: [53, 55],
3076
- inverse: [7, 27],
3077
- hidden: [8, 28],
3078
- strikethrough: [9, 29]
3079
- },
3080
- color: {
3081
- black: [30, 39],
3082
- red: [31, 39],
3083
- green: [32, 39],
3084
- yellow: [33, 39],
3085
- blue: [34, 39],
3086
- magenta: [35, 39],
3087
- cyan: [36, 39],
3088
- white: [37, 39],
3089
- // Bright color
3090
- blackBright: [90, 39],
3091
- gray: [90, 39],
3092
- // Alias of `blackBright`
3093
- grey: [90, 39],
3094
- // Alias of `blackBright`
3095
- redBright: [91, 39],
3096
- greenBright: [92, 39],
3097
- yellowBright: [93, 39],
3098
- blueBright: [94, 39],
3099
- magentaBright: [95, 39],
3100
- cyanBright: [96, 39],
3101
- whiteBright: [97, 39]
3102
- },
3103
- bgColor: {
3104
- bgBlack: [40, 49],
3105
- bgRed: [41, 49],
3106
- bgGreen: [42, 49],
3107
- bgYellow: [43, 49],
3108
- bgBlue: [44, 49],
3109
- bgMagenta: [45, 49],
3110
- bgCyan: [46, 49],
3111
- bgWhite: [47, 49],
3112
- // Bright color
3113
- bgBlackBright: [100, 49],
3114
- bgGray: [100, 49],
3115
- // Alias of `bgBlackBright`
3116
- bgGrey: [100, 49],
3117
- // Alias of `bgBlackBright`
3118
- bgRedBright: [101, 49],
3119
- bgGreenBright: [102, 49],
3120
- bgYellowBright: [103, 49],
3121
- bgBlueBright: [104, 49],
3122
- bgMagentaBright: [105, 49],
3123
- bgCyanBright: [106, 49],
3124
- bgWhiteBright: [107, 49]
3125
- }
3126
- };
3127
- var modifierNames2 = Object.keys(styles3.modifier);
3128
- var foregroundColorNames2 = Object.keys(styles3.color);
3129
- var backgroundColorNames2 = Object.keys(styles3.bgColor);
3130
- var colorNames2 = [...foregroundColorNames2, ...backgroundColorNames2];
3131
- function assembleStyles2() {
3132
- const codes = /* @__PURE__ */ new Map();
3133
- for (const [groupName, group] of Object.entries(styles3)) {
3134
- for (const [styleName, style] of Object.entries(group)) {
3135
- styles3[styleName] = {
3136
- open: `\x1B[${style[0]}m`,
3137
- close: `\x1B[${style[1]}m`
3138
- };
3139
- group[styleName] = styles3[styleName];
3140
- codes.set(style[0], style[1]);
3141
- }
3142
- Object.defineProperty(styles3, groupName, {
3143
- value: group,
3144
- enumerable: false
3145
- });
3146
- }
3147
- Object.defineProperty(styles3, "codes", {
3148
- value: codes,
3149
- enumerable: false
3150
- });
3151
- styles3.color.close = "\x1B[39m";
3152
- styles3.bgColor.close = "\x1B[49m";
3153
- styles3.color.ansi = wrapAnsi162();
3154
- styles3.color.ansi256 = wrapAnsi2562();
3155
- styles3.color.ansi16m = wrapAnsi16m2();
3156
- styles3.bgColor.ansi = wrapAnsi162(ANSI_BACKGROUND_OFFSET2);
3157
- styles3.bgColor.ansi256 = wrapAnsi2562(ANSI_BACKGROUND_OFFSET2);
3158
- styles3.bgColor.ansi16m = wrapAnsi16m2(ANSI_BACKGROUND_OFFSET2);
3159
- Object.defineProperties(styles3, {
3160
- rgbToAnsi256: {
3161
- value(red, green, blue) {
3162
- if (red === green && green === blue) {
3163
- if (red < 8) {
3164
- return 16;
3165
- }
3166
- if (red > 248) {
3167
- return 231;
3168
- }
3169
- return Math.round((red - 8) / 247 * 24) + 232;
3170
- }
3171
- return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
3172
- },
3173
- enumerable: false
3174
- },
3175
- hexToRgb: {
3176
- value(hex) {
3177
- const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
3178
- if (!matches) {
3179
- return [0, 0, 0];
3180
- }
3181
- let [colorString] = matches;
3182
- if (colorString.length === 3) {
3183
- colorString = [...colorString].map((character) => character + character).join("");
3184
- }
3185
- const integer = Number.parseInt(colorString, 16);
3186
- return [
3187
- /* eslint-disable no-bitwise */
3188
- integer >> 16 & 255,
3189
- integer >> 8 & 255,
3190
- integer & 255
3191
- /* eslint-enable no-bitwise */
3192
- ];
2972
+ function buildPanelRects({
2973
+ splitMode,
2974
+ frameWidth,
2975
+ feedStartRow,
2976
+ panelRows,
2977
+ messagePanelWidth,
2978
+ feedPanelWidth,
2979
+ inputStartRow,
2980
+ inputRows
2981
+ }) {
2982
+ const top = feedStartRow;
2983
+ const bottom = feedStartRow + Math.max(0, panelRows - 1);
2984
+ const innerLeft = 2;
2985
+ const inputRect = inputStartRow !== void 0 && inputRows !== void 0 && inputRows > 0 ? {
2986
+ left: innerLeft,
2987
+ right: Math.max(innerLeft, frameWidth - 1),
2988
+ top: inputStartRow,
2989
+ bottom: inputStartRow + inputRows - 1
2990
+ } : void 0;
2991
+ if (!splitMode) {
2992
+ return {
2993
+ feed: {
2994
+ left: innerLeft,
2995
+ right: Math.max(innerLeft, frameWidth - 1),
2996
+ top,
2997
+ bottom
3193
2998
  },
3194
- enumerable: false
2999
+ input: inputRect
3000
+ };
3001
+ }
3002
+ const messageLeft = innerLeft;
3003
+ const messageRight = messageLeft + messagePanelWidth;
3004
+ const feedLeft = messageRight + 1;
3005
+ const feedRight = feedLeft + Math.max(0, feedPanelWidth - 1);
3006
+ return {
3007
+ messages: {
3008
+ left: messageLeft,
3009
+ right: messageRight,
3010
+ top,
3011
+ bottom
3195
3012
  },
3196
- hexToAnsi256: {
3197
- value: (hex) => styles3.rgbToAnsi256(...styles3.hexToRgb(hex)),
3198
- enumerable: false
3199
- },
3200
- ansi256ToAnsi: {
3201
- value(code) {
3202
- if (code < 8) {
3203
- return 30 + code;
3204
- }
3205
- if (code < 16) {
3206
- return 90 + (code - 8);
3207
- }
3208
- let red;
3209
- let green;
3210
- let blue;
3211
- if (code >= 232) {
3212
- red = ((code - 232) * 10 + 8) / 255;
3213
- green = red;
3214
- blue = red;
3215
- } else {
3216
- code -= 16;
3217
- const remainder = code % 36;
3218
- red = Math.floor(code / 36) / 5;
3219
- green = Math.floor(remainder / 6) / 5;
3220
- blue = remainder % 6 / 5;
3221
- }
3222
- const value = Math.max(red, green, blue) * 2;
3223
- if (value === 0) {
3224
- return 30;
3225
- }
3226
- let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
3227
- if (value === 2) {
3228
- result += 60;
3229
- }
3230
- return result;
3231
- },
3232
- enumerable: false
3233
- },
3234
- rgbToAnsi: {
3235
- value: (red, green, blue) => styles3.ansi256ToAnsi(styles3.rgbToAnsi256(red, green, blue)),
3236
- enumerable: false
3237
- },
3238
- hexToAnsi: {
3239
- value: (hex) => styles3.ansi256ToAnsi(styles3.hexToAnsi256(hex)),
3240
- enumerable: false
3241
- }
3242
- });
3243
- return styles3;
3244
- }
3245
- var ansiStyles2 = assembleStyles2();
3246
- var ansi_styles_default2 = ansiStyles2;
3247
-
3248
- // node_modules/is-fullwidth-code-point/index.js
3249
- function isFullwidthCodePoint(codePoint) {
3250
- if (!Number.isInteger(codePoint)) {
3251
- return false;
3252
- }
3253
- return isFullWidth(codePoint) || isWide(codePoint);
3254
- }
3255
-
3256
- // node_modules/slice-ansi/index.js
3257
- var ESCAPES = /* @__PURE__ */ new Set([27, 155]);
3258
- var CODE_POINT_0 = "0".codePointAt(0);
3259
- var CODE_POINT_9 = "9".codePointAt(0);
3260
- var MAX_ANSI_SEQUENCE_LENGTH = 19;
3261
- var endCodesSet = /* @__PURE__ */ new Set();
3262
- var endCodesMap = /* @__PURE__ */ new Map();
3263
- for (const [start, end] of ansi_styles_default2.codes) {
3264
- endCodesSet.add(ansi_styles_default2.color.ansi(end));
3265
- endCodesMap.set(ansi_styles_default2.color.ansi(start), ansi_styles_default2.color.ansi(end));
3266
- }
3267
- function getEndCode(code) {
3268
- if (endCodesSet.has(code)) {
3269
- return code;
3270
- }
3271
- if (endCodesMap.has(code)) {
3272
- return endCodesMap.get(code);
3273
- }
3274
- code = code.slice(2);
3275
- if (code.includes(";")) {
3276
- code = code[0] + "0";
3277
- }
3278
- const returnValue = ansi_styles_default2.codes.get(Number.parseInt(code, 10));
3279
- if (returnValue) {
3280
- return ansi_styles_default2.color.ansi(returnValue);
3281
- }
3282
- return ansi_styles_default2.reset.open;
3283
- }
3284
- function findNumberIndex(string) {
3285
- for (let index = 0; index < string.length; index++) {
3286
- const codePoint = string.codePointAt(index);
3287
- if (codePoint >= CODE_POINT_0 && codePoint <= CODE_POINT_9) {
3288
- return index;
3289
- }
3290
- }
3291
- return -1;
3292
- }
3293
- function parseAnsiCode(string, offset) {
3294
- string = string.slice(offset, offset + MAX_ANSI_SEQUENCE_LENGTH);
3295
- const startIndex = findNumberIndex(string);
3296
- if (startIndex !== -1) {
3297
- let endIndex = string.indexOf("m", startIndex);
3298
- if (endIndex === -1) {
3299
- endIndex = string.length;
3300
- }
3301
- return string.slice(0, endIndex + 1);
3302
- }
3303
- }
3304
- function tokenize(string, endCharacter = Number.POSITIVE_INFINITY) {
3305
- const returnValue = [];
3306
- let index = 0;
3307
- let visibleCount = 0;
3308
- while (index < string.length) {
3309
- const codePoint = string.codePointAt(index);
3310
- if (ESCAPES.has(codePoint)) {
3311
- const code = parseAnsiCode(string, index);
3312
- if (code) {
3313
- returnValue.push({
3314
- type: "ansi",
3315
- code,
3316
- endCode: getEndCode(code)
3317
- });
3318
- index += code.length;
3319
- continue;
3320
- }
3321
- }
3322
- const isFullWidth2 = isFullwidthCodePoint(codePoint);
3323
- const character = String.fromCodePoint(codePoint);
3324
- returnValue.push({
3325
- type: "character",
3326
- value: character,
3327
- isFullWidth: isFullWidth2
3328
- });
3329
- index += character.length;
3330
- visibleCount += isFullWidth2 ? 2 : character.length;
3331
- if (visibleCount >= endCharacter) {
3332
- break;
3333
- }
3334
- }
3335
- return returnValue;
3336
- }
3337
- function reduceAnsiCodes(codes) {
3338
- let returnValue = [];
3339
- for (const code of codes) {
3340
- if (code.code === ansi_styles_default2.reset.open) {
3341
- returnValue = [];
3342
- } else if (endCodesSet.has(code.code)) {
3343
- returnValue = returnValue.filter((returnValueCode) => returnValueCode.endCode !== code.code);
3344
- } else {
3345
- returnValue = returnValue.filter((returnValueCode) => returnValueCode.endCode !== code.endCode);
3346
- returnValue.push(code);
3347
- }
3348
- }
3349
- return returnValue;
3350
- }
3351
- function undoAnsiCodes(codes) {
3352
- const reduced = reduceAnsiCodes(codes);
3353
- const endCodes = reduced.map(({ endCode }) => endCode);
3354
- return endCodes.reverse().join("");
3355
- }
3356
- function sliceAnsi(string, start, end) {
3357
- const tokens = tokenize(string, end);
3358
- let activeCodes = [];
3359
- let position = 0;
3360
- let returnValue = "";
3361
- let include = false;
3362
- for (const token of tokens) {
3363
- if (end !== void 0 && position >= end) {
3364
- break;
3365
- }
3366
- if (token.type === "ansi") {
3367
- activeCodes.push(token);
3368
- if (include) {
3369
- returnValue += token.code;
3370
- }
3371
- } else {
3372
- if (!include && position >= start) {
3373
- include = true;
3374
- activeCodes = reduceAnsiCodes(activeCodes);
3375
- returnValue = activeCodes.map(({ code }) => code).join("");
3376
- }
3377
- if (include) {
3378
- returnValue += token.value;
3379
- }
3380
- position += token.isFullWidth ? 2 : token.value.length;
3381
- }
3382
- }
3383
- returnValue += undoAnsiCodes(activeCodes);
3384
- return returnValue;
3385
- }
3386
-
3387
- // src/shared/utils/format.ts
3388
- var SIMPLE_ASCII_RE = /^[\x20-\x7E]*$/;
3389
- var WIDTH_CACHE_MAX = 2e3;
3390
- var WIDTH_CACHE_MAX_TEXT_LENGTH = 512;
3391
- var SPACE_CACHE_MAX = 128;
3392
- var widthCache = /* @__PURE__ */ new Map();
3393
- var spaceCache = [""];
3394
- function cachedStringWidth(text) {
3395
- if (text.length > WIDTH_CACHE_MAX_TEXT_LENGTH) {
3396
- return stringWidth(text);
3397
- }
3398
- const cached = widthCache.get(text);
3399
- if (cached !== void 0) {
3400
- widthCache.delete(text);
3401
- widthCache.set(text, cached);
3402
- return cached;
3403
- }
3404
- const measured = stringWidth(text);
3405
- widthCache.set(text, measured);
3406
- if (widthCache.size > WIDTH_CACHE_MAX) {
3407
- const oldest = widthCache.keys().next().value;
3408
- if (oldest !== void 0) {
3409
- widthCache.delete(oldest);
3410
- }
3411
- }
3412
- return measured;
3413
- }
3414
- function spaces(count) {
3415
- if (count <= 0) return "";
3416
- if (count < SPACE_CACHE_MAX) {
3417
- if (count in spaceCache) {
3418
- return spaceCache[count];
3419
- }
3420
- const generated = " ".repeat(count);
3421
- spaceCache[count] = generated;
3422
- return generated;
3423
- }
3424
- return " ".repeat(count);
3425
- }
3426
- function isSimpleAscii(text) {
3427
- return SIMPLE_ASCII_RE.test(text);
3428
- }
3429
- function fitAscii(text, width) {
3430
- if (width <= 0) return "";
3431
- const len = text.length;
3432
- if (len <= width) {
3433
- const pad = width - len;
3434
- return pad > 0 ? text + spaces(pad) : text;
3435
- }
3436
- if (width <= 3) return text.slice(0, width);
3437
- return text.slice(0, width - 3) + "...";
3438
- }
3439
- function compactText(value, max) {
3440
- const clean = value.replace(/\s+/g, " ").trim();
3441
- if (max <= 0) return "";
3442
- if (isSimpleAscii(clean)) {
3443
- if (clean.length <= max) return clean;
3444
- if (max <= 3) return clean.slice(0, max);
3445
- return clean.slice(0, max - 3) + "...";
3446
- }
3447
- const w = cachedStringWidth(clean);
3448
- if (w <= max) return clean;
3449
- if (max <= 3) return sliceAnsi(clean, 0, max);
3450
- return sliceAnsi(clean, 0, max - 3) + "...";
3451
- }
3452
- function fit(text, width) {
3453
- if (isSimpleAscii(text)) {
3454
- return fitAscii(text, width);
3455
- }
3456
- if (width <= 0) return "";
3457
- const w = cachedStringWidth(text);
3458
- if (w <= width) {
3459
- const pad = width - w;
3460
- return pad > 0 ? text + spaces(pad) : text;
3461
- }
3462
- if (width <= 3) return sliceAnsi(text, 0, width);
3463
- return sliceAnsi(text, 0, width - 3) + "...";
3464
- }
3465
- function fitAnsi(text, width) {
3466
- if (isSimpleAscii(text)) {
3467
- return fitAscii(text, width);
3468
- }
3469
- if (width <= 0) return "";
3470
- const visualWidth = cachedStringWidth(text);
3471
- if (visualWidth <= width) {
3472
- const pad = width - visualWidth;
3473
- return pad > 0 ? text + spaces(pad) : text;
3474
- }
3475
- if (width <= 3) return sliceAnsi(text, 0, width);
3476
- return sliceAnsi(text, 0, width - 3) + "...";
3477
- }
3478
- function centerAnsi(text, width) {
3479
- if (width <= 0) return "";
3480
- const visualWidth = cachedStringWidth(text);
3481
- if (visualWidth >= width) return sliceAnsi(text, 0, width);
3482
- const left = Math.floor((width - visualWidth) / 2);
3483
- const right = width - left - visualWidth;
3484
- return spaces(left) + text + spaces(right);
3485
- }
3486
- function formatClock(timestamp) {
3487
- const d = new Date(timestamp);
3488
- const hh = String(d.getHours()).padStart(2, "0");
3489
- const mm = String(d.getMinutes()).padStart(2, "0");
3490
- return `${hh}:${mm}`;
3491
- }
3492
- function formatRunLabel(runId) {
3493
- if (!runId) return "R-";
3494
- const direct = runId.match(/^(R\d+)$/i);
3495
- if (direct) return direct[1].toUpperCase();
3496
- const tail = runId.replace(/[^a-zA-Z0-9]/g, "").slice(-4);
3497
- return `R${tail || "-"}`;
3498
- }
3499
- function actorLabel(actorId) {
3500
- if (actorId === "user") return "USER";
3501
- if (actorId === "agent:root") return "AGENT";
3502
- if (actorId === "system") return "SYSTEM";
3503
- if (actorId.startsWith("subagent:")) {
3504
- return "SUB-AGENT";
3505
- }
3506
- return compactText(actorId.toUpperCase(), 12);
3507
- }
3508
- function summarizeValue(value) {
3509
- if (typeof value === "string") return compactText(JSON.stringify(value), 28);
3510
- if (typeof value === "number" || typeof value === "boolean") {
3511
- return String(value);
3512
- }
3513
- if (value === null || value === void 0) return String(value);
3514
- if (Array.isArray(value)) return `[${value.length}]`;
3515
- if (typeof value === "object") return "{...}";
3516
- return compactText(String(value), 20);
3517
- }
3518
- function summarizeToolInput(input) {
3519
- const entries = Object.entries(input);
3520
- const pairs = entries.slice(0, 2).map(([key, value]) => `${key}=${summarizeValue(value)}`);
3521
- const overflow = entries.length - 2;
3522
- if (overflow > 0) {
3523
- pairs.push(`+${overflow}`);
3524
- }
3525
- return pairs.join(" ");
3526
- }
3527
- function shortenPath(filePath) {
3528
- const segments = filePath.split("/").filter(Boolean);
3529
- if (segments.length <= 2) return segments.join("/");
3530
- return "\u2026/" + segments.slice(-2).join("/");
3531
- }
3532
- function compactCommandPaths(cmd) {
3533
- return cmd.replace(
3534
- /\/(?:[\w.@-]+\/){2,}[\w.@-]+/g,
3535
- (match) => shortenPath(match)
3536
- );
3537
- }
3538
- function shortenPathStructured(filePath) {
3539
- const segments = filePath.split("/").filter(Boolean);
3540
- if (segments.length === 0) return { prefix: "", filename: filePath };
3541
- const filename = segments[segments.length - 1];
3542
- if (segments.length === 1) return { prefix: "", filename };
3543
- if (segments.length === 2) return { prefix: segments[0] + "/", filename };
3544
- return { prefix: "\u2026/" + segments[segments.length - 2] + "/", filename };
3545
- }
3546
- var filePathExtractor = (input) => shortenPath(String(input.file_path ?? ""));
3547
- var PRIMARY_INPUT_EXTRACTORS = {
3548
- Read: filePathExtractor,
3549
- Write: filePathExtractor,
3550
- Edit: filePathExtractor,
3551
- Bash: (input) => compactText(compactCommandPaths(String(input.command ?? "")), 96),
3552
- Glob: (input) => String(input.pattern ?? ""),
3553
- Grep: (input) => {
3554
- const p = `"${String(input.pattern ?? "")}"`;
3555
- const g = input.glob ? ` ${String(input.glob)}` : "";
3556
- return p + g;
3557
- },
3558
- Task: (input) => compactText(String(input.description ?? ""), 96),
3559
- Agent: (input) => compactText(String(input.description ?? ""), 96),
3560
- WebSearch: (input) => `"${String(input.query ?? "")}"`,
3561
- WebFetch: (input) => compactText(String(input.url ?? ""), 96),
3562
- Skill: (input) => {
3563
- const name = String(input.skill ?? "");
3564
- const colonIdx = name.indexOf(":");
3565
- return compactText(colonIdx >= 0 ? name.slice(colonIdx + 1) : name, 80);
3566
- },
3567
- NotebookEdit: (input) => {
3568
- const path10 = String(input.notebook_path ?? "");
3569
- return path10 ? shortenPath(path10) : "";
3570
- },
3571
- AskUserQuestion: (input) => {
3572
- const questions = input.questions;
3573
- const n = Array.isArray(questions) ? questions.length : 0;
3574
- return `${n} question${n !== 1 ? "s" : ""}`;
3575
- }
3576
- };
3577
- var eidExtractor = (input) => {
3578
- const eid = String(input.eid ?? "");
3579
- return eid ? `eid:${eid.slice(0, 6)}\u2026` : "";
3580
- };
3581
- var MCP_INPUT_EXTRACTORS = {
3582
- navigate: (input) => {
3583
- const url = String(input.url ?? "");
3584
- try {
3585
- const u = new URL(url);
3586
- return u.hostname.replace(/^www\./, "");
3587
- } catch {
3588
- return compactText(url, 96);
3589
- }
3590
- },
3591
- find_elements: (input) => {
3592
- const parts = [];
3593
- if (input.kind) parts.push(String(input.kind));
3594
- if (input.label) parts.push(`"${String(input.label)}"`);
3595
- if (parts.length === 0 && input.region) parts.push(String(input.region));
3596
- return parts.join(" ") || "elements";
3597
- },
3598
- get_element_details: eidExtractor,
3599
- click: eidExtractor,
3600
- type: (input) => {
3601
- const text = String(input.text ?? "");
3602
- const eid = input.eid ? String(input.eid).slice(0, 5) + "\u2026" : "";
3603
- const quoted = `"${compactText(text, 72)}"`;
3604
- return eid ? `${quoted} \u2192 ${eid}` : quoted;
3605
- },
3606
- hover: eidExtractor,
3607
- select: (input) => {
3608
- const value = String(input.value ?? "");
3609
- return value ? `"${compactText(value, 72)}"` : "";
3610
- },
3611
- press: (input) => String(input.key ?? ""),
3612
- scroll_page: (input) => String(input.direction ?? ""),
3613
- take_screenshot: () => "",
3614
- close_session: () => "session",
3615
- close_page: () => ""
3616
- };
3617
- function summarizeToolPrimaryInput(toolName, toolInput) {
3618
- if (toolName in PRIMARY_INPUT_EXTRACTORS) {
3619
- if (Object.keys(toolInput).length === 0) return "";
3620
- return PRIMARY_INPUT_EXTRACTORS[toolName](toolInput);
3621
- }
3622
- const parsed = parseToolName(toolName);
3623
- if (parsed.isMcp && parsed.mcpAction) {
3624
- if (parsed.mcpAction in MCP_INPUT_EXTRACTORS) {
3625
- return MCP_INPUT_EXTRACTORS[parsed.mcpAction](toolInput);
3626
- }
3627
- }
3628
- if (Object.keys(toolInput).length === 0) return "";
3629
- return summarizeToolInput(toolInput);
3630
- }
3631
- var MAX_INPUT_ROWS = 6;
3632
- var CURSOR_ON = "\x1B[7m";
3633
- var CURSOR_OFF = "\x1B[27m";
3634
- function cursorToVisualPosition(value, cursorOffset, width) {
3635
- if (width <= 0) return { line: 0, col: cursorOffset, totalLines: 1 };
3636
- const segments = value.split("\n");
3637
- let visualLine = 0;
3638
- let globalOffset = 0;
3639
- for (let s = 0; s < segments.length; s++) {
3640
- const seg = segments[s];
3641
- const segEnd = globalOffset + seg.length;
3642
- if (cursorOffset <= segEnd) {
3643
- const posInSeg = cursorOffset - globalOffset;
3644
- const totalLines2 = visualLine + countSegmentVisualLines(segments, s, width);
3645
- if (seg.length === 0) {
3646
- return { line: visualLine, col: 0, totalLines: totalLines2 };
3647
- }
3648
- const lineInSeg = Math.min(
3649
- Math.floor(posInSeg / width),
3650
- segmentVisualLines(seg.length, width) - 1
3651
- );
3652
- const colInLine = posInSeg - lineInSeg * width;
3653
- return { line: visualLine + lineInSeg, col: colInLine, totalLines: totalLines2 };
3654
- }
3655
- visualLine += segmentVisualLines(seg.length, width);
3656
- globalOffset = segEnd + 1;
3657
- }
3658
- const totalLines = wrapText(value, width).length;
3659
- return { line: Math.max(0, totalLines - 1), col: 0, totalLines };
3660
- }
3661
- function segmentVisualLines(segLen, width) {
3662
- return segLen === 0 ? 1 : Math.ceil(segLen / width);
3663
- }
3664
- function countSegmentVisualLines(segments, fromIdx, width) {
3665
- let count = 0;
3666
- for (let i = fromIdx; i < segments.length; i++) {
3667
- count += segmentVisualLines(segments[i].length, width);
3668
- }
3669
- return count;
3670
- }
3671
- function visualPositionToOffset(value, targetLine, targetCol, width) {
3672
- if (width <= 0) return targetCol;
3673
- const segments = value.split("\n");
3674
- let visualLine = 0;
3675
- let globalOffset = 0;
3676
- for (let s = 0; s < segments.length; s++) {
3677
- const seg = segments[s];
3678
- const numWrappedLines = segmentVisualLines(seg.length, width);
3679
- if (targetLine < visualLine + numWrappedLines) {
3680
- const lineInSeg = targetLine - visualLine;
3681
- const lineStart = lineInSeg * width;
3682
- const lineLen = Math.min(width, seg.length - lineStart);
3683
- return globalOffset + lineStart + Math.min(targetCol, lineLen);
3684
- }
3685
- visualLine += numWrappedLines;
3686
- globalOffset += seg.length + 1;
3687
- }
3688
- return value.length;
3689
- }
3690
- function renderInputLines(value, cursorOffset, width, showCursor, placeholder) {
3691
- if (width <= 0) return [""];
3692
- if (value.length === 0) {
3693
- if (!showCursor) return [fit(placeholder, width)];
3694
- const cursor = `${CURSOR_ON} ${CURSOR_OFF}`;
3695
- return [cursor + fit(placeholder, width - 1)];
3696
- }
3697
- if (!showCursor) {
3698
- const rawLines2 = wrapText(value, width);
3699
- const visible = rawLines2.slice(0, MAX_INPUT_ROWS);
3700
- return visible.map((line) => fit(line, width));
3701
- }
3702
- const rawLines = wrapText(value, width);
3703
- const { line: cursorLine, col: cursorCol } = cursorToVisualPosition(
3704
- value,
3705
- cursorOffset,
3706
- width
3707
- );
3708
- let viewStart = 0;
3709
- if (rawLines.length > MAX_INPUT_ROWS) {
3710
- viewStart = Math.max(
3711
- 0,
3712
- Math.min(
3713
- cursorLine - Math.floor(MAX_INPUT_ROWS / 2),
3714
- rawLines.length - MAX_INPUT_ROWS
3715
- )
3716
- );
3717
- }
3718
- const visibleLines = rawLines.slice(viewStart, viewStart + MAX_INPUT_ROWS);
3719
- return visibleLines.map((line, i) => {
3720
- const globalIdx = viewStart + i;
3721
- if (globalIdx === cursorLine) {
3722
- const before = line.slice(0, cursorCol);
3723
- const charAtCursor = cursorCol < line.length ? line[cursorCol] : " ";
3724
- const after = cursorCol < line.length ? line.slice(cursorCol + 1) : "";
3725
- const rendered = `${before}${CURSOR_ON}${charAtCursor}${CURSOR_OFF}${after}`;
3726
- return fitAnsi(rendered, width);
3727
- }
3728
- return fit(line, width);
3729
- });
3730
- }
3731
- function wrapText(text, width) {
3732
- if (width <= 0) return [text];
3733
- const lines = [];
3734
- for (const segment of text.split("\n")) {
3735
- if (segment.length === 0) {
3736
- lines.push("");
3737
- continue;
3738
- }
3739
- for (let i = 0; i < segment.length; i += width) {
3740
- lines.push(segment.slice(i, i + width));
3741
- }
3742
- }
3743
- return lines;
3744
- }
3745
- function computeInputRows(value, width) {
3746
- if (!value || width <= 0) return 1;
3747
- return Math.max(1, Math.min(wrapText(value, width).length, MAX_INPUT_ROWS));
3748
- }
3749
- function isCommandPrefix(value) {
3750
- return value.startsWith("/") && !value.includes(" ");
3751
- }
3752
-
3753
- // src/ui/hooks/useTextInput.ts
3754
- import { useReducer, useCallback as useCallback6, useEffect as useEffect5, useRef as useRef4 } from "react";
3755
- import { useInput as useInput6, useStdin } from "ink";
3756
-
3757
- // src/ui/hooks/usePanelMouseWheel.ts
3758
- import process4 from "process";
3759
- import { useEffect as useEffect4 } from "react";
3760
- var ENABLE_MOUSE_TRACKING = "\x1B[?1000h\x1B[?1006h";
3761
- var DISABLE_MOUSE_TRACKING = "\x1B[?1006l\x1B[?1000l";
3762
- var PANEL_MOUSE_SCROLL_LINES = 3;
3763
- function contains(rect, col, row) {
3764
- return col >= rect.left && col <= rect.right && row >= rect.top && row <= rect.bottom;
3765
- }
3766
- function parseSgrWheelEvents(data) {
3767
- const sgrMouseRe = /\x1B\[<(64|65);(\d+);(\d+)[Mm]/g;
3768
- const events = [];
3769
- let match;
3770
- while ((match = sgrMouseRe.exec(data)) !== null) {
3771
- events.push({
3772
- direction: match[1] === "64" ? "up" : "down",
3773
- col: Number.parseInt(match[2], 10),
3774
- row: Number.parseInt(match[3], 10)
3775
- });
3776
- }
3777
- return events;
3778
- }
3779
- function looksLikeMouseEscapeSequence(input) {
3780
- if (input.length === 0) return false;
3781
- if (parseSgrWheelEvents(input).length > 0) return true;
3782
- return /^\[<\d+;\d+;\d+[Mm]$/.test(input) || /^\d+;\d+;\d+[Mm]$/.test(input);
3783
- }
3784
- function parseSgrClickEvents(data) {
3785
- const sgrMouseRe = /\x1B\[<0;(\d+);(\d+)M/g;
3786
- const events = [];
3787
- let match;
3788
- while ((match = sgrMouseRe.exec(data)) !== null) {
3789
- events.push({
3790
- button: "left",
3791
- col: Number.parseInt(match[1], 10),
3792
- row: Number.parseInt(match[2], 10)
3793
- });
3794
- }
3795
- return events;
3796
- }
3797
- function resolvePanelTarget(rects, col, row) {
3798
- if (rects.input && contains(rects.input, col, row)) {
3799
- return "input";
3800
- }
3801
- if (rects.messages && contains(rects.messages, col, row)) {
3802
- return "messages";
3803
- }
3804
- if (contains(rects.feed, col, row)) {
3805
- return "feed";
3806
- }
3807
- return null;
3808
- }
3809
- function buildPanelRects({
3810
- splitMode,
3811
- frameWidth,
3812
- feedStartRow,
3813
- panelRows,
3814
- messagePanelWidth,
3815
- feedPanelWidth,
3816
- inputStartRow,
3817
- inputRows
3818
- }) {
3819
- const top = feedStartRow;
3820
- const bottom = feedStartRow + Math.max(0, panelRows - 1);
3821
- const innerLeft = 2;
3822
- const inputRect = inputStartRow !== void 0 && inputRows !== void 0 && inputRows > 0 ? {
3823
- left: innerLeft,
3824
- right: Math.max(innerLeft, frameWidth - 1),
3825
- top: inputStartRow,
3826
- bottom: inputStartRow + inputRows - 1
3827
- } : void 0;
3828
- if (!splitMode) {
3829
- return {
3830
- feed: {
3831
- left: innerLeft,
3832
- right: Math.max(innerLeft, frameWidth - 1),
3833
- top,
3834
- bottom
3835
- },
3836
- input: inputRect
3837
- };
3838
- }
3839
- const messageLeft = innerLeft;
3840
- const messageRight = messageLeft + messagePanelWidth;
3841
- const feedLeft = messageRight + 1;
3842
- const feedRight = feedLeft + Math.max(0, feedPanelWidth - 1);
3843
- return {
3844
- messages: {
3845
- left: messageLeft,
3846
- right: messageRight,
3847
- top,
3848
- bottom
3849
- },
3850
- feed: {
3851
- left: feedLeft,
3852
- right: feedRight,
3853
- top,
3854
- bottom
3013
+ feed: {
3014
+ left: feedLeft,
3015
+ right: feedRight,
3016
+ top,
3017
+ bottom
3855
3018
  },
3856
3019
  input: inputRect
3857
3020
  };
@@ -4639,7 +3802,7 @@ function useTodoPanel({
4639
3802
  const todoItemsCacheRef = useRef7(null);
4640
3803
  const nextTodoItems = (() => {
4641
3804
  const fromTasks = tasks.map((task, index) => ({
4642
- id: `task-${index}-${task.content.replace(/[^a-zA-Z0-9]/g, "").slice(0, 16)}`,
3805
+ id: (task.taskId ? `task-${task.taskId}` : void 0) ?? `task-${index}-${task.content.replace(/[^a-zA-Z0-9]/g, "").slice(0, 16)}`,
4643
3806
  text: task.content,
4644
3807
  priority: "P1",
4645
3808
  status: toTodoStatus(task.status),
@@ -4944,2360 +4107,152 @@ function useMessageKeyboard({
4944
4107
  if (key.upArrow) {
4945
4108
  callbacks.moveCursor(-1);
4946
4109
  return;
4947
- }
4948
- if (key.downArrow) {
4949
- callbacks.moveCursor(1);
4950
- return;
4951
- }
4952
- } finally {
4953
- done();
4954
- }
4955
- },
4956
- { isActive }
4957
- );
4958
- }
4959
-
4960
- // src/ui/hooks/useTodoKeyboard.ts
4961
- import { useRef as useRef8 } from "react";
4962
- import { useInput as useInput10 } from "ink";
4963
- function useTodoKeyboard({
4964
- isActive,
4965
- todoCursor,
4966
- visibleTodoItems,
4967
- filteredEntries,
4968
- callbacks
4969
- }) {
4970
- const visibleTodoItemsRef = useRef8(visibleTodoItems);
4971
- visibleTodoItemsRef.current = visibleTodoItems;
4972
- const filteredEntriesRef = useRef8(filteredEntries);
4973
- filteredEntriesRef.current = filteredEntries;
4974
- useInput10(
4975
- (input, key) => {
4976
- const done = startInputMeasure("todo.keyboard", input, key);
4977
- try {
4978
- if (key.escape) {
4979
- callbacks.focusFeed();
4980
- return;
4981
- }
4982
- if (key.tab) {
4983
- callbacks.cycleFocus();
4984
- return;
4985
- }
4986
- if (key.upArrow) {
4987
- callbacks.moveTodoCursor(-1);
4988
- return;
4989
- }
4990
- if (key.downArrow) {
4991
- callbacks.moveTodoCursor(1);
4992
- return;
4993
- }
4994
- if (input === " ") {
4995
- callbacks.toggleTodoStatus(todoCursor);
4996
- return;
4997
- }
4998
- if (key.return) {
4999
- if (todoCursor < 0 || todoCursor >= visibleTodoItemsRef.current.length) {
5000
- return;
5001
- }
5002
- const selected = visibleTodoItemsRef.current[todoCursor];
5003
- if (!selected.linkedEventId) return;
5004
- const idx = filteredEntriesRef.current.findIndex(
5005
- (entry) => entry.id === selected.linkedEventId
5006
- );
5007
- if (idx >= 0) {
5008
- callbacks.revealFeedCursor(idx);
5009
- }
5010
- return;
5011
- }
5012
- if (input.toLowerCase() === "a") {
5013
- callbacks.openNormalInput();
5014
- callbacks.setInputValue("");
5015
- return;
5016
- }
5017
- } finally {
5018
- done();
5019
- }
5020
- },
5021
- { isActive }
5022
- );
5023
- }
5024
-
5025
- // src/ui/hooks/useSpinner.ts
5026
- import { useState as useState8, useEffect as useEffect7 } from "react";
5027
- var BRAILLE_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
5028
- var DEFAULT_SPINNER_INTERVAL_MS = 1e3;
5029
- function useSpinner(active, intervalMs = DEFAULT_SPINNER_INTERVAL_MS) {
5030
- const [frameIndex, setFrameIndex] = useState8(0);
5031
- useEffect7(() => {
5032
- if (!active) {
5033
- setFrameIndex(0);
5034
- return;
5035
- }
5036
- const timer = setInterval(() => {
5037
- startPerfCycle("timer:spinner", { scope: "spinner" });
5038
- setFrameIndex((i) => (i + 1) % BRAILLE_FRAMES.length);
5039
- }, intervalMs);
5040
- return () => clearInterval(timer);
5041
- }, [active, intervalMs]);
5042
- if (!active) return "";
5043
- return BRAILLE_FRAMES[frameIndex] ?? "\u280B";
5044
- }
5045
-
5046
- // src/ui/hooks/useTodoDisplayItems.ts
5047
- import { useEffect as useEffect8, useMemo as useMemo8, useState as useState9 } from "react";
5048
- function hasTickingElapsedItems(items) {
5049
- return items.some(
5050
- (item) => item.status === "doing" && item.startedAtMs !== void 0
5051
- );
5052
- }
5053
- function buildTodoDisplayItems(items, nowMs, isWorking, pausedAtMs) {
5054
- let changed = false;
5055
- const nextItems = items.map((item) => {
5056
- const hasElapsed = item.startedAtMs !== void 0 && (item.status === "doing" || item.status === "done" || item.status === "failed");
5057
- const endMs = item.completedAtMs ?? (isWorking ? nowMs : pausedAtMs ?? nowMs);
5058
- const elapsed = hasElapsed ? formatElapsed(Math.max(0, endMs - item.startedAtMs)) : void 0;
5059
- if (elapsed === item.elapsed) return item;
5060
- changed = true;
5061
- return { ...item, elapsed };
5062
- });
5063
- return changed ? nextItems : items;
5064
- }
5065
- function useTodoDisplayItems({
5066
- items,
5067
- isWorking,
5068
- pausedAtMs,
5069
- active,
5070
- tickMs = 1e3
5071
- }) {
5072
- const [nowMs, setNowMs] = useState9(() => Date.now());
5073
- const hasDoingItems = useMemo8(() => hasTickingElapsedItems(items), [items]);
5074
- useEffect8(() => {
5075
- if (!active || !isWorking || !hasDoingItems) return;
5076
- const id = setInterval(() => {
5077
- startPerfCycle("timer:todo-header", {
5078
- scope: "todo.elapsed",
5079
- items: items.length
5080
- });
5081
- setNowMs(Date.now());
5082
- }, tickMs);
5083
- return () => clearInterval(id);
5084
- }, [active, isWorking, hasDoingItems, items.length, tickMs]);
5085
- return useMemo8(
5086
- () => buildTodoDisplayItems(items, nowMs, isWorking, pausedAtMs),
5087
- [items, nowMs, isWorking, pausedAtMs]
5088
- );
5089
- }
5090
-
5091
- // src/ui/hooks/useTimeline.ts
5092
- import { useMemo as useMemo9, useRef as useRef9, useCallback as useCallback10 } from "react";
5093
-
5094
- // src/shared/utils/toolResponse.ts
5095
- function isRecord(value) {
5096
- return typeof value === "object" && value !== null;
5097
- }
5098
- function formatToolResponse(response) {
5099
- if (response == null) return "";
5100
- if (typeof response === "string") return response.trim();
5101
- if (Array.isArray(response)) {
5102
- const parts = [];
5103
- for (const block of response) {
5104
- if (!isRecord(block)) continue;
5105
- if (block["type"] === "image") {
5106
- parts.push("[image]");
5107
- } else if (typeof block["text"] === "string") {
5108
- parts.push(block["text"]);
5109
- }
5110
- }
5111
- if (parts.length > 0) return parts.join("\n").trim();
5112
- return JSON.stringify(response, null, 2);
5113
- }
5114
- if (isRecord(response)) {
5115
- if (typeof response["text"] === "string" && response["type"] === "text") {
5116
- return response["text"].trim();
5117
- }
5118
- if ("content" in response && response["content"] != null) {
5119
- return formatToolResponse(response["content"]);
5120
- }
5121
- return Object.entries(response).map(([key, val]) => {
5122
- const valStr = typeof val === "string" ? val : JSON.stringify(val);
5123
- return ` ${key}: ${valStr}`;
5124
- }).join("\n");
5125
- }
5126
- return String(response);
5127
- }
5128
- function isBashToolResponse(response) {
5129
- return isRecord(response) && typeof response["stdout"] === "string";
5130
- }
5131
-
5132
- // src/core/feed/toolSummary.ts
5133
- function prop(obj, key) {
5134
- if (typeof obj === "object" && obj !== null) {
5135
- return obj[key];
5136
- }
5137
- return void 0;
5138
- }
5139
- function extractFileContent(response) {
5140
- if (Array.isArray(response)) {
5141
- for (const block of response) {
5142
- const fc = prop(prop(block, "file"), "content");
5143
- if (typeof fc === "string") return fc;
5144
- const text = prop(block, "text");
5145
- if (typeof text === "string") return text;
5146
- }
5147
- }
5148
- return void 0;
5149
- }
5150
- function summarizeBash(_input, response) {
5151
- if (isBashToolResponse(response)) {
5152
- const exitCode = prop(response, "exitCode") ?? 0;
5153
- const stderr = response.stderr.trim();
5154
- const firstLine = stderr.split("\n")[0] ?? "";
5155
- if (stderr && Number(exitCode) !== 0) {
5156
- return `exit ${exitCode} \u2014 ${firstLine}`;
5157
- }
5158
- return `exit ${exitCode}`;
5159
- }
5160
- return "";
5161
- }
5162
- function summarizeRead(_input, response) {
5163
- const content = extractFileContent(response);
5164
- if (content) {
5165
- const lines = content.split("\n").length;
5166
- return `${lines} lines`;
5167
- }
5168
- return "";
5169
- }
5170
- function summarizeEdit(input, _response) {
5171
- const oldStr = typeof input["old_string"] === "string" ? input["old_string"] : "";
5172
- const newStr = typeof input["new_string"] === "string" ? input["new_string"] : "";
5173
- const oldLines = oldStr.split("\n").length;
5174
- const newLines = newStr.split("\n").length;
5175
- return `replaced ${oldLines} \u2192 ${newLines} lines`;
5176
- }
5177
- function summarizeWrite(_input, _response) {
5178
- return "";
5179
- }
5180
- function summarizeGlob(_input, response) {
5181
- const filenames = prop(response, "filenames");
5182
- if (Array.isArray(filenames))
5183
- return `${filenames.length} ${filenames.length === 1 ? "file" : "files"}`;
5184
- const numFiles = prop(response, "numFiles");
5185
- if (typeof numFiles === "number")
5186
- return `${numFiles} ${numFiles === 1 ? "file" : "files"}`;
5187
- return "";
5188
- }
5189
- function summarizeGrep(_input, response) {
5190
- if (typeof response === "string") {
5191
- const matches = response.split("\n").filter(Boolean).length;
5192
- return `${matches} matches`;
5193
- }
5194
- if (typeof response === "object" && response !== null) {
5195
- const numMatches = prop(response, "numMatches");
5196
- if (typeof numMatches === "number") return `${numMatches} matches`;
5197
- const count = prop(response, "count");
5198
- if (typeof count === "number") return `${count} matches`;
5199
- }
5200
- return "";
5201
- }
5202
- function summarizeWebSearch(_input, response) {
5203
- const results = prop(response, "results");
5204
- if (Array.isArray(results)) {
5205
- let count = 0;
5206
- for (const entry of results) {
5207
- const content = prop(entry, "content");
5208
- count += Array.isArray(content) ? content.length : 1;
5209
- }
5210
- return `${count} results`;
5211
- }
5212
- const actionType = prop(response, "type");
5213
- if (typeof actionType === "string") {
5214
- return actionType.replace(/_/g, " ");
5215
- }
5216
- return "";
5217
- }
5218
- function summarizeTask(input, _response) {
5219
- const agentType = input["subagent_type"] ?? "agent";
5220
- return String(agentType);
5221
- }
5222
- var SUMMARIZERS = {
5223
- Bash: summarizeBash,
5224
- Read: summarizeRead,
5225
- Edit: summarizeEdit,
5226
- Write: summarizeWrite,
5227
- Glob: summarizeGlob,
5228
- Grep: summarizeGrep,
5229
- WebSearch: summarizeWebSearch,
5230
- Task: summarizeTask,
5231
- Agent: summarizeTask
5232
- };
5233
- function summarizeFindElements(_input, response) {
5234
- if (typeof response === "object" && response !== null) {
5235
- const elements = prop(response, "elements") ?? prop(response, "items");
5236
- if (Array.isArray(elements)) return `${elements.length} found`;
5237
- if (Array.isArray(response)) return `${response.length} found`;
5238
- }
5239
- return "";
5240
- }
5241
- var MCP_SUMMARIZERS = {
5242
- find_elements: summarizeFindElements
5243
- };
5244
- function summarizeToolResult(toolName, toolInput, toolResponse, error) {
5245
- if (error) {
5246
- const firstLine = error.split("\n")[0] ?? error;
5247
- return compactText(firstLine, 160);
5248
- }
5249
- if (toolName in SUMMARIZERS) {
5250
- try {
5251
- return SUMMARIZERS[toolName](toolInput, toolResponse);
5252
- } catch {
5253
- return "";
5254
- }
5255
- }
5256
- const parsed = parseToolName(toolName);
5257
- if (parsed.isMcp && parsed.mcpAction) {
5258
- if (parsed.mcpAction in MCP_SUMMARIZERS) {
5259
- try {
5260
- return MCP_SUMMARIZERS[parsed.mcpAction](toolInput, toolResponse);
5261
- } catch {
5262
- return "";
5263
- }
5264
- }
5265
- }
5266
- return "";
5267
- }
5268
-
5269
- // src/core/feed/verbMap.ts
5270
- var MCP_VERB_MAP = {
5271
- navigate: "Navigate",
5272
- find_elements: "Find",
5273
- click: "Click",
5274
- close_session: "Close",
5275
- close_page: "Close",
5276
- type: "Type",
5277
- take_screenshot: "Screenshot",
5278
- capture_snapshot: "Snapshot",
5279
- scroll_page: "Scroll",
5280
- scroll_element_into_view: "Scroll",
5281
- hover: "Hover",
5282
- press: "Press",
5283
- select: "Select",
5284
- go_back: "Back",
5285
- go_forward: "Forward",
5286
- reload: "Reload",
5287
- list_pages: "Pages",
5288
- get_element_details: "Inspect",
5289
- get_form_understanding: "FormScan",
5290
- get_field_context: "FieldInfo",
5291
- ping: "Ping",
5292
- // context7
5293
- "resolve-library-id": "Resolve",
5294
- "query-docs": "QueryDocs"
5295
- };
5296
- function resolveVerb(toolName, parsed) {
5297
- if (!parsed.isMcp || !parsed.mcpAction) return toolName;
5298
- const mapped = MCP_VERB_MAP[parsed.mcpAction];
5299
- if (mapped) return mapped;
5300
- const action = parsed.mcpAction;
5301
- return action.charAt(0).toUpperCase() + action.slice(1).replace(/_/g, " ");
5302
- }
5303
-
5304
- // src/core/feed/timeline.ts
5305
- function opCategory(op) {
5306
- const dot = op.indexOf(".");
5307
- return dot >= 0 ? op.slice(0, dot) : op;
5308
- }
5309
- function computeDuplicateActors(entries) {
5310
- for (let i = 0; i < entries.length; i++) {
5311
- const prev = i > 0 ? entries[i - 1] : void 0;
5312
- const sameActor = prev !== void 0 && entries[i].actorId === prev.actorId;
5313
- const isBreak = prev !== void 0 && opCategory(entries[i].opTag) !== opCategory(prev.opTag);
5314
- entries[i].duplicateActor = sameActor && !isBreak;
5315
- }
5316
- }
5317
- function stripMarkdownInline(text) {
5318
- return text.replace(/#{1,6}\s+/g, "").replace(/\*\*(.+?)\*\*/g, "$1").replace(/__(.+?)__/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/`(.+?)`/g, "$1").replace(/~~(.+?)~~/g, "$1");
5319
- }
5320
- function firstSentence(text) {
5321
- const nlIdx = text.indexOf("\n");
5322
- const sentIdx = text.indexOf(". ");
5323
- const nlEnd = nlIdx === -1 ? Infinity : nlIdx;
5324
- const sentEnd = sentIdx === -1 ? Infinity : sentIdx + 1;
5325
- const end = Math.min(nlEnd, sentEnd, text.length);
5326
- return text.slice(0, end).trim();
5327
- }
5328
- function resolveDisplayName(toolName) {
5329
- const parsed = parseToolName(toolName);
5330
- if (parsed.isMcp && parsed.mcpServer && parsed.mcpAction) {
5331
- const friendlyServer = extractFriendlyServerName(parsed.mcpServer);
5332
- return `[${friendlyServer}] ${parsed.mcpAction}`;
5333
- }
5334
- return toolName;
5335
- }
5336
- var PATH_TOOLS = /* @__PURE__ */ new Set(["Read", "Write", "Edit", "Glob", "Grep"]);
5337
- function withMcpServerContext(parsed, primaryInput) {
5338
- if (!parsed.isMcp || !parsed.mcpServer) return primaryInput;
5339
- const server = extractFriendlyServerName(parsed.mcpServer);
5340
- if (!server) return primaryInput;
5341
- return primaryInput ? `[${server}] ${primaryInput}` : `[${server}]`;
5342
- }
5343
- function formatToolSummary(toolName, toolInput, errorSuffix) {
5344
- const parsed = parseToolName(toolName);
5345
- const verb = resolveVerb(toolName, parsed);
5346
- const primaryInput = withMcpServerContext(
5347
- parsed,
5348
- summarizeToolPrimaryInput(toolName, toolInput)
5349
- );
5350
- const secondary = [primaryInput, errorSuffix].filter(Boolean).join(" ");
5351
- if (!secondary) {
5352
- const text2 = compactText(verb, 200);
5353
- return { text: text2, segments: [{ text: text2, role: "verb" }] };
5354
- }
5355
- const full = `${verb} ${secondary}`;
5356
- const text = compactText(full, 200);
5357
- const rest = text.slice(verb.length);
5358
- const baseName = toolName;
5359
- const filePath = toolInput.file_path ?? toolInput.pattern ?? toolInput.path;
5360
- if (PATH_TOOLS.has(baseName) && typeof filePath === "string") {
5361
- const { prefix, filename } = shortenPathStructured(filePath);
5362
- if (prefix && filename) {
5363
- const idx = rest.indexOf(prefix);
5364
- if (idx >= 0) {
5365
- const beforeFilename = rest.slice(0, idx + prefix.length);
5366
- const afterFilename = rest.slice(idx + prefix.length + filename.length);
5367
- return {
5368
- text,
5369
- segments: [
5370
- { text: verb, role: "verb" },
5371
- { text: beforeFilename, role: "target" },
5372
- { text: filename, role: "filename" },
5373
- ...afterFilename ? [{ text: afterFilename, role: "target" }] : []
5374
- ]
5375
- };
5376
- }
5377
- }
5378
- }
5379
- return {
5380
- text,
5381
- segments: [
5382
- { text: verb, role: "verb" },
5383
- { text: rest, role: "target" }
5384
- ]
5385
- };
5386
- }
5387
- function formatPermissionSummary(event) {
5388
- const base = formatToolSummary(event.data.tool_name, event.data.tool_input);
5389
- const host = event.data.network_context?.host;
5390
- if (!host) {
5391
- return base;
5392
- }
5393
- const protocol = event.data.network_context?.protocol;
5394
- const suffix = ` \u2192 ${protocol ? `${protocol} ` : ""}${host}`;
5395
- const text = compactText(`${base.text}${suffix}`, 200);
5396
- return {
5397
- text,
5398
- segments: [...base.segments, { text: suffix, role: "target" }]
5399
- };
5400
- }
5401
- function formatRunEndSummary(event) {
5402
- const toolText = `${event.data.counters.tool_uses} tool${event.data.counters.tool_uses === 1 ? "" : "s"}`;
5403
- const failureCount = event.data.counters.tool_failures;
5404
- if (failureCount > 0) {
5405
- return `${event.data.status} \xB7 ${toolText}, ${failureCount} failure${failureCount === 1 ? "" : "s"}`;
5406
- }
5407
- return `${event.data.status} \xB7 ${toolText}`;
5408
- }
5409
- function harnessSummary(event) {
5410
- const title = event.display?.title?.trim();
5411
- if (!title) return void 0;
5412
- const text = compactText(title, 200);
5413
- return { text, segments: [{ text, role: "target" }] };
5414
- }
5415
- function postOutcome(postEvent) {
5416
- if (postEvent.kind === "tool.failure") {
5417
- return summarizeToolResult(
5418
- postEvent.data.tool_name,
5419
- postEvent.data.tool_input,
5420
- void 0,
5421
- postEvent.data.error
5422
- );
5423
- }
5424
- if (postEvent.kind === "tool.post") {
5425
- return summarizeToolResult(
5426
- postEvent.data.tool_name,
5427
- postEvent.data.tool_input,
5428
- postEvent.data.tool_response
5429
- );
5430
- }
5431
- return void 0;
5432
- }
5433
- function plainSummary(text) {
5434
- const compact = compactText(text, 200);
5435
- return { text: compact, segments: [{ text: compact, role: "target" }] };
5436
- }
5437
- function dataExpansion(event) {
5438
- return JSON.stringify(event.data, null, 2);
5439
- }
5440
- function rawOrDataExpansion(event) {
5441
- return JSON.stringify(event.raw ?? event.data, null, 2);
5442
- }
5443
- function defaultRenderer(summarize2) {
5444
- return {
5445
- operation: () => "event",
5446
- label: () => "Event",
5447
- detail: () => "\u2500",
5448
- summary: (event) => plainSummary(summarize2(event)),
5449
- expansion: rawOrDataExpansion
5450
- };
5451
- }
5452
- var sessionStart = {
5453
- operation: () => "sess.start",
5454
- label: () => "Sess Start",
5455
- detail: (event) => event.data.source,
5456
- summary: (event) => plainSummary(event.data.source),
5457
- expansion: rawOrDataExpansion
5458
- };
5459
- var sessionEnd = {
5460
- operation: () => "sess.end",
5461
- label: () => "Sess End",
5462
- detail: () => "\u2500",
5463
- summary: (event) => plainSummary(event.data.reason),
5464
- expansion: rawOrDataExpansion
5465
- };
5466
- var runStart = {
5467
- operation: () => "run.start",
5468
- label: () => "Run Start",
5469
- detail: () => "\u2500",
5470
- summary: (event) => plainSummary(event.data.trigger.prompt_preview || "interactive"),
5471
- expansion: rawOrDataExpansion
5472
- };
5473
- var runEnd = {
5474
- operation: (event) => {
5475
- if (event.data.status === "completed") return "run.ok";
5476
- if (event.data.status === "failed") return "run.fail";
5477
- return "run.abort";
5478
- },
5479
- label: (event) => {
5480
- if (event.data.status === "completed") return "Run OK";
5481
- if (event.data.status === "failed") return "Run Fail";
5482
- return "Run Abort";
5483
- },
5484
- detail: () => "\u2500",
5485
- summary: (event) => plainSummary(formatRunEndSummary(event)),
5486
- expansion: dataExpansion,
5487
- isError: (event) => event.data.status !== "completed"
5488
- };
5489
- var userPrompt = {
5490
- operation: () => "prompt",
5491
- label: () => "User Prompt",
5492
- detail: () => "\u2500",
5493
- summary: (event) => plainSummary(event.data.prompt),
5494
- expansion: rawOrDataExpansion
5495
- };
5496
- var planUpdate = {
5497
- operation: () => "plan.upd",
5498
- label: () => "Plan Update",
5499
- detail: () => "plan",
5500
- summary: (event) => {
5501
- if (event.data.explanation) return plainSummary(event.data.explanation);
5502
- if (event.data.plan && event.data.plan.length > 0) {
5503
- const completed = event.data.plan.filter(
5504
- (step) => step.status === "completed"
5505
- ).length;
5506
- return plainSummary(`${completed}/${event.data.plan.length} steps`);
5507
- }
5508
- return plainSummary(event.data.delta || "plan updated");
5509
- },
5510
- expansion: dataExpansion
5511
- };
5512
- var reasoningSummary = {
5513
- operation: () => "reason",
5514
- label: () => "Reasoning",
5515
- detail: () => "summary",
5516
- summary: (event) => plainSummary(firstSentence(stripMarkdownInline(event.data.message))),
5517
- expansion: dataExpansion
5518
- };
5519
- var usageUpdate = {
5520
- operation: () => "usage.upd",
5521
- label: () => "Usage Update",
5522
- detail: () => "tokens",
5523
- summary: (event) => {
5524
- const total = event.data.usage?.total;
5525
- const delta = event.data.delta?.total;
5526
- if (typeof total === "number" && typeof delta === "number") {
5527
- return plainSummary(
5528
- `${total.toLocaleString()} total (+${delta.toLocaleString()})`
5529
- );
5530
- }
5531
- if (typeof total === "number") {
5532
- return plainSummary(`${total.toLocaleString()} total`);
5533
- }
5534
- return plainSummary("usage updated");
5535
- },
5536
- expansion: dataExpansion
5537
- };
5538
- var toolDelta = {
5539
- operation: () => "tool.call",
5540
- label: () => "Tool Call",
5541
- detail: (event) => resolveDisplayName(event.data.tool_name),
5542
- summary: (event) => formatToolSummary(event.data.tool_name, event.data.tool_input),
5543
- expansion: (event) => JSON.stringify(
5544
- { tool: event.data.tool_name, args: event.data.tool_input },
5545
- null,
5546
- 2
5547
- )
5548
- };
5549
- var toolPre = {
5550
- operation: () => "tool.call",
5551
- label: () => "Tool Call",
5552
- detail: (event) => resolveDisplayName(event.data.tool_name),
5553
- summary: (event) => formatToolSummary(event.data.tool_name, event.data.tool_input),
5554
- expansion: (event) => JSON.stringify(
5555
- { tool: event.data.tool_name, args: event.data.tool_input },
5556
- null,
5557
- 2
5558
- )
5559
- };
5560
- var toolPost = {
5561
- operation: () => "tool.ok",
5562
- label: () => "Tool OK",
5563
- detail: (event) => resolveDisplayName(event.data.tool_name),
5564
- summary: (event) => formatToolSummary(event.data.tool_name, event.data.tool_input),
5565
- expansion: (event) => JSON.stringify(
5566
- {
5567
- tool: event.data.tool_name,
5568
- args: event.data.tool_input,
5569
- result: event.data.tool_response
5570
- },
5571
- null,
5572
- 2
5573
- )
5574
- };
5575
- var toolFailure = {
5576
- operation: () => "tool.fail",
5577
- label: () => "Tool Fail",
5578
- detail: (event) => resolveDisplayName(event.data.tool_name),
5579
- summary: (event) => formatToolSummary(
5580
- event.data.tool_name,
5581
- event.data.tool_input,
5582
- event.data.error
5583
- ),
5584
- expansion: (event) => JSON.stringify(
5585
- {
5586
- tool: event.data.tool_name,
5587
- args: event.data.tool_input,
5588
- error: event.data.error,
5589
- interrupt: event.data.is_interrupt
5590
- },
5591
- null,
5592
- 2
5593
- ),
5594
- isError: () => true
5595
- };
5596
- var permissionRequest = {
5597
- operation: () => "perm.req",
5598
- label: () => "Perm Request",
5599
- detail: (event) => resolveDisplayName(event.data.tool_name),
5600
- summary: (event) => formatPermissionSummary(event),
5601
- expansion: (event) => JSON.stringify(
5602
- {
5603
- tool: event.data.tool_name,
5604
- args: event.data.tool_input,
5605
- suggestions: event.data.permission_suggestions
5606
- },
5607
- null,
5608
- 2
5609
- )
5610
- };
5611
- var permissionDecision = {
5612
- operation: (event) => `perm.${event.data.decision_type}`,
5613
- label: (event) => {
5614
- switch (event.data.decision_type) {
5615
- case "allow":
5616
- return "Perm Allow";
5617
- case "deny":
5618
- return "Perm Deny";
5619
- case "ask":
5620
- return "Perm Ask";
5621
- case "no_opinion":
5622
- return "Perm Skip";
5623
- default:
5624
- return "Perm Decision";
5625
- }
5626
- },
5627
- detail: () => "\u2500",
5628
- summary: (event) => {
5629
- const detail = event.data.decision_type === "deny" ? event.data.message || event.data.reason : event.data.reason;
5630
- return plainSummary(detail || event.data.decision_type);
5631
- },
5632
- expansion: rawOrDataExpansion,
5633
- isError: (event) => event.data.decision_type === "deny"
5634
- };
5635
- var stopRequest = {
5636
- operation: () => "stop.req",
5637
- label: () => "Stop Request",
5638
- detail: () => "\u2500",
5639
- summary: (event) => plainSummary(
5640
- event.data.stop_hook_active ? "Stop hook active" : "Stop hook inactive"
5641
- ),
5642
- expansion: rawOrDataExpansion
5643
- };
5644
- var stopDecision = {
5645
- operation: (event) => `stop.${event.data.decision_type}`,
5646
- label: (event) => {
5647
- switch (event.data.decision_type) {
5648
- case "block":
5649
- return "Stop Block";
5650
- case "allow":
5651
- return "Stop Allow";
5652
- case "no_opinion":
5653
- return "Stop Skip";
5654
- default:
5655
- return "Stop Decision";
5656
- }
5657
- },
5658
- detail: () => "\u2500",
5659
- summary: (event) => plainSummary(event.data.reason || event.data.decision_type),
5660
- expansion: rawOrDataExpansion,
5661
- isError: (event) => event.data.decision_type === "block"
5662
- };
5663
- var subagentStart = {
5664
- operation: () => "sub.start",
5665
- label: () => "Sub Start",
5666
- detail: (event) => event.data.agent_type,
5667
- summary: (event) => {
5668
- const text = compactText(
5669
- event.data.description?.trim() || `id:${event.data.agent_id}`,
5670
- 200
5671
- );
5672
- return { text, segments: [{ text, role: "target" }] };
5673
- },
5674
- expansion: rawOrDataExpansion
5675
- };
5676
- var subagentStop = {
5677
- operation: () => "sub.stop",
5678
- label: () => "Sub Stop",
5679
- detail: (event) => event.data.agent_type,
5680
- summary: (event) => {
5681
- const text = compactText(
5682
- event.data.description?.trim() || `id:${event.data.agent_id}`,
5683
- 200
5684
- );
5685
- return { text, segments: [{ text, role: "target" }] };
5686
- },
5687
- expansion: dataExpansion
5688
- };
5689
- var notification = {
5690
- operation: () => "notify",
5691
- label: () => "Notify",
5692
- detail: () => "\u2500",
5693
- summary: (event) => plainSummary(stripMarkdownInline(event.data.message)),
5694
- expansion: rawOrDataExpansion
5695
- };
5696
- var runtimeError = {
5697
- operation: () => "error",
5698
- label: () => "Error",
5699
- detail: () => "\u2500",
5700
- summary: (event) => plainSummary(stripMarkdownInline(event.data.message)),
5701
- expansion: dataExpansion,
5702
- isError: () => true
5703
- };
5704
- var threadStatus = {
5705
- operation: () => "thread",
5706
- label: () => "Thread",
5707
- detail: (event) => event.data.status_type ?? "status",
5708
- summary: (event) => plainSummary(event.data.message),
5709
- expansion: dataExpansion
5710
- };
5711
- var turnDiff = {
5712
- operation: () => "diff",
5713
- label: () => "Diff",
5714
- detail: () => "\u2500",
5715
- summary: (event) => plainSummary(event.data.message),
5716
- expansion: dataExpansion
5717
- };
5718
- var serverRequestResolved = {
5719
- operation: () => "req.done",
5720
- label: () => "Request",
5721
- detail: (event) => event.data.request_id ?? "request",
5722
- summary: (event) => plainSummary(event.data.message),
5723
- expansion: dataExpansion
5724
- };
5725
- var webSearch = {
5726
- operation: () => "web.search",
5727
- label: () => "Web Search",
5728
- detail: (event) => event.data.action_type ?? event.data.phase,
5729
- summary: (event) => plainSummary(event.data.message),
5730
- expansion: dataExpansion
5731
- };
5732
- var reviewStatus = {
5733
- operation: () => "review",
5734
- label: () => "Review",
5735
- detail: (event) => event.data.phase,
5736
- summary: (event) => plainSummary(event.data.message),
5737
- expansion: dataExpansion
5738
- };
5739
- var imageView = {
5740
- operation: () => "image",
5741
- label: () => "Image",
5742
- detail: (event) => event.data.path ?? "image",
5743
- summary: (event) => plainSummary(event.data.message),
5744
- expansion: dataExpansion
5745
- };
5746
- var contextCompaction = {
5747
- operation: () => "compact",
5748
- label: () => "Compaction",
5749
- detail: (event) => event.data.phase,
5750
- summary: (event) => plainSummary(event.data.message),
5751
- expansion: dataExpansion
5752
- };
5753
- var mcpProgress = {
5754
- operation: () => "mcp.prog",
5755
- label: () => "MCP Progress",
5756
- detail: () => "\u2500",
5757
- summary: (event) => plainSummary(event.data.message),
5758
- expansion: dataExpansion
5759
- };
5760
- var terminalInput = {
5761
- operation: () => "term.in",
5762
- label: () => "Terminal In",
5763
- detail: () => "\u2500",
5764
- summary: (event) => plainSummary(event.data.message),
5765
- expansion: dataExpansion
5766
- };
5767
- var skillsChanged = {
5768
- operation: () => "skills",
5769
- label: () => "Skills",
5770
- detail: () => "\u2500",
5771
- summary: (event) => plainSummary(event.data.message),
5772
- expansion: dataExpansion
5773
- };
5774
- var skillsLoaded = {
5775
- operation: () => "skills",
5776
- label: () => "Skills",
5777
- detail: () => "\u2500",
5778
- summary: (event) => plainSummary(event.data.message),
5779
- expansion: dataExpansion
5780
- };
5781
- var compactPre = {
5782
- operation: () => "compact",
5783
- label: () => "Compact",
5784
- detail: () => "\u2500",
5785
- summary: (event) => plainSummary(event.data.trigger),
5786
- expansion: dataExpansion
5787
- };
5788
- var setup = {
5789
- operation: () => "setup",
5790
- label: () => "Setup",
5791
- detail: () => "\u2500",
5792
- summary: (event) => plainSummary(event.data.trigger),
5793
- expansion: rawOrDataExpansion
5794
- };
5795
- var unknownHook = {
5796
- operation: () => "unknown",
5797
- label: () => "Unknown",
5798
- detail: () => "\u2500",
5799
- summary: (event) => plainSummary(event.data.hook_event_name),
5800
- expansion: rawOrDataExpansion
5801
- };
5802
- var todoAdd = {
5803
- operation: () => "todo.add",
5804
- label: () => "Todo Add",
5805
- detail: (event) => (event.data.priority ?? "p1").toUpperCase(),
5806
- summary: (event) => plainSummary(
5807
- `${event.data.priority?.toUpperCase() ?? "P1"} ${event.data.text}`
5808
- ),
5809
- expansion: rawOrDataExpansion
5810
- };
5811
- var todoUpdate = {
5812
- operation: () => "todo.upd",
5813
- label: () => "Todo Update",
5814
- detail: (event) => event.data.todo_id,
5815
- summary: (event) => {
5816
- const patchFields = Object.keys(event.data.patch);
5817
- return plainSummary(
5818
- `${event.data.todo_id} ${patchFields.length > 0 ? patchFields.join(",") : "update"}`
5819
- );
5820
- },
5821
- expansion: rawOrDataExpansion
5822
- };
5823
- var todoDone = {
5824
- operation: () => "todo.done",
5825
- label: () => "Todo Done",
5826
- detail: (event) => event.data.todo_id,
5827
- summary: (event) => plainSummary(`${event.data.todo_id} ${event.data.reason || "done"}`),
5828
- expansion: rawOrDataExpansion
5829
- };
5830
- var agentMessage = {
5831
- operation: () => "agent.msg",
5832
- label: () => "Agent Msg",
5833
- detail: () => "\u2500",
5834
- summary: (event) => {
5835
- const text = compactText(
5836
- firstSentence(stripMarkdownInline(event.data.message)),
5837
- 200
5838
- );
5839
- return { text, segments: [{ text, role: "plain" }] };
5840
- },
5841
- expansion: rawOrDataExpansion
5842
- };
5843
- var teammateIdle = {
5844
- operation: () => "tm.idle",
5845
- label: () => "Team Idle",
5846
- detail: () => "\u2500",
5847
- summary: (event) => plainSummary(`${event.data.teammate_name} idle in ${event.data.team_name}`),
5848
- expansion: rawOrDataExpansion
5849
- };
5850
- var taskCompleted = {
5851
- operation: () => "task.ok",
5852
- label: () => "Task OK",
5853
- detail: () => "\u2500",
5854
- summary: (event) => plainSummary(event.data.task_subject),
5855
- expansion: rawOrDataExpansion
5856
- };
5857
- var configChange = {
5858
- operation: () => "cfg.chg",
5859
- label: () => "Config Chg",
5860
- detail: (event) => event.data.source,
5861
- summary: (event) => plainSummary(
5862
- `${event.data.source}${event.data.file_path ? ` ${event.data.file_path}` : ""}`
5863
- ),
5864
- expansion: rawOrDataExpansion
5865
- };
5866
- var compactPost = defaultRenderer(
5867
- (event) => `compacted (${event.data.trigger})`
5868
- );
5869
- var taskCreated = defaultRenderer(
5870
- (event) => event.data.task_subject
5871
- );
5872
- var cwdChanged = defaultRenderer(
5873
- (event) => `cwd \u2192 ${event.data.cwd}`
5874
- );
5875
- var fileChanged = defaultRenderer(
5876
- (event) => `changed ${event.data.file_path}`
5877
- );
5878
- var stopFailure = defaultRenderer(
5879
- (event) => `${event.data.error_type}${event.data.error_message ? `: ${event.data.error_message}` : ""}`
5880
- );
5881
- var permissionDenied = defaultRenderer(
5882
- (event) => `${event.data.tool_name}${event.data.reason ? `: ${event.data.reason}` : ""}`
5883
- );
5884
- var elicitationRequest = defaultRenderer((event) => `elicitation from ${event.data.mcp_server}`);
5885
- var elicitationResult = defaultRenderer(
5886
- (event) => `${event.data.mcp_server} \u2192 ${event.data.action}`
5887
- );
5888
- var channelPermissionRelayed = defaultRenderer(
5889
- (event) => `${event.data.channel_name}: ${event.data.tool_name} (${event.data.channel_request_id})`
5890
- );
5891
- var channelPermissionResolved = defaultRenderer(
5892
- (event) => `${event.data.channel_name} ${event.data.source} ${event.data.tool_name}`
5893
- );
5894
- var channelQuestionRelayed = defaultRenderer(
5895
- (event) => `${event.data.channel_name}: ${event.data.title} (${event.data.channel_request_id})`
5896
- );
5897
- var channelQuestionResolved = defaultRenderer(
5898
- (event) => `${event.data.channel_name || event.data.source} ${event.data.source} ${event.data.title}`
5899
- );
5900
- var channelChatInbound = defaultRenderer((event) => `${event.data.channel_name}: ${event.data.content}`);
5901
- var channelChatOutbound = defaultRenderer(
5902
- (event) => `${event.data.channel_name} \u2192 ${event.data.target_peer_id}: ${event.data.content}`
5903
- );
5904
- var gatewayFunctionInvoked = defaultRenderer(
5905
- (event) => `fn invoked: ${event.data.function_name} (${event.data.caller_kind})`
5906
- );
5907
- var gatewayFunctionCompleted = defaultRenderer(
5908
- (event) => `fn ok: ${event.data.function_name} ${event.data.duration_ms}ms`
5909
- );
5910
- var gatewayFunctionFailed = defaultRenderer(
5911
- (event) => `fn ${event.data.reason}: ${event.data.function_name} \u2014 ${event.data.error_message}`
5912
- );
5913
- var artifactsManifest = defaultRenderer(
5914
- (event) => {
5915
- const manifest = event.data.manifest;
5916
- const count = Array.isArray(manifest.entries) ? manifest.entries.length : 0;
5917
- return `artifacts manifest (${count} item${count === 1 ? "" : "s"})`;
5918
- }
5919
- );
5920
- var RENDERERS = {
5921
- "session.start": sessionStart,
5922
- "session.end": sessionEnd,
5923
- "run.start": runStart,
5924
- "run.end": runEnd,
5925
- "user.prompt": userPrompt,
5926
- "plan.update": planUpdate,
5927
- "reasoning.summary": reasoningSummary,
5928
- "usage.update": usageUpdate,
5929
- "tool.delta": toolDelta,
5930
- "tool.pre": toolPre,
5931
- "tool.post": toolPost,
5932
- "tool.failure": toolFailure,
5933
- "permission.request": permissionRequest,
5934
- "permission.decision": permissionDecision,
5935
- "stop.request": stopRequest,
5936
- "stop.decision": stopDecision,
5937
- "subagent.start": subagentStart,
5938
- "subagent.stop": subagentStop,
5939
- notification,
5940
- "runtime.error": runtimeError,
5941
- "thread.status": threadStatus,
5942
- "turn.diff": turnDiff,
5943
- "server.request.resolved": serverRequestResolved,
5944
- "web.search": webSearch,
5945
- "review.status": reviewStatus,
5946
- "image.view": imageView,
5947
- "context.compaction": contextCompaction,
5948
- "mcp.progress": mcpProgress,
5949
- "terminal.input": terminalInput,
5950
- "skills.changed": skillsChanged,
5951
- "skills.loaded": skillsLoaded,
5952
- "compact.pre": compactPre,
5953
- "compact.post": compactPost,
5954
- setup,
5955
- "unknown.hook": unknownHook,
5956
- "todo.add": todoAdd,
5957
- "todo.update": todoUpdate,
5958
- "todo.done": todoDone,
5959
- "agent.message": agentMessage,
5960
- "teammate.idle": teammateIdle,
5961
- "task.created": taskCreated,
5962
- "task.completed": taskCompleted,
5963
- "config.change": configChange,
5964
- "cwd.changed": cwdChanged,
5965
- "file.changed": fileChanged,
5966
- "stop.failure": stopFailure,
5967
- "permission.denied": permissionDenied,
5968
- "elicitation.request": elicitationRequest,
5969
- "elicitation.result": elicitationResult,
5970
- "channel.permission.relayed": channelPermissionRelayed,
5971
- "channel.permission.resolved": channelPermissionResolved,
5972
- "channel.question.relayed": channelQuestionRelayed,
5973
- "channel.question.resolved": channelQuestionResolved,
5974
- "channel.chat.inbound": channelChatInbound,
5975
- "channel.chat.outbound": channelChatOutbound,
5976
- "gateway.function.invoked": gatewayFunctionInvoked,
5977
- "gateway.function.completed": gatewayFunctionCompleted,
5978
- "gateway.function.failed": gatewayFunctionFailed,
5979
- "artifacts.manifest": artifactsManifest
5980
- };
5981
- function rendererFor(event) {
5982
- return RENDERERS[event.kind];
5983
- }
5984
- function eventOperation(event) {
5985
- return rendererFor(event).operation(event);
5986
- }
5987
- function eventLabel(event) {
5988
- return rendererFor(event).label(event);
5989
- }
5990
- function eventSummary(event) {
5991
- const harness = harnessSummary(event);
5992
- if (harness) return harness;
5993
- return rendererFor(event).summary(event);
5994
- }
5995
- function expansionForEvent(event) {
5996
- return rendererFor(event).expansion(event);
5997
- }
5998
- function isEventError(event) {
5999
- if (event.level === "error") return true;
6000
- const renderer = rendererFor(event);
6001
- return renderer.isError?.(event) ?? false;
6002
- }
6003
- function isEventExpandable(event) {
6004
- void event;
6005
- return true;
6006
- }
6007
- var toolPairOk = {
6008
- operation: () => "tool.ok",
6009
- label: () => "Tool OK",
6010
- summary: (pre, post) => buildMergedToolSummary(pre, post)
6011
- };
6012
- var toolPairFail = {
6013
- operation: () => "tool.fail",
6014
- label: () => "Tool Fail",
6015
- summary: (pre, post) => buildMergedToolSummary(pre, post)
6016
- };
6017
- var TOOL_PAIRS = {
6018
- "tool.post": toolPairOk,
6019
- "tool.failure": toolPairFail
6020
- };
6021
- function buildMergedToolSummary(event, postEvent) {
6022
- const harness = harnessSummary(event) ?? harnessSummary(postEvent);
6023
- if (harness) {
6024
- return {
6025
- ...harness,
6026
- outcome: postOutcome(postEvent),
6027
- outcomeZero: false
6028
- };
6029
- }
6030
- const toolName = event.data.tool_name;
6031
- const preInput = event.data.tool_input;
6032
- const postInput = postEvent.kind === "tool.post" || postEvent.kind === "tool.failure" ? postEvent.data.tool_input : void 0;
6033
- const toolInput = postInput && Object.keys(preInput).every((k) => preInput[k] == null) ? postInput : preInput;
6034
- const parsed = parseToolName(toolName);
6035
- const name = resolveVerb(toolName, parsed);
6036
- const primaryInput = withMcpServerContext(
6037
- parsed,
6038
- summarizeToolPrimaryInput(toolName, toolInput)
6039
- );
6040
- let resultText;
6041
- if (postEvent.kind === "tool.failure") {
6042
- resultText = summarizeToolResult(
6043
- toolName,
6044
- toolInput,
6045
- void 0,
6046
- postEvent.data.error
6047
- );
6048
- } else if (postEvent.kind === "tool.post") {
6049
- resultText = summarizeToolResult(
6050
- toolName,
6051
- toolInput,
6052
- postEvent.data.tool_response
6053
- );
6054
- } else {
6055
- return eventSummary(event);
6056
- }
6057
- const prefix = primaryInput ? `${name} ${primaryInput}` : name;
6058
- const prefixText = compactText(prefix, 200);
6059
- const segments = primaryInput ? [
6060
- { text: name, role: "verb" },
6061
- { text: prefixText.slice(name.length), role: "target" }
6062
- ] : [{ text: prefixText, role: "verb" }];
6063
- if (!resultText) {
6064
- return { text: prefixText, segments };
6065
- }
6066
- return {
6067
- text: prefixText,
6068
- segments,
6069
- outcome: resultText,
6070
- outcomeZero: /^0\s/.test(resultText)
6071
- };
6072
- }
6073
- function mergedEventOperation(event, postEvent) {
6074
- if (!postEvent) return eventOperation(event);
6075
- const pair = TOOL_PAIRS[postEvent.kind];
6076
- if (!pair) return eventOperation(event);
6077
- return pair.operation(event, postEvent);
6078
- }
6079
- function mergedEventLabel(event, postEvent) {
6080
- if (!postEvent) return eventLabel(event);
6081
- const pair = TOOL_PAIRS[postEvent.kind];
6082
- if (!pair) return eventLabel(event);
6083
- return pair.label(event, postEvent);
6084
- }
6085
- function mergedEventSummary(event, postEvent) {
6086
- if (!postEvent) return eventSummary(event);
6087
- if (event.kind !== "tool.pre" && event.kind !== "permission.request") {
6088
- return eventSummary(event);
6089
- }
6090
- const pair = TOOL_PAIRS[postEvent.kind];
6091
- if (!pair) return eventSummary(event);
6092
- return pair.summary(event, postEvent);
6093
- }
6094
- var VERBOSE_ONLY_KINDS = /* @__PURE__ */ new Set([
6095
- "session.start",
6096
- "session.end",
6097
- "run.start",
6098
- "run.end",
6099
- "unknown.hook",
6100
- "compact.pre",
6101
- "config.change",
6102
- "turn.diff",
6103
- "usage.update",
6104
- "reasoning.summary"
6105
- ]);
6106
- function toRunStatus(event) {
6107
- switch (event.data.status) {
6108
- case "completed":
6109
- return "SUCCEEDED";
6110
- case "failed":
6111
- return "FAILED";
6112
- case "aborted":
6113
- return "CANCELLED";
6114
- }
6115
- }
6116
-
6117
- // src/core/feed/toolDisplay.ts
6118
- function prop2(obj, key) {
6119
- if (typeof obj === "object" && obj !== null) {
6120
- return obj[key];
6121
- }
6122
- return void 0;
6123
- }
6124
- function truncate(text, max) {
6125
- if (text.length <= max) return text;
6126
- if (max <= 3) return text.slice(0, max);
6127
- return text.slice(0, max - 1) + "\u2026";
6128
- }
6129
- function extractDomain(url) {
6130
- if (typeof url !== "string") return "";
6131
- try {
6132
- const u = new URL(url);
6133
- return u.hostname.replace(/^www\./, "");
6134
- } catch {
6135
- return compactText(String(url), 40);
6136
- }
6137
- }
6138
- function filePathSegments(input) {
6139
- const path10 = prop2(input, "file_path") ?? prop2(input, "notebook_path") ?? "";
6140
- if (typeof path10 !== "string" || !path10) return [];
6141
- const { prefix, filename } = shortenPathStructured(path10);
6142
- if (prefix && filename) {
6143
- return [
6144
- { text: prefix, role: "target" },
6145
- { text: filename, role: "filename" }
6146
- ];
6147
- }
6148
- return [{ text: filename || path10, role: "filename" }];
6149
- }
6150
- function grepSegments(input) {
6151
- const pattern = String(prop2(input, "pattern") ?? "");
6152
- const glob = prop2(input, "glob");
6153
- const parts = `"${pattern}"${glob ? ` ${String(glob)}` : ""}`;
6154
- return [{ text: parts, role: "target" }];
6155
- }
6156
- function commandSegments(input) {
6157
- const cmd = String(prop2(input, "command") ?? "");
6158
- return [{ text: compactText(compactCommandPaths(cmd), 50), role: "target" }];
6159
- }
6160
- function countOutcome(output, label) {
6161
- if (Array.isArray(output)) {
6162
- return { text: `${output.length} ${label}`, zero: output.length === 0 };
6163
- }
6164
- if (typeof output === "object" && output !== null) {
6165
- const filenames = prop2(output, "filenames");
6166
- if (Array.isArray(filenames)) {
6167
- return {
6168
- text: `${filenames.length} ${label}`,
6169
- zero: filenames.length === 0
6170
- };
6171
- }
6172
- const numFiles = prop2(output, "numFiles");
6173
- if (typeof numFiles === "number") {
6174
- return { text: `${numFiles} ${label}`, zero: numFiles === 0 };
6175
- }
6176
- const numMatches = prop2(output, "numMatches");
6177
- if (typeof numMatches === "number") {
6178
- return { text: `${numMatches} ${label}`, zero: numMatches === 0 };
6179
- }
6180
- const count = prop2(output, "count");
6181
- if (typeof count === "number") {
6182
- return { text: `${count} ${label}`, zero: count === 0 };
6183
- }
6184
- }
6185
- if (typeof output === "string") {
6186
- const lines = output.split("\n").filter(Boolean).length;
6187
- return { text: `${lines} ${label}`, zero: lines === 0 };
6188
- }
6189
- return void 0;
6190
- }
6191
- function exitCodeOutcome(output) {
6192
- if (isBashToolResponse(output)) {
6193
- const code = prop2(output, "exitCode") ?? 0;
6194
- const stderr = output.stderr.trim();
6195
- const firstLine = stderr.split("\n")[0] ?? "";
6196
- if (stderr && Number(code) !== 0) {
6197
- return { text: `exit ${code} \u2014 ${truncate(firstLine, 30)}`, zero: false };
6198
- }
6199
- return { text: `exit ${code}`, zero: false };
6200
- }
6201
- return void 0;
6202
- }
6203
- function webSearchOutcome(output) {
6204
- const results = prop2(output, "results");
6205
- if (Array.isArray(results)) {
6206
- let count = 0;
6207
- for (const entry of results) {
6208
- const content = prop2(entry, "content");
6209
- count += Array.isArray(content) ? content.length : 1;
6210
- }
6211
- return { text: `${count} results`, zero: count === 0 };
6212
- }
6213
- const actionType = prop2(output, "type");
6214
- if (typeof actionType === "string") {
6215
- return { text: actionType.replace(/_/g, " "), zero: false };
6216
- }
6217
- return void 0;
6218
- }
6219
- function taskOutputOutcome(output) {
6220
- if (typeof output === "string" && output.trim()) {
6221
- return { text: truncate(output.trim(), 30), zero: false };
6222
- }
6223
- return void 0;
6224
- }
6225
- function eidExtractor2(input) {
6226
- const eid = String(prop2(input, "eid") ?? "");
6227
- return eid ? [{ text: `eid:${eid.slice(0, 6)}\u2026`, role: "target" }] : [];
6228
- }
6229
- function eidOrLabelExtractor(input) {
6230
- const label = prop2(input, "label");
6231
- if (typeof label === "string" && label) {
6232
- return [{ text: `"${truncate(label, 20)}"`, role: "target" }];
6233
- }
6234
- return eidExtractor2(input);
6235
- }
6236
- function findDetailsExtractor(input) {
6237
- const parts = [];
6238
- const kind = prop2(input, "kind");
6239
- if (kind) parts.push(String(kind));
6240
- const label = prop2(input, "label");
6241
- if (label) parts.push(`"${String(label)}"`);
6242
- if (parts.length === 0) {
6243
- const region = prop2(input, "region");
6244
- if (region) parts.push(String(region));
6245
- }
6246
- return parts.length > 0 ? [{ text: parts.join(" "), role: "target" }] : [{ text: "elements", role: "target" }];
6247
- }
6248
- function typeDetailsExtractor(input) {
6249
- const text = String(prop2(input, "text") ?? "");
6250
- const eid = prop2(input, "eid");
6251
- const quoted = `"${truncate(text, 30)}"`;
6252
- if (eid) {
6253
- return [{ text: `${quoted} \u2192 ${String(eid).slice(0, 5)}\u2026`, role: "target" }];
6254
- }
6255
- return [{ text: quoted, role: "target" }];
6256
- }
6257
- function scrollDetailsExtractor(input) {
6258
- const dir = String(prop2(input, "direction") ?? "");
6259
- const amount = prop2(input, "amount");
6260
- const text = amount ? `${dir} ${amount}px` : dir;
6261
- return text ? [{ text, role: "target" }] : [];
6262
- }
6263
- function tabRefExtractor(input) {
6264
- const pageId = prop2(input, "page_id");
6265
- return pageId ? [{ text: `page:${String(pageId).slice(0, 6)}`, role: "target" }] : [];
6266
- }
6267
- function foundCountOutcome(output) {
6268
- if (Array.isArray(output)) {
6269
- return { text: `${output.length} found`, zero: output.length === 0 };
6270
- }
6271
- if (typeof output === "object" && output !== null) {
6272
- const elements = prop2(output, "elements") ?? prop2(output, "items");
6273
- if (Array.isArray(elements)) {
6274
- return { text: `${elements.length} found`, zero: elements.length === 0 };
6275
- }
6276
- }
6277
- return void 0;
6278
- }
6279
- function tabCountOutcome(output) {
6280
- if (Array.isArray(output)) {
6281
- return { text: `${output.length} tabs`, zero: output.length === 0 };
6282
- }
6283
- const pages = prop2(output, "pages");
6284
- if (Array.isArray(pages)) {
6285
- return { text: `${pages.length} tabs`, zero: pages.length === 0 };
6286
- }
6287
- return void 0;
6288
- }
6289
- function formCountOutcome(output) {
6290
- const fields = prop2(output, "fields");
6291
- if (Array.isArray(fields)) {
6292
- return { text: `${fields.length} fields`, zero: fields.length === 0 };
6293
- }
6294
- return void 0;
6295
- }
6296
- function pingOutcome(output) {
6297
- if (output) return { text: "ok", zero: false };
6298
- return void 0;
6299
- }
6300
- var KNOWN_TOOL_DISPLAY = new Map([
6301
- // ── Core file tools ──
6302
- [
6303
- "Read",
6304
- {
6305
- display: "Read",
6306
- extractDetails: filePathSegments,
6307
- extractOutcome: () => void 0
6308
- }
6309
- ],
6310
- [
6311
- "Write",
6312
- {
6313
- display: "Write",
6314
- extractDetails: filePathSegments,
6315
- extractOutcome: () => void 0
6316
- }
6317
- ],
6318
- [
6319
- "Edit",
6320
- {
6321
- display: "Edit",
6322
- extractDetails: filePathSegments,
6323
- extractOutcome: () => void 0
6324
- }
6325
- ],
6326
- [
6327
- "Glob",
6328
- {
6329
- display: "Glob",
6330
- extractDetails: (input) => [
6331
- { text: String(prop2(input, "pattern") ?? ""), role: "target" }
6332
- ],
6333
- extractOutcome: (output) => countOutcome(output, "files")
6334
- }
6335
- ],
6336
- [
6337
- "Grep",
6338
- {
6339
- display: "Grep",
6340
- extractDetails: grepSegments,
6341
- extractOutcome: (output) => countOutcome(output, "matches")
6342
- }
6343
- ],
6344
- [
6345
- "Bash",
6346
- {
6347
- display: "Bash",
6348
- extractDetails: commandSegments,
6349
- extractOutcome: exitCodeOutcome
6350
- }
6351
- ],
6352
- // ── Web tools ──
6353
- [
6354
- "WebFetch",
6355
- {
6356
- display: "WebFetch",
6357
- extractDetails: (input) => [
6358
- { text: extractDomain(prop2(input, "url")), role: "target" }
6359
- ],
6360
- extractOutcome: () => void 0
6361
- }
6362
- ],
6363
- [
6364
- "WebSearch",
6365
- {
6366
- display: "WebSearch",
6367
- extractDetails: (input) => [
6368
- {
6369
- text: truncate(String(prop2(input, "query") ?? ""), 40),
6370
- role: "target"
6371
- }
6372
- ],
6373
- extractOutcome: webSearchOutcome
6374
- }
6375
- ],
6376
- [
6377
- "NotebookEdit",
6378
- {
6379
- display: "Notebook",
6380
- extractDetails: filePathSegments,
6381
- extractOutcome: () => void 0
6382
- }
6383
- ],
6384
- // ── Agent & task tools ──
6385
- ...["Task", "Agent"].map(
6386
- (name) => [
6387
- name,
6388
- {
6389
- display: "Task",
6390
- extractDetails: (input) => [
6391
- {
6392
- text: truncate(String(prop2(input, "description") ?? ""), 50),
6393
- role: "plain"
6394
- }
6395
- ],
6396
- extractOutcome: (output) => {
6397
- const agentType = prop2(output, "subagent_type");
6398
- return agentType ? { text: String(agentType), zero: false } : void 0;
6399
- }
6400
- }
6401
- ]
6402
- ),
6403
- [
6404
- "TaskOutput",
6405
- {
6406
- display: "TaskOut",
6407
- extractDetails: (input) => [
6408
- { text: String(prop2(input, "task_id") ?? ""), role: "target" }
6409
- ],
6410
- extractOutcome: taskOutputOutcome
6411
- }
6412
- ],
6413
- [
6414
- "TaskStop",
6415
- {
6416
- display: "TaskStop",
6417
- extractDetails: (input) => [
6418
- { text: String(prop2(input, "task_id") ?? ""), role: "target" }
6419
- ],
6420
- extractOutcome: () => ({ text: "stopped", zero: false })
6421
- }
6422
- ],
6423
- [
6424
- "TodoWrite",
6425
- {
6426
- display: "TodoWrite",
6427
- extractDetails: (input) => {
6428
- const todos = prop2(input, "todos");
6429
- const n = Array.isArray(todos) ? todos.length : 0;
6430
- return [{ text: `${n} items`, role: "target" }];
6431
- },
6432
- extractOutcome: () => void 0
6433
- }
6434
- ],
6435
- // ── Planning & interaction ──
6436
- [
6437
- "AskUserQuestion",
6438
- {
6439
- display: "AskUser",
6440
- extractDetails: (input) => {
6441
- const questions = prop2(input, "questions");
6442
- const n = Array.isArray(questions) ? questions.length : 0;
6443
- return [{ text: `${n} question${n !== 1 ? "s" : ""}`, role: "target" }];
6444
- },
6445
- extractOutcome: () => void 0
6446
- }
6447
- ],
6448
- [
6449
- "EnterPlanMode",
6450
- {
6451
- display: "PlanMode",
6452
- extractDetails: () => [],
6453
- extractOutcome: () => ({ text: "entered", zero: false })
6454
- }
6455
- ],
6456
- [
6457
- "ExitPlanMode",
6458
- {
6459
- display: "PlanMode",
6460
- extractDetails: () => [],
6461
- extractOutcome: () => ({ text: "submitted", zero: false })
6462
- }
6463
- ],
6464
- [
6465
- "EnterWorktree",
6466
- {
6467
- display: "Worktree",
6468
- extractDetails: (input) => [
6469
- { text: String(prop2(input, "branch") ?? ""), role: "target" }
6470
- ],
6471
- extractOutcome: () => ({ text: "created", zero: false })
6472
- }
6473
- ],
6474
- [
6475
- "ExitWorktree",
6476
- {
6477
- display: "Worktree",
6478
- extractDetails: (input) => [
6479
- { text: String(prop2(input, "action") ?? ""), role: "target" }
6480
- ],
6481
- extractOutcome: () => ({ text: "exited", zero: false })
6482
- }
6483
- ],
6484
- // ── Cron / scheduling ──
6485
- [
6486
- "CronCreate",
6487
- {
6488
- display: "Cron",
6489
- extractDetails: (input) => [
6490
- { text: truncate(String(prop2(input, "cron") ?? ""), 30), role: "target" }
6491
- ],
6492
- extractOutcome: () => ({ text: "created", zero: false })
6493
- }
6494
- ],
6495
- [
6496
- "CronDelete",
6497
- {
6498
- display: "Cron",
6499
- extractDetails: (input) => [
6500
- { text: String(prop2(input, "id") ?? ""), role: "target" }
6501
- ],
6502
- extractOutcome: () => ({ text: "deleted", zero: false })
6503
- }
6504
- ],
6505
- [
6506
- "CronList",
6507
- {
6508
- display: "Cron",
6509
- extractDetails: () => [{ text: "list", role: "target" }],
6510
- extractOutcome: (output) => countOutcome(output, "triggers")
6511
- }
6512
- ],
6513
- // ── Remote triggers ──
6514
- [
6515
- "RemoteTrigger",
6516
- {
6517
- display: "Trigger",
6518
- extractDetails: (input) => {
6519
- const action = String(prop2(input, "action") ?? "");
6520
- const triggerId = prop2(input, "trigger_id");
6521
- const text = triggerId ? `${action} ${String(triggerId)}` : action;
6522
- return [{ text, role: "target" }];
6523
- },
6524
- extractOutcome: () => void 0
6525
- }
6526
- ],
6527
- [
6528
- "Skill",
6529
- {
6530
- display: "Skill",
6531
- extractDetails: (input) => {
6532
- const name = String(prop2(input, "skill") ?? "");
6533
- const colonIdx = name.indexOf(":");
6534
- const display = colonIdx >= 0 ? name.slice(colonIdx + 1) : name;
6535
- return [{ text: display.replace(/^\//, ""), role: "target" }];
6536
- },
6537
- extractOutcome: () => void 0
6538
- }
6539
- ]
6540
- ]);
6541
- var MCP_VERB_DISPLAY = /* @__PURE__ */ new Map([
6542
- // ── Navigation ──
6543
- [
6544
- "navigate",
6545
- {
6546
- display: "Navigate",
6547
- extractDetails: (i) => [
6548
- { text: extractDomain(prop2(i, "url")), role: "target" }
6549
- ],
6550
- extractOutcome: () => void 0
6551
- }
6552
- ],
6553
- [
6554
- "reload",
6555
- {
6556
- display: "Reload",
6557
- extractDetails: () => [],
6558
- extractOutcome: () => void 0
6559
- }
6560
- ],
6561
- [
6562
- "go_back",
6563
- {
6564
- display: "Back",
6565
- extractDetails: () => [],
6566
- extractOutcome: () => void 0
6567
- }
6568
- ],
6569
- [
6570
- "go_forward",
6571
- {
6572
- display: "Forward",
6573
- extractDetails: () => [],
6574
- extractOutcome: () => void 0
6575
- }
6576
- ],
6577
- // ── Element interaction ──
6578
- [
6579
- "find_elements",
6580
- {
6581
- display: "Find",
6582
- extractDetails: findDetailsExtractor,
6583
- extractOutcome: foundCountOutcome
6584
- }
6585
- ],
6586
- [
6587
- "click",
6588
- {
6589
- display: "Click",
6590
- extractDetails: eidOrLabelExtractor,
6591
- extractOutcome: () => void 0
6592
- }
6593
- ],
6594
- [
6595
- "type",
6596
- {
6597
- display: "Type",
6598
- extractDetails: typeDetailsExtractor,
6599
- extractOutcome: () => void 0
6600
- }
6601
- ],
6602
- [
6603
- "press",
6604
- {
6605
- display: "Press",
6606
- extractDetails: (i) => [
6607
- { text: String(prop2(i, "key") ?? ""), role: "target" }
6608
- ],
6609
- extractOutcome: () => void 0
6610
- }
6611
- ],
6612
- [
6613
- "select",
6614
- {
6615
- display: "Select",
6616
- extractDetails: (i) => [
6617
- { text: String(prop2(i, "value") ?? ""), role: "target" }
6618
- ],
6619
- extractOutcome: () => void 0
6620
- }
6621
- ],
6622
- [
6623
- "hover",
6624
- {
6625
- display: "Hover",
6626
- extractDetails: eidOrLabelExtractor,
6627
- extractOutcome: () => void 0
6628
- }
6629
- ],
6630
- // ── Inspection ──
6631
- [
6632
- "get_element_details",
6633
- {
6634
- display: "Inspect",
6635
- extractDetails: eidExtractor2,
6636
- extractOutcome: () => void 0
6637
- }
6638
- ],
6639
- [
6640
- "take_screenshot",
6641
- {
6642
- display: "Screenshot",
6643
- extractDetails: () => [],
6644
- extractOutcome: () => ({ text: "captured", zero: false })
6645
- }
6646
- ],
6647
- [
6648
- "capture_snapshot",
6649
- {
6650
- display: "Snapshot",
6651
- extractDetails: () => [],
6652
- extractOutcome: () => void 0
6653
- }
6654
- ],
6655
- [
6656
- "get_form_understanding",
6657
- {
6658
- display: "FormScan",
6659
- extractDetails: () => [],
6660
- extractOutcome: formCountOutcome
6661
- }
6662
- ],
6663
- [
6664
- "get_field_context",
6665
- {
6666
- display: "FieldCtx",
6667
- extractDetails: eidExtractor2,
6668
- extractOutcome: () => void 0
6669
- }
6670
- ],
6671
- // ── Scroll ──
6672
- [
6673
- "scroll_page",
6674
- {
6675
- display: "Scroll",
6676
- extractDetails: scrollDetailsExtractor,
6677
- extractOutcome: () => void 0
6678
- }
6679
- ],
6680
- [
6681
- "scroll_element_into_view",
6682
- {
6683
- display: "ScrollTo",
6684
- extractDetails: eidExtractor2,
6685
- extractOutcome: () => void 0
6686
- }
6687
- ],
6688
- // ── Session ──
6689
- [
6690
- "close_session",
6691
- {
6692
- display: "Close",
6693
- extractDetails: () => [{ text: "session", role: "target" }],
6694
- extractOutcome: () => void 0
6695
- }
6696
- ],
6697
- [
6698
- "close_page",
6699
- {
6700
- display: "ClosePage",
6701
- extractDetails: tabRefExtractor,
6702
- extractOutcome: () => void 0
6703
- }
6704
- ],
6705
- [
6706
- "list_pages",
6707
- {
6708
- display: "ListPages",
6709
- extractDetails: () => [],
6710
- extractOutcome: tabCountOutcome
6711
- }
6712
- ],
6713
- [
6714
- "ping",
6715
- {
6716
- display: "Ping",
6717
- extractDetails: () => [],
6718
- extractOutcome: pingOutcome
6719
- }
6720
- ],
6721
- // ── Context7 ──
6722
- [
6723
- "resolve-library-id",
6724
- {
6725
- display: "Resolve",
6726
- extractDetails: (i) => [
6727
- {
6728
- text: truncate(String(prop2(i, "libraryName") ?? ""), 30),
6729
- role: "target"
6730
- }
6731
- ],
6732
- extractOutcome: () => void 0
6733
- }
6734
- ],
6735
- [
6736
- "query-docs",
6737
- {
6738
- display: "QueryDocs",
6739
- extractDetails: (i) => [
6740
- {
6741
- text: truncate(String(prop2(i, "query") ?? ""), 40),
6742
- role: "target"
6743
- }
6744
- ],
6745
- extractOutcome: () => void 0
6746
- }
6747
- ]
6748
- ]);
6749
- function humanizeToolName(raw) {
6750
- const display = raw.split(/[_-]/).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
6751
- return display.length > 14 ? display.slice(0, 13) + "\u2026" : display;
6752
- }
6753
- function resolveToolColumn(toolName) {
6754
- const parsed = parseToolName(toolName);
6755
- const known = KNOWN_TOOL_DISPLAY.get(parsed.displayName);
6756
- if (known) return known.display;
6757
- if (parsed.isMcp && parsed.mcpAction) {
6758
- const mcp = MCP_VERB_DISPLAY.get(parsed.mcpAction);
6759
- if (mcp) return mcp.display;
6760
- }
6761
- return parsed.isMcp && parsed.mcpAction ? humanizeToolName(parsed.mcpAction) : humanizeToolName(parsed.displayName);
6762
- }
6763
- function resolveEventToolColumn(event) {
6764
- switch (event.kind) {
6765
- case "subagent.start":
6766
- case "subagent.stop":
6767
- return event.data.agent_type;
6768
- case "permission.request":
6769
- return resolveToolColumn(event.data.tool_name);
6770
- case "setup":
6771
- case "session.start":
6772
- case "session.end":
6773
- case "run.start":
6774
- case "run.end":
6775
- case "user.prompt":
6776
- case "plan.update":
6777
- case "reasoning.summary":
6778
- case "usage.update":
6779
- case "tool.delta":
6780
- case "tool.pre":
6781
- case "tool.post":
6782
- case "tool.failure":
6783
- case "permission.decision":
6784
- case "permission.denied":
6785
- case "stop.request":
6786
- case "stop.decision":
6787
- case "stop.failure":
6788
- case "notification":
6789
- case "runtime.error":
6790
- case "thread.status":
6791
- case "turn.diff":
6792
- case "server.request.resolved":
6793
- case "web.search":
6794
- case "review.status":
6795
- case "image.view":
6796
- case "context.compaction":
6797
- case "mcp.progress":
6798
- case "terminal.input":
6799
- case "skills.changed":
6800
- case "skills.loaded":
6801
- case "compact.pre":
6802
- case "compact.post":
6803
- case "unknown.hook":
6804
- case "todo.add":
6805
- case "todo.update":
6806
- case "todo.done":
6807
- case "agent.message":
6808
- case "teammate.idle":
6809
- case "task.created":
6810
- case "task.completed":
6811
- case "config.change":
6812
- case "cwd.changed":
6813
- case "file.changed":
6814
- case "elicitation.request":
6815
- case "elicitation.result":
6816
- case "channel.permission.relayed":
6817
- case "channel.permission.resolved":
6818
- case "channel.question.relayed":
6819
- case "channel.question.resolved":
6820
- case "channel.chat.inbound":
6821
- case "channel.chat.outbound":
6822
- case "gateway.function.invoked":
6823
- case "gateway.function.completed":
6824
- case "gateway.function.failed":
6825
- case "artifacts.manifest":
6826
- return "";
6827
- }
6828
- }
6829
-
6830
- // src/core/feed/indexedTimeline.ts
6831
- var MAX_SEARCH_CACHE_SIZE = 8;
6832
- function subagentActorLabel(_agentType, _agentId) {
6833
- return "SUB AGENT";
6834
- }
6835
- function buildSubagentTypeMap(feedEvents) {
6836
- const map = /* @__PURE__ */ new Map();
6837
- updateSubagentTypeMap(map, feedEvents);
6838
- return map;
6839
- }
6840
- function updateSubagentTypeMap(map, feedEvents) {
6841
- for (const event of feedEvents) {
6842
- if (event.kind !== "subagent.start" && event.kind !== "subagent.stop") {
6843
- continue;
6844
- }
6845
- const agentId = event.data.agent_id;
6846
- const agentType = event.data.agent_type;
6847
- if (!agentId || !agentType || map.has(agentId)) continue;
6848
- map.set(agentId, agentType);
6849
- }
6850
- }
6851
- function resolveActorLabel(event, subagentTypes) {
6852
- if (!event.actor_id.startsWith("subagent:")) {
6853
- return actorLabel(event.actor_id);
6854
- }
6855
- const agentId = event.actor_id.slice("subagent:".length);
6856
- const eventAgentType = event.kind === "subagent.start" || event.kind === "subagent.stop" ? event.data.agent_type : void 0;
6857
- return subagentActorLabel(
6858
- eventAgentType || subagentTypes.get(agentId),
6859
- agentId
4110
+ }
4111
+ if (key.downArrow) {
4112
+ callbacks.moveCursor(1);
4113
+ return;
4114
+ }
4115
+ } finally {
4116
+ done();
4117
+ }
4118
+ },
4119
+ { isActive }
6860
4120
  );
6861
4121
  }
6862
- function buildMessageEntry(item, activeRunId, messageCounter) {
6863
- const summary = compactText(item.content, 200);
6864
- const details = item.content;
6865
- return {
6866
- id: `M${String(messageCounter).padStart(3, "0")}`,
6867
- ts: item.timestamp.getTime(),
6868
- runId: activeRunId,
6869
- op: item.role === "user" ? "User Msg" : "Agent Msg",
6870
- opTag: item.role === "user" ? "msg.user" : "msg.agent",
6871
- actor: item.role === "user" ? "USER" : "AGENT",
6872
- actorId: item.role === "user" ? "user" : "agent:root",
6873
- toolColumn: "",
6874
- summary,
6875
- summarySegments: [{ text: summary, role: "plain" }],
6876
- searchText: `${summary}
6877
- ${details}`,
6878
- error: false,
6879
- expandable: details.length > 120,
6880
- details,
6881
- duplicateActor: false
6882
- };
6883
- }
6884
- function shouldSkipEvent(event, verbose) {
6885
- if (!verbose && VERBOSE_ONLY_KINDS.has(event.kind)) {
6886
- return true;
6887
- }
6888
- if (!verbose && event.kind === "stop.request" && !event.data.stop_hook_active) {
6889
- return true;
6890
- }
6891
- return false;
6892
- }
6893
- function mergedToolUseId(event, postByToolUseId) {
6894
- if (event.kind !== "tool.post" && event.kind !== "tool.failure" || isSubagentTool(event.data.tool_name) || !postByToolUseId) {
6895
- return void 0;
6896
- }
6897
- const toolUseId = event.data.tool_use_id;
6898
- if (!toolUseId) return void 0;
6899
- return postByToolUseId.get(toolUseId) === event ? toolUseId : void 0;
6900
- }
6901
- function pairedPostForEvent(event, postByToolUseId) {
6902
- if (event.kind !== "tool.pre" && event.kind !== "permission.request" || isSubagentTool(event.data.tool_name) || !event.data.tool_use_id) {
6903
- return void 0;
6904
- }
6905
- return postByToolUseId?.get(event.data.tool_use_id);
6906
- }
6907
- function pendingToolUpdateUseId(event) {
6908
- if (event.kind !== "tool.delta" && event.kind !== "tool.post" && event.kind !== "tool.failure") {
6909
- return void 0;
6910
- }
6911
- if (isSubagentTool(event.data.tool_name)) {
6912
- return void 0;
6913
- }
6914
- return event.data.tool_use_id;
6915
- }
6916
- function buildEventEntry(event, subagentTypes, pairedPost) {
6917
- const opTag = pairedPost ? mergedEventOperation(event, pairedPost) : eventOperation(event);
6918
- const op = pairedPost ? mergedEventLabel(event, pairedPost) : eventLabel(event);
6919
- const summaryResult = pairedPost ? mergedEventSummary(event, pairedPost) : eventSummary(event);
6920
- const { text: summary, segments: summarySegments } = summaryResult;
6921
- const toolColumn = event.kind === "tool.pre" || event.kind === "tool.post" || event.kind === "tool.failure" ? resolveToolColumn(event.data.tool_name) : resolveEventToolColumn(event);
6922
- return {
6923
- id: event.event_id,
6924
- ts: event.ts,
6925
- runId: event.run_id,
6926
- op,
6927
- opTag,
6928
- actor: resolveActorLabel(event, subagentTypes),
6929
- actorId: event.actor_id,
6930
- toolColumn,
6931
- summary,
6932
- summarySegments,
6933
- summaryOutcome: summaryResult.outcome,
6934
- summaryOutcomeZero: summaryResult.outcomeZero,
6935
- searchText: summary,
6936
- error: isEventError(event) || pairedPost?.kind === "tool.failure",
6937
- expandable: isEventExpandable(event),
6938
- details: "",
6939
- feedEvent: event,
6940
- pairedPostEvent: pairedPost,
6941
- duplicateActor: false
6942
- };
6943
- }
6944
- function maybeBuildEventEntry(event, subagentTypes, postByToolUseId, verbose) {
6945
- if (shouldSkipEvent(event, verbose)) return null;
6946
- if (event.kind === "tool.delta") return null;
6947
- if (mergedToolUseId(event, postByToolUseId)) {
6948
- return null;
6949
- }
6950
- return buildEventEntry(
6951
- event,
6952
- subagentTypes,
6953
- pairedPostForEvent(event, postByToolUseId)
4122
+
4123
+ // src/ui/hooks/useTodoKeyboard.ts
4124
+ import { useRef as useRef8 } from "react";
4125
+ import { useInput as useInput10 } from "ink";
4126
+ function useTodoKeyboard({
4127
+ isActive,
4128
+ todoCursor,
4129
+ visibleTodoItems,
4130
+ filteredEntries,
4131
+ callbacks
4132
+ }) {
4133
+ const visibleTodoItemsRef = useRef8(visibleTodoItems);
4134
+ visibleTodoItemsRef.current = visibleTodoItems;
4135
+ const filteredEntriesRef = useRef8(filteredEntries);
4136
+ filteredEntriesRef.current = filteredEntries;
4137
+ useInput10(
4138
+ (input, key) => {
4139
+ const done = startInputMeasure("todo.keyboard", input, key);
4140
+ try {
4141
+ if (key.escape) {
4142
+ callbacks.focusFeed();
4143
+ return;
4144
+ }
4145
+ if (key.tab) {
4146
+ callbacks.cycleFocus();
4147
+ return;
4148
+ }
4149
+ if (key.upArrow) {
4150
+ callbacks.moveTodoCursor(-1);
4151
+ return;
4152
+ }
4153
+ if (key.downArrow) {
4154
+ callbacks.moveTodoCursor(1);
4155
+ return;
4156
+ }
4157
+ if (input === " ") {
4158
+ callbacks.toggleTodoStatus(todoCursor);
4159
+ return;
4160
+ }
4161
+ if (key.return) {
4162
+ if (todoCursor < 0 || todoCursor >= visibleTodoItemsRef.current.length) {
4163
+ return;
4164
+ }
4165
+ const selected = visibleTodoItemsRef.current[todoCursor];
4166
+ if (!selected.linkedEventId) return;
4167
+ const idx = filteredEntriesRef.current.findIndex(
4168
+ (entry) => entry.id === selected.linkedEventId
4169
+ );
4170
+ if (idx >= 0) {
4171
+ callbacks.revealFeedCursor(idx);
4172
+ }
4173
+ return;
4174
+ }
4175
+ if (input.toLowerCase() === "a") {
4176
+ callbacks.openNormalInput();
4177
+ callbacks.setInputValue("");
4178
+ return;
4179
+ }
4180
+ } finally {
4181
+ done();
4182
+ }
4183
+ },
4184
+ { isActive }
6954
4185
  );
6955
4186
  }
6956
- function rememberPendingEntry(pendingEntryIndexByToolUseId, entry, index) {
6957
- const event = entry.feedEvent;
6958
- if (!event) return;
6959
- if (event.kind !== "tool.pre" && event.kind !== "permission.request" || isSubagentTool(event.data.tool_name) || !event.data.tool_use_id || entry.pairedPostEvent) {
6960
- return;
6961
- }
6962
- pendingEntryIndexByToolUseId.set(event.data.tool_use_id, index);
6963
- }
6964
- function recomputeDuplicateActorAt(entries, index) {
6965
- const entry = entries[index];
6966
- if (index === 0) {
6967
- entry.duplicateActor = false;
6968
- return;
6969
- }
6970
- const prev = entries[index - 1];
6971
- const sameActor = entry.actorId === prev.actorId;
6972
- const isBreak = opCategory(entry.opTag) !== opCategory(prev.opTag);
6973
- entry.duplicateActor = sameActor && !isBreak;
6974
- }
6975
- function recomputeDuplicateActorsAround(entries, index) {
6976
- recomputeDuplicateActorAt(entries, index);
6977
- if (index + 1 < entries.length) {
6978
- recomputeDuplicateActorAt(entries, index + 1);
6979
- }
6980
- }
6981
- function sameFeedItemPrefix(previous, next) {
6982
- if (next.length < previous.length) return false;
6983
- for (let i = 0; i < previous.length; i++) {
6984
- const prev = previous[i];
6985
- const curr = next[i];
6986
- if (prev.type !== curr.type || prev.data !== curr.data) {
6987
- return false;
6988
- }
6989
- }
6990
- return true;
6991
- }
6992
- function sameFeedEventPrefix(previous, next) {
6993
- if (next.length < previous.length) return false;
6994
- for (let i = 0; i < previous.length; i++) {
6995
- if (previous[i] !== next[i]) {
6996
- return false;
4187
+
4188
+ // src/ui/hooks/useSpinner.ts
4189
+ import { useState as useState8, useEffect as useEffect7 } from "react";
4190
+ var BRAILLE_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
4191
+ var DEFAULT_SPINNER_INTERVAL_MS = 1e3;
4192
+ function useSpinner(active, intervalMs = DEFAULT_SPINNER_INTERVAL_MS) {
4193
+ const [frameIndex, setFrameIndex] = useState8(0);
4194
+ useEffect7(() => {
4195
+ if (!active) {
4196
+ setFrameIndex(0);
4197
+ return;
6997
4198
  }
6998
- }
6999
- return true;
4199
+ const timer = setInterval(() => {
4200
+ startPerfCycle("timer:spinner", { scope: "spinner" });
4201
+ setFrameIndex((i) => (i + 1) % BRAILLE_FRAMES.length);
4202
+ }, intervalMs);
4203
+ return () => clearInterval(timer);
4204
+ }, [active, intervalMs]);
4205
+ if (!active) return "";
4206
+ return BRAILLE_FRAMES[frameIndex] ?? "\u280B";
7000
4207
  }
7001
- function canAppendIncrementally(previous, feedItems, feedEvents, verbose) {
7002
- if (!previous) return false;
7003
- if (previous.verbose !== verbose) return false;
7004
- return sameFeedItemPrefix(previous.feedItems, feedItems) && sameFeedEventPrefix(previous.feedEvents, feedEvents);
4208
+
4209
+ // src/ui/hooks/useTodoDisplayItems.ts
4210
+ import { useEffect as useEffect8, useMemo as useMemo8, useState as useState9 } from "react";
4211
+ function hasTickingElapsedItems(items) {
4212
+ return items.some(
4213
+ (item) => item.status === "doing" && item.startedAtMs !== void 0
4214
+ );
7005
4215
  }
7006
- function buildTimelineCache(feedItems, feedEvents, postByToolUseId, verbose) {
7007
- const entries = [];
7008
- let activeRunId;
7009
- let messageCounter = 1;
7010
- const subagentTypes = buildSubagentTypeMap(feedEvents);
7011
- const pendingEntryIndexByToolUseId = /* @__PURE__ */ new Map();
7012
- for (const item of feedItems) {
7013
- if (item.type === "message") {
7014
- entries.push(buildMessageEntry(item.data, activeRunId, messageCounter++));
7015
- continue;
7016
- }
7017
- const event = item.data;
7018
- if (event.kind === "run.start") {
7019
- activeRunId = event.run_id;
7020
- }
7021
- const entry = maybeBuildEventEntry(
7022
- event,
7023
- subagentTypes,
7024
- postByToolUseId,
7025
- verbose
7026
- );
7027
- if (entry) {
7028
- const index = entries.push(entry) - 1;
7029
- rememberPendingEntry(pendingEntryIndexByToolUseId, entry, index);
7030
- }
7031
- if (event.kind === "run.end") {
7032
- activeRunId = void 0;
7033
- }
7034
- }
7035
- computeDuplicateActors(entries);
7036
- return {
7037
- feedItems,
7038
- feedEvents,
7039
- entries,
7040
- activeRunId,
7041
- messageCounter,
7042
- subagentTypes,
7043
- pendingEntryIndexByToolUseId,
7044
- verbose
7045
- };
4216
+ function buildTodoDisplayItems(items, nowMs, isWorking, pausedAtMs) {
4217
+ let changed = false;
4218
+ const nextItems = items.map((item) => {
4219
+ const hasElapsed = item.startedAtMs !== void 0 && (item.status === "doing" || item.status === "done" || item.status === "failed");
4220
+ const endMs = item.completedAtMs ?? (isWorking ? nowMs : pausedAtMs ?? nowMs);
4221
+ const elapsed = hasElapsed ? formatElapsed(Math.max(0, endMs - item.startedAtMs)) : void 0;
4222
+ if (elapsed === item.elapsed) return item;
4223
+ changed = true;
4224
+ return { ...item, elapsed };
4225
+ });
4226
+ return changed ? nextItems : items;
7046
4227
  }
7047
- function appendTimelineCache(previous, feedItems, feedEvents, postByToolUseId) {
7048
- const entries = previous.entries.slice();
7049
- const subagentTypes = new Map(previous.subagentTypes);
7050
- updateSubagentTypeMap(
7051
- subagentTypes,
7052
- feedEvents.slice(previous.feedEvents.length)
7053
- );
7054
- const pendingEntryIndexByToolUseId = new Map(
7055
- previous.pendingEntryIndexByToolUseId
4228
+ function useTodoDisplayItems({
4229
+ items,
4230
+ isWorking,
4231
+ pausedAtMs,
4232
+ active,
4233
+ tickMs = 1e3
4234
+ }) {
4235
+ const [nowMs, setNowMs] = useState9(() => Date.now());
4236
+ const hasDoingItems = useMemo8(() => hasTickingElapsedItems(items), [items]);
4237
+ useEffect8(() => {
4238
+ if (!active || !isWorking || !hasDoingItems) return;
4239
+ const id = setInterval(() => {
4240
+ startPerfCycle("timer:todo-header", {
4241
+ scope: "todo.elapsed",
4242
+ items: items.length
4243
+ });
4244
+ setNowMs(Date.now());
4245
+ }, tickMs);
4246
+ return () => clearInterval(id);
4247
+ }, [active, isWorking, hasDoingItems, items.length, tickMs]);
4248
+ return useMemo8(
4249
+ () => buildTodoDisplayItems(items, nowMs, isWorking, pausedAtMs),
4250
+ [items, nowMs, isWorking, pausedAtMs]
7056
4251
  );
7057
- let activeRunId = previous.activeRunId;
7058
- let messageCounter = previous.messageCounter;
7059
- for (const item of feedItems.slice(previous.feedItems.length)) {
7060
- if (item.type === "message") {
7061
- const index = entries.push(
7062
- buildMessageEntry(item.data, activeRunId, messageCounter++)
7063
- ) - 1;
7064
- recomputeDuplicateActorsAround(entries, index);
7065
- continue;
7066
- }
7067
- const event = item.data;
7068
- if (event.kind === "run.start") {
7069
- activeRunId = event.run_id;
7070
- }
7071
- const resolvedToolUseId = pendingToolUpdateUseId(event);
7072
- if (resolvedToolUseId) {
7073
- const pendingIndex = pendingEntryIndexByToolUseId.get(resolvedToolUseId);
7074
- if (pendingIndex !== void 0) {
7075
- const pendingEntry = entries[pendingIndex];
7076
- if (pendingEntry.feedEvent) {
7077
- entries[pendingIndex] = buildEventEntry(
7078
- pendingEntry.feedEvent,
7079
- subagentTypes,
7080
- event
7081
- );
7082
- if (event.kind === "tool.post" || event.kind === "tool.failure") {
7083
- pendingEntryIndexByToolUseId.delete(resolvedToolUseId);
7084
- }
7085
- recomputeDuplicateActorsAround(entries, pendingIndex);
7086
- }
7087
- }
7088
- continue;
7089
- }
7090
- const entry = maybeBuildEventEntry(
7091
- event,
7092
- subagentTypes,
7093
- postByToolUseId,
7094
- previous.verbose
7095
- );
7096
- if (entry) {
7097
- const index = entries.push(entry) - 1;
7098
- recomputeDuplicateActorsAround(entries, index);
7099
- rememberPendingEntry(pendingEntryIndexByToolUseId, entry, index);
7100
- }
7101
- if (event.kind === "run.end") {
7102
- activeRunId = void 0;
7103
- }
7104
- }
7105
- return {
7106
- feedItems,
7107
- feedEvents,
7108
- entries,
7109
- activeRunId,
7110
- messageCounter,
7111
- subagentTypes,
7112
- pendingEntryIndexByToolUseId,
7113
- verbose: previous.verbose
7114
- };
7115
4252
  }
7116
- var IndexedTimeline = class {
7117
- cache = null;
7118
- runIndex = /* @__PURE__ */ new Map();
7119
- errorPositions = /* @__PURE__ */ new Set();
7120
- _runSummaryMap = /* @__PURE__ */ new Map();
7121
- _runSummariesDirty = true;
7122
- _runSummariesCache = [];
7123
- _lastFeedEventsLength = 0;
7124
- searchCache = /* @__PURE__ */ new Map();
7125
- lastFilteredRef = null;
7126
- detailCache = /* @__PURE__ */ new WeakMap();
7127
- searchTextCache = /* @__PURE__ */ new WeakMap();
7128
- verbose = false;
7129
- update(feedItems, feedEvents, postByToolUseId, verbose) {
7130
- this.verbose = verbose;
7131
- const incremental = canAppendIncrementally(
7132
- this.cache,
7133
- feedItems,
7134
- feedEvents,
7135
- this.verbose
7136
- );
7137
- if (incremental) {
7138
- this.updateRunSummaries(feedEvents);
7139
- this.cache = appendTimelineCache(
7140
- this.cache,
7141
- feedItems,
7142
- feedEvents,
7143
- postByToolUseId
7144
- );
7145
- } else {
7146
- this.rebuildRunSummaries(feedEvents);
7147
- this.cache = buildTimelineCache(
7148
- feedItems,
7149
- feedEvents,
7150
- postByToolUseId,
7151
- this.verbose
7152
- );
7153
- }
7154
- this.rebuildIndexes();
7155
- }
7156
- getEntries() {
7157
- return this.cache?.entries ?? [];
7158
- }
7159
- getFilteredView(runFilter, errorsOnly) {
7160
- const entries = this.getEntries();
7161
- if ((!runFilter || runFilter === "all") && !errorsOnly) {
7162
- return entries;
7163
- }
7164
- let candidateIndices;
7165
- if (runFilter && runFilter !== "all") {
7166
- candidateIndices = this.runIndex.get(runFilter) ?? [];
7167
- } else {
7168
- candidateIndices = Array.from({ length: entries.length }, (_, i) => i);
7169
- }
7170
- if (errorsOnly) {
7171
- candidateIndices = candidateIndices.filter(
7172
- (i) => this.errorPositions.has(i)
7173
- );
7174
- }
7175
- return candidateIndices.map((i) => entries[i]);
7176
- }
7177
- getSearchMatches(filteredEntries, query) {
7178
- const q = query.trim().toLowerCase();
7179
- if (!q) return [];
7180
- if (filteredEntries !== this.lastFilteredRef) {
7181
- this.searchCache.clear();
7182
- this.lastFilteredRef = filteredEntries;
7183
- }
7184
- const cached = this.searchCache.get(q);
7185
- if (cached && cached.lastScanned === filteredEntries.length) {
7186
- return cached.matches;
7187
- }
7188
- const startFrom = cached ? cached.lastScanned : 0;
7189
- const matches = cached ? [...cached.matches] : [];
7190
- for (let i = startFrom; i < filteredEntries.length; i++) {
7191
- const searchText = this.getEntrySearchText(filteredEntries[i]);
7192
- if (searchText.toLowerCase().includes(q)) {
7193
- matches.push(i);
7194
- }
7195
- }
7196
- this.searchCache.set(q, { matches, lastScanned: filteredEntries.length });
7197
- if (this.searchCache.size > MAX_SEARCH_CACHE_SIZE) {
7198
- const oldest = this.searchCache.keys().next().value;
7199
- if (oldest !== void 0) {
7200
- this.searchCache.delete(oldest);
7201
- }
7202
- }
7203
- return matches;
7204
- }
7205
- getEntrySearchText(entry) {
7206
- const cached = this.searchTextCache.get(entry);
7207
- if (cached !== void 0) return cached;
7208
- if (!entry.feedEvent) {
7209
- this.searchTextCache.set(entry, entry.searchText);
7210
- return entry.searchText;
7211
- }
7212
- const details = this.getEntryDetails(entry);
7213
- const searchText = details ? `${entry.summary}
7214
- ${details}` : entry.summary;
7215
- this.searchTextCache.set(entry, searchText);
7216
- return searchText;
7217
- }
7218
- getEntryDetails(entry) {
7219
- if (entry.details) return entry.details;
7220
- if (!entry.feedEvent) return entry.summary;
7221
- const cached = this.detailCache.get(entry);
7222
- if (cached !== void 0) return cached;
7223
- const details = isEventExpandable(entry.feedEvent) ? expansionForEvent(entry.feedEvent) : "";
7224
- this.detailCache.set(entry, details);
7225
- return details;
7226
- }
7227
- getRunSummaries() {
7228
- if (this._runSummariesDirty) {
7229
- this._runSummariesCache = Array.from(this._runSummaryMap.values()).sort(
7230
- (a, b) => a.startedAt - b.startedAt
7231
- );
7232
- this._runSummariesDirty = false;
7233
- }
7234
- return this._runSummariesCache;
7235
- }
7236
- processRunEvent(event) {
7237
- if (event.kind === "run.start") {
7238
- this._runSummaryMap.set(event.run_id, {
7239
- runId: event.run_id,
7240
- title: compactText(
7241
- event.data.trigger.prompt_preview || "Untitled run",
7242
- 46
7243
- ),
7244
- status: "RUNNING",
7245
- startedAt: event.ts
7246
- });
7247
- this._runSummariesDirty = true;
7248
- } else if (event.kind === "run.end") {
7249
- const existing = this._runSummaryMap.get(event.run_id);
7250
- if (existing) {
7251
- existing.status = toRunStatus(event);
7252
- existing.endedAt = event.ts;
7253
- } else {
7254
- this._runSummaryMap.set(event.run_id, {
7255
- runId: event.run_id,
7256
- title: "Untitled run",
7257
- status: toRunStatus(event),
7258
- startedAt: event.ts,
7259
- endedAt: event.ts
7260
- });
7261
- }
7262
- this._runSummariesDirty = true;
7263
- }
7264
- }
7265
- rebuildRunSummaries(feedEvents) {
7266
- this._runSummaryMap.clear();
7267
- this._runSummariesDirty = true;
7268
- this._lastFeedEventsLength = 0;
7269
- this.updateRunSummaries(feedEvents);
7270
- }
7271
- updateRunSummaries(feedEvents) {
7272
- for (let i = this._lastFeedEventsLength; i < feedEvents.length; i++) {
7273
- this.processRunEvent(feedEvents[i]);
7274
- }
7275
- this._lastFeedEventsLength = feedEvents.length;
7276
- }
7277
- addToIndex(entry, index) {
7278
- const runId = entry.runId ?? "__none__";
7279
- let indices = this.runIndex.get(runId);
7280
- if (!indices) {
7281
- indices = [];
7282
- this.runIndex.set(runId, indices);
7283
- }
7284
- indices.push(index);
7285
- if (entry.error) {
7286
- this.errorPositions.add(index);
7287
- }
7288
- }
7289
- rebuildIndexes() {
7290
- this.runIndex.clear();
7291
- this.errorPositions.clear();
7292
- this.searchCache.clear();
7293
- const entries = this.getEntries();
7294
- for (let i = 0; i < entries.length; i++) {
7295
- this.addToIndex(entries[i], i);
7296
- }
7297
- }
7298
- };
7299
4253
 
7300
4254
  // src/ui/hooks/useTimeline.ts
4255
+ import { useMemo as useMemo9, useRef as useRef9, useCallback as useCallback10 } from "react";
7301
4256
  var EMPTY_MATCHES = Object.freeze([]);
7302
4257
  var EMPTY_MATCH_SET = Object.freeze(/* @__PURE__ */ new Set());
7303
4258
  function useTimeline({
@@ -7536,7 +4491,7 @@ function detectLanguage(filePath) {
7536
4491
  function isMarkdownRenderable(language) {
7537
4492
  return language === void 0 || language === "markdown";
7538
4493
  }
7539
- function prop3(obj, key) {
4494
+ function prop(obj, key) {
7540
4495
  if (typeof obj === "object" && obj !== null) {
7541
4496
  return obj[key];
7542
4497
  }
@@ -7551,21 +4506,21 @@ function extractTextContent(response) {
7551
4506
  if (typeof block === "string") {
7552
4507
  parts.push(block);
7553
4508
  } else if (typeof block === "object" && block !== null) {
7554
- const text = prop3(block, "text");
4509
+ const text = prop(block, "text");
7555
4510
  if (typeof text === "string") parts.push(text);
7556
4511
  }
7557
4512
  }
7558
4513
  if (parts.length > 0) return parts.join("\n").trim();
7559
4514
  }
7560
4515
  if (typeof response === "object") {
7561
- const text = prop3(response, "text");
7562
- if (typeof text === "string" && prop3(response, "type") === "text") {
4516
+ const text = prop(response, "text");
4517
+ if (typeof text === "string" && prop(response, "type") === "text") {
7563
4518
  return text.trim();
7564
4519
  }
7565
- const content = prop3(response, "content");
4520
+ const content = prop(response, "content");
7566
4521
  if (content != null) return extractTextContent(content);
7567
4522
  for (const key of ["result", "message", "output"]) {
7568
- const val = prop3(response, key);
4523
+ const val = prop(response, key);
7569
4524
  if (typeof val === "string") return val;
7570
4525
  }
7571
4526
  }
@@ -7610,10 +4565,10 @@ ${err}` : err : out;
7610
4565
  }
7611
4566
  return { type: "code", content: extractTextContent(response), maxLines: 10 };
7612
4567
  }
7613
- function extractFileContent2(block) {
7614
- const fileContent = prop3(prop3(block, "file"), "content");
4568
+ function extractFileContent(block) {
4569
+ const fileContent = prop(prop(block, "file"), "content");
7615
4570
  if (typeof fileContent === "string") return fileContent;
7616
- const text = prop3(block, "text");
4571
+ const text = prop(block, "text");
7617
4572
  if (typeof text === "string") return text;
7618
4573
  return void 0;
7619
4574
  }
@@ -7621,7 +4576,7 @@ function extractRead(input, response) {
7621
4576
  const blocks = Array.isArray(response) ? response : [response];
7622
4577
  let content;
7623
4578
  for (const block of blocks) {
7624
- content = extractFileContent2(block);
4579
+ content = extractFileContent(block);
7625
4580
  if (content) break;
7626
4581
  }
7627
4582
  const language = detectLanguage(input["file_path"]);
@@ -7639,9 +4594,9 @@ function parseDiffLine(raw) {
7639
4594
  return { type: "context", content };
7640
4595
  }
7641
4596
  function parseStructuredPatch(response) {
7642
- const patch = prop3(response, "structuredPatch");
4597
+ const patch = prop(response, "structuredPatch");
7643
4598
  if (!patch) return void 0;
7644
- const rawHunks = prop3(patch, "hunks");
4599
+ const rawHunks = prop(patch, "hunks");
7645
4600
  if (!Array.isArray(rawHunks)) return void 0;
7646
4601
  return rawHunks.map((h) => {
7647
4602
  const oldStart = typeof h.oldStart === "number" ? h.oldStart : 1;
@@ -7678,7 +4633,7 @@ function extractWrite(input, response) {
7678
4633
  }
7679
4634
  const content = typeof input["content"] === "string" ? input["content"] : "";
7680
4635
  const filePath = String(
7681
- prop3(response, "filePath") ?? input["file_path"] ?? ""
4636
+ prop(response, "filePath") ?? input["file_path"] ?? ""
7682
4637
  );
7683
4638
  if (!content) {
7684
4639
  return { type: "text", content: `Wrote ${filePath}` };
@@ -7705,7 +4660,7 @@ function extractGrep(_input, response) {
7705
4660
  return { type: "list", items, maxItems: 10, groupBy: "secondary" };
7706
4661
  }
7707
4662
  function extractGlob(_input, response) {
7708
- const filenames = prop3(response, "filenames");
4663
+ const filenames = prop(response, "filenames");
7709
4664
  if (Array.isArray(filenames)) {
7710
4665
  const items2 = filenames.filter((f) => typeof f === "string").map((f) => ({ primary: f }));
7711
4666
  return { type: "list", items: items2, maxItems: 10, displayMode: "tree" };
@@ -7715,22 +4670,22 @@ function extractGlob(_input, response) {
7715
4670
  return { type: "list", items, maxItems: 10 };
7716
4671
  }
7717
4672
  function extractWebFetch(_input, response) {
7718
- const result = prop3(response, "result");
4673
+ const result = prop(response, "result");
7719
4674
  const content = typeof result === "string" ? result : extractTextContent(response);
7720
4675
  return { type: "text", content, maxLines: 10 };
7721
4676
  }
7722
4677
  function formatSearchLink(item) {
7723
- const title = prop3(item, "title");
4678
+ const title = prop(item, "title");
7724
4679
  if (typeof title !== "string") return null;
7725
- const url = prop3(item, "url");
4680
+ const url = prop(item, "url");
7726
4681
  return typeof url === "string" ? `- [${title}](${url})` : `- ${title}`;
7727
4682
  }
7728
4683
  function extractWebSearch(_input, response) {
7729
- const results = prop3(response, "results");
4684
+ const results = prop(response, "results");
7730
4685
  if (Array.isArray(results)) {
7731
4686
  const links = [];
7732
4687
  for (const entry of results) {
7733
- const content = prop3(entry, "content");
4688
+ const content = prop(entry, "content");
7734
4689
  const items = Array.isArray(content) ? content : [entry];
7735
4690
  for (const item of items) {
7736
4691
  const link = formatSearchLink(item);
@@ -7768,10 +4723,10 @@ function extractSkill(input, response) {
7768
4723
  }
7769
4724
  if (typeof response === "object" && response !== null) {
7770
4725
  const items = [];
7771
- const success = prop3(response, "success");
7772
- const commandName = prop3(response, "commandName");
7773
- const message = prop3(response, "message");
7774
- const allowedTools = prop3(response, "allowedTools");
4726
+ const success = prop(response, "success");
4727
+ const commandName = prop(response, "commandName");
4728
+ const message = prop(response, "message");
4729
+ const allowedTools = prop(response, "allowedTools");
7775
4730
  if (skill) items.push({ secondary: "skill", primary: skill });
7776
4731
  if (typeof commandName === "string" && commandName.trim()) {
7777
4732
  items.push({ secondary: "command", primary: commandName.trim() });
@@ -8298,7 +5253,7 @@ function extractToolSubject(toolName, toolInput) {
8298
5253
  return void 0;
8299
5254
  }
8300
5255
  }
8301
- function eventLabel2(event) {
5256
+ function eventLabel(event) {
8302
5257
  if (isDefaultRenderKind(event.kind)) return "Event";
8303
5258
  switch (event.kind) {
8304
5259
  case "tool.delta":
@@ -8384,7 +5339,7 @@ function eventLabel2(event) {
8384
5339
  }
8385
5340
  function buildCompactHeader(event, width, opts = {}) {
8386
5341
  const theme = opts.theme ?? darkTheme;
8387
- const label = eventLabel2(event);
5342
+ const label = eventLabel(event);
8388
5343
  const time = formatClock(event.ts);
8389
5344
  let title = source_default.bold.hex(theme.detail.title)(label);
8390
5345
  if (opts.subject) {
@@ -8545,6 +5500,9 @@ function renderDetailLines(event, width, pairedPostEvent, theme = darkTheme) {
8545
5500
  case "compact.post":
8546
5501
  case "cwd.changed":
8547
5502
  case "file.changed":
5503
+ case "instructions.loaded":
5504
+ case "worktree.create":
5505
+ case "worktree.remove":
8548
5506
  case "stop.failure":
8549
5507
  case "permission.denied":
8550
5508
  case "elicitation.request":
@@ -11933,7 +8891,7 @@ function useRuntimeSelectors() {
11933
8891
  const questionQueueCount = useHookContextSelector((v) => v.questionQueueCount);
11934
8892
  const resolveQuestion = useHookContextSelector((v) => v.resolveQuestion);
11935
8893
  const isServerRunning = useHookContextSelector((v) => v.isServerRunning);
11936
- const runtimeError2 = useHookContextSelector((v) => v.runtimeError);
8894
+ const runtimeError = useHookContextSelector((v) => v.runtimeError);
11937
8895
  const postByToolUseId = useHookContextSelector((v) => v.postByToolUseId);
11938
8896
  const allocateSeq = useHookContextSelector((v) => v.allocateSeq);
11939
8897
  const clearEvents = useHookContextSelector((v) => v.clearEvents);
@@ -11958,7 +8916,7 @@ function useRuntimeSelectors() {
11958
8916
  questionQueueCount,
11959
8917
  resolveQuestion,
11960
8918
  isServerRunning,
11961
- runtimeError: runtimeError2,
8919
+ runtimeError,
11962
8920
  postByToolUseId,
11963
8921
  allocateSeq,
11964
8922
  clearEvents,
@@ -12942,7 +9900,7 @@ function AppContent({
12942
9900
  isServerRunning,
12943
9901
  recordTokens,
12944
9902
  restoredTokens,
12945
- runtimeError: runtimeError2,
9903
+ runtimeError,
12946
9904
  hookCommandFeed
12947
9905
  } = useRuntimeSelectors();
12948
9906
  const currentSessionId = session?.session_id ?? null;
@@ -13087,7 +10045,7 @@ function AppContent({
13087
10045
  if (!current) {
13088
10046
  return current;
13089
10047
  }
13090
- const isActiveHookServerStartupFailure = current.failureStage === "startup_timeout" && !!runtimeError2 && !isServerRunning && current.message === runtimeError2.message;
10048
+ const isActiveHookServerStartupFailure = current.failureStage === "startup_timeout" && !!runtimeError && !isServerRunning && current.message === runtimeError.message;
13091
10049
  if (isActiveHookServerStartupFailure) {
13092
10050
  return current;
13093
10051
  }
@@ -13096,21 +10054,21 @@ function AppContent({
13096
10054
  }
13097
10055
  return null;
13098
10056
  });
13099
- }, [feedEvents.length, isServerRunning, runtimeError2]);
10057
+ }, [feedEvents.length, isServerRunning, runtimeError]);
13100
10058
  useEffect14(() => {
13101
10059
  if (!shouldTrackClaudeStartup || !isTelemetryEnabled()) return;
13102
- if (!runtimeError2 || isServerRunning) {
10060
+ if (!runtimeError || isServerRunning) {
13103
10061
  runtimeStartupDiagnosticsSignatureRef.current = null;
13104
10062
  return;
13105
10063
  }
13106
- const signature = `${runtimeError2.code}:${runtimeError2.message}`;
10064
+ const signature = `${runtimeError.code}:${runtimeError.message}`;
13107
10065
  if (signature === runtimeStartupDiagnosticsSignatureRef.current) {
13108
10066
  return;
13109
10067
  }
13110
10068
  runtimeStartupDiagnosticsSignatureRef.current = signature;
13111
10069
  const diagnosticsEvent = createPendingStartupDiagnosticsEvent({
13112
10070
  failureStage: "startup_timeout",
13113
- message: runtimeError2.message,
10071
+ message: runtimeError.message,
13114
10072
  feedEventCount: feedEvents.length
13115
10073
  });
13116
10074
  if (diagnosticsConsent === true) {
@@ -13123,7 +10081,7 @@ function AppContent({
13123
10081
  emitClaudeStartupDiagnostics,
13124
10082
  feedEvents.length,
13125
10083
  isServerRunning,
13126
- runtimeError2,
10084
+ runtimeError,
13127
10085
  shouldTrackClaudeStartup
13128
10086
  ]);
13129
10087
  useEffect14(() => {
@@ -13138,7 +10096,7 @@ function AppContent({
13138
10096
  return;
13139
10097
  }
13140
10098
  const derivedFailure = deriveStartupTimeoutFailure({
13141
- runtimeError: runtimeError2,
10099
+ runtimeError,
13142
10100
  isServerRunning,
13143
10101
  isHarnessRunning,
13144
10102
  harnessLabel
@@ -13175,7 +10133,7 @@ function AppContent({
13175
10133
  harnessLabel,
13176
10134
  isHarnessRunning,
13177
10135
  isServerRunning,
13178
- runtimeError2,
10136
+ runtimeError,
13179
10137
  shouldTrackClaudeStartup
13180
10138
  ]);
13181
10139
  const addMessage = useCallback19(
@@ -13292,13 +10250,13 @@ function AppContent({
13292
10250
  setPendingStartupDiagnostics(null);
13293
10251
  setStartupFailure(null);
13294
10252
  addMessage("user", result.text);
13295
- if (!isServerRunning && runtimeError2) {
10253
+ if (!isServerRunning && runtimeError) {
13296
10254
  setStartupFailure({
13297
- message: runtimeError2.message,
13298
- failureCode: runtimeError2.code === "socket_path_too_long" ? "socket_path_too_long" : "hook_server_unavailable"
10255
+ message: runtimeError.message,
10256
+ failureCode: runtimeError.code === "socket_path_too_long" ? "socket_path_too_long" : "hook_server_unavailable"
13299
10257
  });
13300
10258
  emitNotification(
13301
- `Athena failed to start ${harnessLabel}: ${runtimeError2.message}`,
10259
+ `Athena failed to start ${harnessLabel}: ${runtimeError.message}`,
13302
10260
  `${harnessLabel} Startup Error`
13303
10261
  );
13304
10262
  return;
@@ -13354,13 +10312,13 @@ function AppContent({
13354
10312
  spawn: (prompt, sessionId2, configOverride) => {
13355
10313
  setPendingStartupDiagnostics(null);
13356
10314
  setStartupFailure(null);
13357
- if (!isServerRunning && runtimeError2) {
10315
+ if (!isServerRunning && runtimeError) {
13358
10316
  setStartupFailure({
13359
- message: runtimeError2.message,
13360
- failureCode: runtimeError2.code === "socket_path_too_long" ? "socket_path_too_long" : "hook_server_unavailable"
10317
+ message: runtimeError.message,
10318
+ failureCode: runtimeError.code === "socket_path_too_long" ? "socket_path_too_long" : "hook_server_unavailable"
13361
10319
  });
13362
10320
  emitNotification(
13363
- `Athena failed to start ${harnessLabel}: ${runtimeError2.message}`,
10321
+ `Athena failed to start ${harnessLabel}: ${runtimeError.message}`,
13364
10322
  `${harnessLabel} Startup Error`
13365
10323
  );
13366
10324
  return Promise.resolve();
@@ -13388,7 +10346,7 @@ function AppContent({
13388
10346
  spawnHarness,
13389
10347
  currentSessionId,
13390
10348
  isServerRunning,
13391
- runtimeError2,
10349
+ runtimeError,
13392
10350
  exit,
13393
10351
  clearScreen,
13394
10352
  onShowSessions,
@@ -14868,7 +11826,7 @@ var tasksCommand = {
14868
11826
  };
14869
11827
 
14870
11828
  // src/app/commands/builtins/setup.ts
14871
- var setup2 = {
11829
+ var setup = {
14872
11830
  name: "setup",
14873
11831
  description: "Re-run the setup wizard",
14874
11832
  category: "ui",
@@ -14876,7 +11834,7 @@ var setup2 = {
14876
11834
  ctx.showSetup();
14877
11835
  }
14878
11836
  };
14879
- var setup_default = setup2;
11837
+ var setup_default = setup;
14880
11838
 
14881
11839
  // src/app/commands/builtins/telemetry.ts
14882
11840
  var telemetryCommand = {
@@ -15705,7 +12663,7 @@ var cachedVersion = null;
15705
12663
  function readPackageVersion() {
15706
12664
  if (cachedVersion !== null) return cachedVersion;
15707
12665
  try {
15708
- const injected = "0.5.7";
12666
+ const injected = "0.5.10";
15709
12667
  if (typeof injected === "string" && injected.length > 0) {
15710
12668
  cachedVersion = injected;
15711
12669
  return cachedVersion;