@workflow/web-shared 4.1.0-beta.47 → 4.1.0-beta.49

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 (301) hide show
  1. package/README.md +26 -52
  2. package/dist/components/error-boundary.d.ts.map +1 -0
  3. package/dist/{error-boundary.js → components/error-boundary.js} +1 -1
  4. package/dist/components/error-boundary.js.map +1 -0
  5. package/dist/{event-list-view.d.ts → components/event-list-view.d.ts} +2 -3
  6. package/dist/components/event-list-view.d.ts.map +1 -0
  7. package/dist/{event-list-view.js → components/event-list-view.js} +9 -17
  8. package/dist/components/event-list-view.js.map +1 -0
  9. package/dist/{hook-actions.d.ts → components/hook-actions.d.ts} +2 -3
  10. package/dist/components/hook-actions.d.ts.map +1 -0
  11. package/dist/{hook-actions.js → components/hook-actions.js} +3 -4
  12. package/dist/components/hook-actions.js.map +1 -0
  13. package/dist/components/index.d.ts +10 -0
  14. package/dist/components/index.d.ts.map +1 -0
  15. package/dist/components/index.js +8 -0
  16. package/dist/components/index.js.map +1 -0
  17. package/dist/components/run-trace-view.d.ts +22 -0
  18. package/dist/components/run-trace-view.d.ts.map +1 -0
  19. package/dist/components/run-trace-view.js +11 -0
  20. package/dist/components/run-trace-view.js.map +1 -0
  21. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -0
  22. package/dist/{sidebar → components/sidebar}/attribute-panel.js +3 -3
  23. package/dist/components/sidebar/attribute-panel.js.map +1 -0
  24. package/dist/components/sidebar/conversation-view.d.ts.map +1 -0
  25. package/dist/components/sidebar/conversation-view.js.map +1 -0
  26. package/dist/components/sidebar/detail-card.d.ts.map +1 -0
  27. package/dist/components/sidebar/detail-card.js.map +1 -0
  28. package/dist/components/sidebar/entity-detail-panel.d.ts +32 -0
  29. package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -0
  30. package/dist/{sidebar → components/sidebar}/entity-detail-panel.js +61 -49
  31. package/dist/components/sidebar/entity-detail-panel.js.map +1 -0
  32. package/dist/components/sidebar/events-list.d.ts +8 -0
  33. package/dist/components/sidebar/events-list.d.ts.map +1 -0
  34. package/dist/components/sidebar/events-list.js +16 -0
  35. package/dist/components/sidebar/events-list.js.map +1 -0
  36. package/dist/components/sidebar/resolve-hook-modal.d.ts.map +1 -0
  37. package/dist/components/sidebar/resolve-hook-modal.js.map +1 -0
  38. package/dist/components/stream-viewer.d.ts +18 -0
  39. package/dist/components/stream-viewer.d.ts.map +1 -0
  40. package/dist/{stream-viewer.js → components/stream-viewer.js} +1 -59
  41. package/dist/components/stream-viewer.js.map +1 -0
  42. package/dist/components/trace-viewer/components/map.d.ts.map +1 -0
  43. package/dist/components/trace-viewer/components/map.js.map +1 -0
  44. package/dist/components/trace-viewer/components/markers.d.ts.map +1 -0
  45. package/dist/components/trace-viewer/components/markers.js.map +1 -0
  46. package/dist/components/trace-viewer/components/node.d.ts.map +1 -0
  47. package/dist/components/trace-viewer/components/node.js.map +1 -0
  48. package/dist/components/trace-viewer/components/search-input.d.ts.map +1 -0
  49. package/dist/components/trace-viewer/components/search-input.js.map +1 -0
  50. package/dist/components/trace-viewer/components/search.d.ts.map +1 -0
  51. package/dist/components/trace-viewer/components/search.js.map +1 -0
  52. package/dist/components/trace-viewer/components/span-detail-panel.d.ts.map +1 -0
  53. package/dist/components/trace-viewer/components/span-detail-panel.js.map +1 -0
  54. package/dist/components/trace-viewer/components/ui.d.ts.map +1 -0
  55. package/dist/components/trace-viewer/components/ui.js.map +1 -0
  56. package/dist/components/trace-viewer/components/zoom-button.d.ts.map +1 -0
  57. package/dist/components/trace-viewer/components/zoom-button.js.map +1 -0
  58. package/dist/components/trace-viewer/components/zoom-icons.d.ts.map +1 -0
  59. package/dist/components/trace-viewer/components/zoom-icons.js.map +1 -0
  60. package/dist/components/trace-viewer/context.d.ts.map +1 -0
  61. package/dist/components/trace-viewer/context.js.map +1 -0
  62. package/dist/components/trace-viewer/index.d.ts.map +1 -0
  63. package/dist/components/trace-viewer/index.js.map +1 -0
  64. package/dist/components/trace-viewer/trace-viewer.d.ts.map +1 -0
  65. package/dist/components/trace-viewer/trace-viewer.js.map +1 -0
  66. package/dist/components/trace-viewer/types.d.ts.map +1 -0
  67. package/dist/components/trace-viewer/types.js.map +1 -0
  68. package/dist/components/trace-viewer/util/constants.d.ts.map +1 -0
  69. package/dist/components/trace-viewer/util/constants.js.map +1 -0
  70. package/dist/components/trace-viewer/util/scrollbar-width.d.ts.map +1 -0
  71. package/dist/components/trace-viewer/util/scrollbar-width.js.map +1 -0
  72. package/dist/{trace-viewer → components/trace-viewer}/util/timing.d.ts +1 -1
  73. package/dist/components/trace-viewer/util/timing.d.ts.map +1 -0
  74. package/dist/{trace-viewer → components/trace-viewer}/util/timing.js +1 -1
  75. package/dist/components/trace-viewer/util/timing.js.map +1 -0
  76. package/dist/components/trace-viewer/util/tree.d.ts.map +1 -0
  77. package/dist/components/trace-viewer/util/tree.js.map +1 -0
  78. package/dist/components/trace-viewer/util/use-immediate-style.d.ts.map +1 -0
  79. package/dist/components/trace-viewer/util/use-immediate-style.js.map +1 -0
  80. package/dist/components/trace-viewer/util/use-streaming-spans.d.ts.map +1 -0
  81. package/dist/components/trace-viewer/util/use-streaming-spans.js.map +1 -0
  82. package/dist/components/trace-viewer/util/use-trackpad-zoom.d.ts.map +1 -0
  83. package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +1 -0
  84. package/dist/components/trace-viewer/worker.d.ts.map +1 -0
  85. package/dist/components/trace-viewer/worker.js.map +1 -0
  86. package/dist/components/workflow-trace-view.d.ts +24 -0
  87. package/dist/components/workflow-trace-view.d.ts.map +1 -0
  88. package/dist/components/workflow-trace-view.js +152 -0
  89. package/dist/components/workflow-trace-view.js.map +1 -0
  90. package/dist/components/workflow-traces/event-colors.d.ts.map +1 -0
  91. package/dist/components/workflow-traces/event-colors.js.map +1 -0
  92. package/dist/components/workflow-traces/trace-colors.d.ts.map +1 -0
  93. package/dist/components/workflow-traces/trace-colors.js.map +1 -0
  94. package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -0
  95. package/dist/components/workflow-traces/trace-span-construction.js.map +1 -0
  96. package/dist/components/workflow-traces/trace-time-utils.d.ts.map +1 -0
  97. package/dist/components/workflow-traces/trace-time-utils.js.map +1 -0
  98. package/dist/index.d.ts +3 -13
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +2 -9
  101. package/dist/index.js.map +1 -1
  102. package/package.json +15 -11
  103. package/src/components/error-boundary.tsx +79 -0
  104. package/src/components/event-list-view.tsx +429 -0
  105. package/src/components/hook-actions.tsx +167 -0
  106. package/src/components/index.d.ts +1 -0
  107. package/src/components/index.ts +23 -0
  108. package/src/components/run-trace-view.tsx +75 -0
  109. package/src/components/sidebar/attribute-panel.tsx +938 -0
  110. package/src/components/sidebar/conversation-view.tsx +235 -0
  111. package/src/components/sidebar/detail-card.tsx +43 -0
  112. package/src/components/sidebar/entity-detail-panel.tsx +338 -0
  113. package/src/components/sidebar/events-list.tsx +119 -0
  114. package/src/components/sidebar/resolve-hook-modal.tsx +219 -0
  115. package/src/components/stream-viewer.tsx +143 -0
  116. package/src/components/trace-viewer/components/map.tsx +226 -0
  117. package/src/components/trace-viewer/components/markers.tsx +564 -0
  118. package/src/components/trace-viewer/components/node.tsx +259 -0
  119. package/src/components/trace-viewer/components/search-input.tsx +52 -0
  120. package/src/components/trace-viewer/components/search.tsx +47 -0
  121. package/src/components/trace-viewer/components/span-detail-panel.tsx +650 -0
  122. package/src/components/trace-viewer/components/ui.tsx +156 -0
  123. package/src/components/trace-viewer/components/zoom-button.tsx +61 -0
  124. package/src/components/trace-viewer/components/zoom-icons.tsx +65 -0
  125. package/src/components/trace-viewer/context.tsx +633 -0
  126. package/src/components/trace-viewer/index.tsx +4 -0
  127. package/src/components/trace-viewer/modules.d.ts +16 -0
  128. package/src/components/trace-viewer/trace-viewer.module.css +1292 -0
  129. package/src/components/trace-viewer/trace-viewer.tsx +448 -0
  130. package/src/components/trace-viewer/types.ts +234 -0
  131. package/src/components/trace-viewer/util/constants.ts +8 -0
  132. package/src/components/trace-viewer/util/scrollbar-width.ts +13 -0
  133. package/src/components/trace-viewer/util/timing.ts +33 -0
  134. package/src/components/trace-viewer/util/tree.ts +277 -0
  135. package/src/components/trace-viewer/util/use-immediate-style.ts +38 -0
  136. package/src/components/trace-viewer/util/use-streaming-spans.ts +415 -0
  137. package/src/components/trace-viewer/util/use-trackpad-zoom.tsx +51 -0
  138. package/src/components/trace-viewer/worker.ts +128 -0
  139. package/src/components/ui/alert.tsx +59 -0
  140. package/src/components/ui/card.tsx +88 -0
  141. package/src/components/ui/error-card.tsx +65 -0
  142. package/src/components/ui/skeleton.tsx +15 -0
  143. package/src/components/workflow-trace-view.tsx +306 -0
  144. package/src/components/workflow-traces/event-colors.ts +94 -0
  145. package/src/components/workflow-traces/trace-colors.ts +112 -0
  146. package/src/components/workflow-traces/trace-span-construction.ts +299 -0
  147. package/src/components/workflow-traces/trace-time-utils.ts +50 -0
  148. package/src/hooks/use-dark-mode.ts +34 -0
  149. package/src/index.d.ts +1 -0
  150. package/src/index.ts +29 -0
  151. package/src/lib/event-analysis.ts +231 -0
  152. package/src/lib/utils.ts +166 -0
  153. package/dist/api/workflow-api-client.d.ts +0 -543
  154. package/dist/api/workflow-api-client.d.ts.map +0 -1
  155. package/dist/api/workflow-api-client.js +0 -953
  156. package/dist/api/workflow-api-client.js.map +0 -1
  157. package/dist/api/workflow-server-actions.d.ts +0 -230
  158. package/dist/api/workflow-server-actions.d.ts.map +0 -1
  159. package/dist/api/workflow-server-actions.js +0 -861
  160. package/dist/api/workflow-server-actions.js.map +0 -1
  161. package/dist/error-boundary.d.ts.map +0 -1
  162. package/dist/error-boundary.js.map +0 -1
  163. package/dist/event-list-view.d.ts.map +0 -1
  164. package/dist/event-list-view.js.map +0 -1
  165. package/dist/hook-actions.d.ts.map +0 -1
  166. package/dist/hook-actions.js.map +0 -1
  167. package/dist/run-trace-view.d.ts +0 -8
  168. package/dist/run-trace-view.d.ts.map +0 -1
  169. package/dist/run-trace-view.js +0 -15
  170. package/dist/run-trace-view.js.map +0 -1
  171. package/dist/sidebar/attribute-panel.d.ts.map +0 -1
  172. package/dist/sidebar/attribute-panel.js.map +0 -1
  173. package/dist/sidebar/conversation-view.d.ts.map +0 -1
  174. package/dist/sidebar/conversation-view.js.map +0 -1
  175. package/dist/sidebar/detail-card.d.ts.map +0 -1
  176. package/dist/sidebar/detail-card.js.map +0 -1
  177. package/dist/sidebar/entity-detail-panel.d.ts +0 -12
  178. package/dist/sidebar/entity-detail-panel.d.ts.map +0 -1
  179. package/dist/sidebar/entity-detail-panel.js.map +0 -1
  180. package/dist/sidebar/events-list.d.ts +0 -9
  181. package/dist/sidebar/events-list.d.ts.map +0 -1
  182. package/dist/sidebar/events-list.js +0 -36
  183. package/dist/sidebar/events-list.js.map +0 -1
  184. package/dist/sidebar/resolve-hook-modal.d.ts.map +0 -1
  185. package/dist/sidebar/resolve-hook-modal.js.map +0 -1
  186. package/dist/stream-viewer.d.ts +0 -13
  187. package/dist/stream-viewer.d.ts.map +0 -1
  188. package/dist/stream-viewer.js.map +0 -1
  189. package/dist/trace-viewer/components/map.d.ts.map +0 -1
  190. package/dist/trace-viewer/components/map.js.map +0 -1
  191. package/dist/trace-viewer/components/markers.d.ts.map +0 -1
  192. package/dist/trace-viewer/components/markers.js.map +0 -1
  193. package/dist/trace-viewer/components/node.d.ts.map +0 -1
  194. package/dist/trace-viewer/components/node.js.map +0 -1
  195. package/dist/trace-viewer/components/search-input.d.ts.map +0 -1
  196. package/dist/trace-viewer/components/search-input.js.map +0 -1
  197. package/dist/trace-viewer/components/search.d.ts.map +0 -1
  198. package/dist/trace-viewer/components/search.js.map +0 -1
  199. package/dist/trace-viewer/components/span-detail-panel.d.ts.map +0 -1
  200. package/dist/trace-viewer/components/span-detail-panel.js.map +0 -1
  201. package/dist/trace-viewer/components/ui.d.ts.map +0 -1
  202. package/dist/trace-viewer/components/ui.js.map +0 -1
  203. package/dist/trace-viewer/components/zoom-button.d.ts.map +0 -1
  204. package/dist/trace-viewer/components/zoom-button.js.map +0 -1
  205. package/dist/trace-viewer/components/zoom-icons.d.ts.map +0 -1
  206. package/dist/trace-viewer/components/zoom-icons.js.map +0 -1
  207. package/dist/trace-viewer/context.d.ts.map +0 -1
  208. package/dist/trace-viewer/context.js.map +0 -1
  209. package/dist/trace-viewer/index.d.ts.map +0 -1
  210. package/dist/trace-viewer/index.js.map +0 -1
  211. package/dist/trace-viewer/trace-viewer.d.ts.map +0 -1
  212. package/dist/trace-viewer/trace-viewer.js.map +0 -1
  213. package/dist/trace-viewer/types.d.ts.map +0 -1
  214. package/dist/trace-viewer/types.js.map +0 -1
  215. package/dist/trace-viewer/util/constants.d.ts.map +0 -1
  216. package/dist/trace-viewer/util/constants.js.map +0 -1
  217. package/dist/trace-viewer/util/scrollbar-width.d.ts.map +0 -1
  218. package/dist/trace-viewer/util/scrollbar-width.js.map +0 -1
  219. package/dist/trace-viewer/util/timing.d.ts.map +0 -1
  220. package/dist/trace-viewer/util/timing.js.map +0 -1
  221. package/dist/trace-viewer/util/tree.d.ts.map +0 -1
  222. package/dist/trace-viewer/util/tree.js.map +0 -1
  223. package/dist/trace-viewer/util/use-immediate-style.d.ts.map +0 -1
  224. package/dist/trace-viewer/util/use-immediate-style.js.map +0 -1
  225. package/dist/trace-viewer/util/use-streaming-spans.d.ts.map +0 -1
  226. package/dist/trace-viewer/util/use-streaming-spans.js.map +0 -1
  227. package/dist/trace-viewer/util/use-trackpad-zoom.d.ts.map +0 -1
  228. package/dist/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
  229. package/dist/trace-viewer/worker.d.ts.map +0 -1
  230. package/dist/trace-viewer/worker.js.map +0 -1
  231. package/dist/workflow-trace-view.d.ts +0 -14
  232. package/dist/workflow-trace-view.d.ts.map +0 -1
  233. package/dist/workflow-trace-view.js +0 -135
  234. package/dist/workflow-trace-view.js.map +0 -1
  235. package/dist/workflow-traces/event-colors.d.ts.map +0 -1
  236. package/dist/workflow-traces/event-colors.js.map +0 -1
  237. package/dist/workflow-traces/trace-colors.d.ts.map +0 -1
  238. package/dist/workflow-traces/trace-colors.js.map +0 -1
  239. package/dist/workflow-traces/trace-span-construction.d.ts.map +0 -1
  240. package/dist/workflow-traces/trace-span-construction.js.map +0 -1
  241. package/dist/workflow-traces/trace-time-utils.d.ts.map +0 -1
  242. package/dist/workflow-traces/trace-time-utils.js.map +0 -1
  243. package/server/README.md +0 -1
  244. package/server/package.json +0 -4
  245. /package/dist/{error-boundary.d.ts → components/error-boundary.d.ts} +0 -0
  246. /package/dist/{sidebar → components/sidebar}/attribute-panel.d.ts +0 -0
  247. /package/dist/{sidebar → components/sidebar}/conversation-view.d.ts +0 -0
  248. /package/dist/{sidebar → components/sidebar}/conversation-view.js +0 -0
  249. /package/dist/{sidebar → components/sidebar}/detail-card.d.ts +0 -0
  250. /package/dist/{sidebar → components/sidebar}/detail-card.js +0 -0
  251. /package/dist/{sidebar → components/sidebar}/resolve-hook-modal.d.ts +0 -0
  252. /package/dist/{sidebar → components/sidebar}/resolve-hook-modal.js +0 -0
  253. /package/dist/{trace-viewer → components/trace-viewer}/components/map.d.ts +0 -0
  254. /package/dist/{trace-viewer → components/trace-viewer}/components/map.js +0 -0
  255. /package/dist/{trace-viewer → components/trace-viewer}/components/markers.d.ts +0 -0
  256. /package/dist/{trace-viewer → components/trace-viewer}/components/markers.js +0 -0
  257. /package/dist/{trace-viewer → components/trace-viewer}/components/node.d.ts +0 -0
  258. /package/dist/{trace-viewer → components/trace-viewer}/components/node.js +0 -0
  259. /package/dist/{trace-viewer → components/trace-viewer}/components/search-input.d.ts +0 -0
  260. /package/dist/{trace-viewer → components/trace-viewer}/components/search-input.js +0 -0
  261. /package/dist/{trace-viewer → components/trace-viewer}/components/search.d.ts +0 -0
  262. /package/dist/{trace-viewer → components/trace-viewer}/components/search.js +0 -0
  263. /package/dist/{trace-viewer → components/trace-viewer}/components/span-detail-panel.d.ts +0 -0
  264. /package/dist/{trace-viewer → components/trace-viewer}/components/span-detail-panel.js +0 -0
  265. /package/dist/{trace-viewer → components/trace-viewer}/components/ui.d.ts +0 -0
  266. /package/dist/{trace-viewer → components/trace-viewer}/components/ui.js +0 -0
  267. /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-button.d.ts +0 -0
  268. /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-button.js +0 -0
  269. /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-icons.d.ts +0 -0
  270. /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-icons.js +0 -0
  271. /package/dist/{trace-viewer → components/trace-viewer}/context.d.ts +0 -0
  272. /package/dist/{trace-viewer → components/trace-viewer}/context.js +0 -0
  273. /package/dist/{trace-viewer → components/trace-viewer}/index.d.ts +0 -0
  274. /package/dist/{trace-viewer → components/trace-viewer}/index.js +0 -0
  275. /package/dist/{trace-viewer → components/trace-viewer}/trace-viewer.d.ts +0 -0
  276. /package/dist/{trace-viewer → components/trace-viewer}/trace-viewer.js +0 -0
  277. /package/dist/{trace-viewer → components/trace-viewer}/trace-viewer.module.css +0 -0
  278. /package/dist/{trace-viewer → components/trace-viewer}/types.d.ts +0 -0
  279. /package/dist/{trace-viewer → components/trace-viewer}/types.js +0 -0
  280. /package/dist/{trace-viewer → components/trace-viewer}/util/constants.d.ts +0 -0
  281. /package/dist/{trace-viewer → components/trace-viewer}/util/constants.js +0 -0
  282. /package/dist/{trace-viewer → components/trace-viewer}/util/scrollbar-width.d.ts +0 -0
  283. /package/dist/{trace-viewer → components/trace-viewer}/util/scrollbar-width.js +0 -0
  284. /package/dist/{trace-viewer → components/trace-viewer}/util/tree.d.ts +0 -0
  285. /package/dist/{trace-viewer → components/trace-viewer}/util/tree.js +0 -0
  286. /package/dist/{trace-viewer → components/trace-viewer}/util/use-immediate-style.d.ts +0 -0
  287. /package/dist/{trace-viewer → components/trace-viewer}/util/use-immediate-style.js +0 -0
  288. /package/dist/{trace-viewer → components/trace-viewer}/util/use-streaming-spans.d.ts +0 -0
  289. /package/dist/{trace-viewer → components/trace-viewer}/util/use-streaming-spans.js +0 -0
  290. /package/dist/{trace-viewer → components/trace-viewer}/util/use-trackpad-zoom.d.ts +0 -0
  291. /package/dist/{trace-viewer → components/trace-viewer}/util/use-trackpad-zoom.js +0 -0
  292. /package/dist/{trace-viewer → components/trace-viewer}/worker.d.ts +0 -0
  293. /package/dist/{trace-viewer → components/trace-viewer}/worker.js +0 -0
  294. /package/dist/{workflow-traces → components/workflow-traces}/event-colors.d.ts +0 -0
  295. /package/dist/{workflow-traces → components/workflow-traces}/event-colors.js +0 -0
  296. /package/dist/{workflow-traces → components/workflow-traces}/trace-colors.d.ts +0 -0
  297. /package/dist/{workflow-traces → components/workflow-traces}/trace-colors.js +0 -0
  298. /package/dist/{workflow-traces → components/workflow-traces}/trace-span-construction.d.ts +0 -0
  299. /package/dist/{workflow-traces → components/workflow-traces}/trace-span-construction.js +0 -0
  300. /package/dist/{workflow-traces → components/workflow-traces}/trace-time-utils.d.ts +0 -0
  301. /package/dist/{workflow-traces → components/workflow-traces}/trace-time-utils.js +0 -0
