@workflow/web-shared 5.0.0-beta.2 → 5.0.0-beta.21

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 (321) hide show
  1. package/dist/components/error-boundary.js +1 -1
  2. package/dist/components/event-list-view.d.ts +16 -1
  3. package/dist/components/event-list-view.d.ts.map +1 -1
  4. package/dist/components/event-list-view.js +196 -85
  5. package/dist/components/hook-actions.js +1 -1
  6. package/dist/components/index.d.ts +4 -0
  7. package/dist/components/index.d.ts.map +1 -1
  8. package/dist/components/index.js +5 -1
  9. package/dist/components/new-trace-viewer/components/copy-button.d.ts +9 -0
  10. package/dist/components/new-trace-viewer/components/copy-button.d.ts.map +1 -0
  11. package/dist/components/new-trace-viewer/components/copy-button.js +27 -0
  12. package/dist/components/new-trace-viewer/components/event-list.d.ts +10 -0
  13. package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -0
  14. package/dist/components/new-trace-viewer/components/event-list.js +46 -0
  15. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts +18 -0
  16. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
  17. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +54 -0
  18. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts +20 -0
  19. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
  20. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
  21. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts +25 -0
  22. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
  23. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +101 -0
  24. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts +20 -0
  25. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
  26. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
  27. package/dist/components/new-trace-viewer/components/span-markers.d.ts +46 -0
  28. package/dist/components/new-trace-viewer/components/span-markers.d.ts.map +1 -0
  29. package/dist/components/new-trace-viewer/components/span-markers.js +85 -0
  30. package/dist/components/new-trace-viewer/components/split-pane.d.ts +15 -0
  31. package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -0
  32. package/dist/components/new-trace-viewer/components/split-pane.js +105 -0
  33. package/dist/components/new-trace-viewer/components/timeline.d.ts +36 -0
  34. package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -0
  35. package/dist/components/new-trace-viewer/components/timeline.js +254 -0
  36. package/dist/components/new-trace-viewer/components/timeline.module.css +46 -0
  37. package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts +2 -0
  38. package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts.map +1 -0
  39. package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.js +19 -0
  40. package/dist/components/new-trace-viewer/components/use-row-window.d.ts +34 -0
  41. package/dist/components/new-trace-viewer/components/use-row-window.d.ts.map +1 -0
  42. package/dist/components/new-trace-viewer/components/use-row-window.js +107 -0
  43. package/dist/components/new-trace-viewer/context.d.ts +15 -0
  44. package/dist/components/new-trace-viewer/context.d.ts.map +1 -0
  45. package/dist/components/new-trace-viewer/context.js +47 -0
  46. package/dist/components/new-trace-viewer/icons.d.ts +6 -0
  47. package/dist/components/new-trace-viewer/icons.d.ts.map +1 -0
  48. package/dist/components/new-trace-viewer/icons.js +15 -0
  49. package/dist/components/new-trace-viewer/search.d.ts +19 -0
  50. package/dist/components/new-trace-viewer/search.d.ts.map +1 -0
  51. package/dist/components/new-trace-viewer/search.js +134 -0
  52. package/dist/components/new-trace-viewer/trace-viewer.d.ts +11 -0
  53. package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -0
  54. package/dist/components/new-trace-viewer/trace-viewer.js +462 -0
  55. package/dist/components/new-trace-viewer/types.d.ts +3 -0
  56. package/dist/components/new-trace-viewer/types.d.ts.map +1 -0
  57. package/dist/components/new-trace-viewer/types.js +2 -0
  58. package/dist/components/new-trace-viewer/utils.d.ts +61 -0
  59. package/dist/components/new-trace-viewer/utils.d.ts.map +1 -0
  60. package/dist/components/new-trace-viewer/utils.js +345 -0
  61. package/dist/components/run-trace-view.js +1 -1
  62. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
  63. package/dist/components/sidebar/attribute-panel.js +129 -102
  64. package/dist/components/sidebar/attributes-block.d.ts +28 -0
  65. package/dist/components/sidebar/attributes-block.d.ts.map +1 -0
  66. package/dist/components/sidebar/attributes-block.js +81 -0
  67. package/dist/components/sidebar/conversation-view.js +1 -1
  68. package/dist/components/sidebar/copyable-data-block.d.ts +1 -0
  69. package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
  70. package/dist/components/sidebar/copyable-data-block.js +16 -15
  71. package/dist/components/sidebar/detail-card.d.ts +5 -6
  72. package/dist/components/sidebar/detail-card.d.ts.map +1 -1
  73. package/dist/components/sidebar/detail-card.js +32 -16
  74. package/dist/components/sidebar/entity-detail-panel.d.ts +1 -3
  75. package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
  76. package/dist/components/sidebar/entity-detail-panel.js +17 -35
  77. package/dist/components/sidebar/events-list.d.ts +3 -1
  78. package/dist/components/sidebar/events-list.d.ts.map +1 -1
  79. package/dist/components/sidebar/events-list.js +36 -22
  80. package/dist/components/sidebar/resolve-hook-modal.js +1 -1
  81. package/dist/components/sidebar/sidebar-data-context.d.ts +29 -0
  82. package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -0
  83. package/dist/components/sidebar/sidebar-data-context.js +19 -0
  84. package/dist/components/sidebar/span-detail-merge.d.ts +16 -0
  85. package/dist/components/sidebar/span-detail-merge.d.ts.map +1 -0
  86. package/dist/components/sidebar/span-detail-merge.js +53 -0
  87. package/dist/components/stream-viewer.d.ts +1 -1
  88. package/dist/components/stream-viewer.d.ts.map +1 -1
  89. package/dist/components/stream-viewer.js +3 -27
  90. package/dist/components/trace-viewer/components/map.js +1 -1
  91. package/dist/components/trace-viewer/components/markers.js +1 -1
  92. package/dist/components/trace-viewer/components/node.d.ts.map +1 -1
  93. package/dist/components/trace-viewer/components/node.js +2 -1
  94. package/dist/components/trace-viewer/components/search-input.js +1 -1
  95. package/dist/components/trace-viewer/components/search.js +1 -1
  96. package/dist/components/trace-viewer/components/span-content.js +1 -1
  97. package/dist/components/trace-viewer/components/span-detail-panel.js +1 -1
  98. package/dist/components/trace-viewer/components/span-segments.js +1 -1
  99. package/dist/components/trace-viewer/components/span-strategies.js +1 -1
  100. package/dist/components/trace-viewer/components/ui.js +1 -1
  101. package/dist/components/trace-viewer/components/zoom-button.js +1 -1
  102. package/dist/components/trace-viewer/components/zoom-icons.js +1 -1
  103. package/dist/components/trace-viewer/context.js +1 -1
  104. package/dist/components/trace-viewer/index.js +1 -1
  105. package/dist/components/trace-viewer/trace-viewer.js +1 -1
  106. package/dist/components/trace-viewer/trace-viewer.module.css +4 -4
  107. package/dist/components/trace-viewer/types.js +1 -1
  108. package/dist/components/trace-viewer/util/constants.js +1 -1
  109. package/dist/components/trace-viewer/util/scrollbar-width.js +1 -1
  110. package/dist/components/trace-viewer/util/timing.d.ts +3 -3
  111. package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
  112. package/dist/components/trace-viewer/util/timing.js +8 -11
  113. package/dist/components/trace-viewer/util/tree.js +1 -1
  114. package/dist/components/trace-viewer/util/use-immediate-style.js +1 -1
  115. package/dist/components/trace-viewer/util/use-streaming-spans.js +1 -1
  116. package/dist/components/trace-viewer/util/use-trackpad-zoom.js +1 -1
  117. package/dist/components/trace-viewer/worker.js +1 -1
  118. package/dist/components/trace-viewer-new.d.ts +14 -0
  119. package/dist/components/trace-viewer-new.d.ts.map +1 -0
  120. package/dist/components/trace-viewer-new.js +21 -0
  121. package/dist/components/ui/alert.js +1 -1
  122. package/dist/components/ui/button.d.ts +10 -0
  123. package/dist/components/ui/button.d.ts.map +1 -0
  124. package/dist/components/ui/button.js +46 -0
  125. package/dist/components/ui/card.js +1 -1
  126. package/dist/components/ui/context-card.d.ts +47 -0
  127. package/dist/components/ui/context-card.d.ts.map +1 -0
  128. package/dist/components/ui/context-card.js +471 -0
  129. package/dist/components/ui/data-inspector.d.ts +22 -0
  130. package/dist/components/ui/data-inspector.d.ts.map +1 -1
  131. package/dist/components/ui/data-inspector.js +103 -13
  132. package/dist/components/ui/decrypt-button.js +1 -1
  133. package/dist/components/ui/error-card.js +1 -1
  134. package/dist/components/ui/error-stack-block.d.ts +17 -10
  135. package/dist/components/ui/error-stack-block.d.ts.map +1 -1
  136. package/dist/components/ui/error-stack-block.js +49 -30
  137. package/dist/components/ui/icon-button.d.ts +19 -0
  138. package/dist/components/ui/icon-button.d.ts.map +1 -0
  139. package/dist/components/ui/icon-button.js +29 -0
  140. package/dist/components/ui/inspector-theme.d.ts +9 -10
  141. package/dist/components/ui/inspector-theme.d.ts.map +1 -1
  142. package/dist/components/ui/inspector-theme.js +39 -72
  143. package/dist/components/ui/kbd.d.ts +6 -0
  144. package/dist/components/ui/kbd.d.ts.map +1 -0
  145. package/dist/components/ui/kbd.js +6 -0
  146. package/dist/components/ui/load-more-button.js +1 -1
  147. package/dist/components/ui/menu-dropdown.js +1 -1
  148. package/dist/components/ui/skeleton.js +1 -1
  149. package/dist/components/ui/spinner.js +1 -1
  150. package/dist/components/ui/timestamp-tooltip.d.ts +34 -1
  151. package/dist/components/ui/timestamp-tooltip.d.ts.map +1 -1
  152. package/dist/components/ui/timestamp-tooltip.js +80 -132
  153. package/dist/components/ui/tooltip.d.ts +10 -0
  154. package/dist/components/ui/tooltip.d.ts.map +1 -0
  155. package/dist/components/ui/tooltip.js +12 -0
  156. package/dist/components/workflow-trace-view.d.ts +1 -3
  157. package/dist/components/workflow-trace-view.d.ts.map +1 -1
  158. package/dist/components/workflow-trace-view.js +11 -13
  159. package/dist/components/workflow-traces/event-colors.d.ts +1 -0
  160. package/dist/components/workflow-traces/event-colors.d.ts.map +1 -1
  161. package/dist/components/workflow-traces/event-colors.js +12 -1
  162. package/dist/components/workflow-traces/trace-colors.js +1 -1
  163. package/dist/components/workflow-traces/trace-span-construction.d.ts +2 -2
  164. package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
  165. package/dist/components/workflow-traces/trace-span-construction.js +19 -5
  166. package/dist/components/workflow-traces/trace-time-utils.js +1 -1
  167. package/dist/hooks/use-dark-mode.js +1 -1
  168. package/dist/hooks/use-intersection-observer.d.ts +17 -0
  169. package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
  170. package/dist/hooks/use-intersection-observer.js +29 -0
  171. package/dist/hooks/use-load-more-on-scroll.d.ts +21 -0
  172. package/dist/hooks/use-load-more-on-scroll.d.ts.map +1 -0
  173. package/dist/hooks/use-load-more-on-scroll.js +28 -0
  174. package/dist/hooks/use-reduced-motion.d.ts +10 -0
  175. package/dist/hooks/use-reduced-motion.d.ts.map +1 -0
  176. package/dist/hooks/use-reduced-motion.js +29 -0
  177. package/dist/index.d.ts +3 -1
  178. package/dist/index.d.ts.map +1 -1
  179. package/dist/index.js +3 -2
  180. package/dist/lib/event-analysis.js +1 -1
  181. package/dist/lib/event-materialization.js +1 -1
  182. package/dist/lib/exact-event-search-id.d.ts +25 -0
  183. package/dist/lib/exact-event-search-id.d.ts.map +1 -0
  184. package/dist/lib/exact-event-search-id.js +39 -0
  185. package/dist/lib/hydration.d.ts +6 -0
  186. package/dist/lib/hydration.d.ts.map +1 -1
  187. package/dist/lib/hydration.js +154 -2
  188. package/dist/lib/stream-display.d.ts +18 -0
  189. package/dist/lib/stream-display.d.ts.map +1 -0
  190. package/dist/lib/stream-display.js +30 -0
  191. package/dist/lib/toast.js +1 -1
  192. package/dist/lib/trace-builder.d.ts +15 -0
  193. package/dist/lib/trace-builder.d.ts.map +1 -1
  194. package/dist/lib/trace-builder.js +29 -3
  195. package/dist/lib/utils.d.ts +20 -9
  196. package/dist/lib/utils.d.ts.map +1 -1
  197. package/dist/lib/utils.js +74 -31
  198. package/dist/lib/zstd-browser-decoder.d.ts +7 -0
  199. package/dist/lib/zstd-browser-decoder.d.ts.map +1 -0
  200. package/dist/lib/zstd-browser-decoder.js +41 -0
  201. package/dist/styles.css +484 -1
  202. package/package.json +10 -5
  203. package/src/components/event-list-view.tsx +279 -104
  204. package/src/components/index.ts +7 -0
  205. package/src/components/new-trace-viewer/components/copy-button.tsx +68 -0
  206. package/src/components/new-trace-viewer/components/event-list.tsx +136 -0
  207. package/src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts +114 -0
  208. package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +157 -0
  209. package/src/components/new-trace-viewer/components/middle-truncate/truncate.ts +132 -0
  210. package/src/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.ts +167 -0
  211. package/src/components/new-trace-viewer/components/span-markers.tsx +173 -0
  212. package/src/components/new-trace-viewer/components/split-pane.tsx +198 -0
  213. package/src/components/new-trace-viewer/components/timeline.module.css +46 -0
  214. package/src/components/new-trace-viewer/components/timeline.tsx +744 -0
  215. package/src/components/new-trace-viewer/components/trace-viewer-skeleton.tsx +94 -0
  216. package/src/components/new-trace-viewer/components/use-row-window.ts +140 -0
  217. package/src/components/new-trace-viewer/context.tsx +90 -0
  218. package/src/components/new-trace-viewer/icons.tsx +79 -0
  219. package/src/components/new-trace-viewer/search.ts +178 -0
  220. package/src/components/new-trace-viewer/trace-viewer.tsx +843 -0
  221. package/src/components/new-trace-viewer/types.ts +2 -0
  222. package/src/components/new-trace-viewer/utils.test.ts +182 -0
  223. package/src/components/new-trace-viewer/utils.ts +519 -0
  224. package/src/components/sidebar/attribute-panel.tsx +194 -240
  225. package/src/components/sidebar/attributes-block.tsx +173 -0
  226. package/src/components/sidebar/copyable-data-block.tsx +49 -27
  227. package/src/components/sidebar/detail-card.tsx +119 -59
  228. package/src/components/sidebar/entity-detail-panel.tsx +55 -111
  229. package/src/components/sidebar/events-list.tsx +85 -96
  230. package/src/components/sidebar/sidebar-data-context.tsx +62 -0
  231. package/src/components/sidebar/span-detail-merge.ts +65 -0
  232. package/src/components/stream-viewer.tsx +18 -40
  233. package/src/components/trace-viewer/components/node.tsx +3 -2
  234. package/src/components/trace-viewer/trace-viewer.module.css +4 -4
  235. package/src/components/trace-viewer/util/timing.ts +7 -11
  236. package/src/components/trace-viewer-new.tsx +55 -0
  237. package/src/components/ui/button.tsx +68 -0
  238. package/src/components/ui/context-card.tsx +784 -0
  239. package/src/components/ui/data-inspector.tsx +244 -22
  240. package/src/components/ui/error-stack-block.tsx +84 -55
  241. package/src/components/ui/icon-button.tsx +53 -0
  242. package/src/components/ui/inspector-theme.ts +39 -81
  243. package/src/components/ui/kbd.tsx +21 -0
  244. package/src/components/ui/timestamp-tooltip.tsx +132 -194
  245. package/src/components/ui/tooltip.tsx +47 -0
  246. package/src/components/workflow-trace-view.tsx +19 -15
  247. package/src/components/workflow-traces/event-colors.ts +12 -0
  248. package/src/components/workflow-traces/trace-span-construction.ts +24 -5
  249. package/src/hooks/use-intersection-observer.ts +57 -0
  250. package/src/hooks/use-load-more-on-scroll.ts +49 -0
  251. package/src/hooks/use-reduced-motion.ts +34 -0
  252. package/src/index.ts +9 -0
  253. package/src/lib/exact-event-search-id.ts +67 -0
  254. package/src/lib/hydration.ts +166 -1
  255. package/src/lib/stream-display.ts +48 -0
  256. package/src/lib/trace-builder.ts +34 -2
  257. package/src/lib/utils.ts +83 -31
  258. package/src/lib/zstd-browser-decoder.ts +42 -0
  259. package/src/styles.css +484 -1
  260. package/dist/components/error-boundary.js.map +0 -1
  261. package/dist/components/event-list-view.js.map +0 -1
  262. package/dist/components/hook-actions.js.map +0 -1
  263. package/dist/components/index.js.map +0 -1
  264. package/dist/components/run-trace-view.js.map +0 -1
  265. package/dist/components/sidebar/attribute-panel.js.map +0 -1
  266. package/dist/components/sidebar/conversation-view.js.map +0 -1
  267. package/dist/components/sidebar/copyable-data-block.js.map +0 -1
  268. package/dist/components/sidebar/detail-card.js.map +0 -1
  269. package/dist/components/sidebar/entity-detail-panel.js.map +0 -1
  270. package/dist/components/sidebar/events-list.js.map +0 -1
  271. package/dist/components/sidebar/resolve-hook-modal.js.map +0 -1
  272. package/dist/components/stream-viewer.js.map +0 -1
  273. package/dist/components/trace-viewer/components/map.js.map +0 -1
  274. package/dist/components/trace-viewer/components/markers.js.map +0 -1
  275. package/dist/components/trace-viewer/components/node.js.map +0 -1
  276. package/dist/components/trace-viewer/components/search-input.js.map +0 -1
  277. package/dist/components/trace-viewer/components/search.js.map +0 -1
  278. package/dist/components/trace-viewer/components/span-content.js.map +0 -1
  279. package/dist/components/trace-viewer/components/span-detail-panel.js.map +0 -1
  280. package/dist/components/trace-viewer/components/span-segments.js.map +0 -1
  281. package/dist/components/trace-viewer/components/span-strategies.js.map +0 -1
  282. package/dist/components/trace-viewer/components/ui.js.map +0 -1
  283. package/dist/components/trace-viewer/components/zoom-button.js.map +0 -1
  284. package/dist/components/trace-viewer/components/zoom-icons.js.map +0 -1
  285. package/dist/components/trace-viewer/context.js.map +0 -1
  286. package/dist/components/trace-viewer/index.js.map +0 -1
  287. package/dist/components/trace-viewer/trace-viewer.js.map +0 -1
  288. package/dist/components/trace-viewer/types.js.map +0 -1
  289. package/dist/components/trace-viewer/util/constants.js.map +0 -1
  290. package/dist/components/trace-viewer/util/scrollbar-width.js.map +0 -1
  291. package/dist/components/trace-viewer/util/timing.js.map +0 -1
  292. package/dist/components/trace-viewer/util/tree.js.map +0 -1
  293. package/dist/components/trace-viewer/util/use-immediate-style.js.map +0 -1
  294. package/dist/components/trace-viewer/util/use-streaming-spans.js.map +0 -1
  295. package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
  296. package/dist/components/trace-viewer/worker.js.map +0 -1
  297. package/dist/components/ui/alert.js.map +0 -1
  298. package/dist/components/ui/card.js.map +0 -1
  299. package/dist/components/ui/data-inspector.js.map +0 -1
  300. package/dist/components/ui/decrypt-button.js.map +0 -1
  301. package/dist/components/ui/error-card.js.map +0 -1
  302. package/dist/components/ui/error-stack-block.js.map +0 -1
  303. package/dist/components/ui/inspector-theme.js.map +0 -1
  304. package/dist/components/ui/load-more-button.js.map +0 -1
  305. package/dist/components/ui/menu-dropdown.js.map +0 -1
  306. package/dist/components/ui/skeleton.js.map +0 -1
  307. package/dist/components/ui/spinner.js.map +0 -1
  308. package/dist/components/ui/timestamp-tooltip.js.map +0 -1
  309. package/dist/components/workflow-trace-view.js.map +0 -1
  310. package/dist/components/workflow-traces/event-colors.js.map +0 -1
  311. package/dist/components/workflow-traces/trace-colors.js.map +0 -1
  312. package/dist/components/workflow-traces/trace-span-construction.js.map +0 -1
  313. package/dist/components/workflow-traces/trace-time-utils.js.map +0 -1
  314. package/dist/hooks/use-dark-mode.js.map +0 -1
  315. package/dist/index.js.map +0 -1
  316. package/dist/lib/event-analysis.js.map +0 -1
  317. package/dist/lib/event-materialization.js.map +0 -1
  318. package/dist/lib/hydration.js.map +0 -1
  319. package/dist/lib/toast.js.map +0 -1
  320. package/dist/lib/trace-builder.js.map +0 -1
  321. package/dist/lib/utils.js.map +0 -1
