@principal-ai/subsystems-react 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (496) hide show
  1. package/README.md +93 -0
  2. package/dist/components/ConfigurationSelector.d.ts +35 -0
  3. package/dist/components/ConfigurationSelector.d.ts.map +1 -0
  4. package/dist/components/ConfigurationSelector.js +63 -0
  5. package/dist/components/ConfigurationSelector.js.map +1 -0
  6. package/dist/components/GraphRenderer.d.ts +295 -0
  7. package/dist/components/GraphRenderer.d.ts.map +1 -0
  8. package/dist/components/GraphRenderer.js +2008 -0
  9. package/dist/components/GraphRenderer.js.map +1 -0
  10. package/dist/components/MultiCanvasRenderer.d.ts +75 -0
  11. package/dist/components/MultiCanvasRenderer.d.ts.map +1 -0
  12. package/dist/components/MultiCanvasRenderer.js +203 -0
  13. package/dist/components/MultiCanvasRenderer.js.map +1 -0
  14. package/dist/components/NodeTooltip.d.ts +24 -0
  15. package/dist/components/NodeTooltip.d.ts.map +1 -0
  16. package/dist/components/NodeTooltip.js +160 -0
  17. package/dist/components/NodeTooltip.js.map +1 -0
  18. package/dist/components/SelectionSidebar.d.ts +18 -0
  19. package/dist/components/SelectionSidebar.d.ts.map +1 -0
  20. package/dist/components/SelectionSidebar.js +190 -0
  21. package/dist/components/SelectionSidebar.js.map +1 -0
  22. package/dist/components/SequenceDiagramRenderer.d.ts +77 -0
  23. package/dist/components/SequenceDiagramRenderer.d.ts.map +1 -0
  24. package/dist/components/SequenceDiagramRenderer.js +604 -0
  25. package/dist/components/SequenceDiagramRenderer.js.map +1 -0
  26. package/dist/components/WorkflowSequenceDiagram.d.ts +63 -0
  27. package/dist/components/WorkflowSequenceDiagram.d.ts.map +1 -0
  28. package/dist/components/WorkflowSequenceDiagram.js +147 -0
  29. package/dist/components/WorkflowSequenceDiagram.js.map +1 -0
  30. package/dist/components/dashboard/DashboardRenderer.d.ts +10 -0
  31. package/dist/components/dashboard/DashboardRenderer.d.ts.map +1 -0
  32. package/dist/components/dashboard/DashboardRenderer.js +179 -0
  33. package/dist/components/dashboard/DashboardRenderer.js.map +1 -0
  34. package/dist/components/dashboard/MetricPanel.d.ts +10 -0
  35. package/dist/components/dashboard/MetricPanel.d.ts.map +1 -0
  36. package/dist/components/dashboard/MetricPanel.js +103 -0
  37. package/dist/components/dashboard/MetricPanel.js.map +1 -0
  38. package/dist/components/dashboard/MockDataProvider.d.ts +30 -0
  39. package/dist/components/dashboard/MockDataProvider.d.ts.map +1 -0
  40. package/dist/components/dashboard/MockDataProvider.js +270 -0
  41. package/dist/components/dashboard/MockDataProvider.js.map +1 -0
  42. package/dist/components/dashboard/components/BarChart.d.ts +10 -0
  43. package/dist/components/dashboard/components/BarChart.d.ts.map +1 -0
  44. package/dist/components/dashboard/components/BarChart.js +167 -0
  45. package/dist/components/dashboard/components/BarChart.js.map +1 -0
  46. package/dist/components/dashboard/components/LineChart.d.ts +10 -0
  47. package/dist/components/dashboard/components/LineChart.d.ts.map +1 -0
  48. package/dist/components/dashboard/components/LineChart.js +141 -0
  49. package/dist/components/dashboard/components/LineChart.js.map +1 -0
  50. package/dist/components/dashboard/components/MetricCard.d.ts +9 -0
  51. package/dist/components/dashboard/components/MetricCard.d.ts.map +1 -0
  52. package/dist/components/dashboard/components/MetricCard.js +163 -0
  53. package/dist/components/dashboard/components/MetricCard.js.map +1 -0
  54. package/dist/components/dashboard/components/SourceLink.d.ts +9 -0
  55. package/dist/components/dashboard/components/SourceLink.d.ts.map +1 -0
  56. package/dist/components/dashboard/components/SourceLink.js +39 -0
  57. package/dist/components/dashboard/components/SourceLink.js.map +1 -0
  58. package/dist/components/dashboard/components/TimeRangeSelector.d.ts +9 -0
  59. package/dist/components/dashboard/components/TimeRangeSelector.d.ts.map +1 -0
  60. package/dist/components/dashboard/components/TimeRangeSelector.js +167 -0
  61. package/dist/components/dashboard/components/TimeRangeSelector.js.map +1 -0
  62. package/dist/components/dashboard/components/index.d.ts +6 -0
  63. package/dist/components/dashboard/components/index.d.ts.map +1 -0
  64. package/dist/components/dashboard/components/index.js +6 -0
  65. package/dist/components/dashboard/components/index.js.map +1 -0
  66. package/dist/components/dashboard/index.d.ts +6 -0
  67. package/dist/components/dashboard/index.d.ts.map +1 -0
  68. package/dist/components/dashboard/index.js +8 -0
  69. package/dist/components/dashboard/index.js.map +1 -0
  70. package/dist/components/dashboard/types.d.ts +74 -0
  71. package/dist/components/dashboard/types.d.ts.map +1 -0
  72. package/dist/components/dashboard/types.js +8 -0
  73. package/dist/components/dashboard/types.js.map +1 -0
  74. package/dist/components/session-events/SessionEventFeed.d.ts +34 -0
  75. package/dist/components/session-events/SessionEventFeed.d.ts.map +1 -0
  76. package/dist/components/session-events/SessionEventFeed.js +1196 -0
  77. package/dist/components/session-events/SessionEventFeed.js.map +1 -0
  78. package/dist/components/session-events/index.d.ts +7 -0
  79. package/dist/components/session-events/index.d.ts.map +1 -0
  80. package/dist/components/session-events/index.js +6 -0
  81. package/dist/components/session-events/index.js.map +1 -0
  82. package/dist/components/state-view/PipelineView.d.ts +14 -0
  83. package/dist/components/state-view/PipelineView.d.ts.map +1 -0
  84. package/dist/components/state-view/PipelineView.js +195 -0
  85. package/dist/components/state-view/PipelineView.js.map +1 -0
  86. package/dist/components/state-view/index.d.ts +14 -0
  87. package/dist/components/state-view/index.d.ts.map +1 -0
  88. package/dist/components/state-view/index.js +12 -0
  89. package/dist/components/state-view/index.js.map +1 -0
  90. package/dist/components/state-view/types.d.ts +188 -0
  91. package/dist/components/state-view/types.d.ts.map +1 -0
  92. package/dist/components/state-view/types.js +10 -0
  93. package/dist/components/state-view/types.js.map +1 -0
  94. package/dist/components/state-view/useStateView.d.ts +32 -0
  95. package/dist/components/state-view/useStateView.d.ts.map +1 -0
  96. package/dist/components/state-view/useStateView.js +129 -0
  97. package/dist/components/state-view/useStateView.js.map +1 -0
  98. package/dist/contexts/GraphEditContext.d.ts +20 -0
  99. package/dist/contexts/GraphEditContext.d.ts.map +1 -0
  100. package/dist/contexts/GraphEditContext.js +8 -0
  101. package/dist/contexts/GraphEditContext.js.map +1 -0
  102. package/dist/contexts/TooltipPortalContext.d.ts +8 -0
  103. package/dist/contexts/TooltipPortalContext.d.ts.map +1 -0
  104. package/dist/contexts/TooltipPortalContext.js +8 -0
  105. package/dist/contexts/TooltipPortalContext.js.map +1 -0
  106. package/dist/edges/CustomEdge.d.ts +24 -0
  107. package/dist/edges/CustomEdge.d.ts.map +1 -0
  108. package/dist/edges/CustomEdge.js +222 -0
  109. package/dist/edges/CustomEdge.js.map +1 -0
  110. package/dist/edges/GenericEdge.d.ts +18 -0
  111. package/dist/edges/GenericEdge.d.ts.map +1 -0
  112. package/dist/edges/GenericEdge.js +10 -0
  113. package/dist/edges/GenericEdge.js.map +1 -0
  114. package/dist/graphify/anchor.d.ts +28 -0
  115. package/dist/graphify/anchor.d.ts.map +1 -0
  116. package/dist/graphify/anchor.js +132 -0
  117. package/dist/graphify/anchor.js.map +1 -0
  118. package/dist/graphify/consolidated.d.ts +210 -0
  119. package/dist/graphify/consolidated.d.ts.map +1 -0
  120. package/dist/graphify/consolidated.js +11 -0
  121. package/dist/graphify/consolidated.js.map +1 -0
  122. package/dist/graphify/ids.d.ts +19 -0
  123. package/dist/graphify/ids.d.ts.map +1 -0
  124. package/dist/graphify/ids.js +46 -0
  125. package/dist/graphify/ids.js.map +1 -0
  126. package/dist/graphify/index.d.ts +18 -0
  127. package/dist/graphify/index.d.ts.map +1 -0
  128. package/dist/graphify/index.js +12 -0
  129. package/dist/graphify/index.js.map +1 -0
  130. package/dist/graphify/kind.d.ts +23 -0
  131. package/dist/graphify/kind.d.ts.map +1 -0
  132. package/dist/graphify/kind.js +77 -0
  133. package/dist/graphify/kind.js.map +1 -0
  134. package/dist/graphify/resolve.d.ts +48 -0
  135. package/dist/graphify/resolve.d.ts.map +1 -0
  136. package/dist/graphify/resolve.js +83 -0
  137. package/dist/graphify/resolve.js.map +1 -0
  138. package/dist/graphify/signature.d.ts +87 -0
  139. package/dist/graphify/signature.d.ts.map +1 -0
  140. package/dist/graphify/signature.js +276 -0
  141. package/dist/graphify/signature.js.map +1 -0
  142. package/dist/graphify/types.d.ts +141 -0
  143. package/dist/graphify/types.d.ts.map +1 -0
  144. package/dist/graphify/types.js +8 -0
  145. package/dist/graphify/types.js.map +1 -0
  146. package/dist/hooks/useElkLayout.d.ts +66 -0
  147. package/dist/hooks/useElkLayout.d.ts.map +1 -0
  148. package/dist/hooks/useElkLayout.js +136 -0
  149. package/dist/hooks/useElkLayout.js.map +1 -0
  150. package/dist/hooks/usePathBasedEvents.d.ts +42 -0
  151. package/dist/hooks/usePathBasedEvents.d.ts.map +1 -0
  152. package/dist/hooks/usePathBasedEvents.js +119 -0
  153. package/dist/hooks/usePathBasedEvents.js.map +1 -0
  154. package/dist/hooks/useSequenceLayout.d.ts +186 -0
  155. package/dist/hooks/useSequenceLayout.d.ts.map +1 -0
  156. package/dist/hooks/useSequenceLayout.js +327 -0
  157. package/dist/hooks/useSequenceLayout.js.map +1 -0
  158. package/dist/hooks/useUndoRedo.d.ts +80 -0
  159. package/dist/hooks/useUndoRedo.d.ts.map +1 -0
  160. package/dist/hooks/useUndoRedo.js +70 -0
  161. package/dist/hooks/useUndoRedo.js.map +1 -0
  162. package/dist/index.d.ts +73 -0
  163. package/dist/index.d.ts.map +1 -0
  164. package/dist/index.js +51 -0
  165. package/dist/index.js.map +1 -0
  166. package/dist/nodes/CustomNode.d.ts +28 -0
  167. package/dist/nodes/CustomNode.d.ts.map +1 -0
  168. package/dist/nodes/CustomNode.js +820 -0
  169. package/dist/nodes/CustomNode.js.map +1 -0
  170. package/dist/nodes/GenericNode.d.ts +20 -0
  171. package/dist/nodes/GenericNode.d.ts.map +1 -0
  172. package/dist/nodes/GenericNode.js +20 -0
  173. package/dist/nodes/GenericNode.js.map +1 -0
  174. package/dist/nodes/otel/OtelBoundaryNode.d.ts +55 -0
  175. package/dist/nodes/otel/OtelBoundaryNode.d.ts.map +1 -0
  176. package/dist/nodes/otel/OtelBoundaryNode.js +81 -0
  177. package/dist/nodes/otel/OtelBoundaryNode.js.map +1 -0
  178. package/dist/nodes/otel/OtelEventNode.d.ts +59 -0
  179. package/dist/nodes/otel/OtelEventNode.d.ts.map +1 -0
  180. package/dist/nodes/otel/OtelEventNode.js +82 -0
  181. package/dist/nodes/otel/OtelEventNode.js.map +1 -0
  182. package/dist/nodes/otel/OtelResourceNode.d.ts +53 -0
  183. package/dist/nodes/otel/OtelResourceNode.d.ts.map +1 -0
  184. package/dist/nodes/otel/OtelResourceNode.js +105 -0
  185. package/dist/nodes/otel/OtelResourceNode.js.map +1 -0
  186. package/dist/nodes/otel/OtelScopeNode.d.ts +53 -0
  187. package/dist/nodes/otel/OtelScopeNode.d.ts.map +1 -0
  188. package/dist/nodes/otel/OtelScopeNode.js +81 -0
  189. package/dist/nodes/otel/OtelScopeNode.js.map +1 -0
  190. package/dist/nodes/otel/OtelSpanConventionNode.d.ts +61 -0
  191. package/dist/nodes/otel/OtelSpanConventionNode.d.ts.map +1 -0
  192. package/dist/nodes/otel/OtelSpanConventionNode.js +131 -0
  193. package/dist/nodes/otel/OtelSpanConventionNode.js.map +1 -0
  194. package/dist/nodes/otel/index.d.ts +17 -0
  195. package/dist/nodes/otel/index.d.ts.map +1 -0
  196. package/dist/nodes/otel/index.js +13 -0
  197. package/dist/nodes/otel/index.js.map +1 -0
  198. package/dist/nodes/otel/shared/NodeBadges.d.ts +10 -0
  199. package/dist/nodes/otel/shared/NodeBadges.d.ts.map +1 -0
  200. package/dist/nodes/otel/shared/NodeBadges.js +178 -0
  201. package/dist/nodes/otel/shared/NodeBadges.js.map +1 -0
  202. package/dist/nodes/otel/shared/NodeContent.d.ts +10 -0
  203. package/dist/nodes/otel/shared/NodeContent.d.ts.map +1 -0
  204. package/dist/nodes/otel/shared/NodeContent.js +96 -0
  205. package/dist/nodes/otel/shared/NodeContent.js.map +1 -0
  206. package/dist/nodes/otel/shared/index.d.ts +8 -0
  207. package/dist/nodes/otel/shared/index.d.ts.map +1 -0
  208. package/dist/nodes/otel/shared/index.js +8 -0
  209. package/dist/nodes/otel/shared/index.js.map +1 -0
  210. package/dist/nodes/otel/shared/types.d.ts +129 -0
  211. package/dist/nodes/otel/shared/types.d.ts.map +1 -0
  212. package/dist/nodes/otel/shared/types.js +5 -0
  213. package/dist/nodes/otel/shared/types.js.map +1 -0
  214. package/dist/nodes/otel/shared/useNodeBehavior.d.ts +42 -0
  215. package/dist/nodes/otel/shared/useNodeBehavior.d.ts.map +1 -0
  216. package/dist/nodes/otel/shared/useNodeBehavior.js +61 -0
  217. package/dist/nodes/otel/shared/useNodeBehavior.js.map +1 -0
  218. package/dist/pierre/PierreFileView.d.ts +17 -0
  219. package/dist/pierre/PierreFileView.d.ts.map +1 -0
  220. package/dist/pierre/PierreFileView.js +46 -0
  221. package/dist/pierre/PierreFileView.js.map +1 -0
  222. package/dist/pierre/PierreSnippetView.d.ts +28 -0
  223. package/dist/pierre/PierreSnippetView.d.ts.map +1 -0
  224. package/dist/pierre/PierreSnippetView.js +105 -0
  225. package/dist/pierre/PierreSnippetView.js.map +1 -0
  226. package/dist/pierre/PierreThroughlineCodeView.d.ts +22 -0
  227. package/dist/pierre/PierreThroughlineCodeView.d.ts.map +1 -0
  228. package/dist/pierre/PierreThroughlineCodeView.js +206 -0
  229. package/dist/pierre/PierreThroughlineCodeView.js.map +1 -0
  230. package/dist/pierre/constructColors.d.ts +24 -0
  231. package/dist/pierre/constructColors.d.ts.map +1 -0
  232. package/dist/pierre/constructColors.js +91 -0
  233. package/dist/pierre/constructColors.js.map +1 -0
  234. package/dist/pierre/index.d.ts +12 -0
  235. package/dist/pierre/index.d.ts.map +1 -0
  236. package/dist/pierre/index.js +7 -0
  237. package/dist/pierre/index.js.map +1 -0
  238. package/dist/pierre/pierreBackground.d.ts +15 -0
  239. package/dist/pierre/pierreBackground.d.ts.map +1 -0
  240. package/dist/pierre/pierreBackground.js +31 -0
  241. package/dist/pierre/pierreBackground.js.map +1 -0
  242. package/dist/pierre/pierreFileLang.d.ts +27 -0
  243. package/dist/pierre/pierreFileLang.d.ts.map +1 -0
  244. package/dist/pierre/pierreFileLang.js +52 -0
  245. package/dist/pierre/pierreFileLang.js.map +1 -0
  246. package/dist/pierre/pierreSyntaxTheme.d.ts +11 -0
  247. package/dist/pierre/pierreSyntaxTheme.d.ts.map +1 -0
  248. package/dist/pierre/pierreSyntaxTheme.js +20 -0
  249. package/dist/pierre/pierreSyntaxTheme.js.map +1 -0
  250. package/dist/pierre/scrollAnchor.d.ts +5 -0
  251. package/dist/pierre/scrollAnchor.d.ts.map +1 -0
  252. package/dist/pierre/scrollAnchor.js +9 -0
  253. package/dist/pierre/scrollAnchor.js.map +1 -0
  254. package/dist/pierre/sliceSnippet.d.ts +10 -0
  255. package/dist/pierre/sliceSnippet.d.ts.map +1 -0
  256. package/dist/pierre/sliceSnippet.js +16 -0
  257. package/dist/pierre/sliceSnippet.js.map +1 -0
  258. package/dist/pierre/syntaxTokens.d.ts +11 -0
  259. package/dist/pierre/syntaxTokens.d.ts.map +1 -0
  260. package/dist/pierre/syntaxTokens.js +51 -0
  261. package/dist/pierre/syntaxTokens.js.map +1 -0
  262. package/dist/stories/Subsystem/ComponentGraph/fixtures.d.ts +8 -0
  263. package/dist/stories/Subsystem/ComponentGraph/fixtures.d.ts.map +1 -0
  264. package/dist/stories/Subsystem/ComponentGraph/fixtures.js +116 -0
  265. package/dist/stories/Subsystem/ComponentGraph/fixtures.js.map +1 -0
  266. package/dist/subsystem/ComponentDeclaration.d.ts +87 -0
  267. package/dist/subsystem/ComponentDeclaration.d.ts.map +1 -0
  268. package/dist/subsystem/ComponentDeclaration.js +374 -0
  269. package/dist/subsystem/ComponentDeclaration.js.map +1 -0
  270. package/dist/subsystem/FileDrawer.d.ts +17 -0
  271. package/dist/subsystem/FileDrawer.d.ts.map +1 -0
  272. package/dist/subsystem/FileDrawer.js +72 -0
  273. package/dist/subsystem/FileDrawer.js.map +1 -0
  274. package/dist/subsystem/GraphLayoutCover.d.ts +20 -0
  275. package/dist/subsystem/GraphLayoutCover.d.ts.map +1 -0
  276. package/dist/subsystem/GraphLayoutCover.js +42 -0
  277. package/dist/subsystem/GraphLayoutCover.js.map +1 -0
  278. package/dist/subsystem/SubsystemComponentGraph.d.ts +96 -0
  279. package/dist/subsystem/SubsystemComponentGraph.d.ts.map +1 -0
  280. package/dist/subsystem/SubsystemComponentGraph.js +1059 -0
  281. package/dist/subsystem/SubsystemComponentGraph.js.map +1 -0
  282. package/dist/subsystem/SubsystemFileTree.d.ts +24 -0
  283. package/dist/subsystem/SubsystemFileTree.d.ts.map +1 -0
  284. package/dist/subsystem/SubsystemFileTree.js +150 -0
  285. package/dist/subsystem/SubsystemFileTree.js.map +1 -0
  286. package/dist/subsystem/declarationRef.d.ts +39 -0
  287. package/dist/subsystem/declarationRef.d.ts.map +1 -0
  288. package/dist/subsystem/declarationRef.js +32 -0
  289. package/dist/subsystem/declarationRef.js.map +1 -0
  290. package/dist/subsystem/formatDeclaration.d.ts +11 -0
  291. package/dist/subsystem/formatDeclaration.d.ts.map +1 -0
  292. package/dist/subsystem/formatDeclaration.js +146 -0
  293. package/dist/subsystem/formatDeclaration.js.map +1 -0
  294. package/dist/subsystem/model.d.ts +353 -0
  295. package/dist/subsystem/model.d.ts.map +1 -0
  296. package/dist/subsystem/model.js +503 -0
  297. package/dist/subsystem/model.js.map +1 -0
  298. package/dist/subsystem/nodes.d.ts +69 -0
  299. package/dist/subsystem/nodes.d.ts.map +1 -0
  300. package/dist/subsystem/nodes.js +289 -0
  301. package/dist/subsystem/nodes.js.map +1 -0
  302. package/dist/subsystem/paths.d.ts +63 -0
  303. package/dist/subsystem/paths.d.ts.map +1 -0
  304. package/dist/subsystem/paths.js +86 -0
  305. package/dist/subsystem/paths.js.map +1 -0
  306. package/dist/subsystem/tokenizeComponent.d.ts +20 -0
  307. package/dist/subsystem/tokenizeComponent.d.ts.map +1 -0
  308. package/dist/subsystem/tokenizeComponent.js +56 -0
  309. package/dist/subsystem/tokenizeComponent.js.map +1 -0
  310. package/dist/subsystem/tokenizeFormatted.d.ts +12 -0
  311. package/dist/subsystem/tokenizeFormatted.d.ts.map +1 -0
  312. package/dist/subsystem/tokenizeFormatted.js +13 -0
  313. package/dist/subsystem/tokenizeFormatted.js.map +1 -0
  314. package/dist/utils/animationMapping.d.ts +53 -0
  315. package/dist/utils/animationMapping.d.ts.map +1 -0
  316. package/dist/utils/animationMapping.js +126 -0
  317. package/dist/utils/animationMapping.js.map +1 -0
  318. package/dist/utils/canvasBounds.d.ts +50 -0
  319. package/dist/utils/canvasBounds.d.ts.map +1 -0
  320. package/dist/utils/canvasBounds.js +88 -0
  321. package/dist/utils/canvasBounds.js.map +1 -0
  322. package/dist/utils/elkLayout.d.ts +137 -0
  323. package/dist/utils/elkLayout.d.ts.map +1 -0
  324. package/dist/utils/elkLayout.js +596 -0
  325. package/dist/utils/elkLayout.js.map +1 -0
  326. package/dist/utils/graphConverter.d.ts +18 -0
  327. package/dist/utils/graphConverter.d.ts.map +1 -0
  328. package/dist/utils/graphConverter.js +114 -0
  329. package/dist/utils/graphConverter.js.map +1 -0
  330. package/dist/utils/iconResolver.d.ts +29 -0
  331. package/dist/utils/iconResolver.d.ts.map +1 -0
  332. package/dist/utils/iconResolver.js +30 -0
  333. package/dist/utils/iconResolver.js.map +1 -0
  334. package/dist/utils/orientationUtils.d.ts +19 -0
  335. package/dist/utils/orientationUtils.d.ts.map +1 -0
  336. package/dist/utils/orientationUtils.js +62 -0
  337. package/dist/utils/orientationUtils.js.map +1 -0
  338. package/package.json +80 -0
  339. package/src/components/ConfigurationSelector.tsx +133 -0
  340. package/src/components/GraphRenderer.tsx +3195 -0
  341. package/src/components/MultiCanvasRenderer.tsx +295 -0
  342. package/src/components/NodeTooltip.tsx +279 -0
  343. package/src/components/PendingChanges.test.tsx +375 -0
  344. package/src/components/SelectionSidebar.tsx +352 -0
  345. package/src/components/SequenceDiagramRenderer.tsx +1156 -0
  346. package/src/components/WorkflowSequenceDiagram.tsx +270 -0
  347. package/src/components/dashboard/DashboardRenderer.tsx +317 -0
  348. package/src/components/dashboard/MetricPanel.tsx +254 -0
  349. package/src/components/dashboard/MockDataProvider.ts +330 -0
  350. package/src/components/dashboard/components/BarChart.tsx +299 -0
  351. package/src/components/dashboard/components/LineChart.tsx +279 -0
  352. package/src/components/dashboard/components/MetricCard.tsx +270 -0
  353. package/src/components/dashboard/components/SourceLink.tsx +63 -0
  354. package/src/components/dashboard/components/TimeRangeSelector.tsx +280 -0
  355. package/src/components/dashboard/components/index.ts +5 -0
  356. package/src/components/dashboard/index.ts +47 -0
  357. package/src/components/dashboard/types.ts +126 -0
  358. package/src/components/session-events/SessionEventFeed.tsx +1797 -0
  359. package/src/components/session-events/index.ts +13 -0
  360. package/src/components/state-view/PipelineView.tsx +347 -0
  361. package/src/components/state-view/index.ts +14 -0
  362. package/src/components/state-view/types.ts +261 -0
  363. package/src/components/state-view/useStateView.ts +205 -0
  364. package/src/contexts/GraphEditContext.tsx +27 -0
  365. package/src/contexts/TooltipPortalContext.ts +8 -0
  366. package/src/edges/CustomEdge.tsx +402 -0
  367. package/src/edges/GenericEdge.tsx +36 -0
  368. package/src/graphify/anchor.test.ts +124 -0
  369. package/src/graphify/anchor.ts +160 -0
  370. package/src/graphify/consolidated.ts +246 -0
  371. package/src/graphify/ids.ts +48 -0
  372. package/src/graphify/index.ts +72 -0
  373. package/src/graphify/kind.test.ts +108 -0
  374. package/src/graphify/kind.ts +120 -0
  375. package/src/graphify/resolve.test.ts +89 -0
  376. package/src/graphify/resolve.ts +115 -0
  377. package/src/graphify/signature.test.ts +278 -0
  378. package/src/graphify/signature.ts +354 -0
  379. package/src/graphify/types.ts +164 -0
  380. package/src/hooks/useElkLayout.test.ts +134 -0
  381. package/src/hooks/useElkLayout.ts +191 -0
  382. package/src/hooks/usePathBasedEvents.ts +192 -0
  383. package/src/hooks/useSequenceLayout.ts +543 -0
  384. package/src/hooks/useUndoRedo.ts +144 -0
  385. package/src/index.ts +341 -0
  386. package/src/nodes/CustomNode.tsx +1231 -0
  387. package/src/nodes/GenericNode.tsx +55 -0
  388. package/src/nodes/otel/OtelBoundaryNode.tsx +224 -0
  389. package/src/nodes/otel/OtelEventNode.tsx +225 -0
  390. package/src/nodes/otel/OtelResourceNode.tsx +251 -0
  391. package/src/nodes/otel/OtelScopeNode.tsx +221 -0
  392. package/src/nodes/otel/OtelSpanConventionNode.tsx +295 -0
  393. package/src/nodes/otel/index.ts +23 -0
  394. package/src/nodes/otel/shared/NodeBadges.tsx +295 -0
  395. package/src/nodes/otel/shared/NodeContent.tsx +204 -0
  396. package/src/nodes/otel/shared/index.ts +8 -0
  397. package/src/nodes/otel/shared/types.ts +138 -0
  398. package/src/nodes/otel/shared/useNodeBehavior.ts +114 -0
  399. package/src/pierre/PierreFileView.tsx +81 -0
  400. package/src/pierre/PierreSnippetView.tsx +184 -0
  401. package/src/pierre/PierreThroughlineCodeView.tsx +304 -0
  402. package/src/pierre/constructColors.test.ts +52 -0
  403. package/src/pierre/constructColors.ts +112 -0
  404. package/src/pierre/index.ts +18 -0
  405. package/src/pierre/pierreBackground.ts +33 -0
  406. package/src/pierre/pierreFileLang.test.ts +26 -0
  407. package/src/pierre/pierreFileLang.ts +55 -0
  408. package/src/pierre/pierreSyntaxTheme.ts +23 -0
  409. package/src/pierre/scrollAnchor.test.ts +13 -0
  410. package/src/pierre/scrollAnchor.ts +11 -0
  411. package/src/pierre/sliceSnippet.test.ts +21 -0
  412. package/src/pierre/sliceSnippet.ts +31 -0
  413. package/src/pierre/syntaxTokens.test.ts +35 -0
  414. package/src/pierre/syntaxTokens.ts +60 -0
  415. package/src/stories/Audit/BoundaryNodes.stories.tsx +385 -0
  416. package/src/stories/Audit/CanvasEdgeTypes.stories.tsx +1448 -0
  417. package/src/stories/Audit/CanvasNodeTypes.stories.tsx +1049 -0
  418. package/src/stories/Audit/ColorPriority.stories.tsx +895 -0
  419. package/src/stories/Audit/DiamondBadges.stories.tsx +629 -0
  420. package/src/stories/Audit/NodeDimensionsTesting.stories.tsx +724 -0
  421. package/src/stories/Audit/NodeFieldsAudit.stories.tsx +996 -0
  422. package/src/stories/Audit/NodeFontSizeTesting.stories.tsx +715 -0
  423. package/src/stories/Audit/NodeShapes.stories.tsx +1208 -0
  424. package/src/stories/Audit/WideNodesTesting.stories.tsx +1045 -0
  425. package/src/stories/Components/DashboardRenderer.stories.tsx +263 -0
  426. package/src/stories/Components/GraphRenderer.stories.tsx +3236 -0
  427. package/src/stories/Components/MultiCanvasRenderer.stories.tsx +370 -0
  428. package/src/stories/Components/SequenceDiagram.stories.tsx +255 -0
  429. package/src/stories/Components/StateView.stories.tsx +417 -0
  430. package/src/stories/Components/TraceViewer.stories.tsx +442 -0
  431. package/src/stories/Components/WorkflowSequenceDiagram.stories.tsx +802 -0
  432. package/src/stories/Features/AnimationWorkshop.stories.tsx +727 -0
  433. package/src/stories/Features/ChangeTypeVisual.stories.tsx +67 -0
  434. package/src/stories/Features/EventDrivenAnimations.stories.tsx +513 -0
  435. package/src/stories/Features/MultiConfig.stories.tsx +539 -0
  436. package/src/stories/Introduction.mdx +34 -0
  437. package/src/stories/Layout/ElkEdgeRouting.stories.tsx +539 -0
  438. package/src/stories/Layout/GraphOrientation.stories.tsx +500 -0
  439. package/src/stories/Layout/MultiDirectionalConnections.stories.tsx +352 -0
  440. package/src/stories/Nodes/NodeDefinitionComparison.stories.tsx +560 -0
  441. package/src/stories/Nodes/NodeNameFallbacks.stories.tsx +491 -0
  442. package/src/stories/Nodes/NumericColors.stories.tsx +440 -0
  443. package/src/stories/OTEL/EventNameDisplay.stories.tsx +694 -0
  444. package/src/stories/OTEL/EventNameFallback.stories.tsx +578 -0
  445. package/src/stories/OTEL/OtelComponents.stories.tsx +422 -0
  446. package/src/stories/OTEL/OtelNodeTypesPrototype.stories.tsx +806 -0
  447. package/src/stories/OTEL/RawEventCards.stories.tsx +57 -0
  448. package/src/stories/OTEL/SpanBadges.stories.tsx +840 -0
  449. package/src/stories/OTEL/ValidationEventsCanvas.stories.tsx +209 -0
  450. package/src/stories/Pierre/CodeView.stories.tsx +219 -0
  451. package/src/stories/RealWorld/BacklogMdCanvases.stories.tsx +721 -0
  452. package/src/stories/RealWorld/FileCitySequence.stories.tsx +516 -0
  453. package/src/stories/RealWorld/RealCanvasFiles.stories.tsx +336 -0
  454. package/src/stories/Subsystem/ComponentDeclarationAudit.stories.tsx +321 -0
  455. package/src/stories/Subsystem/ComponentGraph/Appearance.stories.tsx +365 -0
  456. package/src/stories/Subsystem/ComponentGraph/Basics.stories.tsx +137 -0
  457. package/src/stories/Subsystem/ComponentGraph/Captures.stories.tsx +238 -0
  458. package/src/stories/Subsystem/ComponentGraph/DetailPanel.stories.tsx +315 -0
  459. package/src/stories/Subsystem/ComponentGraph/Flows.stories.tsx +239 -0
  460. package/src/stories/Subsystem/ComponentGraph/FrameworkStereotype.stories.tsx +216 -0
  461. package/src/stories/Subsystem/ComponentGraph/GraphTitle.stories.tsx +70 -0
  462. package/src/stories/Subsystem/ComponentGraph/Processes.stories.tsx +68 -0
  463. package/src/stories/Subsystem/ComponentGraph/Scenarios.stories.tsx +959 -0
  464. package/src/stories/Subsystem/ComponentGraph/Spotlights.stories.tsx +681 -0
  465. package/src/stories/Subsystem/ComponentGraph/fixtures.ts +129 -0
  466. package/src/stories/__traces__/test-run.canvas.json +241 -0
  467. package/src/stories/data/activity-feed-analytics.dashboard.json +300 -0
  468. package/src/stories/data/file-city-images-transformed.otel.canvas.json +295 -0
  469. package/src/stories/data/file-city-workflows.json +269 -0
  470. package/src/stories/data/graph-converter-test-execution.json +443 -0
  471. package/src/stories/data/graph-converter-test.workflow.json +105 -0
  472. package/src/stories/data/graph-converter-validated-execution.json +58 -0
  473. package/src/stories/data/opencode-session-raw-events.json +273396 -0
  474. package/src/subsystem/ComponentDeclaration.tsx +643 -0
  475. package/src/subsystem/FileDrawer.tsx +106 -0
  476. package/src/subsystem/GraphLayoutCover.tsx +69 -0
  477. package/src/subsystem/SubsystemComponentGraph.tsx +1644 -0
  478. package/src/subsystem/SubsystemFileTree.tsx +190 -0
  479. package/src/subsystem/declarationRef.test.ts +33 -0
  480. package/src/subsystem/declarationRef.ts +63 -0
  481. package/src/subsystem/formatDeclaration.ts +174 -0
  482. package/src/subsystem/model.test.ts +244 -0
  483. package/src/subsystem/model.ts +850 -0
  484. package/src/subsystem/nodes.test.ts +56 -0
  485. package/src/subsystem/nodes.tsx +443 -0
  486. package/src/subsystem/paths.test.ts +123 -0
  487. package/src/subsystem/paths.ts +127 -0
  488. package/src/subsystem/tokenizeComponent.ts +70 -0
  489. package/src/subsystem/tokenizeFormatted.ts +19 -0
  490. package/src/utils/animationMapping.ts +166 -0
  491. package/src/utils/canvasBounds.ts +146 -0
  492. package/src/utils/elkLayout.test.ts +240 -0
  493. package/src/utils/elkLayout.ts +779 -0
  494. package/src/utils/graphConverter.ts +148 -0
  495. package/src/utils/iconResolver.tsx +53 -0
  496. package/src/utils/orientationUtils.ts +73 -0
