@timetotest/cli 0.1.10 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/README.md +201 -190
  2. package/dist/bin/ttt.js +4 -2
  3. package/dist/bin/ttt.js.map +1 -1
  4. package/dist/package.json +20 -3
  5. package/dist/src/commands/ask/AskApp.js +121 -0
  6. package/dist/src/commands/ask/AskApp.js.map +1 -0
  7. package/dist/src/commands/ask/components/AssistantResponse.js +31 -0
  8. package/dist/src/commands/ask/components/AssistantResponse.js.map +1 -0
  9. package/dist/src/commands/ask/components/Banner.js +15 -0
  10. package/dist/src/commands/ask/components/Banner.js.map +1 -0
  11. package/dist/src/commands/ask/components/ChatInput.js +93 -0
  12. package/dist/src/commands/ask/components/ChatInput.js.map +1 -0
  13. package/dist/src/commands/ask/components/Divider.js +17 -0
  14. package/dist/src/commands/ask/components/Divider.js.map +1 -0
  15. package/dist/src/commands/ask/components/IntroTips.js +19 -0
  16. package/dist/src/commands/ask/components/IntroTips.js.map +1 -0
  17. package/dist/src/commands/ask/components/MessageBubble.js +47 -0
  18. package/dist/src/commands/ask/components/MessageBubble.js.map +1 -0
  19. package/dist/src/commands/ask/components/SessionInfo.js +20 -0
  20. package/dist/src/commands/ask/components/SessionInfo.js.map +1 -0
  21. package/dist/src/commands/ask/components/StatusIndicator.js +67 -0
  22. package/dist/src/commands/ask/components/StatusIndicator.js.map +1 -0
  23. package/dist/src/commands/ask-ink.js +380 -0
  24. package/dist/src/commands/ask-ink.js.map +1 -0
  25. package/dist/src/commands/ask.js +138 -50
  26. package/dist/src/commands/ask.js.map +1 -1
  27. package/dist/src/commands/chat/ChatApp.js +125 -0
  28. package/dist/src/commands/chat/ChatApp.js.map +1 -0
  29. package/dist/src/commands/chat-ink.js +436 -0
  30. package/dist/src/commands/chat-ink.js.map +1 -0
  31. package/dist/src/commands/chat.js +82 -0
  32. package/dist/src/commands/chat.js.map +1 -0
  33. package/dist/src/commands/login.js +6 -4
  34. package/dist/src/commands/login.js.map +1 -1
  35. package/dist/src/commands/start-test.js +62 -88
  36. package/dist/src/commands/start-test.js.map +1 -1
  37. package/dist/src/commands/stream.js +9 -9
  38. package/dist/src/commands/stream.js.map +1 -1
  39. package/dist/src/commands/test.js +58 -125
  40. package/dist/src/commands/test.js.map +1 -1
  41. package/dist/src/lib/agent-orchestrator.js +546 -0
  42. package/dist/src/lib/agent-orchestrator.js.map +1 -0
  43. package/dist/src/lib/cloudinary-service.js +65 -0
  44. package/dist/src/lib/cloudinary-service.js.map +1 -0
  45. package/dist/src/lib/config.js +3 -2
  46. package/dist/src/lib/config.js.map +1 -1
  47. package/dist/src/lib/events.js +73 -60
  48. package/dist/src/lib/events.js.map +1 -1
  49. package/dist/src/lib/http.js +34 -1
  50. package/dist/src/lib/http.js.map +1 -1
  51. package/dist/src/lib/legacy-chat-runner.js +37 -0
  52. package/dist/src/lib/legacy-chat-runner.js.map +1 -0
  53. package/dist/src/lib/local-tools/api/api-discovery.js +17 -0
  54. package/dist/src/lib/local-tools/api/api-discovery.js.map +1 -0
  55. package/dist/src/lib/local-tools/api/build-request.js +20 -0
  56. package/dist/src/lib/local-tools/api/build-request.js.map +1 -0
  57. package/dist/src/lib/local-tools/api/extract-response-fields.js +26 -0
  58. package/dist/src/lib/local-tools/api/extract-response-fields.js.map +1 -0
  59. package/dist/src/lib/local-tools/api/generate-api-test.js +20 -0
  60. package/dist/src/lib/local-tools/api/generate-api-test.js.map +1 -0
  61. package/dist/src/lib/local-tools/api/generate-curl.js +8 -0
  62. package/dist/src/lib/local-tools/api/generate-curl.js.map +1 -0
  63. package/dist/src/lib/local-tools/api/get-api-parameters.js +17 -0
  64. package/dist/src/lib/local-tools/api/get-api-parameters.js.map +1 -0
  65. package/dist/src/lib/local-tools/api/index.js +10 -0
  66. package/dist/src/lib/local-tools/api/index.js.map +1 -0
  67. package/dist/src/lib/local-tools/api/request.js +43 -0
  68. package/dist/src/lib/local-tools/api/request.js.map +1 -0
  69. package/dist/src/lib/local-tools/api/set-auth-header.js +8 -0
  70. package/dist/src/lib/local-tools/api/set-auth-header.js.map +1 -0
  71. package/dist/src/lib/local-tools/api/types.js +2 -0
  72. package/dist/src/lib/local-tools/api/types.js.map +1 -0
  73. package/dist/src/lib/local-tools/api/utils.js +33 -0
  74. package/dist/src/lib/local-tools/api/utils.js.map +1 -0
  75. package/dist/src/lib/local-tools/api/validate-response.js +41 -0
  76. package/dist/src/lib/local-tools/api/validate-response.js.map +1 -0
  77. package/dist/src/lib/local-tools/file-tools.js +45 -0
  78. package/dist/src/lib/local-tools/file-tools.js.map +1 -0
  79. package/dist/src/lib/local-tools/general/discover-local-services.js +95 -0
  80. package/dist/src/lib/local-tools/general/discover-local-services.js.map +1 -0
  81. package/dist/src/lib/local-tools/general/index.js +2 -0
  82. package/dist/src/lib/local-tools/general/index.js.map +1 -0
  83. package/dist/src/lib/local-tools/ui/click-element.js +105 -0
  84. package/dist/src/lib/local-tools/ui/click-element.js.map +1 -0
  85. package/dist/src/lib/local-tools/ui/dom-rag.js +201 -0
  86. package/dist/src/lib/local-tools/ui/dom-rag.js.map +1 -0
  87. package/dist/src/lib/local-tools/ui/find-element.js +31 -0
  88. package/dist/src/lib/local-tools/ui/find-element.js.map +1 -0
  89. package/dist/src/lib/local-tools/ui/hover-element.js +94 -0
  90. package/dist/src/lib/local-tools/ui/hover-element.js.map +1 -0
  91. package/dist/src/lib/local-tools/ui/index.js +3 -0
  92. package/dist/src/lib/local-tools/ui/index.js.map +1 -0
  93. package/dist/src/lib/local-tools/ui/manage-tab.js +65 -0
  94. package/dist/src/lib/local-tools/ui/manage-tab.js.map +1 -0
  95. package/dist/src/lib/local-tools/ui/navigate.js +35 -0
  96. package/dist/src/lib/local-tools/ui/navigate.js.map +1 -0
  97. package/dist/src/lib/local-tools/ui/page-discovery.js +32 -0
  98. package/dist/src/lib/local-tools/ui/page-discovery.js.map +1 -0
  99. package/dist/src/lib/local-tools/ui/playwright-mcp.js +217 -0
  100. package/dist/src/lib/local-tools/ui/playwright-mcp.js.map +1 -0
  101. package/dist/src/lib/local-tools/ui/screenshot.js +19 -0
  102. package/dist/src/lib/local-tools/ui/screenshot.js.map +1 -0
  103. package/dist/src/lib/local-tools/ui/search-interactive-elements.js +18 -0
  104. package/dist/src/lib/local-tools/ui/search-interactive-elements.js.map +1 -0
  105. package/dist/src/lib/local-tools/ui/selector-resolver.js +153 -0
  106. package/dist/src/lib/local-tools/ui/selector-resolver.js.map +1 -0
  107. package/dist/src/lib/local-tools/ui/snapshot-query.js +129 -0
  108. package/dist/src/lib/local-tools/ui/snapshot-query.js.map +1 -0
  109. package/dist/src/lib/local-tools/ui/type-text.js +40 -0
  110. package/dist/src/lib/local-tools/ui/type-text.js.map +1 -0
  111. package/dist/src/lib/local-tools/ui/types.js +2 -0
  112. package/dist/src/lib/local-tools/ui/types.js.map +1 -0
  113. package/dist/src/lib/local-tools/utility/finish-overall-test.js +12 -0
  114. package/dist/src/lib/local-tools/utility/finish-overall-test.js.map +1 -0
  115. package/dist/src/lib/local-tools/utility/index.js +2 -0
  116. package/dist/src/lib/local-tools/utility/index.js.map +1 -0
  117. package/dist/src/lib/prompts/builder.js +38 -0
  118. package/dist/src/lib/prompts/builder.js.map +1 -0
  119. package/dist/src/lib/prompts/index.js +7 -0
  120. package/dist/src/lib/prompts/index.js.map +1 -0
  121. package/dist/src/lib/prompts/templates.js +166 -0
  122. package/dist/src/lib/prompts/templates.js.map +1 -0
  123. package/dist/src/lib/session-manager.js +201 -0
  124. package/dist/src/lib/session-manager.js.map +1 -0
  125. package/dist/src/lib/socket.js +78 -6
  126. package/dist/src/lib/socket.js.map +1 -1
  127. package/dist/src/lib/testing-mode.js +33 -0
  128. package/dist/src/lib/testing-mode.js.map +1 -0
  129. package/dist/src/lib/tool-descriptions.js +59 -0
  130. package/dist/src/lib/tool-descriptions.js.map +1 -0
  131. package/dist/src/lib/tool-executor.js +537 -0
  132. package/dist/src/lib/tool-executor.js.map +1 -0
  133. package/dist/src/lib/tool-registry.js +803 -0
  134. package/dist/src/lib/tool-registry.js.map +1 -0
  135. package/dist/src/lib/tool-result-pruner.js +384 -0
  136. package/dist/src/lib/tool-result-pruner.js.map +1 -0
  137. package/dist/src/lib/tui/components/AskIntro.js +6 -0
  138. package/dist/src/lib/tui/components/AskIntro.js.map +1 -0
  139. package/dist/src/lib/tui/components/Banner.js +15 -0
  140. package/dist/src/lib/tui/components/Banner.js.map +1 -0
  141. package/dist/src/lib/tui/components/Divider.js +17 -0
  142. package/dist/src/lib/tui/components/Divider.js.map +1 -0
  143. package/dist/src/lib/tui/components/EventLine.js +110 -0
  144. package/dist/src/lib/tui/components/EventLine.js.map +1 -0
  145. package/dist/src/lib/tui/components/Header.js +15 -0
  146. package/dist/src/lib/tui/components/Header.js.map +1 -0
  147. package/dist/src/lib/tui/components/InputBox.js +9 -0
  148. package/dist/src/lib/tui/components/InputBox.js.map +1 -0
  149. package/dist/src/lib/tui/components/Mapping.js +8 -0
  150. package/dist/src/lib/tui/components/Mapping.js.map +1 -0
  151. package/dist/src/lib/tui/components/ProjectList.js +6 -0
  152. package/dist/src/lib/tui/components/ProjectList.js.map +1 -0
  153. package/dist/src/lib/tui/components/Spinner.js +20 -0
  154. package/dist/src/lib/tui/components/Spinner.js.map +1 -0
  155. package/dist/src/lib/tui/components/StatusBanner.js +12 -0
  156. package/dist/src/lib/tui/components/StatusBanner.js.map +1 -0
  157. package/dist/src/lib/tui/components/StatusBar.js +11 -0
  158. package/dist/src/lib/tui/components/StatusBar.js.map +1 -0
  159. package/dist/src/lib/tui/components/UserBubble.js +6 -0
  160. package/dist/src/lib/tui/components/UserBubble.js.map +1 -0
  161. package/dist/src/lib/tui/components/index.js +16 -0
  162. package/dist/src/lib/tui/components/index.js.map +1 -0
  163. package/dist/src/lib/tui/events.js +716 -76
  164. package/dist/src/lib/tui/events.js.map +1 -1
  165. package/dist/src/lib/tui/icons.js +14 -0
  166. package/dist/src/lib/tui/icons.js.map +1 -1
  167. package/dist/src/lib/tui/ink-print.js +41 -0
  168. package/dist/src/lib/tui/ink-print.js.map +1 -0
  169. package/dist/src/lib/tui/interactive-chat.js +345 -0
  170. package/dist/src/lib/tui/interactive-chat.js.map +1 -0
  171. package/dist/src/lib/tui/print.js +31 -26
  172. package/dist/src/lib/tui/print.js.map +1 -1
  173. package/dist/src/lib/tui/prompt.js +21 -18
  174. package/dist/src/lib/tui/prompt.js.map +1 -1
  175. package/dist/src/test-agent-flow.js +148 -0
  176. package/dist/src/test-agent-flow.js.map +1 -0
  177. package/dist/src/test-browser-session.js +152 -0
  178. package/dist/src/test-browser-session.js.map +1 -0
  179. package/dist/src/test-browser-snapshot.js +187 -0
  180. package/dist/src/test-browser-snapshot.js.map +1 -0
  181. package/dist/src/test-snapshot-detailed.js +219 -0
  182. package/dist/src/test-snapshot-detailed.js.map +1 -0
  183. package/dist/src/test-snapshot-simple.js +85 -0
  184. package/dist/src/test-snapshot-simple.js.map +1 -0
  185. package/dist/src/test-snapshot-tabs.js +110 -0
  186. package/dist/src/test-snapshot-tabs.js.map +1 -0
  187. package/package.json +20 -3
