@workflow/web-shared 5.0.0-beta.3 → 5.0.0-beta.31

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 (402) hide show
  1. package/README.md +2 -10
  2. package/dist/components/error-boundary.js +1 -1
  3. package/dist/components/event-list-view.d.ts +46 -1
  4. package/dist/components/event-list-view.d.ts.map +1 -1
  5. package/dist/components/event-list-view.js +228 -90
  6. package/dist/components/hook-actions.js +1 -1
  7. package/dist/components/index.d.ts +6 -2
  8. package/dist/components/index.d.ts.map +1 -1
  9. package/dist/components/index.js +5 -2
  10. package/dist/components/new-trace-viewer/components/copy-button.js +3 -3
  11. package/dist/components/new-trace-viewer/components/detail-panel-width.d.ts +34 -0
  12. package/dist/components/new-trace-viewer/components/detail-panel-width.d.ts.map +1 -0
  13. package/dist/components/new-trace-viewer/components/detail-panel-width.js +67 -0
  14. package/dist/components/new-trace-viewer/components/detail-panel.d.ts +14 -0
  15. package/dist/components/new-trace-viewer/components/detail-panel.d.ts.map +1 -0
  16. package/dist/components/new-trace-viewer/components/detail-panel.js +122 -0
  17. package/dist/components/new-trace-viewer/components/draggable-border.d.ts +31 -0
  18. package/dist/components/new-trace-viewer/components/draggable-border.d.ts.map +1 -0
  19. package/dist/components/new-trace-viewer/components/draggable-border.js +140 -0
  20. package/dist/components/new-trace-viewer/components/event-list.d.ts +4 -2
  21. package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -1
  22. package/dist/components/new-trace-viewer/components/event-list.js +22 -13
  23. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts +18 -0
  24. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
  25. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +54 -0
  26. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts +20 -0
  27. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
  28. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
  29. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts +25 -0
  30. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
  31. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +101 -0
  32. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts +20 -0
  33. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
  34. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
  35. package/dist/components/new-trace-viewer/components/minimap.d.ts +14 -0
  36. package/dist/components/new-trace-viewer/components/minimap.d.ts.map +1 -0
  37. package/dist/components/new-trace-viewer/components/minimap.js +337 -0
  38. package/dist/components/new-trace-viewer/components/pane-constants.d.ts +14 -0
  39. package/dist/components/new-trace-viewer/components/pane-constants.d.ts.map +1 -0
  40. package/dist/components/new-trace-viewer/components/pane-constants.js +16 -0
  41. package/dist/components/new-trace-viewer/components/span-markers.d.ts +46 -0
  42. package/dist/components/new-trace-viewer/components/span-markers.d.ts.map +1 -0
  43. package/dist/components/new-trace-viewer/components/span-markers.js +85 -0
  44. package/dist/components/new-trace-viewer/components/split-pane.d.ts +3 -7
  45. package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -1
  46. package/dist/components/new-trace-viewer/components/split-pane.js +25 -84
  47. package/dist/components/new-trace-viewer/components/timeline.d.ts +19 -15
  48. package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -1
  49. package/dist/components/new-trace-viewer/components/timeline.js +229 -111
  50. package/dist/components/new-trace-viewer/components/timeline.module.css +46 -0
  51. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.d.ts +5 -0
  52. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.d.ts.map +1 -0
  53. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.js +55 -0
  54. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.module.css +20 -0
  55. package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts +2 -0
  56. package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts.map +1 -0
  57. package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.js +26 -0
  58. package/dist/components/new-trace-viewer/components/use-element-width.d.ts +8 -0
  59. package/dist/components/new-trace-viewer/components/use-element-width.d.ts.map +1 -0
  60. package/dist/components/new-trace-viewer/components/use-element-width.js +25 -0
  61. package/dist/components/new-trace-viewer/components/use-row-window.d.ts +34 -0
  62. package/dist/components/new-trace-viewer/components/use-row-window.d.ts.map +1 -0
  63. package/dist/components/new-trace-viewer/components/use-row-window.js +107 -0
  64. package/dist/components/new-trace-viewer/context.d.ts +3 -1
  65. package/dist/components/new-trace-viewer/context.d.ts.map +1 -1
  66. package/dist/components/new-trace-viewer/context.js +9 -10
  67. package/dist/components/new-trace-viewer/icons.js +3 -3
  68. package/dist/components/new-trace-viewer/search.d.ts +19 -0
  69. package/dist/components/new-trace-viewer/search.d.ts.map +1 -0
  70. package/dist/components/new-trace-viewer/search.js +134 -0
  71. package/dist/components/new-trace-viewer/trace-viewer.d.ts +6 -3
  72. package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -1
  73. package/dist/components/new-trace-viewer/trace-viewer.js +167 -162
  74. package/dist/components/new-trace-viewer/types.d.ts +2 -0
  75. package/dist/components/new-trace-viewer/types.d.ts.map +1 -1
  76. package/dist/components/new-trace-viewer/types.js +2 -2
  77. package/dist/components/new-trace-viewer/utils.d.ts +48 -13
  78. package/dist/components/new-trace-viewer/utils.d.ts.map +1 -1
  79. package/dist/components/new-trace-viewer/utils.js +135 -107
  80. package/dist/components/run-trace-view.d.ts +5 -7
  81. package/dist/components/run-trace-view.d.ts.map +1 -1
  82. package/dist/components/run-trace-view.js +3 -3
  83. package/dist/components/sidebar/attribute-panel.d.ts +4 -1
  84. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
  85. package/dist/components/sidebar/attribute-panel.js +133 -113
  86. package/dist/components/sidebar/attributes-block.d.ts +40 -0
  87. package/dist/components/sidebar/attributes-block.d.ts.map +1 -0
  88. package/dist/components/sidebar/attributes-block.js +140 -0
  89. package/dist/components/sidebar/conversation-view.js +1 -1
  90. package/dist/components/sidebar/copyable-data-block.d.ts +2 -0
  91. package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
  92. package/dist/components/sidebar/copyable-data-block.js +17 -16
  93. package/dist/components/sidebar/entity-detail-panel.d.ts +11 -11
  94. package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
  95. package/dist/components/sidebar/entity-detail-panel.js +35 -69
  96. package/dist/components/sidebar/events-list.d.ts +6 -2
  97. package/dist/components/sidebar/events-list.d.ts.map +1 -1
  98. package/dist/components/sidebar/events-list.js +76 -62
  99. package/dist/components/sidebar/resolve-hook-modal.js +1 -1
  100. package/dist/components/sidebar/sidebar-data-context.d.ts +10 -7
  101. package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -1
  102. package/dist/components/sidebar/sidebar-data-context.js +1 -1
  103. package/dist/components/sidebar/span-detail-merge.d.ts +31 -0
  104. package/dist/components/sidebar/span-detail-merge.d.ts.map +1 -0
  105. package/dist/components/sidebar/span-detail-merge.js +92 -0
  106. package/dist/components/sidebar/use-selected-span-detail.d.ts +16 -0
  107. package/dist/components/sidebar/use-selected-span-detail.d.ts.map +1 -0
  108. package/dist/components/sidebar/use-selected-span-detail.js +93 -0
  109. package/dist/components/stream-viewer.js +1 -1
  110. package/dist/components/trace-viewer/components/map.d.ts +2 -2
  111. package/dist/components/trace-viewer/components/map.d.ts.map +1 -1
  112. package/dist/components/trace-viewer/components/map.js +1 -1
  113. package/dist/components/trace-viewer/components/markers.js +1 -1
  114. package/dist/components/trace-viewer/components/node.d.ts +7 -7
  115. package/dist/components/trace-viewer/components/node.d.ts.map +1 -1
  116. package/dist/components/trace-viewer/components/node.js +2 -1
  117. package/dist/components/trace-viewer/components/search-input.js +1 -1
  118. package/dist/components/trace-viewer/components/search.js +1 -1
  119. package/dist/components/trace-viewer/components/span-content.js +1 -1
  120. package/dist/components/trace-viewer/components/span-detail-panel.js +1 -1
  121. package/dist/components/trace-viewer/components/span-segments.js +1 -1
  122. package/dist/components/trace-viewer/components/span-strategies.js +1 -1
  123. package/dist/components/trace-viewer/components/ui.js +1 -1
  124. package/dist/components/trace-viewer/components/zoom-button.js +1 -1
  125. package/dist/components/trace-viewer/components/zoom-icons.js +1 -1
  126. package/dist/components/trace-viewer/context.js +1 -1
  127. package/dist/components/trace-viewer/index.js +1 -1
  128. package/dist/components/trace-viewer/trace-viewer.js +1 -1
  129. package/dist/components/trace-viewer/trace-viewer.module.css +4 -4
  130. package/dist/components/trace-viewer/types.js +1 -1
  131. package/dist/components/trace-viewer/util/constants.js +1 -1
  132. package/dist/components/trace-viewer/util/scrollbar-width.js +1 -1
  133. package/dist/components/trace-viewer/util/timing.d.ts +3 -3
  134. package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
  135. package/dist/components/trace-viewer/util/timing.js +8 -11
  136. package/dist/components/trace-viewer/util/tree.js +1 -1
  137. package/dist/components/trace-viewer/util/use-immediate-style.js +1 -1
  138. package/dist/components/trace-viewer/util/use-streaming-spans.js +1 -1
  139. package/dist/components/trace-viewer/util/use-trackpad-zoom.js +1 -1
  140. package/dist/components/trace-viewer/worker.js +1 -1
  141. package/dist/components/trace-viewer-new.d.ts +5 -1
  142. package/dist/components/trace-viewer-new.d.ts.map +1 -1
  143. package/dist/components/trace-viewer-new.js +8 -10
  144. package/dist/components/ui/alert.js +2 -2
  145. package/dist/components/ui/button.d.ts +10 -0
  146. package/dist/components/ui/button.d.ts.map +1 -0
  147. package/dist/components/ui/button.js +46 -0
  148. package/dist/components/ui/card.js +2 -2
  149. package/dist/components/ui/collapsible.d.ts +46 -0
  150. package/dist/components/ui/collapsible.d.ts.map +1 -0
  151. package/dist/components/ui/collapsible.js +66 -0
  152. package/dist/components/ui/context-card.d.ts +47 -0
  153. package/dist/components/ui/context-card.d.ts.map +1 -0
  154. package/dist/components/ui/context-card.js +471 -0
  155. package/dist/components/ui/data-inspector.d.ts +7 -6
  156. package/dist/components/ui/data-inspector.d.ts.map +1 -1
  157. package/dist/components/ui/data-inspector.js +232 -99
  158. package/dist/components/ui/data-inspector.styles.d.ts +29 -0
  159. package/dist/components/ui/data-inspector.styles.d.ts.map +1 -0
  160. package/dist/components/ui/data-inspector.styles.js +95 -0
  161. package/dist/components/ui/decrypt-button.js +1 -1
  162. package/dist/components/ui/error-card.js +2 -2
  163. package/dist/components/ui/error-stack-block.d.ts +17 -10
  164. package/dist/components/ui/error-stack-block.d.ts.map +1 -1
  165. package/dist/components/ui/error-stack-block.js +49 -30
  166. package/dist/components/ui/icon-button.d.ts +19 -0
  167. package/dist/components/ui/icon-button.d.ts.map +1 -0
  168. package/dist/components/ui/icon-button.js +29 -0
  169. package/dist/components/ui/kbd.d.ts +10 -0
  170. package/dist/components/ui/kbd.d.ts.map +1 -0
  171. package/dist/components/ui/kbd.js +25 -0
  172. package/dist/components/ui/load-more-button.js +1 -1
  173. package/dist/components/ui/menu-dropdown.js +1 -1
  174. package/dist/components/ui/skeleton.js +2 -2
  175. package/dist/components/ui/spinner.js +1 -1
  176. package/dist/components/ui/timestamp-tooltip.d.ts +34 -1
  177. package/dist/components/ui/timestamp-tooltip.d.ts.map +1 -1
  178. package/dist/components/ui/timestamp-tooltip.js +80 -132
  179. package/dist/components/ui/tooltip.d.ts +10 -0
  180. package/dist/components/ui/tooltip.d.ts.map +1 -0
  181. package/dist/components/ui/tooltip.js +12 -0
  182. package/dist/components/workflow-trace-view.d.ts +7 -8
  183. package/dist/components/workflow-trace-view.d.ts.map +1 -1
  184. package/dist/components/workflow-trace-view.js +11 -16
  185. package/dist/components/workflow-traces/event-colors.d.ts +2 -1
  186. package/dist/components/workflow-traces/event-colors.d.ts.map +1 -1
  187. package/dist/components/workflow-traces/event-colors.js +15 -7
  188. package/dist/components/workflow-traces/trace-colors.d.ts.map +1 -1
  189. package/dist/components/workflow-traces/trace-colors.js +3 -4
  190. package/dist/components/workflow-traces/trace-span-construction.d.ts +7 -4
  191. package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
  192. package/dist/components/workflow-traces/trace-span-construction.js +87 -33
  193. package/dist/components/workflow-traces/trace-time-utils.js +1 -1
  194. package/dist/hooks/use-dark-mode.js +1 -1
  195. package/dist/hooks/use-intersection-observer.d.ts +17 -0
  196. package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
  197. package/dist/hooks/use-intersection-observer.js +29 -0
  198. package/dist/hooks/use-load-more-on-scroll.d.ts +21 -0
  199. package/dist/hooks/use-load-more-on-scroll.d.ts.map +1 -0
  200. package/dist/hooks/use-load-more-on-scroll.js +28 -0
  201. package/dist/hooks/use-reduced-motion.d.ts +10 -0
  202. package/dist/hooks/use-reduced-motion.d.ts.map +1 -0
  203. package/dist/hooks/use-reduced-motion.js +29 -0
  204. package/dist/index.d.ts +3 -2
  205. package/dist/index.d.ts.map +1 -1
  206. package/dist/index.js +4 -3
  207. package/dist/lib/cn.d.ts +10 -0
  208. package/dist/lib/cn.d.ts.map +1 -0
  209. package/dist/lib/cn.js +83 -0
  210. package/dist/lib/event-analysis.d.ts +1 -1
  211. package/dist/lib/event-analysis.d.ts.map +1 -1
  212. package/dist/lib/event-analysis.js +3 -2
  213. package/dist/lib/event-materialization.d.ts +1 -1
  214. package/dist/lib/event-materialization.d.ts.map +1 -1
  215. package/dist/lib/event-materialization.js +29 -21
  216. package/dist/lib/exact-event-search-id.d.ts +25 -0
  217. package/dist/lib/exact-event-search-id.d.ts.map +1 -0
  218. package/dist/lib/exact-event-search-id.js +39 -0
  219. package/dist/lib/hydration.d.ts +17 -2
  220. package/dist/lib/hydration.d.ts.map +1 -1
  221. package/dist/lib/hydration.js +185 -22
  222. package/dist/lib/stream-display.js +1 -1
  223. package/dist/lib/toast.js +1 -1
  224. package/dist/lib/trace-builder.d.ts +16 -4
  225. package/dist/lib/trace-builder.d.ts.map +1 -1
  226. package/dist/lib/trace-builder.js +34 -15
  227. package/dist/lib/utils.d.ts +23 -9
  228. package/dist/lib/utils.d.ts.map +1 -1
  229. package/dist/lib/utils.js +73 -33
  230. package/dist/lib/zstd-browser-decoder.d.ts +7 -0
  231. package/dist/lib/zstd-browser-decoder.d.ts.map +1 -0
  232. package/dist/lib/zstd-browser-decoder.js +41 -0
  233. package/dist/styles.css +14 -0
  234. package/package.json +10 -7
  235. package/src/components/event-list-view.tsx +375 -116
  236. package/src/components/index.ts +12 -5
  237. package/src/components/new-trace-viewer/components/copy-button.tsx +2 -2
  238. package/src/components/new-trace-viewer/components/detail-panel-width.test.ts +123 -0
  239. package/src/components/new-trace-viewer/components/detail-panel-width.ts +76 -0
  240. package/src/components/new-trace-viewer/components/detail-panel.tsx +273 -0
  241. package/src/components/new-trace-viewer/components/draggable-border.tsx +216 -0
  242. package/src/components/new-trace-viewer/components/event-list.tsx +57 -32
  243. package/src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts +114 -0
  244. package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +157 -0
  245. package/src/components/new-trace-viewer/components/middle-truncate/truncate.ts +132 -0
  246. package/src/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.ts +167 -0
  247. package/src/components/new-trace-viewer/components/minimap.tsx +559 -0
  248. package/src/components/new-trace-viewer/components/pane-constants.ts +19 -0
  249. package/src/components/new-trace-viewer/components/span-markers.tsx +173 -0
  250. package/src/components/new-trace-viewer/components/split-pane.tsx +80 -135
  251. package/src/components/new-trace-viewer/components/timeline.module.css +46 -0
  252. package/src/components/new-trace-viewer/components/timeline.tsx +603 -239
  253. package/src/components/new-trace-viewer/components/trace-shortcut-helper.module.css +20 -0
  254. package/src/components/new-trace-viewer/components/trace-shortcut-helper.tsx +116 -0
  255. package/src/components/new-trace-viewer/components/trace-viewer-skeleton.tsx +114 -0
  256. package/src/components/new-trace-viewer/components/use-element-width.ts +29 -0
  257. package/src/components/new-trace-viewer/components/use-row-window.ts +140 -0
  258. package/src/components/new-trace-viewer/context.tsx +13 -14
  259. package/src/components/new-trace-viewer/icons.tsx +2 -2
  260. package/src/components/new-trace-viewer/search.ts +178 -0
  261. package/src/components/new-trace-viewer/trace-viewer.tsx +336 -293
  262. package/src/components/new-trace-viewer/types.ts +2 -0
  263. package/src/components/new-trace-viewer/utils.test.ts +247 -0
  264. package/src/components/new-trace-viewer/utils.ts +203 -134
  265. package/src/components/run-trace-view.tsx +10 -14
  266. package/src/components/sidebar/attribute-panel.tsx +276 -275
  267. package/src/components/sidebar/attributes-block.tsx +326 -0
  268. package/src/components/sidebar/copyable-data-block.tsx +50 -28
  269. package/src/components/sidebar/entity-detail-panel.tsx +89 -123
  270. package/src/components/sidebar/events-list.tsx +196 -178
  271. package/src/components/sidebar/sidebar-data-context.tsx +11 -11
  272. package/src/components/sidebar/span-detail-merge.ts +134 -0
  273. package/src/components/sidebar/use-selected-span-detail.ts +146 -0
  274. package/src/components/trace-viewer/components/node.tsx +3 -2
  275. package/src/components/trace-viewer/trace-viewer.module.css +4 -4
  276. package/src/components/trace-viewer/util/timing.ts +7 -11
  277. package/src/components/trace-viewer-new.tsx +21 -15
  278. package/src/components/ui/alert.tsx +1 -1
  279. package/src/components/ui/button.tsx +68 -0
  280. package/src/components/ui/card.tsx +1 -1
  281. package/src/components/ui/collapsible.tsx +219 -0
  282. package/src/components/ui/context-card.tsx +784 -0
  283. package/src/components/ui/data-inspector.styles.ts +96 -0
  284. package/src/components/ui/data-inspector.tsx +501 -204
  285. package/src/components/ui/error-card.tsx +1 -1
  286. package/src/components/ui/error-stack-block.tsx +84 -55
  287. package/src/components/ui/icon-button.tsx +53 -0
  288. package/src/components/ui/kbd.tsx +43 -0
  289. package/src/components/ui/skeleton.tsx +1 -1
  290. package/src/components/ui/timestamp-tooltip.tsx +132 -194
  291. package/src/components/ui/tooltip.tsx +47 -0
  292. package/src/components/workflow-trace-view.tsx +31 -36
  293. package/src/components/workflow-traces/event-colors.ts +15 -11
  294. package/src/components/workflow-traces/trace-colors.ts +6 -6
  295. package/src/components/workflow-traces/trace-span-construction.test.ts +85 -0
  296. package/src/components/workflow-traces/trace-span-construction.ts +118 -35
  297. package/src/hooks/use-intersection-observer.ts +57 -0
  298. package/src/hooks/use-load-more-on-scroll.ts +49 -0
  299. package/src/hooks/use-reduced-motion.ts +34 -0
  300. package/src/index.ts +9 -0
  301. package/src/lib/cn.ts +93 -0
  302. package/src/lib/event-analysis.ts +6 -4
  303. package/src/lib/event-materialization.ts +35 -21
  304. package/src/lib/exact-event-search-id.ts +67 -0
  305. package/src/lib/hydration.ts +203 -29
  306. package/src/lib/trace-builder.ts +44 -19
  307. package/src/lib/utils.test.ts +33 -0
  308. package/src/lib/utils.ts +82 -35
  309. package/src/lib/zstd-browser-decoder.ts +42 -0
  310. package/src/styles.css +14 -0
  311. package/dist/components/error-boundary.js.map +0 -1
  312. package/dist/components/event-list-view.js.map +0 -1
  313. package/dist/components/hook-actions.js.map +0 -1
  314. package/dist/components/index.js.map +0 -1
  315. package/dist/components/new-trace-viewer/components/copy-button.js.map +0 -1
  316. package/dist/components/new-trace-viewer/components/event-list.js.map +0 -1
  317. package/dist/components/new-trace-viewer/components/split-pane.js.map +0 -1
  318. package/dist/components/new-trace-viewer/components/timeline.js.map +0 -1
  319. package/dist/components/new-trace-viewer/context.js.map +0 -1
  320. package/dist/components/new-trace-viewer/detail-panel.d.ts +0 -10
  321. package/dist/components/new-trace-viewer/detail-panel.d.ts.map +0 -1
  322. package/dist/components/new-trace-viewer/detail-panel.js +0 -11
  323. package/dist/components/new-trace-viewer/detail-panel.js.map +0 -1
  324. package/dist/components/new-trace-viewer/icons.js.map +0 -1
  325. package/dist/components/new-trace-viewer/trace-viewer.js.map +0 -1
  326. package/dist/components/new-trace-viewer/types.js.map +0 -1
  327. package/dist/components/new-trace-viewer/util/constants.d.ts +0 -1
  328. package/dist/components/new-trace-viewer/util/constants.d.ts.map +0 -1
  329. package/dist/components/new-trace-viewer/util/constants.js +0 -2
  330. package/dist/components/new-trace-viewer/util/constants.js.map +0 -1
  331. package/dist/components/new-trace-viewer/utils.js.map +0 -1
  332. package/dist/components/run-trace-view.js.map +0 -1
  333. package/dist/components/sidebar/attribute-panel.js.map +0 -1
  334. package/dist/components/sidebar/conversation-view.js.map +0 -1
  335. package/dist/components/sidebar/copyable-data-block.js.map +0 -1
  336. package/dist/components/sidebar/detail-card.d.ts +0 -14
  337. package/dist/components/sidebar/detail-card.d.ts.map +0 -1
  338. package/dist/components/sidebar/detail-card.js +0 -20
  339. package/dist/components/sidebar/detail-card.js.map +0 -1
  340. package/dist/components/sidebar/entity-detail-panel.js.map +0 -1
  341. package/dist/components/sidebar/events-list.js.map +0 -1
  342. package/dist/components/sidebar/resolve-hook-modal.js.map +0 -1
  343. package/dist/components/sidebar/sidebar-data-context.js.map +0 -1
  344. package/dist/components/stream-viewer.js.map +0 -1
  345. package/dist/components/trace-viewer/components/map.js.map +0 -1
  346. package/dist/components/trace-viewer/components/markers.js.map +0 -1
  347. package/dist/components/trace-viewer/components/node.js.map +0 -1
  348. package/dist/components/trace-viewer/components/search-input.js.map +0 -1
  349. package/dist/components/trace-viewer/components/search.js.map +0 -1
  350. package/dist/components/trace-viewer/components/span-content.js.map +0 -1
  351. package/dist/components/trace-viewer/components/span-detail-panel.js.map +0 -1
  352. package/dist/components/trace-viewer/components/span-segments.js.map +0 -1
  353. package/dist/components/trace-viewer/components/span-strategies.js.map +0 -1
  354. package/dist/components/trace-viewer/components/ui.js.map +0 -1
  355. package/dist/components/trace-viewer/components/zoom-button.js.map +0 -1
  356. package/dist/components/trace-viewer/components/zoom-icons.js.map +0 -1
  357. package/dist/components/trace-viewer/context.js.map +0 -1
  358. package/dist/components/trace-viewer/index.js.map +0 -1
  359. package/dist/components/trace-viewer/trace-viewer.js.map +0 -1
  360. package/dist/components/trace-viewer/types.js.map +0 -1
  361. package/dist/components/trace-viewer/util/constants.js.map +0 -1
  362. package/dist/components/trace-viewer/util/scrollbar-width.js.map +0 -1
  363. package/dist/components/trace-viewer/util/timing.js.map +0 -1
  364. package/dist/components/trace-viewer/util/tree.js.map +0 -1
  365. package/dist/components/trace-viewer/util/use-immediate-style.js.map +0 -1
  366. package/dist/components/trace-viewer/util/use-streaming-spans.js.map +0 -1
  367. package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
  368. package/dist/components/trace-viewer/worker.js.map +0 -1
  369. package/dist/components/trace-viewer-new.js.map +0 -1
  370. package/dist/components/ui/alert.js.map +0 -1
  371. package/dist/components/ui/card.js.map +0 -1
  372. package/dist/components/ui/data-inspector.js.map +0 -1
  373. package/dist/components/ui/decrypt-button.js.map +0 -1
  374. package/dist/components/ui/error-card.js.map +0 -1
  375. package/dist/components/ui/error-stack-block.js.map +0 -1
  376. package/dist/components/ui/inspector-theme.d.ts +0 -95
  377. package/dist/components/ui/inspector-theme.d.ts.map +0 -1
  378. package/dist/components/ui/inspector-theme.js +0 -82
  379. package/dist/components/ui/inspector-theme.js.map +0 -1
  380. package/dist/components/ui/load-more-button.js.map +0 -1
  381. package/dist/components/ui/menu-dropdown.js.map +0 -1
  382. package/dist/components/ui/skeleton.js.map +0 -1
  383. package/dist/components/ui/spinner.js.map +0 -1
  384. package/dist/components/ui/timestamp-tooltip.js.map +0 -1
  385. package/dist/components/workflow-trace-view.js.map +0 -1
  386. package/dist/components/workflow-traces/event-colors.js.map +0 -1
  387. package/dist/components/workflow-traces/trace-colors.js.map +0 -1
  388. package/dist/components/workflow-traces/trace-span-construction.js.map +0 -1
  389. package/dist/components/workflow-traces/trace-time-utils.js.map +0 -1
  390. package/dist/hooks/use-dark-mode.js.map +0 -1
  391. package/dist/index.js.map +0 -1
  392. package/dist/lib/event-analysis.js.map +0 -1
  393. package/dist/lib/event-materialization.js.map +0 -1
  394. package/dist/lib/hydration.js.map +0 -1
  395. package/dist/lib/stream-display.js.map +0 -1
  396. package/dist/lib/toast.js.map +0 -1
  397. package/dist/lib/trace-builder.js.map +0 -1
  398. package/dist/lib/utils.js.map +0 -1
  399. package/src/components/new-trace-viewer/detail-panel.tsx +0 -57
  400. package/src/components/new-trace-viewer/util/constants.ts +0 -0
  401. package/src/components/sidebar/detail-card.tsx +0 -65
  402. package/src/components/ui/inspector-theme.ts +0 -110