@@ -0,0 +1,1196 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * SessionEventFeed — a three-column diagnostic feed over one agent session's
4
+ * events, showing the raw → repo-normalized → accumulated (UI) pipeline
5
+ * for every row.
6
+ *
7
+ * Input rows match the principal-studio's `SessionEventRow` wire shape:
8
+ * { seq, type, raw, normalized, accumulated }
9
+ * `raw` is the agent-specific payload (opencode V1 sqlite rows, or durable
10
+ * reader blobs such as Cursor store.db messages), `normalized` its
11
+ * repo-normalized form, and `accumulated` the AgentSessionEvent the File City
12
+ * UI actually renders (null when the accumulator drops the event).
13
+ *
14
+ * Dark diagnostic palette — intentionally self-contained rather than themed.
15
+ */
16
+ import { useCallback, useEffect, useMemo, useState } from 'react';
17
+ import { useTheme } from '@principal-ade/industry-theme';
18
+ import { Check, Copy } from 'lucide-react';
19
+ /** Shared collapse state keyed by row seq. */
20
+ function useCollapse(seqs, defaultCollapsed = false) {
21
+ const [collapsed, setCollapsed] = useState(() => (defaultCollapsed ? new Set(seqs) : new Set()));
22
+ // When the feed grows (incremental paging appends rows), default newly added
23
+ // rows to collapsed so the invariant holds for rows that arrive after mount.
24
+ useEffect(() => {
25
+ if (!defaultCollapsed)
26
+ return;
27
+ setCollapsed((prev) => {
28
+ let changed = false;
29
+ const next = new Set(prev);
30
+ for (const seq of seqs) {
31
+ if (!next.has(seq)) {
32
+ next.add(seq);
33
+ changed = true;
34
+ }
35
+ }
36
+ return changed ? next : prev;
37
+ });
38
+ }, [seqs, defaultCollapsed]);
39
+ const toggle = useCallback((seq) => {
40
+ setCollapsed((prev) => {
41
+ const next = new Set(prev);
42
+ if (next.has(seq))
43
+ next.delete(seq);
44
+ else
45
+ next.add(seq);
46
+ return next;
47
+ });
48
+ }, []);
49
+ const setAll = useCallback((value) => setCollapsed(value ? new Set(seqs) : new Set()), [seqs]);
50
+ return { collapsed, toggle, setAll };
51
+ }
52
+ function toRaw(raw) {
53
+ if (raw === null || raw === undefined || typeof raw !== 'object')
54
+ return null;
55
+ return raw;
56
+ }
57
+ function toNormalized(normalized) {
58
+ return normalized;
59
+ }
60
+ // =============================================================================
61
+ // Raw event → presentable pieces
62
+ // =============================================================================
63
+ function dataOf(e) {
64
+ return (e?.data ?? {});
65
+ }
66
+ function partOf(e) {
67
+ return dataOf(e).part;
68
+ }
69
+ /** True when the payload looks like an opencode V1 sqlite event row. */
70
+ function isV1RawEvent(e) {
71
+ return typeof e?.type === 'string' && e.type.length > 0;
72
+ }
73
+ /**
74
+ * Cursor store.db blobs (and other durable readers) put the whole message in
75
+ * `raw` — no `type` / `data` envelope. Pull a presentable kind + summary from
76
+ * the common shapes CursorSessionReader emits:
77
+ * - chat message: `{ role, content, id? }`
78
+ * - tool wrapper: `{ message, block }` where block is tool-call / tool-result
79
+ * - session meta: `{ title?, cwd?, schemaVersion? }`
80
+ */
81
+ function durableRawKind(e) {
82
+ const block = e.block;
83
+ if (block && typeof block === 'object') {
84
+ const toolName = (block.toolName ?? block.name);
85
+ const blockType = block.type;
86
+ if (blockType === 'tool-call' || blockType === 'tool_use') {
87
+ return toolName ? `tool-call:${toolName}` : 'tool-call';
88
+ }
89
+ if (blockType === 'tool-result' || blockType === 'tool_result') {
90
+ return toolName ? `tool-result:${toolName}` : 'tool-result';
91
+ }
92
+ if (typeof blockType === 'string')
93
+ return blockType;
94
+ }
95
+ if (typeof e.role === 'string')
96
+ return e.role;
97
+ if (typeof e.title === 'string' || typeof e.cwd === 'string' || typeof e.schemaVersion === 'number') {
98
+ return 'session-meta';
99
+ }
100
+ return 'durable-raw';
101
+ }
102
+ function durableRawDescribe(e) {
103
+ const block = e.block;
104
+ if (block && typeof block === 'object') {
105
+ const toolName = (block.toolName ?? block.name);
106
+ const blockType = block.type;
107
+ if (blockType === 'tool-call' || blockType === 'tool_use') {
108
+ const args = block.args ?? block.input;
109
+ const summary = toolSummary(args);
110
+ return [toolName, summary].filter(Boolean).join(' · ') || 'tool call';
111
+ }
112
+ if (blockType === 'tool-result' || blockType === 'tool_result') {
113
+ const result = block.result;
114
+ const text = typeof result === 'string'
115
+ ? result.slice(0, 120)
116
+ : result !== undefined
117
+ ? JSON.stringify(result).slice(0, 120)
118
+ : '';
119
+ return [toolName, text].filter(Boolean).join(' · ') || 'tool result';
120
+ }
121
+ }
122
+ if (typeof e.role === 'string') {
123
+ const content = e.content;
124
+ if (typeof content === 'string') {
125
+ const tagged = content.match(/<user_query>\s*([\s\S]*?)\s*<\/user_query>/i);
126
+ const text = (tagged?.[1] ?? content).trim().replace(/\s+/g, ' ');
127
+ return text.slice(0, 120) || e.role;
128
+ }
129
+ if (Array.isArray(content)) {
130
+ const texts = content
131
+ .filter((c) => !!c && typeof c === 'object')
132
+ .map((c) => (typeof c.text === 'string' ? c.text : c.toolName ?? c.name ?? c.type))
133
+ .filter(Boolean);
134
+ return texts.join(' · ').slice(0, 120) || e.role;
135
+ }
136
+ return e.role;
137
+ }
138
+ if (typeof e.title === 'string')
139
+ return e.title;
140
+ if (typeof e.cwd === 'string')
141
+ return e.cwd;
142
+ return 'durable raw event';
143
+ }
144
+ function eventTimestamp(e) {
145
+ if (!e)
146
+ return 0;
147
+ const d = dataOf(e);
148
+ if (typeof d.time === 'number')
149
+ return d.time;
150
+ const info = d.info;
151
+ const infoTime = info?.time;
152
+ if (typeof infoTime?.created === 'number')
153
+ return infoTime.created;
154
+ const part = partOf(e);
155
+ if (typeof part?.time === 'number')
156
+ return part.time;
157
+ const state = part?.state;
158
+ const stateTime = state?.time;
159
+ if (typeof stateTime?.start === 'number')
160
+ return stateTime.start;
161
+ if (typeof stateTime?.end === 'number')
162
+ return stateTime.end;
163
+ return 0;
164
+ }
165
+ const ALL_CATEGORIES = [
166
+ 'session',
167
+ 'conversation',
168
+ 'tool',
169
+ 'step',
170
+ 'patch',
171
+ 'compaction',
172
+ ];
173
+ function eventCategory(e) {
174
+ if (!e)
175
+ return 'session';
176
+ if (!isV1RawEvent(e)) {
177
+ const kind = durableRawKind(e);
178
+ if (kind.startsWith('tool-call') || kind.startsWith('tool-result') || kind.startsWith('tool')) {
179
+ return 'tool';
180
+ }
181
+ if (kind === 'session-meta')
182
+ return 'session';
183
+ return 'conversation';
184
+ }
185
+ switch (e.type) {
186
+ case 'session.created.1':
187
+ case 'session.updated.1':
188
+ return 'session';
189
+ case 'message.updated.1':
190
+ case 'message.removed.1':
191
+ case 'message.part.updated.1': {
192
+ const partType = partOf(e)?.type;
193
+ switch (partType) {
194
+ case 'text':
195
+ case 'reasoning':
196
+ return 'conversation';
197
+ case 'tool':
198
+ return 'tool';
199
+ case 'step-start':
200
+ case 'step-finish':
201
+ return 'step';
202
+ case 'patch':
203
+ return 'patch';
204
+ case 'compaction':
205
+ return 'compaction';
206
+ default:
207
+ return 'conversation';
208
+ }
209
+ }
210
+ default:
211
+ return 'conversation';
212
+ }
213
+ }
214
+ const PRESETS = [
215
+ { id: 'all', label: 'All', include: ALL_CATEGORIES },
216
+ { id: 'activity', label: 'Activity', include: ['conversation', 'tool', 'patch'] },
217
+ { id: 'conversation', label: 'Conversation', include: ['conversation'] },
218
+ { id: 'tools', label: 'Tools', include: ['tool'] },
219
+ { id: 'noise', label: 'Session & steps', include: ['session', 'step', 'compaction'] },
220
+ ];
221
+ /** Granular key for a card (raw event type, or part type for parts). */
222
+ function eventKind(e) {
223
+ if (!e)
224
+ return 'no-raw';
225
+ if (!isV1RawEvent(e))
226
+ return durableRawKind(e);
227
+ if (e.type === 'message.part.updated.1') {
228
+ return `part:${partOf(e)?.type ?? 'unknown'}`;
229
+ }
230
+ return e.type;
231
+ }
232
+ function kindLabel(kind) {
233
+ if (!kind)
234
+ return 'unknown';
235
+ if (kind.startsWith('part:'))
236
+ return `part · ${kind.slice(5)}`;
237
+ if (kind.startsWith('tool-call:'))
238
+ return `call · ${kind.slice('tool-call:'.length)}`;
239
+ if (kind.startsWith('tool-result:'))
240
+ return `result · ${kind.slice('tool-result:'.length)}`;
241
+ return kind;
242
+ }
243
+ const KIND_COLORS = {
244
+ 'session.created.1': '#64748b',
245
+ 'session.updated.1': '#94a3b8',
246
+ 'message.updated.1': '#06b6d4',
247
+ 'message.removed.1': '#ef4444',
248
+ 'part:text': '#10b981',
249
+ 'part:reasoning': '#8b5cf6',
250
+ 'part:tool': '#3b82f6',
251
+ 'part:step-start': '#f59e0b',
252
+ 'part:step-finish': '#f59e0b',
253
+ 'part:patch': '#ef4444',
254
+ 'part:compaction': '#ec4899',
255
+ 'part:unknown': '#6b7280',
256
+ };
257
+ function kindColor(kind) {
258
+ return KIND_COLORS[kind] ?? '#6b7280';
259
+ }
260
+ function describe(e) {
261
+ if (!e)
262
+ return 'finished';
263
+ if (!isV1RawEvent(e))
264
+ return durableRawDescribe(e);
265
+ const d = dataOf(e);
266
+ const info = d.info;
267
+ const part = partOf(e);
268
+ const state = part?.state;
269
+ switch (e.type) {
270
+ case 'session.created.1':
271
+ return info?.title ?? 'Session created';
272
+ case 'session.updated.1': {
273
+ const bits = [];
274
+ const tokens = info?.tokens;
275
+ if (typeof info?.cost === 'number')
276
+ bits.push(`$${info.cost.toFixed(4)}`);
277
+ if (typeof tokens?.input === 'number')
278
+ bits.push(`${tokens.input} in`);
279
+ if (typeof tokens?.output === 'number')
280
+ bits.push(`${tokens.output} out`);
281
+ return bits.length > 0 ? `Session updated · ${bits.join(' · ')}` : 'Session updated';
282
+ }
283
+ case 'message.updated.1': {
284
+ const role = info?.role ?? 'message';
285
+ const model = info?.model?.modelID;
286
+ return model ? `${role} message · ${model}` : `${role} message`;
287
+ }
288
+ case 'message.removed.1':
289
+ return `Removed ${d.messageID}`;
290
+ case 'message.part.updated.1': {
291
+ const partType = part?.type;
292
+ const toolName = part?.tool;
293
+ const status = state?.status;
294
+ switch (partType) {
295
+ case 'text':
296
+ return part?.text ?? 'Text';
297
+ case 'reasoning':
298
+ return part?.text || 'Reasoning';
299
+ case 'tool': {
300
+ const bits = [toolName, status];
301
+ const n = todoCountOf(state?.input);
302
+ if (n > 0)
303
+ bits.push(`${n} todo${n === 1 ? '' : 's'}`);
304
+ return bits.filter(Boolean).join(' · ') || 'Tool';
305
+ }
306
+ case 'step-start':
307
+ return 'Step start';
308
+ case 'step-finish':
309
+ return part?.reason ? `Step finish · ${part.reason}` : 'Step finish';
310
+ case 'patch': {
311
+ const files = part?.files;
312
+ return `Patch · ${files?.length ?? 0} file${(files?.length ?? 0) === 1 ? '' : 's'}`;
313
+ }
314
+ case 'compaction':
315
+ return `Compaction${part?.auto ? ' · auto' : ''}`;
316
+ default:
317
+ return partType ?? 'Part';
318
+ }
319
+ }
320
+ default:
321
+ return e.type;
322
+ }
323
+ }
324
+ /** Number of todos carried by a todowrite tool input, if any. */
325
+ function todoCountOf(input) {
326
+ if (input && typeof input === 'object') {
327
+ const todos = input['todos'];
328
+ if (Array.isArray(todos))
329
+ return todos.length;
330
+ }
331
+ return 0;
332
+ }
333
+ function toolSummary(input) {
334
+ if (input === null || input === undefined)
335
+ return '';
336
+ if (typeof input === 'string')
337
+ return input;
338
+ if (Array.isArray(input))
339
+ return JSON.stringify(input).slice(0, 120);
340
+ const obj = input;
341
+ // A todowrite input carries the full todo list — summarize by count rather
342
+ // than dumping truncated JSON.
343
+ if (Array.isArray(obj['todos']))
344
+ return `${obj['todos'].length} todos`;
345
+ for (const key of ['command', 'filePath', 'file_path', 'path', 'pattern', 'include', 'tool']) {
346
+ if (typeof obj[key] === 'string' && obj[key] !== '')
347
+ return obj[key];
348
+ }
349
+ return JSON.stringify(input).slice(0, 120);
350
+ }
351
+ // =============================================================================
352
+ // Cards
353
+ // =============================================================================
354
+ function formatTime(ts) {
355
+ if (!ts)
356
+ return '';
357
+ return new Date(ts).toLocaleTimeString([], {
358
+ hour: '2-digit',
359
+ minute: '2-digit',
360
+ second: '2-digit',
361
+ });
362
+ }
363
+ function RawEventCard({ event, runCount, snapshotCount, expanded, onToggle, }) {
364
+ const { theme } = useTheme();
365
+ const kind = eventKind(event);
366
+ const d = dataOf(event);
367
+ const part = partOf(event);
368
+ const state = part?.state;
369
+ const color = kindColor(kind);
370
+ if (!event) {
371
+ return (_jsx("div", { style: {
372
+ display: 'flex',
373
+ alignItems: 'center',
374
+ gap: 8,
375
+ padding: '10px 14px',
376
+ borderRadius: 0,
377
+ minWidth: 0,
378
+ overflow: 'hidden',
379
+ border: '1px dashed #1f2937',
380
+ backgroundColor: '#0d1117',
381
+ fontFamily: theme.fonts.body,
382
+ fontSize: 12,
383
+ }, children: _jsx("span", { style: { color: '#4b5563', fontStyle: 'italic' }, children: "no raw payload" }) }));
384
+ }
385
+ const body = (() => {
386
+ switch (event.type) {
387
+ case 'session.created.1': {
388
+ const info = d.info;
389
+ return (_jsx(MetaRows, { rows: [
390
+ ['agent', info?.agent],
391
+ ['model', info?.model?.id ?? info?.model?.modelID],
392
+ ['directory', info?.directory],
393
+ ['version', info?.version],
394
+ ['slug', info?.slug],
395
+ ] }));
396
+ }
397
+ case 'session.updated.1': {
398
+ const info = d.info;
399
+ return (_jsx(MetaRows, { rows: [
400
+ ['cost', typeof info?.cost === 'number' ? `$${info.cost.toFixed(4)}` : undefined],
401
+ ['tokens', info?.tokens],
402
+ ['title', info?.title],
403
+ ] }));
404
+ }
405
+ case 'message.updated.1': {
406
+ const info = d.info;
407
+ return (_jsx(MetaRows, { rows: [
408
+ ['role', info?.role],
409
+ ['agent', info?.agent],
410
+ ['model', info?.model],
411
+ ['tokens', info?.tokens],
412
+ ['messageID', info?.id],
413
+ ] }));
414
+ }
415
+ case 'message.removed.1':
416
+ return _jsx(MetaRows, { rows: [['messageID', d.messageID]] });
417
+ case 'message.part.updated.1': {
418
+ switch (part?.type) {
419
+ case 'text':
420
+ case 'reasoning':
421
+ return _jsx(TextView, { text: part?.text });
422
+ case 'tool': {
423
+ const todos = state?.input?.['todos'];
424
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsxs("div", { style: { fontSize: 12, color: '#9ca3af' }, children: ["callID ", String(part?.callID ?? ''), " \u00B7 ", String(state?.status ?? '')] }), Array.isArray(todos) ? _jsx(TodosView, { todos: todos }) : null, _jsx(ToolIO, { input: state?.input, output: state?.status === 'error' ? state?.error : state?.output })] }));
425
+ }
426
+ case 'step-start':
427
+ return _jsx(MetaRows, { rows: [['snapshot', part?.snapshot]] });
428
+ case 'step-finish':
429
+ return (_jsx(MetaRows, { rows: [
430
+ ['reason', part?.reason],
431
+ ['cost', typeof part?.cost === 'number' ? `$${part.cost.toFixed(4)}` : undefined],
432
+ ['tokens', part?.tokens],
433
+ ] }));
434
+ case 'patch':
435
+ return (_jsx(MetaRows, { rows: [
436
+ ['files', part?.files],
437
+ ['hash', part?.hash],
438
+ ] }));
439
+ case 'compaction':
440
+ return (_jsx(MetaRows, { rows: [
441
+ ['auto', typeof part?.auto === 'boolean' ? String(part.auto) : undefined],
442
+ ['overflow', typeof part?.overflow === 'boolean' ? String(part.overflow) : undefined],
443
+ ] }));
444
+ default:
445
+ return _jsx(JsonView, { value: d });
446
+ }
447
+ }
448
+ default:
449
+ // Durable-agent raw blobs (Cursor store.db, etc.) have no V1 `data`
450
+ // envelope — dump the whole payload so the expanded card isn't empty.
451
+ return _jsx(JsonView, { value: isV1RawEvent(event) ? d : event });
452
+ }
453
+ })();
454
+ return (_jsxs("div", { style: {
455
+ display: 'flex',
456
+ flexDirection: 'column',
457
+ gap: expanded ? 8 : 0,
458
+ padding: '10px 14px',
459
+ borderRadius: 0,
460
+ minWidth: 0,
461
+ overflow: 'hidden',
462
+ backgroundColor: expanded ? '#111827' : '#161b26',
463
+ fontFamily: theme.fonts.body,
464
+ fontSize: 13,
465
+ }, children: [_jsxs("button", { onClick: onToggle, "aria-expanded": expanded, style: {
466
+ display: 'flex',
467
+ alignItems: 'center',
468
+ gap: 8,
469
+ width: '100%',
470
+ border: 'none',
471
+ background: 'none',
472
+ padding: 0,
473
+ cursor: 'pointer',
474
+ fontFamily: 'inherit',
475
+ textAlign: 'left',
476
+ }, children: [_jsxs("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: ["#", event.seq] }), _jsx("span", { style: {
477
+ fontSize: 11,
478
+ fontWeight: 600,
479
+ textTransform: 'uppercase',
480
+ letterSpacing: 0.5,
481
+ color,
482
+ whiteSpace: 'nowrap',
483
+ }, children: kindLabel(kind) }), runCount && runCount > 1 ? (_jsxs("span", { title: `${runCount} separate runs of this command`, style: {
484
+ fontSize: 11,
485
+ fontWeight: 700,
486
+ color: '#f59e0b',
487
+ whiteSpace: 'nowrap',
488
+ }, children: ["\u00D7", runCount] })) : null, snapshotCount && snapshotCount > 1 ? (_jsxs("span", { title: `${snapshotCount} raw event snapshots collapsed into this row`, style: {
489
+ fontSize: 11,
490
+ fontWeight: 600,
491
+ color: '#60a5fa',
492
+ whiteSpace: 'nowrap',
493
+ }, children: [snapshotCount, " events"] })) : null, _jsx("span", { style: {
494
+ flex: 1,
495
+ overflow: 'hidden',
496
+ textOverflow: 'ellipsis',
497
+ whiteSpace: 'nowrap',
498
+ color: '#e5e7eb',
499
+ }, children: describe(event) }), _jsx("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: formatTime(eventTimestamp(event)) })] }), expanded ? body : null] }));
500
+ }
501
+ function prettifyEventType(t) {
502
+ return (t ?? '').replace(/-/g, ' ');
503
+ }
504
+ function normalizedDescribe(n) {
505
+ if (n.toolName)
506
+ return [n.toolName, n.operation].filter(Boolean).join(' · ');
507
+ if (n.operation)
508
+ return n.operation;
509
+ const d = n.data;
510
+ if (typeof d?.message === 'string')
511
+ return d.message.slice(0, 90);
512
+ return prettifyEventType(n.eventType);
513
+ }
514
+ function repoLabel(repo) {
515
+ const identity = repo.owner && repo.repo ? `${repo.owner}/${repo.repo}` : repo.repo ?? '';
516
+ return identity && repo.root ? `${identity} @ ${repo.root}` : repo.root ?? '';
517
+ }
518
+ function NormalizedEventCard({ event, seq, color, expanded, onToggle, }) {
519
+ const { theme } = useTheme();
520
+ return (_jsxs("div", { style: {
521
+ display: 'flex',
522
+ flexDirection: 'column',
523
+ gap: expanded ? 8 : 0,
524
+ padding: '10px 14px',
525
+ borderRadius: 0,
526
+ minWidth: 0,
527
+ overflow: 'hidden',
528
+ backgroundColor: expanded ? '#0d1520' : '#101722',
529
+ fontFamily: theme.fonts.body,
530
+ fontSize: 13,
531
+ }, children: [_jsxs("button", { onClick: onToggle, "aria-expanded": expanded, style: {
532
+ display: 'flex',
533
+ alignItems: 'center',
534
+ gap: 8,
535
+ width: '100%',
536
+ border: 'none',
537
+ background: 'none',
538
+ padding: 0,
539
+ cursor: 'pointer',
540
+ fontFamily: 'inherit',
541
+ textAlign: 'left',
542
+ }, children: [_jsxs("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: ["#", seq] }), _jsx("span", { style: {
543
+ fontSize: 11,
544
+ fontWeight: 600,
545
+ textTransform: 'uppercase',
546
+ letterSpacing: 0.5,
547
+ color,
548
+ whiteSpace: 'nowrap',
549
+ }, children: prettifyEventType(event.eventType) }), _jsx("span", { style: {
550
+ flex: 1,
551
+ overflow: 'hidden',
552
+ textOverflow: 'ellipsis',
553
+ whiteSpace: 'nowrap',
554
+ color: '#e5e7eb',
555
+ }, children: normalizedDescribe(event) }), _jsx("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: formatTime(event.timestamp) })] }), expanded ? (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsx(MetaRows, { rows: [
556
+ ['eventType', event.eventType],
557
+ ['operation', event.operation],
558
+ ['toolName', event.toolName],
559
+ ['sessionId', event.sessionId],
560
+ ['workingDir', event.normalizedWorkingDirectory],
561
+ ['repository', event.repository ? repoLabel(event.repository) : undefined],
562
+ ] }), event.files && event.files.length > 0 ? (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 3 }, children: [_jsxs("div", { style: { fontSize: 11, color: '#6b7280' }, children: ["files (", event.files.length, ")"] }), event.files.map((file, i) => (_jsx(FileRow, { file: file }, i)))] })) : null, event.toolInput !== undefined ? (_jsx(ToolIO, { input: event.toolInput, output: event.toolOutput })) : null] })) : null] }));
563
+ }
564
+ function FileRow({ file }) {
565
+ const { theme } = useTheme();
566
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 1 }, children: [_jsx("div", { style: {
567
+ color: '#93c5fd',
568
+ fontSize: 12,
569
+ wordBreak: 'break-word',
570
+ fontFamily: theme.fonts.monospace,
571
+ }, children: file.displayPath }), _jsxs("div", { style: { color: '#6b7280', fontSize: 11, wordBreak: 'break-word' }, children: [file.context, file.repository
572
+ ? ` · ${file.repository.gitRoot} → ${file.repository.relativePath}`
573
+ : ` · ${file.absolutePath}`] })] }));
574
+ }
575
+ const OPERATION_COLORS = {
576
+ starting: '#6b7280',
577
+ prompting: '#a78bfa',
578
+ reading: '#a855f7',
579
+ grepping: '#e879f9',
580
+ globbing: '#14b8a6',
581
+ listing: '#f97316',
582
+ editing: '#22c55e',
583
+ tool: '#3b82f6',
584
+ errored: '#ef4444',
585
+ waiting: '#9ca3af',
586
+ finished: '#10b981',
587
+ compacting: '#ec4899',
588
+ subagent: '#f59e0b',
589
+ };
590
+ function AccumulatedEventCard({ event, seq, dropReason, expanded, onToggle, }) {
591
+ const { theme } = useTheme();
592
+ if (!event) {
593
+ return (_jsxs("div", { style: {
594
+ display: 'flex',
595
+ alignItems: 'center',
596
+ gap: 8,
597
+ padding: '10px 14px',
598
+ borderRadius: 0,
599
+ minWidth: 0,
600
+ overflow: 'hidden',
601
+ border: '1px dashed #1f2937',
602
+ backgroundColor: '#0d1117',
603
+ fontFamily: theme.fonts.body,
604
+ fontSize: 12,
605
+ }, children: [_jsxs("span", { style: { color: '#374151', whiteSpace: 'nowrap' }, children: ["#", seq] }), _jsx("span", { style: { color: dropReason ? '#b45309' : '#4b5563', fontStyle: 'italic' }, children: dropReason ?? 'no UI event (accumulator dropped)' })] }));
606
+ }
607
+ const opColor = OPERATION_COLORS[event.operation] ?? '#6b7280';
608
+ return (_jsxs("div", { style: {
609
+ display: 'flex',
610
+ flexDirection: 'column',
611
+ gap: expanded ? 8 : 0,
612
+ padding: '10px 14px',
613
+ borderRadius: 0,
614
+ minWidth: 0,
615
+ overflow: 'hidden',
616
+ backgroundColor: expanded ? '#121a13' : '#141b16',
617
+ fontFamily: theme.fonts.body,
618
+ fontSize: 13,
619
+ }, children: [_jsxs("button", { onClick: onToggle, "aria-expanded": expanded, style: {
620
+ display: 'flex',
621
+ alignItems: 'center',
622
+ gap: 8,
623
+ width: '100%',
624
+ border: 'none',
625
+ background: 'none',
626
+ padding: 0,
627
+ cursor: 'pointer',
628
+ fontFamily: 'inherit',
629
+ textAlign: 'left',
630
+ }, children: [_jsx("span", { style: {
631
+ width: 8,
632
+ height: 8,
633
+ borderRadius: '50%',
634
+ flexShrink: 0,
635
+ backgroundColor: event.sessionColor,
636
+ } }), _jsxs("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: ["#", seq] }), _jsx("span", { style: {
637
+ fontSize: 11,
638
+ fontWeight: 600,
639
+ textTransform: 'uppercase',
640
+ letterSpacing: 0.5,
641
+ color: opColor,
642
+ whiteSpace: 'nowrap',
643
+ }, children: event.operation }), _jsx("span", { style: {
644
+ flex: 1,
645
+ overflow: 'hidden',
646
+ textOverflow: 'ellipsis',
647
+ whiteSpace: 'nowrap',
648
+ color: '#e5e7eb',
649
+ }, children: event.description }), _jsx("span", { style: { color: '#6b7280', fontSize: 11, whiteSpace: 'nowrap' }, children: formatTime(event.timestamp) })] }), expanded ? (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: [_jsx(MetaRows, { rows: [
650
+ ['operation', event.operation],
651
+ ['session', event.sessionName],
652
+ ['contextTokens', event.contextTokens],
653
+ ['toolName', event.toolName],
654
+ ['subagent', event.subagentType],
655
+ ['childSessionId', event.childSessionId],
656
+ ] }), _jsx("div", { style: { fontSize: 12, color: '#6b7280' }, children: event.description }), event.files.length > 0 ? _jsx(PathList, { label: "files", paths: event.files }) : null, event.dependencies.length > 0 ? (_jsx(PathList, { label: "dependencies", paths: event.dependencies })) : null, event.layers.length > 0 ? (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx("div", { style: { fontSize: 11, color: '#6b7280' }, children: "layers" }), event.layers.map((layer) => (_jsxs("div", { style: { display: 'flex', gap: 6, alignItems: 'center', fontSize: 12 }, children: [_jsx("span", { style: {
657
+ width: 8,
658
+ height: 8,
659
+ borderRadius: '50%',
660
+ backgroundColor: layer.color,
661
+ opacity: 0.8,
662
+ } }), _jsxs("span", { style: { color: '#d1d5db' }, children: [layer.name, " (", layer.items.length, ")"] })] }, layer.id)))] })) : null] })) : null] }));
663
+ }
664
+ function PathList({ label, paths }) {
665
+ const { theme } = useTheme();
666
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx("div", { style: { fontSize: 11, color: '#6b7280' }, children: label }), paths.map((p, i) => (_jsx("div", { style: { color: '#93c5fd', fontSize: 11.5, fontFamily: theme.fonts.monospace, wordBreak: 'break-word' }, children: p.displayPath }, i)))] }));
667
+ }
668
+ function TextView({ text }) {
669
+ if (!text)
670
+ return _jsx("div", { style: { color: '#6b7280', fontSize: 12 }, children: "(empty)" });
671
+ return (_jsx("div", { style: {
672
+ color: '#d1d5db',
673
+ fontSize: 12.5,
674
+ lineHeight: 1.5,
675
+ maxHeight: 120,
676
+ overflowY: 'auto',
677
+ whiteSpace: 'pre-wrap',
678
+ wordBreak: 'break-word',
679
+ }, children: text }));
680
+ }
681
+ const TODO_STATUS_COLORS = {
682
+ completed: '#22c55e',
683
+ in_progress: '#f59e0b',
684
+ pending: '#6b7280',
685
+ };
686
+ function TodosView({ todos }) {
687
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 3 }, children: [_jsxs("div", { style: { fontSize: 11, color: '#6b7280' }, children: ["todos (", todos.length, ")"] }), todos.map((t, i) => (_jsxs("div", { style: { display: 'flex', gap: 8, fontSize: 12, alignItems: 'baseline' }, children: [_jsx("span", { style: {
688
+ color: TODO_STATUS_COLORS[String(t.status ?? '')] ?? '#6b7280',
689
+ fontWeight: 600,
690
+ minWidth: 84,
691
+ whiteSpace: 'nowrap',
692
+ }, children: String(t.status ?? '') }), _jsx("span", { style: { color: '#d1d5db', wordBreak: 'break-word' }, children: String(t.content ?? '') }), typeof t.priority === 'string' && t.priority ? (_jsxs("span", { style: { color: '#6b7280', whiteSpace: 'nowrap' }, children: ["\u00B7 ", t.priority] })) : null] }, i)))] }));
693
+ }
694
+ function ToolIO({ input, output }) {
695
+ const summary = toolSummary(input);
696
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 6 }, children: [summary ? (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx("span", { style: { fontSize: 11, color: '#60a5fa', fontWeight: 600 }, children: "IN" }), _jsx("code", { style: { color: '#93c5fd', fontSize: 12, wordBreak: 'break-word' }, children: summary })] })) : null, input !== undefined && input !== null && typeof input === 'object' ? (_jsx(CodeBlock, { value: JSON.stringify(input, null, 2) })) : null, output !== undefined && output !== null ? (_jsxs(_Fragment, { children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx("span", { style: { fontSize: 11, color: '#34d399', fontWeight: 600 }, children: "OUT" }), _jsx("span", { style: { fontSize: 11, color: '#6b7280' }, children: typeof output === 'string' ? `${output.length.toLocaleString()} chars` : 'object' })] }), _jsx(CodeBlock, { value: typeof output === 'string' ? output : JSON.stringify(output, null, 2) })] })) : null] }));
697
+ }
698
+ function CodeBlock({ value }) {
699
+ return (_jsx("pre", { style: {
700
+ margin: 0,
701
+ padding: 8,
702
+ borderRadius: 6,
703
+ backgroundColor: '#0b1220',
704
+ color: '#9ca3af',
705
+ fontSize: 11.5,
706
+ lineHeight: 1.45,
707
+ maxHeight: 180,
708
+ overflow: 'auto',
709
+ whiteSpace: 'pre-wrap',
710
+ wordBreak: 'break-word',
711
+ }, children: value }));
712
+ }
713
+ function MetaRows({ rows }) {
714
+ const present = rows.filter(([, v]) => v !== undefined && v !== null && v !== '');
715
+ if (present.length === 0)
716
+ return null;
717
+ return (_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 3 }, children: present.map(([label, value]) => (_jsxs("div", { style: { display: 'flex', gap: 8, fontSize: 12 }, children: [_jsx("span", { style: { color: '#6b7280', minWidth: 76, whiteSpace: 'nowrap' }, children: label }), _jsx("span", { style: {
718
+ color: '#d1d5db',
719
+ wordBreak: 'break-word',
720
+ whiteSpace: typeof value === 'string' ? 'pre-wrap' : 'nowrap',
721
+ }, children: typeof value === 'string'
722
+ ? value
723
+ : Array.isArray(value)
724
+ ? value.join(', ')
725
+ : JSON.stringify(value) })] }, label))) }));
726
+ }
727
+ function JsonView({ value }) {
728
+ return _jsx(CodeBlock, { value: JSON.stringify(value, null, 2) });
729
+ }
730
+ /**
731
+ * Why the accumulator dropped a row's UI event, derived from the raw event
732
+ * alone (no stream context needed). Rows that don't match a known category keep
733
+ * the generic "dropped" label.
734
+ */
735
+ function dropReasonFor(raw) {
736
+ if (!raw)
737
+ return null;
738
+ if (raw.type === 'message.updated.1') {
739
+ const role = dataOf(raw).info?.role;
740
+ if (role === 'assistant') {
741
+ return 'assistant message — metadata only (feeds context/token tracking)';
742
+ }
743
+ return null; // user messages are handled by the re-save pass below
744
+ }
745
+ if (raw.type === 'message.removed.1')
746
+ return 'message removed — no UI event';
747
+ if (raw.type === 'message.part.updated.1') {
748
+ switch (partOf(raw)?.type) {
749
+ case 'reasoning':
750
+ return 'model reasoning — not surfaced in the UI';
751
+ case 'step-start':
752
+ case 'step-finish':
753
+ return 'step lifecycle — not surfaced in the UI';
754
+ case 'text':
755
+ return 'text content — not surfaced in the UI';
756
+ case 'tool':
757
+ return 'tool snapshot — folded into the tool run';
758
+ default:
759
+ return null;
760
+ }
761
+ }
762
+ return null;
763
+ }
764
+ /**
765
+ * Annotate rows the accumulator drops with *why* they were dropped, walking in
766
+ * stream order. opencode re-saves a user message on every change (seq 1, 6, 24,
767
+ * 39, 51… share one messageID), so the first occurrence becomes the `prompting`
768
+ * UI event and every re-save is deduped away — those read "re-save, ignored"
769
+ * instead of a generic "dropped".
770
+ */
771
+ function annotateDrops(items) {
772
+ const seenUserMessageIDs = new Set();
773
+ return items.map((item) => {
774
+ const raw = toRaw(item.raw);
775
+ if (!raw)
776
+ return item;
777
+ // Track user message IDs on every occurrence — the first one is the real
778
+ // prompt (it carries the accumulated UI event); later re-saves are deduped.
779
+ if (raw.type === 'message.updated.1') {
780
+ const info = dataOf(raw).info;
781
+ const messageID = info?.id;
782
+ const role = info?.role;
783
+ if (typeof messageID === 'string' && role === 'user') {
784
+ if (seenUserMessageIDs.has(messageID)) {
785
+ if (item.accumulated === null) {
786
+ return {
787
+ ...item,
788
+ dropReason: 're-save of user message — already counted as a prompt',
789
+ };
790
+ }
791
+ return item;
792
+ }
793
+ seenUserMessageIDs.add(messageID);
794
+ }
795
+ }
796
+ if (item.accumulated !== null)
797
+ return item;
798
+ const reason = dropReasonFor(raw);
799
+ if (reason)
800
+ return { ...item, dropReason: reason };
801
+ return item;
802
+ });
803
+ }
804
+ /**
805
+ * Collapse a tool invocation's snapshots into a single row. The raw V1 stream
806
+ * emits one part update per status flip (pending → running → completed) — and
807
+ * those flips can be interleaved with other events (reasoning, text, session
808
+ * bookkeeping) — so snapshots are matched by callID across the whole stream,
809
+ * not just when consecutive. Distinct calls that repeat the same command and
810
+ * are consecutive still fold into one ×N row.
811
+ *
812
+ * The merged row keeps the run's first seq as a stable key and adopts the
813
+ * **latest** snapshot's raw/normalized payload (the completed/errored part
814
+ * carries the tool output). The UI (accumulated) column instead prefers the
815
+ * group's one non-null accumulated event — the accumulator dedupes to at most
816
+ * one per invocation, and it's usually the *first* snapshot (e.g. todowrite's
817
+ * pending emits the `tool` event; running/completed are dropped).
818
+ */
819
+ function groupToolRuns(items) {
820
+ const out = [];
821
+ const byCallID = new Map();
822
+ let lastGroup = null;
823
+ let lastGroupCmd = null;
824
+ const adopt = (group, r, cmd) => {
825
+ group.snapshotCount = (group.snapshotCount ?? 1) + 1;
826
+ group.raw = r.raw;
827
+ group.normalized = r.normalized;
828
+ const acc = r.accumulated;
829
+ if (acc !== null) {
830
+ // Prefer the run's meaningful accumulated. The pending snapshot of a
831
+ // bash `ls` (empty input) emits a generic `tool` before the completed
832
+ // snapshot's `listing` arrives — replace a generic `tool` with a more
833
+ // specific operation, and never downgrade a specific one.
834
+ if (group.accumulated === null ||
835
+ (group.accumulated.operation === 'tool' && acc.operation !== 'tool')) {
836
+ group.accumulated = acc;
837
+ }
838
+ }
839
+ group.type = r.type;
840
+ lastGroup = group;
841
+ lastGroupCmd = cmd;
842
+ };
843
+ for (const r of items) {
844
+ const raw = toRaw(r.raw);
845
+ const isTool = !!raw && raw.type === 'message.part.updated.1' && partOf(raw)?.type === 'tool';
846
+ const part = partOf(raw);
847
+ const cmd = isTool
848
+ ? toolSummary(part?.state?.input)
849
+ : null;
850
+ const callID = isTool ? part?.callID : undefined;
851
+ if (!isTool) {
852
+ out.push(r);
853
+ lastGroup = null;
854
+ lastGroupCmd = null;
855
+ continue;
856
+ }
857
+ // Same invocation — fold this status snapshot in wherever it appears.
858
+ const existing = callID ? byCallID.get(callID) : undefined;
859
+ if (existing) {
860
+ adopt(existing, r, cmd);
861
+ continue;
862
+ }
863
+ // A distinct call repeating the previous group's command folds into it.
864
+ if (lastGroup && cmd !== null && cmd !== '' && cmd === lastGroupCmd) {
865
+ if (callID) {
866
+ lastGroup.callIDs = lastGroup.callIDs ?? new Set();
867
+ lastGroup.callIDs.add(callID);
868
+ byCallID.set(callID, lastGroup);
869
+ }
870
+ lastGroup.runCount = lastGroup.callIDs ? lastGroup.callIDs.size : 1;
871
+ adopt(lastGroup, r, cmd);
872
+ continue;
873
+ }
874
+ const group = {
875
+ ...r,
876
+ runCount: 1,
877
+ snapshotCount: 1,
878
+ callIDs: new Set(callID ? [callID] : []),
879
+ };
880
+ if (callID)
881
+ byCallID.set(callID, group);
882
+ out.push(group);
883
+ lastGroup = group;
884
+ lastGroupCmd = cmd;
885
+ }
886
+ return out;
887
+ }
888
+ /**
889
+ * Fold a user message's events into a single row keyed by messageID: the
890
+ * original `message.updated.1` (which carries the `prompting` accumulated
891
+ * event), every re-save of the same message (opencode re-saves a user message
892
+ * on each change), and the text part(s) that carry its content (the
893
+ * `notification` events sharing the same messageID). They all resolve to the
894
+ * one `prompting` accumulated event, so they render as one row with a snapshot
895
+ * count instead of a wall of "re-save" rows.
896
+ */
897
+ function groupPromptParts(items) {
898
+ const out = [];
899
+ const byMessageID = new Map();
900
+ for (const item of items) {
901
+ const raw = toRaw(item.raw);
902
+ if (!raw) {
903
+ out.push(item);
904
+ continue;
905
+ }
906
+ if (raw.type === 'message.updated.1') {
907
+ const info = dataOf(raw).info;
908
+ const messageID = info?.id;
909
+ const role = info?.role;
910
+ if (typeof messageID === 'string' && role === 'user') {
911
+ const existing = byMessageID.get(messageID);
912
+ if (existing) {
913
+ // re-save of the same user message — fold into its prompt row
914
+ existing.snapshotCount = (existing.snapshotCount ?? 1) + 1;
915
+ if (existing.accumulated === null && item.accumulated !== null) {
916
+ existing.accumulated = item.accumulated;
917
+ }
918
+ continue;
919
+ }
920
+ byMessageID.set(messageID, item);
921
+ }
922
+ out.push(item);
923
+ continue;
924
+ }
925
+ if (raw.type === 'message.part.updated.1') {
926
+ const part = partOf(raw);
927
+ const messageID = part?.messageID;
928
+ if (part?.type === 'text' && typeof messageID === 'string') {
929
+ const existing = byMessageID.get(messageID);
930
+ if (existing) {
931
+ existing.snapshotCount = (existing.snapshotCount ?? 1) + 1;
932
+ if (existing.accumulated === null && item.accumulated !== null) {
933
+ existing.accumulated = item.accumulated;
934
+ }
935
+ continue; // absorb the text part into its message row
936
+ }
937
+ }
938
+ out.push(item);
939
+ continue;
940
+ }
941
+ out.push(item);
942
+ }
943
+ return out;
944
+ }
945
+ export function SessionEventFeed({ title, rows }) {
946
+ const { theme } = useTheme();
947
+ const items = useMemo(() => [...rows].sort((a, b) => a.seq - b.seq), [rows]);
948
+ const [active, setActive] = useState('activity');
949
+ const [groupTools, setGroupTools] = useState(true);
950
+ const displayItems = useMemo(() => annotateDrops(groupPromptParts(groupTools ? groupToolRuns(items) : items)), [items, groupTools]);
951
+ const seqs = useMemo(() => displayItems.map((r) => r.seq), [displayItems]);
952
+ const { collapsed, toggle, setAll } = useCollapse(seqs, true);
953
+ const activePreset = PRESETS.find((p) => p.id === active) ?? PRESETS[0];
954
+ // "Generic tools" surfaces the improvement backlog: tool rows whose
955
+ // accumulated operation is still the generic `tool` fallback (e.g. bash
956
+ // commands that haven't been given a listing/reading/… type yet).
957
+ const [unprocessedOnly, setUnprocessedOnly] = useState(false);
958
+ const isVisible = (r) => unprocessedOnly
959
+ ? r.accumulated?.operation === 'tool'
960
+ : activePreset.include.includes(eventCategory(toRaw(r.raw)));
961
+ const visibleEvents = displayItems.filter(isVisible);
962
+ const presetCounts = useMemo(() => {
963
+ const map = new Map();
964
+ for (const preset of PRESETS) {
965
+ map.set(preset.id, displayItems.filter((r) => preset.include.includes(eventCategory(toRaw(r.raw)))).length);
966
+ }
967
+ return map;
968
+ }, [displayItems]);
969
+ const unprocessedCount = useMemo(() => displayItems.filter((r) => r.accumulated?.operation === 'tool').length, [displayItems]);
970
+ const expandedCount = visibleEvents.filter((r) => !collapsed.has(r.seq)).length;
971
+ return (_jsxs("div", { style: { padding: 24, backgroundColor: '#0d1117', minHeight: '100vh' }, children: [_jsxs("div", { style: {
972
+ display: 'flex',
973
+ alignItems: 'baseline',
974
+ gap: 12,
975
+ marginBottom: 4,
976
+ fontFamily: theme.fonts.body,
977
+ }, children: [_jsx("h1", { style: { margin: 0, color: '#f3f4f6', fontSize: 18, fontWeight: 600 }, children: title }), _jsxs("span", { style: { color: '#6b7280', fontSize: 12 }, children: [items.length, " raw events \u00B7 ", visibleEvents.length, " visible \u00B7 ", expandedCount, " expanded"] })] }), _jsxs("div", { style: {
978
+ display: 'flex',
979
+ gap: 6,
980
+ flexWrap: 'wrap',
981
+ marginBottom: 16,
982
+ fontFamily: theme.fonts.body,
983
+ }, children: [_jsx(FilterChip, { label: "all", active: active === 'all', onClick: () => setActive('all') }), PRESETS.filter((p) => p.id !== 'all').map((preset) => (_jsx(FilterChip, { label: `${preset.label} (${presetCounts.get(preset.id) ?? 0})`, active: active === preset.id, onClick: () => setActive(preset.id) }, preset.id))), _jsx("span", { style: { flex: 1 } }), _jsx(FilterChip, { label: `Generic tools (${unprocessedCount})`, active: unprocessedOnly, onClick: () => setUnprocessedOnly((v) => !v) }), _jsx(FilterChip, { label: groupTools ? 'Group tool runs: on' : 'Group tool runs: off', active: groupTools, onClick: () => setGroupTools((v) => !v) }), _jsx(FilterChip, { label: "Expand all", active: false, onClick: () => setAll(false) }), _jsx(FilterChip, { label: "Collapse all", active: false, onClick: () => setAll(true) })] }), _jsx(ColumnHeaders, {}), _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 8 }, children: displayItems.map((r) => (_jsx(EventRow, { row: r, sessionTitle: title, runCount: r.runCount, snapshotCount: r.snapshotCount, visible: isVisible(r), expanded: !collapsed.has(r.seq), onToggle: () => toggle(r.seq) }, r.seq))) })] }));
984
+ }
985
+ export function SessionEventFeedGrouped({ title, rows }) {
986
+ const { theme } = useTheme();
987
+ const items = useMemo(() => annotateDrops(groupPromptParts([...rows].sort((a, b) => a.seq - b.seq))), [rows]);
988
+ const byKind = useMemo(() => {
989
+ const map = new Map();
990
+ for (const r of items) {
991
+ const kind = eventKind(toRaw(r.raw));
992
+ map.set(kind, [...(map.get(kind) ?? []), r]);
993
+ }
994
+ return map;
995
+ }, [items]);
996
+ return (_jsxs("div", { style: { padding: 24, backgroundColor: '#0d1117', minHeight: '100vh' }, children: [title ? (_jsx("h1", { style: { margin: '0 0 12px', color: '#f3f4f6', fontSize: 18, fontWeight: 600, fontFamily: theme.fonts.body }, children: title })) : null, _jsx(ColumnHeaders, {}), Array.from(byKind.entries())
997
+ .sort((a, b) => b[1].length - a[1].length)
998
+ .map(([kind, group]) => (_jsx(GroupSection, { kind: kind, group: group, sessionTitle: title }, kind)))] }));
999
+ }
1000
+ function GroupSection({ kind, group, sessionTitle, }) {
1001
+ const { theme } = useTheme();
1002
+ const seqs = useMemo(() => group.map((r) => r.seq), [group]);
1003
+ const { collapsed, toggle, setAll } = useCollapse(seqs, true);
1004
+ return (_jsxs("div", { style: { marginBottom: 20 }, children: [_jsxs("div", { style: {
1005
+ display: 'flex',
1006
+ alignItems: 'center',
1007
+ gap: 8,
1008
+ marginBottom: 8,
1009
+ fontFamily: theme.fonts.body,
1010
+ }, children: [_jsx("span", { style: { color: kindColor(kind), fontWeight: 600, fontSize: 13 }, children: kindLabel(kind) }), _jsx("span", { style: { color: '#6b7280', fontSize: 12 }, children: group.length }), _jsx("span", { style: { flex: 1 } }), _jsx(FilterChip, { label: "Expand all", active: false, onClick: () => setAll(false) }), _jsx(FilterChip, { label: "Collapse all", active: false, onClick: () => setAll(true) })] }), _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: 6 }, children: group.map((r) => (_jsx(EventRow, { row: r, sessionTitle: sessionTitle, visible: true, expanded: !collapsed.has(r.seq), onToggle: () => toggle(r.seq) }, r.seq))) })] }));
1011
+ }
1012
+ function ColumnHeaders() {
1013
+ const { theme } = useTheme();
1014
+ return (_jsxs("div", { style: {
1015
+ position: 'sticky',
1016
+ top: 0,
1017
+ zIndex: 10,
1018
+ display: 'grid',
1019
+ gridTemplateColumns: '3px 1fr 1fr 1fr 28px',
1020
+ gap: 8,
1021
+ padding: '8px 14px',
1022
+ marginBottom: 8,
1023
+ backgroundColor: '#0d1117',
1024
+ borderBottom: '1px solid #1f2937',
1025
+ fontFamily: theme.fonts.body,
1026
+ }, children: [_jsx("span", {}), _jsx(HeaderLabel, { children: "Raw event" }), _jsx(HeaderLabel, { children: "Repo-normalized" }), _jsx(HeaderLabel, { children: "UI event (accumulated)" }), _jsx("span", {})] }));
1027
+ }
1028
+ function HeaderLabel({ children }) {
1029
+ return (_jsx("span", { style: {
1030
+ fontSize: 11,
1031
+ fontWeight: 600,
1032
+ textTransform: 'uppercase',
1033
+ letterSpacing: 0.5,
1034
+ color: '#9ca3af',
1035
+ }, children: children }));
1036
+ }
1037
+ /**
1038
+ * Assemble a self-contained, discussion-ready text block for one row: enough
1039
+ * identifiers and detail (session, seq, raw → normalized → UI) that the block
1040
+ * carries the whole issue without the viewer open. Paste this into a chat, an
1041
+ * agent conversation, or an issue to talk about the event.
1042
+ */
1043
+ function buildRowContext(row, sessionTitle) {
1044
+ const raw = toRaw(row.raw);
1045
+ const d = dataOf(raw);
1046
+ const part = partOf(raw);
1047
+ const state = part?.state;
1048
+ const normalized = toNormalized(row.normalized);
1049
+ const acc = row.accumulated;
1050
+ const lines = [];
1051
+ const runCount = row.runCount;
1052
+ const snapshotCount = row.snapshotCount;
1053
+ const runLabel = runCount && runCount > 1 ? ` ×${runCount} runs` : '';
1054
+ const snapLabel = snapshotCount && snapshotCount > 1 ? ` · ${snapshotCount} snapshots collapsed` : '';
1055
+ lines.push(`## Event #${row.seq} — ${kindLabel(eventKind(raw))}${runLabel}${snapLabel}`);
1056
+ lines.push(`_${formatTime(eventTimestamp(raw))} · \`${row.type}\`_`);
1057
+ lines.push('');
1058
+ if (sessionTitle)
1059
+ lines.push(`**Session:** ${sessionTitle}`);
1060
+ const sessionID = d.sessionID ?? normalized?.sessionId ?? acc?.sessionId;
1061
+ if (sessionID)
1062
+ lines.push(`Session id: \`${sessionID}\``);
1063
+ lines.push('');
1064
+ lines.push('**Raw:**');
1065
+ if (!raw) {
1066
+ lines.push('- no raw payload');
1067
+ }
1068
+ else {
1069
+ lines.push(`- event type: \`${raw.type}\``);
1070
+ if (typeof part?.type === 'string')
1071
+ lines.push(`- part type: \`${part.type}\``);
1072
+ if (typeof part?.callID === 'string')
1073
+ lines.push(`- callID: \`${part.callID}\``);
1074
+ if (typeof part?.tool === 'string')
1075
+ lines.push(`- tool: \`${part.tool}\``);
1076
+ if (typeof state?.status === 'string')
1077
+ lines.push(`- status: \`${state.status}\``);
1078
+ const inSummary = toolSummary(state?.input);
1079
+ if (inSummary)
1080
+ lines.push(`- input: \`${inSummary}\``);
1081
+ const out = state?.status === 'error' ? state?.error : state?.output;
1082
+ if (typeof out === 'string') {
1083
+ const preview = out.length > 500 ? `${out.slice(0, 500)}\n…[+${out.length - 500} chars]` : out;
1084
+ lines.push(`- output (${out.length.toLocaleString()} chars):\n\`\`\`\n${preview}\n\`\`\``);
1085
+ }
1086
+ }
1087
+ lines.push('');
1088
+ if (normalized && typeof normalized.eventType === 'string') {
1089
+ lines.push('**Normalized:**');
1090
+ lines.push(`- eventType: \`${normalized.eventType}\``);
1091
+ if (typeof normalized.operation === 'string' && normalized.operation) {
1092
+ lines.push(`- operation: \`${normalized.operation}\``);
1093
+ }
1094
+ if (typeof normalized.toolName === 'string' && normalized.toolName) {
1095
+ lines.push(`- toolName: \`${normalized.toolName}\``);
1096
+ }
1097
+ const files = normalized.files ?? [];
1098
+ if (files.length > 0) {
1099
+ lines.push(`- files: ${files.map((f) => `\`${f.displayPath}\``).join(', ')}`);
1100
+ }
1101
+ lines.push('');
1102
+ }
1103
+ if (acc) {
1104
+ lines.push('**UI event (accumulated):**');
1105
+ lines.push(`- operation: \`${acc.operation}\``);
1106
+ lines.push(`- description: ${acc.description}`);
1107
+ if (typeof acc.contextTokens === 'number' && acc.contextTokens > 0) {
1108
+ lines.push(`- contextTokens: ${acc.contextTokens}`);
1109
+ }
1110
+ if (acc.files.length > 0) {
1111
+ lines.push(`- files: ${acc.files.map((f) => f.displayPath).join(', ')}`);
1112
+ }
1113
+ }
1114
+ else {
1115
+ const dropReason = row.dropReason;
1116
+ lines.push(`**UI event:** ${dropReason ?? 'none (accumulator dropped this event)'}`);
1117
+ }
1118
+ return lines.join('\n');
1119
+ }
1120
+ async function copyRowContext(row, sessionTitle) {
1121
+ const text = buildRowContext(row, sessionTitle);
1122
+ try {
1123
+ await navigator.clipboard.writeText(text);
1124
+ return true;
1125
+ }
1126
+ catch (err) {
1127
+ console.error('[session-events] copy failed:', err);
1128
+ return false;
1129
+ }
1130
+ }
1131
+ function EventRow({ row, sessionTitle, runCount, snapshotCount, visible, expanded, onToggle, }) {
1132
+ const raw = toRaw(row.raw);
1133
+ const normalized = toNormalized(row.normalized);
1134
+ const { theme } = useTheme();
1135
+ const [copied, setCopied] = useState(false);
1136
+ if (!visible)
1137
+ return _jsx(FilteredOutLine, { raw: raw });
1138
+ const color = kindColor(eventKind(raw));
1139
+ const files = normalized?.files;
1140
+ const hasPaths = !!files && files.length > 0;
1141
+ const onCopy = () => {
1142
+ void copyRowContext(row, sessionTitle).then((ok) => {
1143
+ if (!ok)
1144
+ return;
1145
+ setCopied(true);
1146
+ setTimeout(() => setCopied(false), 2000);
1147
+ });
1148
+ };
1149
+ return (_jsxs("div", { style: {
1150
+ display: 'grid',
1151
+ gridTemplateColumns: '3px 1fr 1fr 1fr 28px',
1152
+ gridAutoRows: 'min-content',
1153
+ gap: 8,
1154
+ }, children: [_jsx("div", { title: hasPaths ? `${files.length} normalized path(s)` : 'no paths to normalize', style: {
1155
+ backgroundColor: hasPaths ? '#10b981' : '#232c39',
1156
+ } }), _jsx(RawEventCard, { event: raw, runCount: runCount, snapshotCount: snapshotCount, expanded: expanded, onToggle: onToggle }), normalized ? (_jsx(NormalizedEventCard, { event: normalized, seq: row.seq, color: color, expanded: expanded, onToggle: onToggle })) : null, _jsx(AccumulatedEventCard, { event: row.accumulated, seq: row.seq, dropReason: row.dropReason, expanded: expanded, onToggle: onToggle }), _jsx("button", { type: "button", onClick: (e) => {
1157
+ e.preventDefault();
1158
+ e.stopPropagation();
1159
+ onCopy();
1160
+ }, title: "Copy this row's context for a discussion", "aria-label": "Copy row context", style: {
1161
+ display: 'flex',
1162
+ alignItems: 'center',
1163
+ justifyContent: 'center',
1164
+ alignSelf: 'stretch',
1165
+ padding: 0,
1166
+ border: 'none',
1167
+ borderRadius: 4,
1168
+ appearance: 'none',
1169
+ cursor: 'pointer',
1170
+ background: copied ? 'rgba(16,185,129,0.12)' : 'transparent',
1171
+ color: copied ? '#10b981' : theme.colors.textTertiary,
1172
+ fontSize: 12,
1173
+ }, children: copied ? _jsx(Check, { size: 13 }) : _jsx(Copy, { size: 13 }) })] }));
1174
+ }
1175
+ function FilteredOutLine({ raw }) {
1176
+ const color = kindColor(eventKind(raw));
1177
+ return (_jsx("div", { title: describe(raw), style: {
1178
+ height: 2,
1179
+ backgroundColor: color,
1180
+ opacity: 0.16,
1181
+ cursor: 'default',
1182
+ } }));
1183
+ }
1184
+ function FilterChip({ label, active, color, onClick, }) {
1185
+ return (_jsx("button", { onClick: onClick, style: {
1186
+ padding: '4px 10px',
1187
+ borderRadius: 999,
1188
+ border: `1px solid ${active ? color ?? '#3b82f6' : '#1f2937'}`,
1189
+ backgroundColor: active ? (color ?? '#3b82f6') + '22' : 'transparent',
1190
+ color: active ? '#f3f4f6' : '#9ca3af',
1191
+ fontSize: 11.5,
1192
+ cursor: 'pointer',
1193
+ fontFamily: 'inherit',
1194
+ }, children: label }));
1195
+ }
1196
+ //# sourceMappingURL=SessionEventFeed.js.map