@@ -12,8 +12,8 @@ import {
12
12
  hookToSpan,
13
13
  runToSpan,
14
14
  stepToSpan,
15
- waitToSpan,
16
15
  WORKFLOW_LIBRARY,
16
+ waitToSpan,
17
17
  } from '../components/workflow-traces/trace-span-construction';
18
18
  import { otelTimeToMs } from '../components/workflow-traces/trace-time-utils';
19
19
 
@@ -31,6 +31,37 @@ export const isHookLifecycleEvent = (eventType: string) =>
31
31
  eventType === 'hook_created' ||
32
32
  eventType === 'hook_disposed';
33
33
 
34
+ /**
35
+ * Events that belong to the run root span rather than a child entity span.
36
+ * Mirrors the fallthrough logic in {@link groupEventsByCorrelation}: events
37
+ * without a correlationId (run lifecycle) plus correlated events that aren't
38
+ * step/timer/hook events (e.g. `attr_set`, whose correlationId is a dedup
39
+ * token rather than a child entity ID).
40
+ */
41
+ export const isRunLevelEvent = (event: Event): boolean =>
42
+ !event.correlationId ||
43
+ (!isTimerEvent(event.eventType) &&
44
+ !isHookLifecycleEvent(event.eventType) &&
45
+ !isStepEvent(event.eventType));
46
+
47
+ /**
48
+ * Filter the raw event list down to the events for a selected span.
49
+ * For the run root span this returns run-level events (see
50
+ * {@link isRunLevelEvent}); for child spans it returns the events
51
+ * correlated to that span's ID.
52
+ */
53
+ export function filterSpanRawEvents(
54
+ events: Event[],
55
+ resource: string | undefined,
56
+ spanId: string | undefined
57
+ ): Event[] {
58
+ if (resource === 'run') {
59
+ return events.filter(isRunLevelEvent);
60
+ }
61
+ if (!spanId) return [];
62
+ return events.filter((e) => e.correlationId === spanId);
63
+ }
64
+
34
65
  // ---------------------------------------------------------------------------