@@ -10,7 +10,13 @@
10
10
  * of making separate API calls for each entity type.
11
11
  */
12
12
 
13
- import type { Event, StepStatus } from '@workflow/world';
13
+ import {
14
+ type Event,
15
+ isHookLifecycleEventType,
16
+ isStepEventType,
17
+ isWaitEventType,
18
+ type StepStatus,
19
+ } from '@workflow/world';
14
20
 
15
21
  // ---------------------------------------------------------------------------
16
22
  // Materialized entity types
@@ -60,18 +66,18 @@ export interface MaterializedEntities {
60
66
  }
61
67
 
62
68
  // ---------------------------------------------------------------------------
63
- // Helper: group events by correlationId prefix
69
+ // Helper: group events by correlationId
64
70
  // ---------------------------------------------------------------------------
65
71
 
66
72
  function groupByCorrelationId(
67
73
  events: Event[],
68
- prefixes: string[]
74
+ matchesEventType: (eventType: string) => boolean
69
75
  ): Map<string, Event[]> {
70
76
  const groups = new Map<string, Event[]>();
71
77
  for (const event of events) {
72
78
  const cid = event.correlationId;
73
79
  if (!cid) continue;
74
- if (!prefixes.some((p) => cid.startsWith(p))) continue;
80
+ if (!matchesEventType(event.eventType)) continue;
75
81
  const existing = groups.get(cid);
76
82
  if (existing) {
77
83
  existing.push(event);
@@ -82,6 +88,14 @@ function groupByCorrelationId(
82
88
  return groups;
83
89
  }
84
90
 
91
+ function getEventTimestamp(event: Event | undefined): Date | undefined {
92
+ const value = event?.occurredAt ?? event?.createdAt;
93
+ if (!value) return undefined;
94
+
95
+ const date = value instanceof Date ? value : new Date(value);
96
+ return Number.isNaN(date.getTime()) ? undefined : date;
97
+ }
98
+
85
99
  // ---------------------------------------------------------------------------
86
100
  // materializeSteps
87
101
  // ---------------------------------------------------------------------------
@@ -93,7 +107,7 @@ function groupByCorrelationId(
93
107
  * step_created event with no completion yet.
94
108
  */
95
109
  export function materializeSteps(events: Event[]): MaterializedStep[] {
96
- const groups = groupByCorrelationId(events, ['step_']);
110
+ const groups = groupByCorrelationId(events, isStepEventType);
97
111
  const steps: MaterializedStep[] = [];
98
112
 
99
113
  for (const [correlationId, stepEvents] of groups) {
@@ -104,31 +118,31 @@ export function materializeSteps(events: Event[]): MaterializedStep[] {
104
118
  let attempt = 0;
105
119
  let startedAt: Date | undefined;
106
120
  let completedAt: Date | undefined;
107
- let updatedAt = created.createdAt;
121
+ let updatedAt = getEventTimestamp(created) ?? created.createdAt;
108
122
 
109
123
  for (const e of stepEvents) {
110
124
  switch (e.eventType) {
111
125
  case 'step_started':
112
126
  status = 'running';
113
127
  attempt += 1;
114
- if (!startedAt) startedAt = e.createdAt;
128
+ if (!startedAt) startedAt = getEventTimestamp(e) ?? e.createdAt;
115
129
  completedAt = undefined;
116
- updatedAt = e.createdAt;
130
+ updatedAt = getEventTimestamp(e) ?? e.createdAt;
117
131
  break;
118
132
  case 'step_completed':
119
133
  status = 'completed';
120
- completedAt = e.createdAt;
121
- updatedAt = e.createdAt;
134
+ completedAt = getEventTimestamp(e) ?? e.createdAt;
135
+ updatedAt = getEventTimestamp(e) ?? e.createdAt;
122
136
  break;
123
137
  case 'step_failed':
124
138
  status = 'failed';
125
- completedAt = e.createdAt;
126
- updatedAt = e.createdAt;
139
+ completedAt = getEventTimestamp(e) ?? e.createdAt;
140
+ updatedAt = getEventTimestamp(e) ?? e.createdAt;
127
141
  break;
128
142
  case 'step_retrying':
129
143
  status = 'pending';
130
144
  completedAt = undefined;
131
- updatedAt = e.createdAt;
145
+ updatedAt = getEventTimestamp(e) ?? e.createdAt;
132
146
  break;
133
147
  }
134
148
  }
@@ -142,7 +156,7 @@ export function materializeSteps(events: Event[]): MaterializedStep[] {
142
156
  : correlationId,
143
157
  status,
144
158
  attempt,
145
- createdAt: created.createdAt,
159
+ createdAt: getEventTimestamp(created) ?? created.createdAt,
146
160
  startedAt,
147
161
  completedAt,
148
162
  updatedAt,
@@ -161,7 +175,7 @@ export function materializeSteps(events: Event[]): MaterializedStep[] {
161
175
  * Group hook_* events by correlationId and build Hook-like entities.
162
176
  */
163
177
  export function materializeHooks(events: Event[]): MaterializedHook[] {
164
- const groups = groupByCorrelationId(events, ['hook_']);
178
+ const groups = groupByCorrelationId(events, isHookLifecycleEventType);
165
179
  const hooks: MaterializedHook[] = [];
166
180
 
167
181
  for (const [correlationId, hookEvents] of groups) {
@@ -181,10 +195,10 @@ export function materializeHooks(events: Event[]): MaterializedHook[] {
181
195
  created.eventType === 'hook_created'
182
196
  ? created.eventData?.token
183
197
  : undefined,
184
- createdAt: created.createdAt,
198
+ createdAt: getEventTimestamp(created) ?? created.createdAt,
185
199
  receivedCount: receivedEvents.length,
186
- lastReceivedAt: lastReceived?.createdAt,
187
- disposedAt: disposed?.createdAt,
200
+ lastReceivedAt: getEventTimestamp(lastReceived),
201
+ disposedAt: getEventTimestamp(disposed),
188
202
  events: hookEvents,
189
203
  });
190
204
  }
@@ -200,7 +214,7 @@ export function materializeHooks(events: Event[]): MaterializedHook[] {
200
214
  * Group wait_* events by correlationId and build Wait-like entities.
201
215
  */
202
216
  export function materializeWaits(events: Event[]): MaterializedWait[] {
203
- const groups = groupByCorrelationId(events, ['wait_']);
217
+ const groups = groupByCorrelationId(events, isWaitEventType);
204
218
  const waits: MaterializedWait[] = [];
205
219
 
206
220
  for (const [correlationId, waitEvents] of groups) {
@@ -213,12 +227,12 @@ export function materializeWaits(events: Event[]): MaterializedWait[] {
213
227
  waitId: correlationId,
214
228
  runId: created.runId,
215
229
  status: completed ? 'completed' : 'waiting',
216
- createdAt: created.createdAt,
230
+ createdAt: getEventTimestamp(created) ?? created.createdAt,
217
231
  resumeAt:
218
232
  created.eventType === 'wait_created'
219
233
  ? created.eventData?.resumeAt
220
234
  : undefined,
221
- completedAt: completed?.createdAt,
235
+ completedAt: getEventTimestamp(completed),
222
236
  events: waitEvents,
223
237
  });
224
238
  }
@@ -0,0 +1,67 @@
1
+ import type { Event } from '@workflow/world';
2
+
3
+ const WORKFLOW_ULID_BODY = '[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}';
4
+
5
+ const STEP_ID_PATTERN = new RegExp(`^step_(${WORKFLOW_ULID_BODY})$`, 'i');
6
+ const WAIT_ID_PATTERN = new RegExp(`^wait_(${WORKFLOW_ULID_BODY})$`, 'i');
7
+ const HOOK_ID_PATTERN = new RegExp(`^hook_(${WORKFLOW_ULID_BODY})$`, 'i');
8
+ const EVENT_ID_PATTERN = new RegExp(`^evnt_(${WORKFLOW_ULID_BODY})$`, 'i');
9
+
10
+ const WORKFLOW_ID_PREFIX_PATTERN = /^(step_|wait_|hook_|evnt_|wrun_)/i;
11
+
12
+ export type ExactWorkflowSearchIdKind = 'step' | 'wait' | 'hook' | 'event';
13
+
14
+ export type ExactWorkflowSearchId = {
15
+ kind: ExactWorkflowSearchIdKind;
16
+ id: string;
17
+ };
18
+
19
+ export type ExactIdSearchResult =
20
+ | { status: 'ok'; events: Event[]; truncated?: boolean }
21
+ | { status: 'not_found' }
22
+ | { status: 'error'; message: string };
23
+
24
+ function matchPrefixedId(
25
+ pattern: RegExp,
26
+ prefix: 'step' | 'wait' | 'hook' | 'evnt',
27
+ kind: ExactWorkflowSearchIdKind,
28
+ query: string
29
+ ): ExactWorkflowSearchId | null {
30
+ const match = query.match(pattern);
31
+ if (!match) {
32
+ return null;
33
+ }
34
+ return { kind, id: `${prefix}_${match[1].toUpperCase()}` };
35
+ }
36
+
37
+ /**
38
+ * Returns a parsed workflow ID when `query` is a full step, wait, hook, or event ID.
39
+ * Partial IDs and run IDs (`wrun_`) are ignored. ULID bodies are matched case-insensitively
40
+ * and normalized to uppercase in the returned ID.
41
+ */
42
+ export function parseExactWorkflowSearchId(
43
+ query: string
44
+ ): ExactWorkflowSearchId | null {
45
+ const trimmed = query.trim();
46
+ if (!trimmed) {
47
+ return null;
48
+ }
49
+
50
+ return (
51
+ matchPrefixedId(STEP_ID_PATTERN, 'step', 'step', trimmed) ??
52
+ matchPrefixedId(WAIT_ID_PATTERN, 'wait', 'wait', trimmed) ??
53
+ matchPrefixedId(HOOK_ID_PATTERN, 'hook', 'hook', trimmed) ??
54
+ matchPrefixedId(EVENT_ID_PATTERN, 'evnt', 'event', trimmed)
55
+ );
56
+ }
57
+
58
+ /** True when input looks like the user is attempting an ID search (including partial). */
59
+ export function looksLikeWorkflowIdSearchInput(query: string): boolean {
60
+ const trimmed = query.trim();
61
+ if (!WORKFLOW_ID_PREFIX_PATTERN.test(trimmed)) {
62
+ return false;
63
+ }
64
+ // Distinguish IDs (contain digits) from event-type strings like step_started.
65
+ // Assumes workflow event types do not include digits in their names.
66
+ return /\d/.test(trimmed);
67
+ }
@@ -16,7 +16,7 @@ import {
16
16
  type Revivers,
17
17
  serializedInstanceToRef,
18
18
  } from '@workflow/core/serialization-format';
19
- import { EVENT_DATA_REF_FIELDS } from '@workflow/world';
19
+ import { getEventDataRefFields } from '@workflow/world';
20
20
 
21
21
  // Re-export types and utilities that consumers need
22
22
  export {
@@ -58,12 +58,60 @@ function base64ToArrayBuffer(base64: string): ArrayBuffer {
58
58
  // Web revivers (browser-safe, no Buffer dependency)
59
59
  // ---------------------------------------------------------------------------
60
60
 
61
+ /**
62
+ * Build a reviver for one of the built-in `Error` subclasses (e.g.
63
+ * `TypeError`, `RangeError`). The constructor for the named subclass is
64
+ * resolved off `globalThis` at call time so the produced instance has the
65
+ * correct prototype chain in the consumer realm. Falls back to a generic
66
+ * `Error` (with `name` set) if the global isn't available, which keeps the
67
+ * o11y UI rendering even on exotic browsers.
68
+ *
69
+ * `cause` is passed through `ErrorOptions` to the constructor when present,
70
+ * matching `getCommonRevivers` in `@workflow/core` so the resulting `cause`
71
+ * property has the same semantics (non-enumerable, set by the engine) as a
72
+ * freshly thrown Error in the consumer realm. The `'cause' in value` check
73
+ * preserves the distinction between "no cause" and "cause is undefined".
74
+ */
75
+ function makeWebErrorSubclassReviver(
76
+ name:
77
+ | 'EvalError'
78
+ | 'RangeError'
79
+ | 'ReferenceError'
80
+ | 'SyntaxError'
81
+ | 'TypeError'
82
+ | 'URIError'
83
+ ) {
84
+ return (value: { message: string; stack?: string; cause?: unknown }) => {
85
+ const opts = 'cause' in value ? { cause: value.cause } : undefined;
86
+ const Ctor = (globalThis as Record<string, any>)[name] as
87
+ | ErrorConstructor
88
+ | undefined;
89
+ let error: Error;
90
+ if (typeof Ctor === 'function') {
91
+ error = new Ctor(value.message, opts);
92
+ } else {
93
+ // Fallback path: no built-in subclass available (exotic env). Construct
94
+ // a plain Error with the right `name` and copy `cause` manually since
95
+ // the base Error constructor is what we actually called.
96
+ error = Object.assign(new Error(value.message, opts), { name });
97
+ }
98
+ if (value.stack !== undefined) error.stack = value.stack;
99
+ return error;
100
+ };
101
+ }
102
+
61
103
  /**
62
104
  * Get the web-specific revivers for hydrating serialized data.
63
105
  *
64
106
  * Uses `atob()` for base64 decoding (no Node.js Buffer dependency).
65
107
  * All types are revived as real instances (Date, Map, Set, URL,
66
108
  * URLSearchParams, Headers, Error, etc.).
109
+ *
110
+ * NOTE: this set must mirror the keys in `SerializableSpecial` (see
111
+ * `@workflow/core/serialization/types`). Any reducer key added on the
112
+ * serialization side that isn't covered here will cause `devalue.unflatten`
113
+ * to throw `Unknown type X`, which `hydrateResourceIO` swallows and
114
+ * surfaces as a "Failed to load resource details" banner in the o11y UI.
67
115
  */
68
116
  export function getWebRevivers(): Revivers {
69
117
  function reviveArrayBuffer(value: string): ArrayBuffer {
@@ -83,10 +131,120 @@ export function getWebRevivers(): Revivers {
83
131
  BigUint64Array: (value: string) =>
84
132
  new BigUint64Array(reviveArrayBuffer(value)),
85
133
  Date: (value) => new Date(value),
134
+
135
+ // Error family. The reducer side (see
136
+ // `packages/core/src/serialization/reducers/common.ts`) emits a tagged
137
+ // entry for each built-in Error subclass plus the workflow-specific
138
+ // `FatalError` / `RetryableError` / `HookConflictError` /
139
+ // `RuntimeDecryptionError` and `AggregateError`. Without
140
+ // matching revivers here, `devalue.unflatten` throws "Unknown type X"
141
+ // — which surfaces in the web o11y UI as "Failed to load resource
142
+ // details: Unknown type FatalError".
86
143
  Error: (value) => {
144
+ const opts = 'cause' in value ? { cause: value.cause } : undefined;
145
+ const error = new Error(value.message, opts);
146
+ error.name = value.name;
147
+ if (value.stack !== undefined) error.stack = value.stack;
148
+ return error;
149
+ },
150
+ EvalError: makeWebErrorSubclassReviver('EvalError'),
151
+ RangeError: makeWebErrorSubclassReviver('RangeError'),
152
+ ReferenceError: makeWebErrorSubclassReviver('ReferenceError'),
153
+ SyntaxError: makeWebErrorSubclassReviver('SyntaxError'),
154
+ TypeError: makeWebErrorSubclassReviver('TypeError'),
155
+ URIError: makeWebErrorSubclassReviver('URIError'),
156
+ AggregateError: (value) => {
157
+ const opts = 'cause' in value ? { cause: value.cause } : undefined;
158
+ const Ctor = (
159
+ globalThis as { AggregateError?: AggregateErrorConstructor }
160
+ ).AggregateError;
161
+ const error =
162
+ typeof Ctor === 'function'
163
+ ? new Ctor(value.errors, value.message, opts)
164
+ : Object.assign(new Error(value.message, opts), {
165
+ name: 'AggregateError',
166
+ errors: value.errors,
167
+ });
168
+ if (value.stack !== undefined) error.stack = value.stack;
169
+ return error;
170
+ },
171
+ // `FatalError` and `RetryableError` are not built-in browser globals,
172
+ // so we can't resolve a constructor from globalThis. The web o11y UI
173
+ // doesn't need `instanceof FatalError` to pass (no user code runs
174
+ // here) — it just needs `name`, `message`, `stack`, and any extra
175
+ // enumerable fields to render. Construct a plain `Error` with `name`
176
+ // set; ObjectInspector reads `constructor.name` for the displayed
177
+ // class label, but we don't have the real class, so we emit a tagged
178
+ // Error whose `name` field carries the class identity. This matches
179
+ // how the existing base `Error` reviver presents unknown subclasses.
180
+ FatalError: (value) => {
181
+ const opts = 'cause' in value ? { cause: value.cause } : undefined;
182
+ const error = new Error(value.message, opts);
183
+ error.name = 'FatalError';
184
+ if (value.stack !== undefined) error.stack = value.stack;
185
+ return error;
186
+ },
187
+ HookConflictError: (value) => {
188
+ const opts = 'cause' in value ? { cause: value.cause } : undefined;
189
+ const error = new Error(value.message, opts) as Error & {
190
+ token?: string;
191
+ conflictingRunId?: string;
192
+ };
193
+ error.name = 'HookConflictError';
194
+ error.token = value.token;
195
+ if (value.conflictingRunId !== undefined) {
196
+ error.conflictingRunId = value.conflictingRunId;
197
+ }
198
+ if (value.stack !== undefined) error.stack = value.stack;
199
+ return error;
200
+ },
201
+ RetryableError: (value) => {
202
+ const opts = 'cause' in value ? { cause: value.cause } : undefined;
203
+ const error = new Error(value.message, opts) as Error & {
204
+ retryAfter?: Date;
205
+ };
206
+ error.name = 'RetryableError';
207
+ if (value.stack !== undefined) error.stack = value.stack;
208
+ // `retryAfter` is serialized as an epoch ms number (see the runtime
209
+ // RetryableError reducer for the rationale around realm-safety).
210
+ // Rehydrate as a Date so o11y consumers can render it directly.
211
+ // Guard against payloads from older runtime versions that predate
212
+ // the field — without this check, `new Date(undefined)` would
213
+ // produce an Invalid Date rather than omitting the property.
214
+ if (value.retryAfter != null) {
215
+ error.retryAfter = new Date(value.retryAfter);
216
+ }
217
+ return error;
218
+ },
219
+ RuntimeDecryptionError: (value) => {
220
+ const opts = 'cause' in value ? { cause: value.cause } : undefined;
221
+ const error = new Error(value.message, opts) as Error & {
222
+ context?: unknown;
223
+ };
224
+ error.name = 'RuntimeDecryptionError';
225
+ if (value.context !== undefined) {
226
+ error.context = value.context;
227
+ }
228
+ if (value.stack !== undefined) error.stack = value.stack;
229
+ return error;
230
+ },
231
+ DOMException: (value) => {
232
+ // Modern browsers and Node 18+ expose `DOMException` on globalThis.
233
+ // `AbortController.abort()` with no argument synthesizes one as the
234
+ // signal's reason, so this is a common payload for any aborted step.
235
+ const G = globalThis as { DOMException?: typeof DOMException };
236
+ if (typeof G.DOMException === 'function') {
237
+ const e = new G.DOMException(value.message, value.name);
238
+ if (value.stack !== undefined) e.stack = value.stack;
239
+ if ('cause' in value) (e as { cause?: unknown }).cause = value.cause;
240
+ return e;
241
+ }
87
242
  const error = new Error(value.message);
88
243
  error.name = value.name;
89
- error.stack = value.stack;
244
+ if (value.stack !== undefined) error.stack = value.stack;
245
+ if ('cause' in value) {
246
+ (error as Error & { cause?: unknown }).cause = value.cause;
247
+ }
90
248
  return error;
91
249
  },
92
250
  Float32Array: (value: string) => new Float32Array(reviveArrayBuffer(value)),
@@ -140,7 +298,7 @@ export function getWebRevivers(): Revivers {
140
298
 
141
299
  // Web-specific overrides for class instances.
142
300
  // Create objects with a dynamically-named constructor so that
143
- // react-inspector shows the class name (it reads constructor.name).
301
+ // the data inspector shows the class name (it reads constructor.name).
144
302
  Class: (value) => `<class:${extractClassName(value.classId)}>`,
145
303
  Instance: (value) => {
146
304
  // Run instances are rendered as clickable RunRef badges
@@ -153,7 +311,7 @@ export function getWebRevivers(): Revivers {
153
311
  const props =
154
312
  data && typeof data === 'object' ? { ...data } : { value: data };
155
313
  // Create a constructor with the right name using computed property
156
- // so react-inspector's `object.constructor.name` shows the class name.
314
+ // so the data inspector's `object.constructor.name` shows the class name.
157
315
  // Must use `function` (not arrow) because arrow functions have no .prototype.
158
316
  // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype
159
317
  const ctor = { [className]: function () {} }[className]!;
@@ -288,7 +446,7 @@ function replaceEncryptedAndExpiredWithMarkers<T>(resource: T): T {
288
446
  if (result.eventData && typeof result.eventData === 'object') {
289
447
  const eventType =
290
448
  typeof result.eventType === 'string' ? result.eventType : '';
291
- const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];
449
+ const refKeys = getEventDataRefFields(eventType);
292
450
  const ed = { ...(result.eventData as Record<string, unknown>) };
293
451
  for (const key of refKeys) {
294
452
  if (key in ed) {
@@ -307,36 +465,56 @@ function replaceEncryptedAndExpiredWithMarkers<T>(resource: T): T {
307
465
  * When a key is provided, encrypted fields are decrypted before hydration.
308
466
  * This is the async version used when the user clicks "Decrypt" in the web UI.
309
467
  *
310
- * Handles both top-level fields (input, output, metadata) and nested
311
- * eventData subfields per `EVENT_DATA_REF_FIELDS` from `@workflow/world` for that event type.
468
+ * Handles both top-level fields (input, output, metadata) and nested eventData
469
+ * payload fields for that event type.
312
470
  */
313
471
  export async function hydrateResourceIOWithKey<T>(
314
472
  resource: T,
315
473
  key: Uint8Array
474
+ ): Promise<T> {
475
+ return hydrateResourceIOAsync(resource, key);
476
+ }
477
+
478
+ /**
479
+ * Async hydration for web display.
480
+ *
481
+ * This follows the same resource-field mapping as {@link hydrateResourceIO},
482
+ * but can also inflate compressed browser payloads through the registered
483
+ * zstd WASM decoder. When a key is provided, encrypted fields are decrypted
484
+ * first and then inflated/hydrated.
485
+ */
486
+ export async function hydrateResourceIOAsync<T>(
487
+ resource: T,
488
+ key?: Uint8Array
316
489
  ): Promise<T> {
317
490
  const { hydrateDataWithKey } = await import(
318
491
  '@workflow/core/serialization-format'
319
492
  );
320
- const { importKey } = await import('@workflow/core/encryption');
321
- const cryptoKey = await importKey(key);
493
+ // Payloads may be zstd-compressed (the Web DecompressionStream has no zstd);
494
+ // register the WASM-backed browser decoder before hydrating. Idempotent and
495
+ // lazy — the WASM is only compiled when a zstd payload is actually decoded.
496
+ const { ensureZstdDecoderRegistered } = await import(
497
+ './zstd-browser-decoder.js'
498
+ );
499
+ ensureZstdDecoderRegistered();
500
+ const cryptoKey = key
501
+ ? await import('@workflow/core/encryption').then(({ importKey }) =>
502
+ importKey(key)
503
+ )
504
+ : undefined;
322
505
  const revivers = getRevivers();
323
506
 
324
- /** Extract original encrypted bytes from a marker or raw Uint8Array, then decrypt + hydrate */
325
- async function decryptField(
326
- value: unknown,
327
- rev: Revivers,
328
- k: Awaited<ReturnType<typeof importKey>>
329
- ): Promise<unknown> {
507
+ async function hydrateField(value: unknown): Promise<unknown> {
330
508
  // Already-hydrated: encrypted marker with stored bytes
331
509
  if (isEncryptedMarker(value)) {
332
510
  const raw = (value as any).__encryptedData as Uint8Array;
333
- return hydrateDataWithKey(raw, rev, k);
511
+ return cryptoKey ? hydrateDataWithKey(raw, revivers, cryptoKey) : value;
334
512
  }
335
- // Raw encrypted Uint8Array (not yet hydrated)
513
+ // Raw Uint8Array: may be encrypted, compressed, or plain devalue.
336
514
  if (value instanceof Uint8Array) {
337
- return hydrateDataWithKey(value, rev, k);
515
+ return hydrateDataWithKey(value, revivers, cryptoKey);
338
516
  }
339
- // Not encrypted — return as-is
517
+ // Not serialized — return as-is.
340
518
  return value;
341
519
  }
342
520
 
@@ -346,29 +524,25 @@ export async function hydrateResourceIOWithKey<T>(
346
524
  // Decrypt + hydrate top-level serialized fields (runs, steps, hooks)
347
525
  for (const field of ['input', 'output', 'metadata', 'error']) {
348
526
  if (field in result) {
349
- result[field] = await decryptField(result[field], revivers, cryptoKey);
527
+ result[field] = await hydrateField(result[field]);
350
528
  }
351
529
  }
352
530
 
353
- // Decrypt + hydrate eventData subfields (events)
531
+ // Hydrate eventData subfields (events)
354
532
  if (result.eventData && typeof result.eventData === 'object') {
355
533
  const eventType =
356
534
  typeof result.eventType === 'string' ? result.eventType : '';
357
- const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];
535
+ const refKeys = getEventDataRefFields(eventType);
358
536
  const eventData = { ...(result.eventData as Record<string, unknown>) };
359
537
  for (const field of refKeys) {
360
538
  if (field in eventData) {
361
- eventData[field] = await decryptField(
362
- eventData[field],
363
- revivers,
364
- cryptoKey
365
- );
539
+ eventData[field] = await hydrateField(eventData[field]);
366
540
  }
367
541
  }
368
542
  result.eventData = eventData;
369
543
  }
370
544
 
371
- return result as T;
545
+ return replaceEncryptedAndExpiredWithMarkers(result as T);
372
546
  }
373
547
 
374
548
  /**
@@ -387,7 +561,7 @@ export function hasEncryptedFields(resource: unknown): boolean {
387
561
 
388
562
  if (r.eventData && typeof r.eventData === 'object') {
389
563
  const eventType = typeof r.eventType === 'string' ? r.eventType : '';
390
- const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];
564
+ const refKeys = getEventDataRefFields(eventType);
391
565
  const ed = r.eventData as Record<string, unknown>;
392
566
  for (const key of refKeys) {
393
567
  if (key in ed && isEncryptedMarker(ed[key])) return true;
@@ -6,30 +6,54 @@
6
6
  * a fully-formed Trace ready for the trace viewer.
7
7
  */
8
8
 
9
- import type { Event, WorkflowRun } from '@workflow/world';
9
+ import {
10
+ type Event,
11
+ isHookLifecycleEventType,
12
+ isStepEventType,
13
+ isWaitEventType,
14
+ type WorkflowRun,
15
+ } from '@workflow/world';
10
16
  import type { Span } from '../components/trace-viewer/types';
11
17
  import {
18
+ getEventTimestamp,
12
19
  hookToSpan,
13
20
  runToSpan,
14
21
  stepToSpan,
15
- waitToSpan,
16
22
  WORKFLOW_LIBRARY,
23
+ waitToSpan,
17
24
  } from '../components/workflow-traces/trace-span-construction';
18
25
  import { otelTimeToMs } from '../components/workflow-traces/trace-time-utils';
19
26
 
20
- // ---------------------------------------------------------------------------
21
- // Event type classifiers
22
- // ---------------------------------------------------------------------------
23
-
24
- export const isStepEvent = (eventType: string) => eventType.startsWith('step_');
25
-
26
- export const isTimerEvent = (eventType: string) =>
27
- eventType === 'wait_created' || eventType === 'wait_completed';
27
+ /**
28
+ * Events that belong to the run root span rather than a child entity span.
29
+ * Mirrors the fallthrough logic in {@link groupEventsByCorrelation}: events
30
+ * without a correlationId (run lifecycle) plus correlated events that aren't
31
+ * step/timer/hook events (e.g. `attr_set`, whose correlationId is a dedup
32
+ * token rather than a child entity ID).
33
+ */
34
+ export const isRunLevelEvent = (event: Event): boolean =>
35
+ !event.correlationId ||
36
+ (!isWaitEventType(event.eventType) &&
37
+ !isHookLifecycleEventType(event.eventType) &&
38
+ !isStepEventType(event.eventType));
28
39
 
29
- export const isHookLifecycleEvent = (eventType: string) =>
30
- eventType === 'hook_received' ||
31
- eventType === 'hook_created' ||
32
- eventType === 'hook_disposed';
40
+ /**
41
+ * Filter the raw event list down to the events for a selected span.
42
+ * For the run root span this returns run-level events (see
43
+ * {@link isRunLevelEvent}); for child spans it returns the events
44
+ * correlated to that span's ID.
45
+ */
46
+ export function filterSpanRawEvents(
47
+ events: Event[],
48
+ resource: string | undefined,
49
+ spanId: string | undefined
50
+ ): Event[] {
51
+ if (resource === 'run') {
52
+ return events.filter(isRunLevelEvent);
53
+ }
54
+ if (!spanId) return [];
55
+ return events.filter((e) => e.correlationId === spanId);
56
+ }
33
57
 
34
58
  // ---------------------------------------------------------------------------
35
59
  // Event grouping
@@ -68,17 +92,17 @@ export function groupEventsByCorrelation(events: Event[]): GroupedEvents {
68
92
  continue;
69
93
  }
70
94
 
71
- if (isTimerEvent(event.eventType)) {
95
+ if (isWaitEventType(event.eventType)) {
72
96
  pushEvent(timerEvents, correlationId, event);
73
97
  continue;
74
98
  }
75
99
 
76
- if (isHookLifecycleEvent(event.eventType)) {
100
+ if (isHookLifecycleEventType(event.eventType)) {
77
101
  pushEvent(hookEvents, correlationId, event);
78
102
  continue;
79
103
  }
80
104
 
81
- if (isStepEvent(event.eventType)) {
105
+ if (isStepEventType(event.eventType)) {
82
106
  pushEvent(eventsByStepId, correlationId, event);
83
107
  continue;
84
108
  }
@@ -101,7 +125,7 @@ export function groupEventsByCorrelation(events: Event[]): GroupedEvents {
101
125
  function computeLatestKnownTime(events: Event[], run: WorkflowRun): Date {
102
126
  let latest = new Date(run.createdAt).getTime();
103
127
  for (const event of events) {
104
- const t = new Date(event.createdAt).getTime();
128
+ const t = (getEventTimestamp(event) ?? new Date(event.createdAt)).getTime();
105
129
  if (t > latest) latest = t;
106
130
  }
107
131
  return new Date(latest);
@@ -117,6 +141,7 @@ function buildSpans(
117
141
  // unknown territory. Even when the run is completed, we may not have loaded
118
142
  // all events yet, so always use the latest event we've actually seen.
119
143
  const childMaxEnd = latestKnownTime;
144
+ const runMaxEnd = run.completedAt ?? now;
120
145
 
121
146
  const stepSpans = Array.from(groupedEvents.eventsByStepId.values())
122
147
  .map((events) => stepToSpan(events, childMaxEnd))
@@ -127,7 +152,7 @@ function buildSpans(
127
152
  .filter((span): span is Span => span !== null);
128
153
 
129
154
  const waitSpans = Array.from(groupedEvents.timerEvents.values())
130
- .map((events) => waitToSpan(events, childMaxEnd))
155
+ .map((events) => waitToSpan(events, childMaxEnd, runMaxEnd))
131
156
  .filter((span): span is Span => span !== null);
132
157
 
133
158
  return {