@@ -0,0 +1,79 @@
1
+ 'use client';
2
+
3
+ import React, { type ReactNode } from 'react';
4
+ import { ErrorCard } from './ui/error-card';
5
+
6
+ interface ErrorBoundaryProps {
7
+ children: ReactNode;
8
+ /** Optional title for the error message */
9
+ title?: string;
10
+ /** Optional fallback component to render on error */
11
+ fallback?: (error: Error, reset: () => void) => ReactNode;
12
+ }
13
+
14
+ interface ErrorBoundaryState {
15
+ hasError: boolean;
16
+ error: Error | null;
17
+ }
18
+
19
+ /**
20
+ * Error boundary component that catches errors in child components
21
+ * and displays them without breaking the entire application.
22
+ *
23
+ * Errors are localized to this boundary, so other parts of the UI
24
+ * remain functional.
25
+ */
26
+ export class ErrorBoundary extends React.Component<
27
+ ErrorBoundaryProps,
28
+ ErrorBoundaryState
29
+ > {
30
+ constructor(props: ErrorBoundaryProps) {
31
+ super(props);
32
+ this.state = {
33
+ hasError: false,
34
+ error: null,
35
+ };
36
+ }
37
+
38
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState {
39
+ return {
40
+ hasError: true,
41
+ error,
42
+ };
43
+ }
44
+
45
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
46
+ // Log error for debugging
47
+ console.error('Error caught by boundary:', error, errorInfo);
48
+ }
49
+
50
+ handleReset = () => {
51
+ this.setState({
52
+ hasError: false,
53
+ error: null,
54
+ });
55
+ };
56
+
57
+ render() {
58
+ if (this.state.hasError && this.state.error) {
59
+ // Use custom fallback if provided
60
+ if (this.props.fallback) {
61
+ return this.props.fallback(this.state.error, this.handleReset);
62
+ }
63
+
64
+ // Default error UI
65
+ const errorDetails = this.state.error.stack
66
+ ? `${this.state.error.message}\n\n${this.state.error.stack}`
67
+ : this.state.error.message;
68
+
69
+ return (
70
+ <ErrorCard
71
+ title={this.props.title || 'An error occurred'}
72
+ details={errorDetails}
73
+ />
74
+ );
75
+ }
76
+
77
+ return this.props.children;
78
+ }
79
+ }
@@ -0,0 +1,429 @@
1
+ 'use client';
2
+
3
+ import type { Event } from '@workflow/world';
4
+ import { ChevronRight, Loader2 } from 'lucide-react';
5
+ import { useCallback, useMemo, useState } from 'react';
6
+ import { getEventColor } from './workflow-traces/event-colors';
7
+
8
+ /**
9
+ * Format a date to a human-readable local time string with milliseconds
10
+ */
11
+ function formatEventTime(date: Date): string {
12
+ return (
13
+ date.toLocaleTimeString('en-US', {
14
+ hour: '2-digit',
15
+ minute: '2-digit',
16
+ second: '2-digit',
17
+ hour12: false,
18
+ }) +
19
+ '.' +
20
+ date.getMilliseconds().toString().padStart(3, '0')
21
+ );
22
+ }
23
+
24
+ /**
25
+ * Format a date to full local datetime string with milliseconds
26
+ */
27
+ function formatEventDateTime(date: Date): string {
28
+ return date.toLocaleString(undefined, {
29
+ year: 'numeric',
30
+ month: 'numeric',
31
+ day: 'numeric',
32
+ hour: 'numeric',
33
+ minute: 'numeric',
34
+ second: 'numeric',
35
+ fractionalSecondDigits: 3,
36
+ });
37
+ }
38
+
39
+ /**
40
+ * Format event type to a more readable label
41
+ */
42
+ function formatEventType(eventType: Event['eventType']): string {
43
+ return eventType
44
+ .split('_')
45
+ .map((word: string) => word.charAt(0).toUpperCase() + word.slice(1))
46
+ .join(' ');
47
+ }
48
+
49
+ interface EventsListProps {
50
+ events: Event[] | null;
51
+ onLoadEventData?: (event: Event) => Promise<unknown | null>;
52
+ }
53
+
54
+ /**
55
+ * Single event row component with expandable details
56
+ */
57
+ function EventRow({
58
+ event,
59
+ onLoadEventData,
60
+ }: {
61
+ event: Event;
62
+ onLoadEventData?: (event: Event) => Promise<unknown | null>;
63
+ }) {
64
+ const [isExpanded, setIsExpanded] = useState(false);
65
+ const [isLoading, setIsLoading] = useState(false);
66
+ const [loadedEventData, setLoadedEventData] = useState<unknown | null>(null);
67
+ const [loadError, setLoadError] = useState<string | null>(null);
68
+
69
+ const colors = getEventColor(event.eventType);
70
+ const createdAt = new Date(event.createdAt);
71
+
72
+ // Check if event already has eventData (from initial fetch)
73
+ const hasExistingEventData = 'eventData' in event && event.eventData != null;
74
+
75
+ // Load full event details when expanding
76
+ const loadEventDetails = useCallback(async () => {
77
+ // Skip if we already have data or no correlationId
78
+ if (
79
+ loadedEventData !== null ||
80
+ hasExistingEventData ||
81
+ !event.correlationId
82
+ ) {
83
+ return;
84
+ }
85
+
86
+ setIsLoading(true);
87
+ setLoadError(null);
88
+
89
+ try {
90
+ if (!onLoadEventData) {
91
+ setLoadError('Event details unavailable');
92
+ return;
93
+ }
94
+ const eventData = await onLoadEventData(event);
95
+ if (eventData !== null && eventData !== undefined) {
96
+ setLoadedEventData(eventData);
97
+ }
98
+ } catch (err) {
99
+ setLoadError(
100
+ err instanceof Error ? err.message : 'Failed to load event details'
101
+ );
102
+ } finally {
103
+ setIsLoading(false);
104
+ }
105
+ }, [
106
+ event.correlationId,
107
+ loadedEventData,
108
+ hasExistingEventData,
109
+ onLoadEventData,
110
+ ]);
111
+
112
+ // Handle expand/collapse
113
+ const handleToggle = useCallback(() => {
114
+ const newExpanded = !isExpanded;
115
+ setIsExpanded(newExpanded);
116
+
117
+ // Load details when expanding for the first time
118
+ if (newExpanded && loadedEventData === null && !hasExistingEventData) {
119
+ loadEventDetails();
120
+ }
121
+ }, [isExpanded, loadedEventData, hasExistingEventData, loadEventDetails]);
122
+
123
+ // Get the event data to display (either from initial fetch, loaded data, or null)
124
+ const eventData = hasExistingEventData
125
+ ? (event as Event & { eventData: unknown }).eventData
126
+ : loadedEventData;
127
+
128
+ return (
129
+ <div
130
+ className="rounded-lg border overflow-hidden transition-all"
131
+ style={{
132
+ backgroundColor: 'var(--ds-background-100)',
133
+ borderColor: colors.border,
134
+ borderLeftWidth: '1px',
135
+ borderLeftColor: colors.color,
136
+ }}
137
+ >
138
+ {/* Clickable row header */}
139
+ <button
140
+ type="button"
141
+ onClick={handleToggle}
142
+ className="w-full text-left grid gap-3 items-center px-0 py-2 text-xs hover:brightness-[0.98] transition-all cursor-pointer"
143
+ style={{
144
+ backgroundColor: 'var(--ds-background-100)',
145
+ gridTemplateColumns: '24px 100px minmax(120px, auto) 1fr 1fr',
146
+ }}
147
+ >
148
+ {/* Expand icon */}
149
+ <div className="flex justify-center">
150
+ <ChevronRight
151
+ className="h-3.5 w-3.5 transition-transform"
152
+ style={{
153
+ color: colors.secondary,
154
+ transform: isExpanded ? 'rotate(90deg)' : 'rotate(0deg)',
155
+ }}
156
+ />
157
+ </div>
158
+
159
+ {/* Time */}
160
+ <div
161
+ className="font-mono tabular-nums"
162
+ style={{ color: colors.secondary }}
163
+ >
164
+ {formatEventTime(createdAt)}
165
+ </div>
166
+
167
+ {/* Event Type */}
168
+ <div className="font-medium" style={{ color: colors.text }}>
169
+ <span className="inline-flex items-center gap-1.5">
170
+ <span
171
+ className="w-2 h-2 rounded-full flex-shrink-0"
172
+ style={{ backgroundColor: colors.color }}
173
+ />
174
+ {formatEventType(event.eventType)}
175
+ </span>
176
+ </div>
177
+
178
+ {/* Correlation ID */}
179
+ <div
180
+ className="font-mono text-[11px] overflow-hidden text-ellipsis whitespace-nowrap"
181
+ style={{ color: colors.secondary }}
182
+ title={event.correlationId || '-'}
183
+ >
184
+ {event.correlationId || '-'}
185
+ </div>
186
+
187
+ {/* Event ID */}
188
+ <div
189
+ className="font-mono text-[11px] pr-3 overflow-hidden text-ellipsis whitespace-nowrap"
190
+ style={{ color: colors.secondary }}
191
+ title={event.eventId}
192
+ >
193
+ {event.eventId}
194
+ </div>
195
+ </button>
196
+
197
+ {/* Expanded details */}
198
+ {isExpanded && (
199
+ <div
200
+ className="border-t px-4 py-3"
201
+ style={{
202
+ borderColor: colors.border,
203
+ backgroundColor: 'var(--ds-background-100)',
204
+ }}
205
+ >
206
+ {/* Event attributes in a structured table */}
207
+ <div
208
+ className="flex flex-col divide-y rounded-md border overflow-hidden"
209
+ style={{
210
+ borderColor: 'var(--ds-gray-300)',
211
+ backgroundColor: 'var(--ds-gray-100)',
212
+ }}
213
+ >
214
+ <AttributeRow label="Event ID" value={event.eventId} mono />
215
+ <AttributeRow label="Event Type" value={event.eventType} />
216
+ <AttributeRow
217
+ label="Correlation ID"
218
+ value={event.correlationId || '-'}
219
+ mono
220
+ />
221
+ <AttributeRow label="Run ID" value={event.runId} mono />
222
+ <AttributeRow
223
+ label="Created At"
224
+ value={formatEventDateTime(createdAt)}
225
+ />
226
+ </div>
227
+
228
+ {/* Event data section */}
229
+ <div className="mt-3">
230
+ <div
231
+ className="text-xs font-medium mb-1.5"
232
+ style={{ color: 'var(--ds-gray-700)' }}
233
+ >
234
+ Event Data
235
+ </div>
236
+
237
+ {/* Loading state */}
238
+ {isLoading && (
239
+ <div
240
+ className="flex items-center gap-2 rounded-md border p-3"
241
+ style={{
242
+ borderColor: 'var(--ds-gray-300)',
243
+ backgroundColor: 'var(--ds-gray-100)',
244
+ }}
245
+ >
246
+ <Loader2
247
+ className="h-4 w-4 animate-spin"
248
+ style={{ color: 'var(--ds-gray-700)' }}
249
+ />
250
+ <span
251
+ className="text-xs"
252
+ style={{ color: 'var(--ds-gray-700)' }}
253
+ >
254
+ Loading event details...
255
+ </span>
256
+ </div>
257
+ )}
258
+
259
+ {/* Error state */}
260
+ {loadError && !isLoading && (
261
+ <div
262
+ className="rounded-md border p-3 text-xs"
263
+ style={{
264
+ borderColor: 'var(--ds-red-400)',
265
+ backgroundColor: 'var(--ds-red-100)',
266
+ color: 'var(--ds-red-900)',
267
+ }}
268
+ >
269
+ {loadError}
270
+ </div>
271
+ )}
272
+
273
+ {/* Event data display */}
274
+ {!isLoading && !loadError && eventData != null && (
275
+ <pre
276
+ className="text-[11px] overflow-x-auto rounded-md border p-3"
277
+ style={{
278
+ borderColor: 'var(--ds-gray-300)',
279
+ backgroundColor: 'var(--ds-gray-100)',
280
+ color: 'var(--ds-gray-1000)',
281
+ }}
282
+ >
283
+ <code>{JSON.stringify(eventData, null, 2)}</code>
284
+ </pre>
285
+ )}
286
+
287
+ {/* No event data */}
288
+ {!isLoading &&
289
+ !loadError &&
290
+ eventData == null &&
291
+ !event.correlationId && (
292
+ <div
293
+ className="rounded-md border p-3 text-xs"
294
+ style={{
295
+ borderColor: 'var(--ds-gray-300)',
296
+ backgroundColor: 'var(--ds-gray-100)',
297
+ color: 'var(--ds-gray-700)',
298
+ }}
299
+ >
300
+ No event data available
301
+ </div>
302
+ )}
303
+
304
+ {/* No correlation ID - can't load data */}
305
+ {!isLoading &&
306
+ !loadError &&
307
+ eventData == null &&
308
+ event.correlationId &&
309
+ !hasExistingEventData &&
310
+ loadedEventData === null && (
311
+ <div
312
+ className="rounded-md border p-3 text-xs"
313
+ style={{
314
+ borderColor: 'var(--ds-gray-300)',
315
+ backgroundColor: 'var(--ds-gray-100)',
316
+ color: 'var(--ds-gray-700)',
317
+ }}
318
+ >
319
+ No event data for this event type
320
+ </div>
321
+ )}
322
+ </div>
323
+ </div>
324
+ )}
325
+ </div>
326
+ );
327
+ }
328
+
329
+ /**
330
+ * Helper component for attribute rows in the expanded details
331
+ */
332
+ function AttributeRow({
333
+ label,
334
+ value,
335
+ mono = false,
336
+ }: {
337
+ label: string;
338
+ value: string;
339
+ mono?: boolean;
340
+ }) {
341
+ return (
342
+ <div
343
+ className="flex items-center justify-between px-2.5 py-1.5"
344
+ style={{ borderColor: 'var(--ds-gray-300)' }}
345
+ >
346
+ <span
347
+ className="text-[11px] font-medium"
348
+ style={{ color: 'var(--ds-gray-700)' }}
349
+ >
350
+ {label}
351
+ </span>
352
+ <span
353
+ className={`text-[11px] ${mono ? 'font-mono' : ''} text-right max-w-[70%] break-all`}
354
+ style={{ color: 'var(--ds-gray-1000)' }}
355
+ >
356
+ {value}
357
+ </span>
358
+ </div>
359
+ );
360
+ }
361
+
362
+ /**
363
+ * Displays a list of all events for a workflow run as colored cards in a pseudo-table.
364
+ * Events are sorted by createdAt (oldest first).
365
+ */
366
+ export function EventListView({ events, onLoadEventData }: EventsListProps) {
367
+ // Sort events by createdAt (oldest first)
368
+ const sortedEvents = useMemo(() => {
369
+ if (!events || events.length === 0) return [];
370
+ return [...events].sort(
371
+ (a, b) =>
372
+ new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
373
+ );
374
+ }, [events]);
375
+
376
+ if (!events || events.length === 0) {
377
+ return (
378
+ <div
379
+ className="flex items-center justify-center h-full text-sm"
380
+ style={{ color: 'var(--ds-gray-700)' }}
381
+ >
382
+ No events found
383
+ </div>
384
+ );
385
+ }
386
+
387
+ return (
388
+ <div className="h-full overflow-auto m-2">
389
+ {/* Header row */}
390
+ <div
391
+ className="grid gap-3 pb-2 mb-2 border-b text-xs font-medium sticky top-0 z-10"
392
+ style={{
393
+ gridTemplateColumns: '24px 100px minmax(120px, auto) 1fr 1fr',
394
+ borderColor: 'var(--ds-gray-300)',
395
+ backgroundColor: 'transparent',
396
+ color: 'var(--ds-gray-700)',
397
+ }}
398
+ >
399
+ <div>{/* Expand icon column */}</div>
400
+ <div>Time</div>
401
+ <div>Event Type</div>
402
+ <div>Correlation ID</div>
403
+ <div>Event ID</div>
404
+ </div>
405
+
406
+ {/* Event rows */}
407
+ <div className="flex flex-col gap-2">
408
+ {sortedEvents.map((event) => (
409
+ <EventRow
410
+ key={event.eventId}
411
+ event={event}
412
+ onLoadEventData={onLoadEventData}
413
+ />
414
+ ))}
415
+ </div>
416
+
417
+ {/* Summary */}
418
+ <div
419
+ className="mt-4 pt-3 border-t text-xs"
420
+ style={{
421
+ borderColor: 'var(--ds-gray-300)',
422
+ color: 'var(--ds-gray-700)',
423
+ }}
424
+ >
425
+ {sortedEvents.length} event{sortedEvents.length !== 1 ? 's' : ''} total
426
+ </div>
427
+ </div>
428
+ );
429
+ }
@@ -0,0 +1,167 @@
1
+ 'use client';
2
+
3
+ import type { Hook, WorkflowRunStatus } from '@workflow/world';
4
+ import { Send } from 'lucide-react';
5
+ import { useCallback, useState } from 'react';
6
+ import { toast } from 'sonner';
7
+ import { ResolveHookModal } from './sidebar/resolve-hook-modal';
8
+
9
+ // ============================================================================
10
+ // Types
11
+ // ============================================================================
12
+
13
+ export interface HookActionCallbacks {
14
+ /** Called after a successful action */
15
+ onSuccess?: () => void;
16
+ }
17
+
18
+ export interface UseHookActionsOptions {
19
+ onResolve: (hook: Hook, payload: unknown) => Promise<void>;
20
+ callbacks?: HookActionCallbacks;
21
+ }
22
+
23
+ export interface UseHookActionsReturn {
24
+ /** Whether the hook is currently being resolved */
25
+ isResolving: boolean;
26
+ /** The hook currently selected for resolution (null if none) */
27
+ selectedHook: Hook | null;
28
+ /** Open the resolve modal for a specific hook */
29
+ openResolveModal: (hook: Hook) => void;
30
+ /** Close the resolve modal */
31
+ closeResolveModal: () => void;
32
+ /** Handle submitting the resolve payload */
33
+ handleResolve: (payload: unknown) => Promise<void>;
34
+ }
35
+
36
+ // ============================================================================
37
+ // Hook for managing hook actions state
38
+ // ============================================================================
39
+
40
+ /**
41
+ * React hook for managing hook action state.
42
+ * Use this to coordinate the resolve modal across components.
43
+ */
44
+ export function useHookActions({
45
+ onResolve,
46
+ callbacks,
47
+ }: UseHookActionsOptions): UseHookActionsReturn {
48
+ const [isResolving, setIsResolving] = useState(false);
49
+ const [selectedHook, setSelectedHook] = useState<Hook | null>(null);
50
+
51
+ const openResolveModal = useCallback((hook: Hook) => {
52
+ setSelectedHook(hook);
53
+ }, []);
54
+
55
+ const closeResolveModal = useCallback(() => {
56
+ setSelectedHook(null);
57
+ }, []);
58
+
59
+ const handleResolve = useCallback(
60
+ async (payload: unknown) => {
61
+ if (isResolving || !selectedHook) return;
62
+
63
+ try {
64
+ setIsResolving(true);
65
+ await onResolve(selectedHook, payload);
66
+ toast.success('Hook resolved', {
67
+ description: 'The payload has been sent and the hook resolved.',
68
+ });
69
+ setSelectedHook(null);
70
+ callbacks?.onSuccess?.();
71
+ } catch (err) {
72
+ console.error('Failed to resolve hook:', err);
73
+ toast.error('Failed to resolve hook', {
74
+ description:
75
+ err instanceof Error ? err.message : 'An unknown error occurred',
76
+ });
77
+ } finally {
78
+ setIsResolving(false);
79
+ }
80
+ },
81
+ [onResolve, selectedHook, isResolving, callbacks]
82
+ );
83
+
84
+ return {
85
+ isResolving,
86
+ selectedHook,
87
+ openResolveModal,
88
+ closeResolveModal,
89
+ handleResolve,
90
+ };
91
+ }
92
+
93
+ // ============================================================================
94
+ // Dropdown Menu Item Component
95
+ // ============================================================================
96
+
97
+ export interface HookActionsDropdownItemProps {
98
+ /** The hook to act on */
99
+ hook: Hook;
100
+ /** The current run status (used to determine if actions are available) */
101
+ runStatus?: WorkflowRunStatus;
102
+ /** Stop click event propagation (useful in table rows) */
103
+ stopPropagation?: boolean;
104
+ /** Called when the resolve action is triggered */
105
+ onResolveClick: (hook: Hook) => void;
106
+ /** Custom DropdownMenuItem component (allows using the consumer's UI library) */
107
+ DropdownMenuItem: React.ComponentType<{
108
+ onClick?: (e: React.MouseEvent) => void;
109
+ disabled?: boolean;
110
+ children: React.ReactNode;
111
+ }>;
112
+ }
113
+
114
+ /**
115
+ * Dropdown menu item for resolving a hook.
116
+ * This is a single menu item component that can be composed into dropdown menus.
117
+ */
118
+ export function ResolveHookDropdownItem({
119
+ hook,
120
+ stopPropagation = false,
121
+ onResolveClick,
122
+ DropdownMenuItem,
123
+ }: HookActionsDropdownItemProps): React.JSX.Element {
124
+ const handleClick = (e: React.MouseEvent) => {
125
+ if (stopPropagation) e.stopPropagation();
126
+ onResolveClick(hook);
127
+ };
128
+
129
+ return (
130
+ <DropdownMenuItem onClick={handleClick}>
131
+ <Send className="h-4 w-4 mr-2" />
132
+ Resolve Hook
133
+ </DropdownMenuItem>
134
+ );
135
+ }
136
+
137
+ // ============================================================================
138
+ // Modal wrapper for convenience
139
+ // ============================================================================
140
+
141
+ export interface HookResolveModalProps {
142
+ /** The hook actions state from useHookActions */
143
+ hookActions: UseHookActionsReturn;
144
+ }
145
+
146
+ /**
147
+ * Convenience wrapper that renders the ResolveHookModal using useHookActions state.
148
+ * Place this at the top level of your component (outside any iteration).
149
+ */
150
+ export function HookResolveModalWrapper({
151
+ hookActions,
152
+ }: HookResolveModalProps): React.JSX.Element | null {
153
+ const { selectedHook, closeResolveModal, handleResolve, isResolving } =
154
+ hookActions;
155
+
156
+ return (
157
+ <ResolveHookModal
158
+ isOpen={selectedHook !== null}
159
+ onClose={closeResolveModal}
160
+ onSubmit={handleResolve}
161
+ isSubmitting={isResolving}
162
+ />
163
+ );
164
+ }
165
+
166
+ // Re-export the modal for direct use
167
+ export { ResolveHookModal } from './sidebar/resolve-hook-modal';
@@ -0,0 +1 @@
1
+ export * from './index';
@@ -0,0 +1,23 @@
1
+ export { ErrorBoundary } from './error-boundary';
2
+ export { EventListView } from './event-list-view';
3
+ export type {
4
+ HookActionCallbacks,
5
+ HookActionsDropdownItemProps,
6
+ HookResolveModalProps,
7
+ UseHookActionsOptions,
8
+ UseHookActionsReturn,
9
+ } from './hook-actions';
10
+ export {
11
+ HookResolveModalWrapper,
12
+ ResolveHookDropdownItem,
13
+ ResolveHookModal,
14
+ useHookActions,
15
+ } from './hook-actions';
16
+ export { RunTraceView } from './run-trace-view';
17
+ export { ConversationView } from './sidebar/conversation-view';
18
+ export { StreamViewer } from './stream-viewer';
19
+ export type { Span, SpanEvent } from './trace-viewer/types';
20
+ export {
21
+ WorkflowTraceViewer,
22
+ type SpanSelectionInfo,
23
+ } from './workflow-trace-view';