@@ -1,11 +1,70 @@
1
1
  import chalk from "chalk";
2
2
  import { icons } from "./icons.js";
3
- import { stripAnsi, sanitizeText, asPercent, safeCount, formatKeyValues, formatTimestamp, isPlainObject, } from "./utils.js";
3
+ import { stripAnsi, sanitizeText, asPercent, safeCount, formatKeyValues, formatTimestamp, isPlainObject, summarizeList, } from "./utils.js";
4
+ const toolIconMap = {
5
+ // Browser tools
6
+ browser_session: "tool",
7
+ browser_navigate: "navigate",
8
+ browser_take_screenshot: "screenshotTool",
9
+ browser_click: "click",
10
+ browser_hover: "hover",
11
+ browser_type: "type",
12
+ browser_fill_form: "form",
13
+ browser_select_option: "select",
14
+ browser_press_key: "keypress",
15
+ browser_wait_for: "wait",
16
+ browser_handle_dialog: "dialog",
17
+ browser_tabs: "tabs",
18
+ browser_resize: "resize",
19
+ browser_drag: "drag",
20
+ browser_snapshot_query: "snapshot",
21
+ browser_network_requests: "tool",
22
+ browser_console_messages: "tool",
23
+ // API tools
24
+ api_discovery: "tool",
25
+ build_api_request: "tool",
26
+ generate_curl: "tool",
27
+ generate_api_test: "tool",
28
+ search_discovered_endpoints: "tool",
29
+ get_api_parameters: "tool",
30
+ get_api: "tool",
31
+ post_api: "tool",
32
+ put_api: "tool",
33
+ patch_api: "tool",
34
+ delete_api: "tool",
35
+ validate_api_response: "tool",
36
+ assert_response_schema: "tool",
37
+ api_request: "tool",
38
+ extract_response_fields: "tool",
39
+ set_auth_header: "tool",
40
+ // General tools
41
+ set_testing_mode: "tool",
42
+ finish: "done",
43
+ finish_overall_test: "done",
44
+ generate_test_cases: "cases",
45
+ // Legacy tool names (for backward compatibility)
46
+ navigate: "navigate",
47
+ click_element: "click",
48
+ hover_element: "hover",
49
+ type_text: "type",
50
+ screenshot: "screenshotTool",
51
+ search_interactive_elements: "tool",
52
+ manage_tab: "tabs",
53
+ page_discovery: "tool",
54
+ };
4
55
  const EVENT_META = {
5
- test_started: { icon: icons.start, label: "test_started", color: chalk.bold },
6
- test_progress: { icon: icons.progress, label: "progress", color: chalk.cyan },
7
- test_completed: { icon: icons.done, label: "completed", color: chalk.green },
8
- test_failed: { icon: icons.fail, label: "failed", color: chalk.red },
56
+ session_started: {
57
+ icon: icons.start,
58
+ label: "session_started",
59
+ color: chalk.bold,
60
+ },
61
+ session_progress: {
62
+ icon: icons.progress,
63
+ label: "progress",
64
+ color: chalk.cyan,
65
+ },
66
+ session_completed: { icon: icons.done, label: "completed", color: chalk.green },
67
+ session_error: { icon: icons.fail, label: "error", color: chalk.red },
9
68
  browser_initialized: {
10
69
  icon: icons.browser,
11
70
  label: "browser",
@@ -39,31 +98,12 @@ const EVENT_META = {
39
98
  label: "test_cases",
40
99
  color: chalk.magenta,
41
100
  },
42
- test_execution_started: {
43
- icon: icons.exec,
44
- label: "execution",
45
- color: chalk.yellow,
46
- },
47
- test_execution_progress: {
101
+ agent_thinking_started: {
48
102
  icon: icons.exec,
49
- label: "execution",
50
- color: chalk.yellow,
51
- },
52
- test_execution_completed: {
53
- icon: icons.done,
54
- label: "execution",
55
- color: chalk.green,
56
- },
57
- test_execution_failed: {
58
- icon: icons.fail,
59
- label: "execution",
60
- color: chalk.red,
61
- },
62
- test_execution_stopped: {
63
- icon: icons.warn,
64
- label: "execution",
65
- color: chalk.yellow,
103
+ label: "agent_think",
104
+ color: chalk.magenta,
66
105
  },
106
+ session_stopped: { icon: icons.warn, label: "stopped", color: chalk.yellow },
67
107
  test_case_execution_started: {
68
108
  icon: icons.exec,
69
109
  label: "test_case",
@@ -84,7 +124,7 @@ const EVENT_META = {
84
124
  label: "step_shot",
85
125
  color: chalk.cyan,
86
126
  },
87
- test_step_user_input_required: {
127
+ user_input_required: {
88
128
  icon: icons.user,
89
129
  label: "user_input",
90
130
  color: chalk.yellow,
@@ -105,27 +145,23 @@ const EVENT_META = {
105
145
  label: "user_input",
106
146
  color: chalk.red,
107
147
  },
108
- agent_thinking_started: {
109
- icon: icons.think,
110
- label: "agent",
111
- color: chalk.magenta,
112
- },
113
148
  agent_thinking_stopped: {
114
149
  icon: icons.think,
115
150
  label: "agent",
116
151
  color: chalk.magenta,
117
152
  },
118
- agent_thought_process: {
119
- icon: icons.think,
120
- label: "agent",
121
- color: chalk.magenta,
122
- },
153
+ agent_thought: { icon: icons.think, label: "agent", color: chalk.magenta },
123
154
  agent_plan_generated: {
124
155
  icon: icons.plan,
125
156
  label: "agent_plan",
126
157
  color: chalk.magenta,
127
158
  },
128
- agent_tool_execution: {
159
+ agent_tool_start: {
160
+ icon: icons.tool,
161
+ label: "agent_tool",
162
+ color: chalk.magenta,
163
+ },
164
+ agent_tool_result: {
129
165
  icon: icons.tool,
130
166
  label: "agent_tool",
131
167
  color: chalk.magenta,
@@ -164,23 +200,12 @@ const EVENT_META = {
164
200
  error: { icon: icons.fail, label: "error", color: chalk.red },
165
201
  stats_response: { icon: icons.info, label: "stats", color: chalk.gray },
166
202
  pong: { icon: icons.info, label: "pong", color: chalk.white },
167
- ask_thinking_started: { icon: icons.think, label: "ask", color: chalk.magenta },
168
- ask_thinking_stopped: { icon: icons.think, label: "ask", color: chalk.magenta },
169
- ask_agent_thought: { icon: icons.think, label: "ask", color: chalk.magenta },
170
- ask_tool_start: { icon: icons.tool, label: "ask_tool", color: chalk.magenta },
171
- ask_tool_result: { icon: icons.tool, label: "ask_tool", color: chalk.magenta },
172
- ask_agent_answer: {
173
- icon: icons.plan,
174
- label: "ask_answer",
175
- color: chalk.magenta,
176
- },
177
- ask_user_message: { icon: icons.info, label: "ask_user", color: chalk.white },
178
- ask_session_completed: {
179
- icon: icons.done,
180
- label: "ask_session",
181
- color: chalk.green,
182
- },
183
- ask_session_error: { icon: icons.fail, label: "ask_session", color: chalk.red },
203
+ thinking_started: { icon: icons.think, label: "ask", color: chalk.magenta },
204
+ thinking_stopped: { icon: icons.think, label: "ask", color: chalk.magenta },
205
+ tool_start: { icon: icons.tool, label: "ask_tool", color: chalk.magenta },
206
+ tool_result: { icon: icons.tool, label: "ask_tool", color: chalk.magenta },
207
+ agent_answer: { icon: icons.plan, label: "ask_answer", color: chalk.magenta },
208
+ user_message: { icon: icons.info, label: "user_message", color: chalk.white },
184
209
  };
185
210
  export function formatEventLines(type, payload) {
186
211
  const base = isPlainObject(payload) ? payload : {};
@@ -208,21 +233,51 @@ export function formatEventLines(type, payload) {
208
233
  ? descriptor.color(descriptor.label)
209
234
  : descriptor.label;
210
235
  const timestamp = formatTimestamp(base.timestamp);
211
- const testIdSource = base.test_id ??
236
+ const sessionKind = base.session_kind || eventData.session_kind;
237
+ const sessionIdsRaw = (isPlainObject(base.ids) && base.ids) ||
238
+ (isPlainObject(eventData.ids) && eventData.ids) ||
239
+ {};
240
+ const sessionIds = isPlainObject(sessionIdsRaw)
241
+ ? sessionIdsRaw
242
+ : {};
243
+ const parentRaw = base.parent || eventData.parent;
244
+ const parent = isPlainObject(parentRaw)
245
+ ? parentRaw
246
+ : undefined;
247
+ const actorRaw = base.actor || eventData.actor;
248
+ const actor = isPlainObject(actorRaw)
249
+ ? actorRaw
250
+ : undefined;
251
+ const correlationId = base.correlation_id || eventData.correlation_id;
252
+ const sanitizeId = (value) => sanitizeText(value, { maxLength: 48 }) || "";
253
+ const badgeParts = [];
254
+ const testIdValue = sanitizeId(sessionIds.test_id ??
255
+ base.test_id ??
212
256
  eventData.test_id ??
213
257
  (isPlainObject(base.data)
214
258
  ? base.data.test_id
215
- : undefined);
216
- const testIdValue = sanitizeText(testIdSource, { maxLength: 32 });
217
- const testIdPart = testIdValue ? chalk.gray(`#${testIdValue}`) : "";
259
+ : undefined));
260
+ if (testIdValue)
261
+ badgeParts.push(`#${testIdValue}`);
262
+ const conversationIdValue = sanitizeId(sessionIds.conversation_id ??
263
+ base.conversation_id ??
264
+ eventData.conversation_id);
265
+ if (conversationIdValue)
266
+ badgeParts.push(`ask:${conversationIdValue}`);
267
+ const subagentIdValue = sanitizeId(sessionIds.subagent_id ??
268
+ base.subagent_id ??
269
+ eventData.subagent_id);
270
+ if (subagentIdValue)
271
+ badgeParts.push(`sub:${subagentIdValue}`);
272
+ const sessionBadge = badgeParts.length > 0 ? chalk.gray(badgeParts.join(" · ")) : "";
218
273
  const lines = [];
219
274
  const additional = [];
220
275
  const ensureExtra = (value) => value && stripAnsi(value).length > 0 ? value : undefined;
221
276
  const addLine = (icon, labelText, message, extra) => {
222
277
  const iconToUse = icon || icons.info;
223
278
  const parts = [`${timestamp} ${iconToUse} ${labelText}`];
224
- if (testIdPart)
225
- parts.push(testIdPart);
279
+ if (sessionBadge)
280
+ parts.push(sessionBadge);
226
281
  if (message)
227
282
  parts.push(message);
228
283
  if (extra)
@@ -265,27 +320,57 @@ export function formatEventLines(type, payload) {
265
320
  })();
266
321
  let extra;
267
322
  const detailLines = [];
268
- // Switch with identical logic as original file
323
+ if (parent) {
324
+ const parentLabel = `parent:${sanitizeText(parent.session_kind) || ""}`;
325
+ const parentIds = isPlainObject(parent.ids)
326
+ ? parent.ids
327
+ : {};
328
+ const parentExtra = ensureExtra(formatKeyValues([
329
+ ["test_id", sanitizeId(parentIds.test_id)],
330
+ ["conversation_id", sanitizeId(parentIds.conversation_id)],
331
+ ["subagent_id", sanitizeId(parentIds.subagent_id)],
332
+ ]));
333
+ additional.push({
334
+ icon: icons.link,
335
+ label: parentLabel.trim(),
336
+ extra: parentExtra,
337
+ });
338
+ }
339
+ if (actor) {
340
+ const actorLabel = `actor:${sanitizeText(actor.role) || ""}`.trim();
341
+ const actorExtra = ensureExtra(formatKeyValues([
342
+ ["id", sanitizeId(actor.id)],
343
+ ["kind", sanitizeText(actor.kind || actor.type)],
344
+ ]));
345
+ additional.push({
346
+ icon: icons.user,
347
+ label: actorLabel || "actor",
348
+ extra: actorExtra,
349
+ });
350
+ }
269
351
  switch (normalizedType) {
270
- // The entire switch body is preserved verbatim from the original file
271
- // for fidelity and to avoid behavior changes.
272
- case "test_started": {
352
+ case "session_started": {
273
353
  if (!eventMessage)
274
- eventMessage = "Test started";
354
+ eventMessage = "Session started";
275
355
  extra = ensureExtra(formatKeyValues([
356
+ ["kind", sanitizeText(sessionKind)],
276
357
  ["type", sanitizeText(eventData.test_type)],
277
358
  ["mode", sanitizeText(eventData.execution_mode)],
278
359
  ["execute", eventData.execute_tests ? "yes" : undefined],
279
360
  ["project", safeCount(eventData.project_id)],
361
+ ["test_id", safeCount(sessionIds.test_id)],
362
+ ["conversation_id", sanitizeText(sessionIds.conversation_id)],
363
+ ["subagent_id", safeCount(sessionIds.subagent_id)],
280
364
  ]));
281
365
  break;
282
366
  }
283
- case "test_progress": {
367
+ case "session_progress": {
284
368
  if (!eventMessage)
285
369
  eventMessage = "Progress update";
286
370
  const progressValue = asPercent(eventData.progress_percentage ?? eventData.progress) ??
287
371
  safeCount(eventData.progress_percentage ?? eventData.progress);
288
372
  extra = ensureExtra(formatKeyValues([
373
+ ["kind", sanitizeText(sessionKind)],
289
374
  ["progress", progressValue],
290
375
  ["stage", sanitizeText(eventData.stage)],
291
376
  [
@@ -300,18 +385,573 @@ export function formatEventLines(type, payload) {
300
385
  ]));
301
386
  break;
302
387
  }
303
- // ... full switch cases continue unchanged ...
304
- default: {
388
+ case "session_completed": {
305
389
  if (!eventMessage)
306
- eventMessage = derivedType || "event";
390
+ eventMessage = "Session completed";
391
+ extra = ensureExtra(formatKeyValues([
392
+ ["kind", sanitizeText(sessionKind)],
393
+ ["status", sanitizeText(eventData.status)],
394
+ ["test_id", safeCount(sessionIds.test_id)],
395
+ ["conversation_id", sanitizeText(sessionIds.conversation_id)],
396
+ ]));
397
+ break;
398
+ }
399
+ case "session_error": {
400
+ if (!eventMessage)
401
+ eventMessage = "Session error";
402
+ extra = ensureExtra(formatKeyValues([
403
+ ["kind", sanitizeText(sessionKind)],
404
+ ["error", sanitizeText(eventData.error)],
405
+ ["test_id", safeCount(sessionIds.test_id)],
406
+ ["conversation_id", sanitizeText(sessionIds.conversation_id)],
407
+ ]));
408
+ break;
409
+ }
410
+ case "user_input_required": {
411
+ if (!eventMessage)
412
+ eventMessage = "User input required";
413
+ extra = ensureExtra(formatKeyValues([
414
+ ["kind", sanitizeText(sessionKind)],
415
+ ["request_id", sanitizeText(eventData.request_id)],
416
+ ["correlation_id", sanitizeText(correlationId)],
417
+ ]));
418
+ break;
419
+ }
420
+ case "agent_thinking_started":
421
+ case "thinking_started": {
422
+ if (!eventMessage)
423
+ eventMessage = "Agent thinking";
424
+ extra = ensureExtra(formatKeyValues([
425
+ ["kind", sanitizeText(sessionKind)],
426
+ ["actor", sanitizeText(actor?.role)],
427
+ ["correlation_id", sanitizeText(correlationId)],
428
+ ]));
429
+ break;
430
+ }
431
+ case "agent_tool_start":
432
+ case "tool_start": {
433
+ if (!eventMessage)
434
+ eventMessage = "Tool execution";
435
+ const rawToolName = eventData.tool || eventData.tool_name || "";
436
+ const toolName = sanitizeText(rawToolName);
437
+ // Try to find the icon key by checking multiple variations
438
+ let iconKey = toolIconMap[toolName] || toolIconMap[rawToolName] || "tool";
439
+ // If still not found, try common variations
440
+ if (iconKey === "tool") {
441
+ // Try with "mcp_" prefix removed
442
+ const withoutMcpPrefix = toolName.replace(/^mcp_/, "");
443
+ iconKey =
444
+ toolIconMap[withoutMcpPrefix] ||
445
+ toolIconMap[rawToolName.replace(/^mcp_/, "")] ||
446
+ "tool";
447
+ }
448
+ // Try with underscores replaced by hyphens (common variation)
449
+ if (iconKey === "tool") {
450
+ const withHyphens = toolName.replace(/_/g, "-");
451
+ const rawWithHyphens = rawToolName.replace(/_/g, "-");
452
+ iconKey =
453
+ toolIconMap[withHyphens] || toolIconMap[rawWithHyphens] || "tool";
454
+ }
455
+ // Try with spaces instead of underscores
456
+ if (iconKey === "tool") {
457
+ const withSpaces = toolName.replace(/_/g, " ");
458
+ const rawWithSpaces = rawToolName.replace(/_/g, " ");
459
+ iconKey =
460
+ toolIconMap[withSpaces] || toolIconMap[rawWithSpaces] || "tool";
461
+ }
462
+ extra = ensureExtra(formatKeyValues([
463
+ ["kind", sanitizeText(sessionKind)],
464
+ ["tool", toolName],
465
+ ["actor", sanitizeText(actor?.role)],
466
+ ["correlation_id", sanitizeText(correlationId)],
467
+ ]));
468
+ descriptor.icon = icons[iconKey] || icons.tool;
469
+ break;
470
+ }
471
+ case "agent_tool_result":
472
+ case "tool_result": {
473
+ if (!eventMessage)
474
+ eventMessage = "Tool completed";
475
+ const rawToolName = eventData.tool || eventData.tool_name || "";
476
+ const toolName = sanitizeText(rawToolName);
477
+ // Try to find the icon key by checking multiple variations
478
+ let iconKey = toolIconMap[toolName] || toolIconMap[rawToolName] || "tool";
479
+ // If still not found, try common variations
480
+ if (iconKey === "tool") {
481
+ // Try with "mcp_" prefix removed
482
+ const withoutMcpPrefix = toolName.replace(/^mcp_/, "");
483
+ iconKey =
484
+ toolIconMap[withoutMcpPrefix] ||
485
+ toolIconMap[rawToolName.replace(/^mcp_/, "")] ||
486
+ "tool";
487
+ }
488
+ // Try with underscores replaced by hyphens (common variation)
489
+ if (iconKey === "tool") {
490
+ const withHyphens = toolName.replace(/_/g, "-");
491
+ const rawWithHyphens = rawToolName.replace(/_/g, "-");
492
+ iconKey =
493
+ toolIconMap[withHyphens] || toolIconMap[rawWithHyphens] || "tool";
494
+ }
495
+ // Try with spaces instead of underscores
496
+ if (iconKey === "tool") {
497
+ const withSpaces = toolName.replace(/_/g, " ");
498
+ const rawWithSpaces = rawToolName.replace(/_/g, " ");
499
+ iconKey =
500
+ toolIconMap[withSpaces] || toolIconMap[rawWithSpaces] || "tool";
501
+ }
502
+ extra = ensureExtra(formatKeyValues([
503
+ ["kind", sanitizeText(sessionKind)],
504
+ ["tool", toolName],
505
+ ["actor", sanitizeText(actor?.role)],
506
+ ["correlation_id", sanitizeText(correlationId)],
507
+ ]));
508
+ descriptor.icon = icons[iconKey] || icons.tool;
509
+ break;
510
+ }
511
+ case "browser_initialized": {
512
+ if (!eventMessage)
513
+ eventMessage = "Browser initialized";
514
+ const browserInfo = isPlainObject(eventData.browser_info)
515
+ ? eventData.browser_info
516
+ : {};
517
+ extra = ensureExtra(formatKeyValues([
518
+ ["kind", sanitizeText(sessionKind)],
519
+ ["phase", sanitizeText(eventData.phase)],
520
+ ["browser", sanitizeText(browserInfo.name ?? browserInfo.browser)],
521
+ ["version", sanitizeText(browserInfo.version)],
522
+ [
523
+ "mode",
524
+ browserInfo.headless === undefined
525
+ ? undefined
526
+ : browserInfo.headless
527
+ ? "headless"
528
+ : "headed",
529
+ ],
530
+ ]));
531
+ break;
532
+ }
533
+ case "page_discovered": {
534
+ if (!eventMessage)
535
+ eventMessage = "Pages discovered";
536
+ const pages = Array.isArray(eventData.discovered_pages)
537
+ ? eventData.discovered_pages
538
+ : [];
539
+ extra = ensureExtra(formatKeyValues([
540
+ ["kind", sanitizeText(sessionKind)],
541
+ ["count", safeCount(pages.length)],
542
+ ["total", safeCount(eventData.total_pages)],
543
+ ]));
544
+ if (pages.length) {
545
+ const listings = pages
546
+ .map((p) => sanitizeText(p) || "")
547
+ .filter(Boolean);
548
+ if (listings.length) {
549
+ detailLines.push("Pages discovered:");
550
+ detailLines.push(...summarizeList(listings, 6));
551
+ }
552
+ }
553
+ break;
554
+ }
555
+ case "page_processing": {
556
+ if (!eventMessage)
557
+ eventMessage =
558
+ sanitizeText(eventData.processing_stage) ||
559
+ "Processing page";
560
+ extra = ensureExtra(formatKeyValues([
561
+ ["kind", sanitizeText(sessionKind)],
562
+ ["stage", sanitizeText(eventData.processing_stage)],
563
+ ["url", sanitizeText(eventData.page_url)],
564
+ ]));
565
+ break;
566
+ }
567
+ case "screenshot_captured":
568
+ case "screenshot_with_analysis": {
569
+ if (!eventMessage)
570
+ eventMessage = "Screenshot captured";
571
+ const metadata = isPlainObject(eventData.metadata)
572
+ ? eventData.metadata
573
+ : {};
574
+ let resolution;
575
+ if (isPlainObject(metadata.dimensions)) {
576
+ const dims = metadata.dimensions;
577
+ const width = sanitizeText(dims.width);
578
+ const height = sanitizeText(dims.height);
579
+ resolution =
580
+ width && height ? `${width}×${height}` : width || height || undefined;
581
+ }
582
+ else {
583
+ const dimText = sanitizeText(metadata.dimensions);
584
+ resolution = dimText || undefined;
585
+ }
586
+ extra = ensureExtra(formatKeyValues([
587
+ ["kind", sanitizeText(sessionKind)],
588
+ ["url", sanitizeText(eventData.page_url)],
589
+ ["path", sanitizeText(eventData.screenshot_path)],
590
+ ["resolution", resolution],
591
+ ["size", safeCount(metadata.file_size)],
592
+ ]));
593
+ const analysisSummary = sanitizeText(eventData.analysis_summary, { preserveNewlines: true });
594
+ if (analysisSummary) {
595
+ detailLines.push(analysisSummary);
596
+ }
597
+ break;
598
+ }
599
+ case "page_analyzed": {
600
+ if (!eventMessage)
601
+ eventMessage = "Page analyzed";
602
+ extra = ensureExtra(formatKeyValues([
603
+ ["kind", sanitizeText(sessionKind)],
604
+ ["url", sanitizeText(eventData.page_url)],
605
+ ["status", sanitizeText(eventData.status)],
606
+ ]));
607
+ const insights = sanitizeText(eventData.insights, {
608
+ preserveNewlines: true,
609
+ });
610
+ if (insights) {
611
+ detailLines.push(insights);
612
+ }
613
+ break;
614
+ }
615
+ case "ai_analysis_started": {
616
+ if (!eventMessage)
617
+ eventMessage = "AI analysis started";
618
+ extra = ensureExtra(formatKeyValues([
619
+ ["kind", sanitizeText(sessionKind)],
620
+ ["analysis_id", sanitizeText(eventData.analysis_id)],
621
+ ]));
622
+ break;
623
+ }
624
+ case "ai_analysis_completed": {
625
+ if (!eventMessage)
626
+ eventMessage = "AI analysis completed";
627
+ extra = ensureExtra(formatKeyValues([
628
+ ["kind", sanitizeText(sessionKind)],
629
+ ["analysis_id", sanitizeText(eventData.analysis_id)],
630
+ ["status", sanitizeText(eventData.status)],
631
+ ]));
632
+ const summary = sanitizeText(eventData.summary, {
633
+ preserveNewlines: true,
634
+ });
635
+ if (summary) {
636
+ detailLines.push(summary);
637
+ }
638
+ break;
639
+ }
640
+ case "test_cases_generated": {
641
+ if (!eventMessage)
642
+ eventMessage = "Test cases generated";
643
+ const cases = Array.isArray(eventData.cases)
644
+ ? eventData.cases
645
+ : [];
646
+ extra = ensureExtra(formatKeyValues([
647
+ ["kind", sanitizeText(sessionKind)],
648
+ ["count", safeCount(cases.length || eventData.count)],
649
+ ]));
650
+ if (cases.length) {
651
+ const items = cases
652
+ .map((testCase) => {
653
+ if (isPlainObject(testCase)) {
654
+ return (sanitizeText(testCase.name ??
655
+ testCase.title) || "");
656
+ }
657
+ return sanitizeText(testCase) || "";
658
+ })
659
+ .filter(Boolean);
660
+ if (items.length) {
661
+ detailLines.push("Generated cases:");
662
+ detailLines.push(...summarizeList(items, 6));
663
+ }
664
+ }
665
+ break;
666
+ }
667
+ case "test_case_execution_started": {
668
+ if (!eventMessage)
669
+ eventMessage = "Test case started";
670
+ extra = ensureExtra(formatKeyValues([
671
+ ["kind", sanitizeText(sessionKind)],
672
+ ["case", sanitizeText(eventData.case_name)],
673
+ ["id", sanitizeText(eventData.test_case_id)],
674
+ ]));
675
+ break;
676
+ }
677
+ case "test_case_execution_completed": {
678
+ if (!eventMessage)
679
+ eventMessage = "Test case completed";
680
+ extra = ensureExtra(formatKeyValues([
681
+ ["kind", sanitizeText(sessionKind)],
682
+ ["case", sanitizeText(eventData.case_name)],
683
+ ["status", sanitizeText(eventData.status)],
684
+ ["duration", sanitizeText(eventData.duration)],
685
+ ]));
686
+ break;
687
+ }
688
+ case "test_step_execution": {
689
+ if (!eventMessage)
690
+ eventMessage = "Test step update";
691
+ const step = eventData.step || eventData.step_data;
307
692
  extra = ensureExtra(formatKeyValues([
693
+ ["kind", sanitizeText(sessionKind)],
308
694
  [
309
- "status",
310
- chalk
311
- ? chalk.white(sanitizeText(eventData.status))
312
- : sanitizeText(eventData.status),
695
+ "step",
696
+ safeCount(step?.step_number ?? eventData.step_number),
313
697
  ],
698
+ [
699
+ "action",
700
+ sanitizeText(step?.action ?? eventData.action),
701
+ ],
702
+ [
703
+ "target",
704
+ sanitizeText(step?.target ?? eventData.target),
705
+ ],
706
+ ["status", sanitizeText(eventData.status)],
707
+ ]));
708
+ break;
709
+ }
710
+ case "test_step_screenshot": {
711
+ if (!eventMessage)
712
+ eventMessage = "Step screenshot";
713
+ extra = ensureExtra(formatKeyValues([
714
+ ["kind", sanitizeText(sessionKind)],
715
+ ["step", safeCount(eventData.step_number)],
716
+ ["url", sanitizeText(eventData.page_url)],
717
+ ]));
718
+ break;
719
+ }
720
+ case "user_input_provided": {
721
+ if (!eventMessage)
722
+ eventMessage = "User input provided";
723
+ extra = ensureExtra(formatKeyValues([
724
+ ["kind", sanitizeText(sessionKind)],
725
+ ["request_id", sanitizeText(eventData.request_id)],
726
+ ["correlation_id", sanitizeText(correlationId)],
727
+ ]));
728
+ break;
729
+ }
730
+ case "user_input_acknowledged": {
731
+ if (!eventMessage)
732
+ eventMessage = "User input acknowledged";
733
+ extra = ensureExtra(formatKeyValues([
734
+ ["kind", sanitizeText(sessionKind)],
735
+ ["request_id", sanitizeText(eventData.request_id)],
736
+ ]));
737
+ break;
738
+ }
739
+ case "user_input_timeout": {
740
+ if (!eventMessage)
741
+ eventMessage = "User input timed out";
742
+ extra = ensureExtra(formatKeyValues([
743
+ ["kind", sanitizeText(sessionKind)],
744
+ ["request_id", sanitizeText(eventData.request_id)],
745
+ ["timeout", safeCount(eventData.timeout_seconds)],
746
+ ]));
747
+ break;
748
+ }
749
+ case "user_input_cancelled": {
750
+ if (!eventMessage)
751
+ eventMessage = "User input cancelled";
752
+ extra = ensureExtra(formatKeyValues([
753
+ ["kind", sanitizeText(sessionKind)],
754
+ ["request_id", sanitizeText(eventData.request_id)],
755
+ ["reason", sanitizeText(eventData.reason)],
756
+ ]));
757
+ break;
758
+ }
759
+ case "agent_thinking_stopped":
760
+ case "thinking_stopped": {
761
+ if (!eventMessage)
762
+ eventMessage = "Thinking completed";
763
+ extra = ensureExtra(formatKeyValues([
764
+ ["kind", sanitizeText(sessionKind)],
765
+ ["actor", sanitizeText(actor?.role)],
766
+ ["correlation_id", sanitizeText(correlationId)],
767
+ ]));
768
+ break;
769
+ }
770
+ case "agent_thought": {
771
+ if (!eventMessage)
772
+ eventMessage =
773
+ sanitizeText(eventData.message) ||
774
+ sanitizeText(eventData.content) ||
775
+ "Agent thought";
776
+ const detail = sanitizeText(eventData.detail || eventData.analysis, { preserveNewlines: true });
777
+ if (detail)
778
+ detailLines.push(detail);
779
+ extra = ensureExtra(formatKeyValues([
780
+ ["kind", sanitizeText(sessionKind)],
781
+ ["correlation_id", sanitizeText(correlationId)],
782
+ ]));
783
+ break;
784
+ }
785
+ case "agent_plan_generated": {
786
+ if (!eventMessage)
787
+ eventMessage = "Plan generated";
788
+ const steps = Array.isArray(eventData.steps)
789
+ ? eventData.steps
790
+ : [];
791
+ extra = ensureExtra(formatKeyValues([
792
+ ["kind", sanitizeText(sessionKind)],
793
+ ["steps", safeCount(steps.length)],
794
+ ]));
795
+ if (steps.length) {
796
+ const stepSummaries = steps
797
+ .map((step) => {
798
+ if (isPlainObject(step)) {
799
+ return (sanitizeText(step.summary ??
800
+ step.description ??
801
+ step.title) || "");
802
+ }
803
+ return sanitizeText(step) || "";
804
+ })
805
+ .filter(Boolean);
806
+ if (stepSummaries.length) {
807
+ detailLines.push("Plan:");
808
+ detailLines.push(...summarizeList(stepSummaries, 6));
809
+ }
810
+ }
811
+ break;
812
+ }
813
+ case "agent_step_completed": {
814
+ if (!eventMessage)
815
+ eventMessage = "Agent step completed";
816
+ extra = ensureExtra(formatKeyValues([
817
+ ["kind", sanitizeText(sessionKind)],
818
+ ["step", sanitizeText(eventData.step_name)],
819
+ ["status", sanitizeText(eventData.status)],
820
+ ]));
821
+ break;
822
+ }
823
+ case "agent_recovery_attempt": {
824
+ if (!eventMessage)
825
+ eventMessage = "Recovery attempt";
826
+ extra = ensureExtra(formatKeyValues([
827
+ ["kind", sanitizeText(sessionKind)],
828
+ ["attempt", safeCount(eventData.attempt)],
829
+ ["reason", sanitizeText(eventData.reason)],
830
+ ]));
831
+ break;
832
+ }
833
+ case "agent_error": {
834
+ if (!eventMessage)
835
+ eventMessage = "Agent error";
836
+ const detail = sanitizeText(eventData.stack, {
837
+ preserveNewlines: true,
838
+ }) ||
839
+ sanitizeText(eventData.detail, {
840
+ preserveNewlines: true,
841
+ });
842
+ if (detail)
843
+ detailLines.push(detail);
844
+ extra = ensureExtra(formatKeyValues([
845
+ ["kind", sanitizeText(sessionKind)],
846
+ ["error", sanitizeText(eventData.error)],
847
+ ["code", sanitizeText(eventData.error_code)],
848
+ ]));
849
+ break;
850
+ }
851
+ case "browser_stream_started":
852
+ case "browser_stream_stopped": {
853
+ if (!eventMessage)
854
+ eventMessage =
855
+ normalizedType === "browser_stream_started"
856
+ ? "Browser stream started"
857
+ : "Browser stream stopped";
858
+ extra = ensureExtra(formatKeyValues([
859
+ ["kind", sanitizeText(sessionKind)],
860
+ ["url", sanitizeText(eventData.stream_url)],
861
+ ]));
862
+ break;
863
+ }
864
+ case "subscription_confirmed":
865
+ case "subscription_removed": {
866
+ if (!eventMessage)
867
+ eventMessage = "Subscription update";
868
+ const selectorParts = [];
869
+ const selectorTestId = sanitizeId(sessionIds.test_id);
870
+ if (selectorTestId) {
871
+ selectorParts.push(`test_id=${selectorTestId}`);
872
+ }
873
+ const selectorConversationId = sanitizeId(sessionIds.conversation_id);
874
+ if (selectorConversationId) {
875
+ selectorParts.push(`conversation_id=${selectorConversationId}`);
876
+ }
877
+ const selectorSubagentId = sanitizeId(sessionIds.subagent_id);
878
+ if (selectorSubagentId) {
879
+ selectorParts.push(`subagent_id=${selectorSubagentId}`);
880
+ }
881
+ const selectorDisplay = selectorParts.join(" ");
882
+ extra = ensureExtra(formatKeyValues([
883
+ ["kind", sanitizeText(sessionKind)],
884
+ ["selector", selectorDisplay],
885
+ ]));
886
+ break;
887
+ }
888
+ case "tool_screenshot": {
889
+ if (!eventMessage)
890
+ eventMessage = "Tool screenshot";
891
+ extra = ensureExtra(formatKeyValues([
892
+ ["kind", sanitizeText(sessionKind)],
893
+ ["url", sanitizeText(eventData.image_url)],
894
+ ["correlation_id", sanitizeText(correlationId)],
895
+ ]));
896
+ break;
897
+ }
898
+ case "stats_response": {
899
+ if (!eventMessage)
900
+ eventMessage = "Stats received";
901
+ extra = ensureExtra(formatKeyValues([
902
+ ["kind", sanitizeText(sessionKind)],
903
+ ["duration_ms", safeCount(eventData.duration_ms)],
904
+ ["connections", safeCount(eventData.connection_count)],
905
+ ]));
906
+ if (isPlainObject(eventData.stats)) {
907
+ const statsLine = formatKeyValues(Object.entries(eventData.stats).map(([key, value]) => [
908
+ key,
909
+ sanitizeText(value),
910
+ ]));
911
+ if (statsLine) {
912
+ detailLines.push("Stats:");
913
+ detailLines.push(statsLine);
914
+ }
915
+ }
916
+ break;
917
+ }
918
+ case "pong": {
919
+ if (!eventMessage)
920
+ eventMessage = "Pong";
921
+ extra = ensureExtra(formatKeyValues([
922
+ ["kind", sanitizeText(sessionKind)],
923
+ ["latency_ms", safeCount(eventData.latency_ms)],
924
+ ]));
925
+ break;
926
+ }
927
+ case "agent_answer": {
928
+ if (!eventMessage)
929
+ eventMessage = "Agent answer";
930
+ const summary = sanitizeText(eventData.summary, {
931
+ preserveNewlines: true,
932
+ });
933
+ if (summary)
934
+ detailLines.push(summary);
935
+ break;
936
+ }
937
+ case "user_message": {
938
+ if (!eventMessage)
939
+ eventMessage = "User message";
940
+ const content = sanitizeText(eventData.content, {
941
+ preserveNewlines: true,
942
+ });
943
+ if (content)
944
+ detailLines.push(content);
945
+ break;
946
+ }
947
+ default: {
948
+ if (!eventMessage)
949
+ eventMessage = derivedType || "event";
950
+ extra = ensureExtra(formatKeyValues([
951
+ ["kind", sanitizeText(sessionKind)],
952
+ ["status", sanitizeText(eventData.status)],
314
953
  ["code", sanitizeText(eventData.error_code)],
954
+ ["correlation_id", sanitizeText(correlationId)],
315
955
  ]));
316
956
  }
317
957
  }