35
66
  // Event grouping
36
67
  // ---------------------------------------------------------------------------
@@ -117,6 +148,7 @@ function buildSpans(
117
148
  // unknown territory. Even when the run is completed, we may not have loaded
118
149
  // all events yet, so always use the latest event we've actually seen.
119
150
  const childMaxEnd = latestKnownTime;
151
+ const runMaxEnd = run.completedAt ?? now;
120
152
 
121
153
  const stepSpans = Array.from(groupedEvents.eventsByStepId.values())
122
154
  .map((events) => stepToSpan(events, childMaxEnd))
@@ -127,7 +159,7 @@ function buildSpans(
127
159
  .filter((span): span is Span => span !== null);
128
160
 
129
161
  const waitSpans = Array.from(groupedEvents.timerEvents.values())
130
- .map((events) => waitToSpan(events, childMaxEnd))
162
+ .map((events) => waitToSpan(events, childMaxEnd, runMaxEnd))
131
163
  .filter((span): span is Span => span !== null);
132
164
 
133
165
  return {
package/src/lib/utils.ts CHANGED
@@ -7,10 +7,6 @@ export function cn(...inputs: ClassValue[]) {
7
7
  return twMerge(clsx(inputs));
8
8
  }
9
9
 
10
- const durationFormatter = new Intl.NumberFormat(undefined, {
11
- maximumFractionDigits: 2,
12
- });
13
-
14
10
  const MS_IN_SECOND = 1000;
15
11
  const MS_IN_MINUTE = 60 * MS_IN_SECOND;
16
12
  const MS_IN_HOUR = 60 * MS_IN_MINUTE;
@@ -20,52 +16,53 @@ const MS_IN_DAY = 24 * MS_IN_HOUR;
20
16
  * Formats a duration in milliseconds to a human-readable string.
21
17
  *
22
18
  * @param ms - Duration in milliseconds
23
- * @param compact - If true, returns a single-unit format (e.g., "45s", "2.5m").
24
- * If false (default), returns multi-part format (e.g., "1h 30m", "2d 5h").
19
+ * @param compact - If true, returns a compact format (e.g., "380ms", "2m 30s").
20
+ * If false (default), returns multi-part format (e.g., "1m 13s", "2d 5h 3m 12s").
25
21
  *
26
- * Compact format:
27
- * - < 1s: shows milliseconds (e.g., "500ms")
22
+ * Compact format (timeline markers):
23
+ * - < 1s: shows milliseconds (e.g., "380ms")
28
24
  * - < 1m: shows seconds (e.g., "45s")
29
- * - < 1h: shows minutes (e.g., "45m")
30
- * - >= 1h: shows hours (e.g., "2.5h")
25
+ * - < 1h: shows minutes and seconds (e.g., "2m 30s")
26
+ * - >= 1h: shows hours and minutes (e.g., "2h 30m")
31
27
  *
32
28
  * Full format:
33
- * - < 1s: shows milliseconds (e.g., "500ms")
34
- * - < 1m: shows seconds (e.g., "45.5s")
35
- * - >= 1m: shows human-readable format (e.g., "1h 30m", "2d 5h")
29
+ * - < 1s: shows milliseconds (e.g., "380ms")
30
+ * - < 1m: shows seconds (e.g., "45s")
31
+ * - >= 1m: shows decomposed format with whole seconds (e.g., "1m 13s", "2m 13s")
36
32
  */
37
33
  export function formatDuration(ms: number, compact = false): string {
38
34
  if (ms === 0) {
39
- return '0';
35
+ return '0s';
40
36
  }
41
37
 
42
- // For durations less than 1 second, show milliseconds
43
38
  if (ms < MS_IN_SECOND) {
44
- return `${durationFormatter.format(ms)}ms`;
39
+ const roundedMs = Math.round(ms);
40
+ return roundedMs < MS_IN_SECOND ? `${roundedMs}ms` : '1s';
45
41
  }
46
42
 
47
- // For durations less than 1 minute, show seconds
48
- if (ms < MS_IN_MINUTE) {
49
- return `${durationFormatter.format(ms / MS_IN_SECOND)}s`;
43
+ const roundedMs = Math.round(ms / MS_IN_SECOND) * MS_IN_SECOND;
44
+
45
+ if (roundedMs < MS_IN_MINUTE) {
46
+ return `${Math.floor(roundedMs / MS_IN_SECOND)}s`;
50
47
  }
51
48
 
52
49
  // Compact format: multi-unit without decimals (e.g. "8m 20s", "2h 30m")
53
50
  if (compact) {
54
- if (ms < MS_IN_HOUR) {
55
- const m = Math.floor(ms / MS_IN_MINUTE);
56
- const s = Math.floor((ms % MS_IN_MINUTE) / MS_IN_SECOND);
51
+ if (roundedMs < MS_IN_HOUR) {
52
+ const m = Math.floor(roundedMs / MS_IN_MINUTE);
53
+ const s = Math.floor((roundedMs % MS_IN_MINUTE) / MS_IN_SECOND);
57
54
  return s > 0 ? `${m}m ${s}s` : `${m}m`;
58
55
  }
59
- const h = Math.floor(ms / MS_IN_HOUR);
60
- const m = Math.floor((ms % MS_IN_HOUR) / MS_IN_MINUTE);
56
+ const h = Math.floor(roundedMs / MS_IN_HOUR);
57
+ const m = Math.floor((roundedMs % MS_IN_HOUR) / MS_IN_MINUTE);
61
58
  return m > 0 ? `${h}h ${m}m` : `${h}h`;
62
59
  }
63
60
 
64
- // Full format: human-readable multi-part
65
- const days = Math.floor(ms / MS_IN_DAY);
66
- const hours = Math.floor((ms % MS_IN_DAY) / MS_IN_HOUR);
67
- const minutes = Math.floor((ms % MS_IN_HOUR) / MS_IN_MINUTE);
68
- const seconds = Math.floor((ms % MS_IN_MINUTE) / MS_IN_SECOND);
61
+ // Full format: decompose into larger units + whole seconds.
62
+ const days = Math.floor(roundedMs / MS_IN_DAY);
63
+ const hours = Math.floor((roundedMs % MS_IN_DAY) / MS_IN_HOUR);
64
+ const minutes = Math.floor((roundedMs % MS_IN_HOUR) / MS_IN_MINUTE);
65
+ const seconds = Math.floor((roundedMs % MS_IN_MINUTE) / MS_IN_SECOND);
69
66
 
70
67
  const parts: string[] = [];
71
68
 
@@ -78,9 +75,64 @@ export function formatDuration(ms: number, compact = false): string {
78
75
  if (minutes > 0) {
79
76
  parts.push(`${minutes}m`);
80
77
  }
81
- if (hours <= 1 && (seconds > 0 || parts.length === 0)) {
82
- parts.push(`${seconds}s`);
78
+ parts.push(`${seconds}s`);
79
+
80
+ return parts.join(' ');
81
+ }
82
+
83
+ // Locale-aware formatter that always renders exactly two fraction digits.
84
+ // Used for the seconds component of precise durations so values are never
85
+ // snapped to a whole second (and thousands separators stay correct).
86
+ const preciseSecondsFormatter = new Intl.NumberFormat(undefined, {
87
+ minimumFractionDigits: 2,
88
+ maximumFractionDigits: 2,
89
+ });
90
+
91
+ /**
92
+ * Formats a duration in milliseconds without snapping to whole seconds.
93
+ *
94
+ * Unlike {@link formatDuration}, this never rounds a sub-minute value up to
95
+ * the next whole second (e.g. 1626ms renders as "1.63s", not "2s").
96
+ *
97
+ * - < 1s: shows whole milliseconds (e.g. "626ms")
98
+ * - 1s – 1m: shows seconds with two decimals (e.g. "1.63s", "45.20s")
99
+ * - >= 1m: decomposes into d/h/m with two-decimal seconds (e.g. "1m 13.45s")
100
+ */
101
+ export function formatDurationPrecise(ms: number): string {
102
+ if (ms === 0) {
103
+ return '0s';
104
+ }
105
+
106
+ if (ms < MS_IN_SECOND) {
107
+ const roundedMs = Math.round(ms);
108
+ if (roundedMs < MS_IN_SECOND) {
109
+ return `${roundedMs}ms`;
110
+ }
111
+ }
112
+
113
+ const normalizedMs = Math.round(ms / 10) * 10;
114
+
115
+ if (normalizedMs < MS_IN_MINUTE) {
116
+ return `${preciseSecondsFormatter.format(normalizedMs / MS_IN_SECOND)}s`;
117
+ }
118
+
119
+ const days = Math.floor(normalizedMs / MS_IN_DAY);
120
+ const hours = Math.floor((normalizedMs % MS_IN_DAY) / MS_IN_HOUR);
121
+ const minutes = Math.floor((normalizedMs % MS_IN_HOUR) / MS_IN_MINUTE);
122
+ const seconds = (normalizedMs % MS_IN_MINUTE) / MS_IN_SECOND;
123
+
124
+ const parts: string[] = [];
125
+
126
+ if (days > 0) {
127
+ parts.push(`${days}d`);
128
+ }
129
+ if (hours > 0) {
130
+ parts.push(`${hours}h`);
131
+ }
132
+ if (minutes > 0) {
133
+ parts.push(`${minutes}m`);
83
134
  }
135
+ parts.push(`${preciseSecondsFormatter.format(seconds)}s`);
84
136
 
85
137
  return parts.join(' ');
86
138
  }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Browser zstd decoder for the o11y read path.
3
+ *
4
+ * The Web `DecompressionStream` has no zstd support, so `@workflow/core`'s
5
+ * `hydrateDataWithKey` delegates zstd inflation to a decoder registered via
6
+ * `registerZstdDecoder`. This module supplies that decoder, backed by the
7
+ * `@tootallnate/zstd-wasm` single-file WASM decoder.
8
+ *
9
+ * The package leaves WASM sourcing to the caller; we resolve the shipped
10
+ * `zstd.wasm` as a bundler asset (`new URL(..., import.meta.url)`, the same
11
+ * pattern the trace-viewer Worker uses) and compile it once, lazily — the
12
+ * WASM is fetched only the first time a zstd payload is actually decoded.
13
+ */
14
+ import { registerZstdDecoder } from '@workflow/core/serialization-format';
15
+
16
+ let registered = false;
17
+ let modulePromise: Promise<WebAssembly.Module> | undefined;
18
+
19
+ function loadWasmModule(): Promise<WebAssembly.Module> {
20
+ if (!modulePromise) {
21
+ const url = new URL('@tootallnate/zstd-wasm/zstd.wasm', import.meta.url);
22
+ modulePromise = fetch(url)
23
+ .then((res) => res.arrayBuffer())
24
+ .then((bytes) => WebAssembly.compile(bytes));
25
+ }
26
+ return modulePromise;
27
+ }
28
+
29
+ /**
30
+ * Register the browser zstd decoder with `@workflow/core` (idempotent).
31
+ * Call this before hydrating payloads that may be zstd-compressed; the
32
+ * actual WASM compile + decode happens lazily on first use.
33
+ */
34
+ export function ensureZstdDecoderRegistered(): void {
35
+ if (registered) return;
36
+ registered = true;
37
+ registerZstdDecoder(async (payload) => {
38
+ const { decompressBytes } = await import('@tootallnate/zstd-wasm');
39
+ const wasmModule = await loadWasmModule();
40
+ return decompressBytes(wasmModule, payload);
41
+ });
42
+ }