@flanksource/clicky-ui 0.3.29 → 0.3.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/dist/ai.cjs +48 -3
  2. package/dist/ai.cjs.map +1 -1
  3. package/dist/ai.js +46 -1
  4. package/dist/ai.js.map +1 -1
  5. package/dist/comments/CommentCard.cjs +110 -262
  6. package/dist/comments/CommentCard.cjs.map +1 -1
  7. package/dist/comments/CommentCard.d.ts +3 -1
  8. package/dist/comments/CommentCard.d.ts.map +1 -1
  9. package/dist/comments/CommentCard.js +105 -257
  10. package/dist/comments/CommentCard.js.map +1 -1
  11. package/dist/comments/CommentCardParts.cjs +95 -0
  12. package/dist/comments/CommentCardParts.cjs.map +1 -0
  13. package/dist/comments/CommentCardParts.d.ts +17 -0
  14. package/dist/comments/CommentCardParts.d.ts.map +1 -0
  15. package/dist/comments/CommentCardParts.js +95 -0
  16. package/dist/comments/CommentCardParts.js.map +1 -0
  17. package/dist/comments/CommentSidePanel.cjs +14 -7
  18. package/dist/comments/CommentSidePanel.cjs.map +1 -1
  19. package/dist/comments/CommentSidePanel.d.ts +3 -1
  20. package/dist/comments/CommentSidePanel.d.ts.map +1 -1
  21. package/dist/comments/CommentSidePanel.js +14 -7
  22. package/dist/comments/CommentSidePanel.js.map +1 -1
  23. package/dist/comments/CommentThread.cjs +2 -0
  24. package/dist/comments/CommentThread.cjs.map +1 -1
  25. package/dist/comments/CommentThread.d.ts +2 -1
  26. package/dist/comments/CommentThread.d.ts.map +1 -1
  27. package/dist/comments/CommentThread.js +2 -0
  28. package/dist/comments/CommentThread.js.map +1 -1
  29. package/dist/comments/CommentThreadList.cjs +50 -34
  30. package/dist/comments/CommentThreadList.cjs.map +1 -1
  31. package/dist/comments/CommentThreadList.d.ts +3 -1
  32. package/dist/comments/CommentThreadList.d.ts.map +1 -1
  33. package/dist/comments/CommentThreadList.js +50 -34
  34. package/dist/comments/CommentThreadList.js.map +1 -1
  35. package/dist/components/ComboboxMenu.cjs +4 -1
  36. package/dist/components/ComboboxMenu.cjs.map +1 -1
  37. package/dist/components/ComboboxMenu.d.ts.map +1 -1
  38. package/dist/components/ComboboxMenu.js +5 -2
  39. package/dist/components/ComboboxMenu.js.map +1 -1
  40. package/dist/components/ComboboxTags.cjs +5 -1
  41. package/dist/components/ComboboxTags.cjs.map +1 -1
  42. package/dist/components/ComboboxTags.d.ts.map +1 -1
  43. package/dist/components/ComboboxTags.js +6 -2
  44. package/dist/components/ComboboxTags.js.map +1 -1
  45. package/dist/components/ConnectionLoggingPolicy.cjs +24 -35
  46. package/dist/components/ConnectionLoggingPolicy.cjs.map +1 -1
  47. package/dist/components/ConnectionLoggingPolicy.d.ts.map +1 -1
  48. package/dist/components/ConnectionLoggingPolicy.js +24 -35
  49. package/dist/components/ConnectionLoggingPolicy.js.map +1 -1
  50. package/dist/components/DateField.d.ts +1 -1
  51. package/dist/components/DatePicker.d.ts +1 -1
  52. package/dist/components/DateTimePicker.d.ts +1 -1
  53. package/dist/components/MultiSelect.cjs.map +1 -1
  54. package/dist/components/MultiSelect.d.ts +7 -0
  55. package/dist/components/MultiSelect.d.ts.map +1 -1
  56. package/dist/components/MultiSelect.js.map +1 -1
  57. package/dist/components/filter-bar-multi.cjs +10 -1
  58. package/dist/components/filter-bar-multi.cjs.map +1 -1
  59. package/dist/components/filter-bar-multi.d.ts.map +1 -1
  60. package/dist/components/filter-bar-multi.js +11 -2
  61. package/dist/components/filter-bar-multi.js.map +1 -1
  62. package/dist/components/mdx-editor-callout-model.d.ts +1 -1
  63. package/dist/data/MarkdownEditor.model.d.ts +1 -1
  64. package/dist/data/ai/ChatWindow.catalogs.cjs +11 -5
  65. package/dist/data/ai/ChatWindow.catalogs.cjs.map +1 -1
  66. package/dist/data/ai/ChatWindow.catalogs.d.ts +2 -1
  67. package/dist/data/ai/ChatWindow.catalogs.d.ts.map +1 -1
  68. package/dist/data/ai/ChatWindow.catalogs.js +11 -5
  69. package/dist/data/ai/ChatWindow.catalogs.js.map +1 -1
  70. package/dist/data/ai/ChatWindow.cjs +1 -0
  71. package/dist/data/ai/ChatWindow.cjs.map +1 -1
  72. package/dist/data/ai/ChatWindow.d.ts.map +1 -1
  73. package/dist/data/ai/ChatWindow.js +1 -0
  74. package/dist/data/ai/ChatWindow.js.map +1 -1
  75. package/dist/data/ai/PromptRunEditor/VariablesField.cjs +79 -0
  76. package/dist/data/ai/PromptRunEditor/VariablesField.cjs.map +1 -0
  77. package/dist/data/ai/PromptRunEditor/VariablesField.d.ts +8 -0
  78. package/dist/data/ai/PromptRunEditor/VariablesField.d.ts.map +1 -0
  79. package/dist/data/ai/PromptRunEditor/VariablesField.js +79 -0
  80. package/dist/data/ai/PromptRunEditor/VariablesField.js.map +1 -0
  81. package/dist/data/ai/PromptRunEditor/index.cjs +61 -69
  82. package/dist/data/ai/PromptRunEditor/index.cjs.map +1 -1
  83. package/dist/data/ai/PromptRunEditor/index.d.ts +11 -1
  84. package/dist/data/ai/PromptRunEditor/index.d.ts.map +1 -1
  85. package/dist/data/ai/PromptRunEditor/index.js +61 -69
  86. package/dist/data/ai/PromptRunEditor/index.js.map +1 -1
  87. package/dist/data/ai/PromptRunEditor/model.cjs.map +1 -1
  88. package/dist/data/ai/PromptRunEditor/model.d.ts +2 -0
  89. package/dist/data/ai/PromptRunEditor/model.d.ts.map +1 -1
  90. package/dist/data/ai/PromptRunEditor/model.js.map +1 -1
  91. package/dist/data/ai/SessionViewer.model.cjs +23 -8
  92. package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
  93. package/dist/data/ai/SessionViewer.model.d.ts +8 -0
  94. package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
  95. package/dist/data/ai/SessionViewer.model.js +23 -8
  96. package/dist/data/ai/SessionViewer.model.js.map +1 -1
  97. package/dist/data/ai/SessionViewer.rows.cjs +9 -1
  98. package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
  99. package/dist/data/ai/SessionViewer.rows.js +9 -1
  100. package/dist/data/ai/SessionViewer.rows.js.map +1 -1
  101. package/dist/data/ai/SpecRuntimeEditor/ModelSection.cjs +4 -3
  102. package/dist/data/ai/SpecRuntimeEditor/ModelSection.cjs.map +1 -1
  103. package/dist/data/ai/SpecRuntimeEditor/ModelSection.d.ts.map +1 -1
  104. package/dist/data/ai/SpecRuntimeEditor/ModelSection.js +2 -1
  105. package/dist/data/ai/SpecRuntimeEditor/ModelSection.js.map +1 -1
  106. package/dist/data/ai/SpecRuntimeEditor/PermissionModeField.cjs +2 -2
  107. package/dist/data/ai/SpecRuntimeEditor/PermissionModeField.cjs.map +1 -1
  108. package/dist/data/ai/SpecRuntimeEditor/PermissionModeField.js +1 -1
  109. package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs +24 -2
  110. package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs.map +1 -1
  111. package/dist/data/ai/SpecRuntimeEditor/VerifySection.d.ts.map +1 -1
  112. package/dist/data/ai/SpecRuntimeEditor/VerifySection.js +25 -3
  113. package/dist/data/ai/SpecRuntimeEditor/VerifySection.js.map +1 -1
  114. package/dist/data/ai/SpecRuntimeEditor/index.cjs +4 -3
  115. package/dist/data/ai/SpecRuntimeEditor/index.cjs.map +1 -1
  116. package/dist/data/ai/SpecRuntimeEditor/index.d.ts.map +1 -1
  117. package/dist/data/ai/SpecRuntimeEditor/index.js +2 -1
  118. package/dist/data/ai/SpecRuntimeEditor/index.js.map +1 -1
  119. package/dist/data/ai/SpecRuntimeEditor/summaries.cjs.map +1 -1
  120. package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts.map +1 -1
  121. package/dist/data/ai/SpecRuntimeEditor/summaries.js.map +1 -1
  122. package/dist/data/ai/SpecRuntimeEditor.model.cjs +4 -0
  123. package/dist/data/ai/SpecRuntimeEditor.model.cjs.map +1 -1
  124. package/dist/data/ai/SpecRuntimeEditor.model.d.ts +4 -0
  125. package/dist/data/ai/SpecRuntimeEditor.model.d.ts.map +1 -1
  126. package/dist/data/ai/SpecRuntimeEditor.model.js +4 -0
  127. package/dist/data/ai/SpecRuntimeEditor.model.js.map +1 -1
  128. package/dist/data/ai/index.d.ts +3 -2
  129. package/dist/data/ai/index.d.ts.map +1 -1
  130. package/dist/data/ai/runtime-profile.cjs.map +1 -1
  131. package/dist/data/ai/runtime-profile.d.ts +9 -7
  132. package/dist/data/ai/runtime-profile.d.ts.map +1 -1
  133. package/dist/data/ai/runtime-profile.js.map +1 -1
  134. package/dist/data/ai/runtime-profiles/OrderedPresetSelect.cjs +111 -0
  135. package/dist/data/ai/runtime-profiles/OrderedPresetSelect.cjs.map +1 -0
  136. package/dist/data/ai/runtime-profiles/OrderedPresetSelect.d.ts +7 -0
  137. package/dist/data/ai/runtime-profiles/OrderedPresetSelect.d.ts.map +1 -0
  138. package/dist/data/ai/runtime-profiles/OrderedPresetSelect.js +111 -0
  139. package/dist/data/ai/runtime-profiles/OrderedPresetSelect.js.map +1 -0
  140. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs +313 -0
  141. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs.map +1 -0
  142. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.d.ts +8 -0
  143. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.d.ts.map +1 -0
  144. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js +313 -0
  145. package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js.map +1 -0
  146. package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.cjs +98 -0
  147. package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.cjs.map +1 -0
  148. package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.d.ts +11 -0
  149. package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.d.ts.map +1 -0
  150. package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.js +98 -0
  151. package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.js.map +1 -0
  152. package/dist/data/ai/runtime-profiles/PresetSpecEditor.cjs +35 -0
  153. package/dist/data/ai/runtime-profiles/PresetSpecEditor.cjs.map +1 -0
  154. package/dist/data/ai/runtime-profiles/PresetSpecEditor.d.ts +11 -0
  155. package/dist/data/ai/runtime-profiles/PresetSpecEditor.d.ts.map +1 -0
  156. package/dist/data/ai/runtime-profiles/PresetSpecEditor.js +35 -0
  157. package/dist/data/ai/runtime-profiles/PresetSpecEditor.js.map +1 -0
  158. package/dist/data/ai/runtime-profiles/PresetWorkspace.cjs +179 -0
  159. package/dist/data/ai/runtime-profiles/PresetWorkspace.cjs.map +1 -0
  160. package/dist/data/ai/runtime-profiles/PresetWorkspace.d.ts +22 -0
  161. package/dist/data/ai/runtime-profiles/PresetWorkspace.d.ts.map +1 -0
  162. package/dist/data/ai/runtime-profiles/PresetWorkspace.js +179 -0
  163. package/dist/data/ai/runtime-profiles/PresetWorkspace.js.map +1 -0
  164. package/dist/data/ai/runtime-profiles/ProfileSpecEditor.cjs +57 -0
  165. package/dist/data/ai/runtime-profiles/ProfileSpecEditor.cjs.map +1 -0
  166. package/dist/data/ai/runtime-profiles/ProfileSpecEditor.d.ts +18 -0
  167. package/dist/data/ai/runtime-profiles/ProfileSpecEditor.d.ts.map +1 -0
  168. package/dist/data/ai/runtime-profiles/ProfileSpecEditor.js +57 -0
  169. package/dist/data/ai/runtime-profiles/ProfileSpecEditor.js.map +1 -0
  170. package/dist/data/ai/runtime-profiles/ProfileWorkspace.cjs +135 -0
  171. package/dist/data/ai/runtime-profiles/ProfileWorkspace.cjs.map +1 -0
  172. package/dist/data/ai/runtime-profiles/ProfileWorkspace.d.ts +23 -0
  173. package/dist/data/ai/runtime-profiles/ProfileWorkspace.d.ts.map +1 -0
  174. package/dist/data/ai/runtime-profiles/ProfileWorkspace.js +135 -0
  175. package/dist/data/ai/runtime-profiles/ProfileWorkspace.js.map +1 -0
  176. package/dist/data/ai/runtime-profiles/ResolutionInspector.cjs +85 -0
  177. package/dist/data/ai/runtime-profiles/ResolutionInspector.cjs.map +1 -0
  178. package/dist/data/ai/runtime-profiles/ResolutionInspector.d.ts +7 -0
  179. package/dist/data/ai/runtime-profiles/ResolutionInspector.d.ts.map +1 -0
  180. package/dist/data/ai/runtime-profiles/ResolutionInspector.js +85 -0
  181. package/dist/data/ai/runtime-profiles/ResolutionInspector.js.map +1 -0
  182. package/dist/data/ai/runtime-profiles/ResolutionTrace.cjs +42 -0
  183. package/dist/data/ai/runtime-profiles/ResolutionTrace.cjs.map +1 -0
  184. package/dist/data/ai/runtime-profiles/ResolutionTrace.d.ts +6 -0
  185. package/dist/data/ai/runtime-profiles/ResolutionTrace.d.ts.map +1 -0
  186. package/dist/data/ai/runtime-profiles/ResolutionTrace.js +42 -0
  187. package/dist/data/ai/runtime-profiles/ResolutionTrace.js.map +1 -0
  188. package/dist/data/ai/runtime-profiles/RuntimeLibraryList.cjs +93 -0
  189. package/dist/data/ai/runtime-profiles/RuntimeLibraryList.cjs.map +1 -0
  190. package/dist/data/ai/runtime-profiles/RuntimeLibraryList.d.ts +18 -0
  191. package/dist/data/ai/runtime-profiles/RuntimeLibraryList.d.ts.map +1 -0
  192. package/dist/data/ai/runtime-profiles/RuntimeLibraryList.js +93 -0
  193. package/dist/data/ai/runtime-profiles/RuntimeLibraryList.js.map +1 -0
  194. package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.cjs +44 -0
  195. package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.cjs.map +1 -0
  196. package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.d.ts +6 -0
  197. package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.d.ts.map +1 -0
  198. package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.js +44 -0
  199. package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.js.map +1 -0
  200. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.cjs +198 -0
  201. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.cjs.map +1 -0
  202. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.d.ts +12 -0
  203. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.d.ts.map +1 -0
  204. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.js +198 -0
  205. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.js.map +1 -0
  206. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.cjs +97 -0
  207. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.cjs.map +1 -0
  208. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.d.ts +26 -0
  209. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.d.ts.map +1 -0
  210. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.js +97 -0
  211. package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.js.map +1 -0
  212. package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.cjs +143 -0
  213. package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.cjs.map +1 -0
  214. package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.d.ts +25 -0
  215. package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.d.ts.map +1 -0
  216. package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.js +143 -0
  217. package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.js.map +1 -0
  218. package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.cjs +41 -0
  219. package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.cjs.map +1 -0
  220. package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.d.ts +8 -0
  221. package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.d.ts.map +1 -0
  222. package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.js +41 -0
  223. package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.js.map +1 -0
  224. package/dist/data/ai/runtime-profiles/index.d.ts +20 -0
  225. package/dist/data/ai/runtime-profiles/index.d.ts.map +1 -0
  226. package/dist/data/ai/runtime-profiles/types.d.ts +50 -0
  227. package/dist/data/ai/runtime-profiles/types.d.ts.map +1 -0
  228. package/dist/data/ai/runtime-profiles/use-permission-catalog.cjs +37 -0
  229. package/dist/data/ai/runtime-profiles/use-permission-catalog.cjs.map +1 -0
  230. package/dist/data/ai/runtime-profiles/use-permission-catalog.d.ts +5 -0
  231. package/dist/data/ai/runtime-profiles/use-permission-catalog.d.ts.map +1 -0
  232. package/dist/data/ai/runtime-profiles/use-permission-catalog.js +37 -0
  233. package/dist/data/ai/runtime-profiles/use-permission-catalog.js.map +1 -0
  234. package/dist/data/ai/runtime-profiles/use-resolution.cjs +43 -0
  235. package/dist/data/ai/runtime-profiles/use-resolution.cjs.map +1 -0
  236. package/dist/data/ai/runtime-profiles/use-resolution.d.ts +4 -0
  237. package/dist/data/ai/runtime-profiles/use-resolution.d.ts.map +1 -0
  238. package/dist/data/ai/runtime-profiles/use-resolution.js +43 -0
  239. package/dist/data/ai/runtime-profiles/use-resolution.js.map +1 -0
  240. package/dist/data/ai/runtime-profiles/use-runtime-families.cjs +38 -0
  241. package/dist/data/ai/runtime-profiles/use-runtime-families.cjs.map +1 -0
  242. package/dist/data/ai/runtime-profiles/use-runtime-families.d.ts +3 -0
  243. package/dist/data/ai/runtime-profiles/use-runtime-families.d.ts.map +1 -0
  244. package/dist/data/ai/runtime-profiles/use-runtime-families.js +38 -0
  245. package/dist/data/ai/runtime-profiles/use-runtime-families.js.map +1 -0
  246. package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.cjs +107 -0
  247. package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.cjs.map +1 -0
  248. package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.d.ts +35 -0
  249. package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.d.ts.map +1 -0
  250. package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.js +107 -0
  251. package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.js.map +1 -0
  252. package/dist/data/ai/use-session-scroll.cjs.map +1 -1
  253. package/dist/data/ai/use-session-scroll.d.ts +2 -2
  254. package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
  255. package/dist/data/ai/use-session-scroll.js.map +1 -1
  256. package/dist/data/badge-variants.d.ts +1 -1
  257. package/dist/data/runtime/RuntimeBar.cjs +3 -2
  258. package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
  259. package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
  260. package/dist/data/runtime/RuntimeBar.js +3 -2
  261. package/dist/data/runtime/RuntimeBar.js.map +1 -1
  262. package/dist/data/runtime/runtime-field-support.cjs +3 -3
  263. package/dist/data/runtime/runtime-field-support.cjs.map +1 -1
  264. package/dist/data/runtime/runtime-field-support.js +1 -1
  265. package/dist/data/runtime/runtime-mode.cjs +14 -47
  266. package/dist/data/runtime/runtime-mode.cjs.map +1 -1
  267. package/dist/data/runtime/runtime-mode.d.ts +5 -7
  268. package/dist/data/runtime/runtime-mode.d.ts.map +1 -1
  269. package/dist/data/runtime/runtime-mode.js +7 -39
  270. package/dist/data/runtime/runtime-mode.js.map +1 -1
  271. package/dist/data/test-runner/TestRunner.cjs +6 -4
  272. package/dist/data/test-runner/TestRunner.cjs.map +1 -1
  273. package/dist/data/test-runner/TestRunner.d.ts +10 -1
  274. package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
  275. package/dist/data/test-runner/TestRunner.js +6 -4
  276. package/dist/data/test-runner/TestRunner.js.map +1 -1
  277. package/dist/data/verification/VerificationResults.cjs +99 -0
  278. package/dist/data/verification/VerificationResults.cjs.map +1 -0
  279. package/dist/data/verification/VerificationResults.d.ts +27 -0
  280. package/dist/data/verification/VerificationResults.d.ts.map +1 -0
  281. package/dist/data/verification/VerificationResults.js +99 -0
  282. package/dist/data/verification/VerificationResults.js.map +1 -0
  283. package/dist/data/verification/adapterViews.cjs +116 -0
  284. package/dist/data/verification/adapterViews.cjs.map +1 -0
  285. package/dist/data/verification/adapterViews.d.ts +13 -0
  286. package/dist/data/verification/adapterViews.d.ts.map +1 -0
  287. package/dist/data/verification/adapterViews.js +116 -0
  288. package/dist/data/verification/adapterViews.js.map +1 -0
  289. package/dist/data/verification/adapters.cjs +26 -0
  290. package/dist/data/verification/adapters.cjs.map +1 -0
  291. package/dist/data/verification/adapters.d.ts +6 -0
  292. package/dist/data/verification/adapters.d.ts.map +1 -0
  293. package/dist/data/verification/adapters.js +26 -0
  294. package/dist/data/verification/adapters.js.map +1 -0
  295. package/dist/data/verification/index.d.ts +5 -0
  296. package/dist/data/verification/index.d.ts.map +1 -0
  297. package/dist/data/verification/verify-report.cjs +58 -0
  298. package/dist/data/verification/verify-report.cjs.map +1 -0
  299. package/dist/data/verification/verify-report.d.ts +96 -0
  300. package/dist/data/verification/verify-report.d.ts.map +1 -0
  301. package/dist/data/verification/verify-report.js +58 -0
  302. package/dist/data/verification/verify-report.js.map +1 -0
  303. package/dist/data/verification/verifyReportTests.cjs +83 -0
  304. package/dist/data/verification/verifyReportTests.cjs.map +1 -0
  305. package/dist/data/verification/verifyReportTests.d.ts +13 -0
  306. package/dist/data/verification/verifyReportTests.d.ts.map +1 -0
  307. package/dist/data/verification/verifyReportTests.js +83 -0
  308. package/dist/data/verification/verifyReportTests.js.map +1 -0
  309. package/dist/data/version-info.cjs +3 -3
  310. package/dist/data/version-info.js +3 -3
  311. package/dist/data.cjs +10 -0
  312. package/dist/data.cjs.map +1 -1
  313. package/dist/data.d.ts +1 -0
  314. package/dist/data.d.ts.map +1 -1
  315. package/dist/data.js +10 -0
  316. package/dist/data.js.map +1 -1
  317. package/dist/index.cjs +62 -0
  318. package/dist/index.cjs.map +1 -1
  319. package/dist/index.js +62 -0
  320. package/dist/index.js.map +1 -1
  321. package/dist/lib/permission-strategies.cjs +155 -0
  322. package/dist/lib/permission-strategies.cjs.map +1 -0
  323. package/dist/lib/permission-strategies.d.ts +35 -0
  324. package/dist/lib/permission-strategies.d.ts.map +1 -0
  325. package/dist/lib/permission-strategies.js +155 -0
  326. package/dist/lib/permission-strategies.js.map +1 -0
  327. package/dist/lib/runtime-family.cjs +51 -0
  328. package/dist/lib/runtime-family.cjs.map +1 -0
  329. package/dist/lib/runtime-family.d.ts +25 -0
  330. package/dist/lib/runtime-family.d.ts.map +1 -0
  331. package/dist/lib/runtime-family.js +51 -0
  332. package/dist/lib/runtime-family.js.map +1 -0
  333. package/dist/lib/runtime-profile-model.cjs +129 -0
  334. package/dist/lib/runtime-profile-model.cjs.map +1 -0
  335. package/dist/lib/runtime-profile-model.d.ts +30 -0
  336. package/dist/lib/runtime-profile-model.d.ts.map +1 -0
  337. package/dist/lib/runtime-profile-model.js +129 -0
  338. package/dist/lib/runtime-profile-model.js.map +1 -0
  339. package/dist/styles.css +1 -1
  340. package/dist/utils.cjs +52 -0
  341. package/dist/utils.cjs.map +1 -1
  342. package/dist/utils.d.ts +5 -0
  343. package/dist/utils.d.ts.map +1 -1
  344. package/dist/utils.js +53 -1
  345. package/dist/utils.js.map +1 -1
  346. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-mode.js","sources":["../../../src/data/runtime/runtime-mode.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\nimport { UiCloud, UiColumns, UiRobotAi, UiTerminal } from \"../../icons\";\nimport type { JsonSchemaProperty } from \"../../components/json-schema-form-types\";\nimport type { ChatModel, RuntimeAvailability } from \"../chat/types\";\nimport {\n availabilityText,\n isSelectableModel,\n isUnavailable,\n unsupportedAvailability,\n} from \"./availability\";\n\n// A runtime has two independent axes: the model selects a provider family and\n// `spec.mode` selects api | agent | cli | cmux. The mode never contains a\n// provider name. This file used to call that axis `backend`, which is also what\n// captain called the composite adapter id it once served — so a value read from\n// one and posted back as the other type-checked and ran the wrong runtime.\n\nexport const SPEC_RUNTIME_MODES = [\"api\", \"agent\", \"cli\", \"cmux\"] as const;\nexport type SpecRuntimeMode = (typeof SPEC_RUNTIME_MODES)[number];\n\nexport function isSpecRuntimeMode(\n value: string | undefined,\n): value is SpecRuntimeMode {\n return SPEC_RUNTIME_MODES.some((mode) => mode === value);\n}\n\nexport function runtimeModeFromModel(\n model: string | undefined,\n): SpecRuntimeMode | undefined {\n const [prefix] = (model ?? \"\").trim().toLowerCase().split(\":\");\n return isSpecRuntimeMode(prefix) ? prefix : undefined;\n}\n\nexport function runtimeModelError(\n model: string | undefined,\n): string | undefined {\n for (const raw of (model ?? \"\").split(\",\")) {\n const compact = raw.trim();\n if (!compact || !compact.includes(\":\")) continue;\n const parts = compact.split(\":\").map((part) => part.trim());\n const [mode, name, effort] = parts;\n if (!isSpecRuntimeMode(mode)) {\n return `Invalid model configuration: mode ${JSON.stringify(mode)} in model ${JSON.stringify(compact)}. Expected api, agent, cli, or cmux.`;\n }\n if (!name || parts.length > 3) {\n return `Invalid model configuration: model ${JSON.stringify(compact)}. Expected mode:model[:effort].`;\n }\n if (\n effort !== undefined &&\n ![\"low\", \"medium\", \"high\", \"xhigh\", \"max\", \"ultra\"].includes(effort)\n ) {\n return `Invalid model configuration: effort ${JSON.stringify(effort)} in model ${JSON.stringify(compact)}.`;\n }\n }\n return undefined;\n}\n\nexport function runtimeModeError(\n families: SpecRuntimeFamily[],\n mode: string | undefined,\n familyId?: string | undefined,\n): string | undefined {\n if (!mode) return undefined;\n if (!isSpecRuntimeMode(mode)) {\n return `Invalid model configuration: mode ${JSON.stringify(mode)}. Expected api, agent, cli, or cmux.`;\n }\n const family = familyId\n ? families.find((entry) => entry.id === familyId)\n : undefined;\n if (family && !family.modes.some((entry) => entry.id === mode)) {\n return `Invalid model configuration: mode ${JSON.stringify(mode)} is not available for ${family.label}.`;\n }\n if (!families.some((entry) => entry.modes.some((m) => m.id === mode))) {\n return `Invalid model configuration: mode ${JSON.stringify(mode)} is missing from the runtime catalog.`;\n }\n return undefined;\n}\n\nexport type SpecRuntimeModeOption = {\n /** The canonical `spec.mode`: api | agent | cli | cmux. */\n id: string;\n label: string;\n icon?: StaticIconComponent | undefined;\n title?: string | undefined;\n provider?: string | undefined;\n defaultModel?: string | undefined;\n availability?: RuntimeAvailability | undefined;\n permissions?: RuntimePermissionCapabilities | undefined;\n schema?: RuntimeSpecSchema | undefined;\n};\n\nexport type RuntimeArgumentImplementation = \"mapped\" | \"managed\";\n\nexport type RuntimeArgumentMapping = {\n name: string;\n implementation: RuntimeArgumentImplementation;\n description?: string | undefined;\n};\n\nexport type RuntimeSpecSchema = JsonSchemaProperty & {\n \"x-clicky-arguments\"?: RuntimeArgumentMapping[] | undefined;\n \"x-clicky-managed-arguments\"?: RuntimeArgumentMapping[] | undefined;\n};\n\nexport type RuntimePermissionSupportKind =\n | \"native\"\n | \"approximated\"\n | \"requires-broker\"\n | \"unsupported\";\n\nexport type RuntimePermissionSupport = {\n kind: RuntimePermissionSupportKind;\n effects?:\n | {\n flag?: string | undefined;\n sandbox?: string | undefined;\n approval?: string | undefined;\n note?: string | undefined;\n }\n | undefined;\n};\n\nexport type RuntimePermissionCapabilities = {\n modes: Record<string, RuntimePermissionSupport>;\n toolPolicies: Record<string, Record<string, RuntimePermissionSupport>>;\n resources: Record<string, Record<string, RuntimePermissionSupport>>;\n tools?: string[] | undefined;\n};\n\nexport type SpecRuntimeFamily = {\n id: string;\n label: string;\n /** The model-catalog provider (`ChatModel.provider`) whose models this family runs. */\n provider: string;\n modes: SpecRuntimeModeOption[];\n};\n\n// Offline catalog for stories and tests. Live hosts should pass Captain's\n// registry projection; both use the same provider + mode structure.\nexport const SPEC_RUNTIME_FAMILIES: SpecRuntimeFamily[] = [\n {\n id: \"claude\",\n label: \"Claude\",\n provider: \"anthropic\",\n modes: [\n {\n id: \"api\",\n label: \"API\",\n icon: UiCloud,\n title: \"Anthropic API\",\n provider: \"anthropic\",\n },\n {\n id: \"agent\",\n label: \"Agent\",\n icon: UiRobotAi,\n title: \"Claude Agent SDK\",\n provider: \"anthropic\",\n },\n {\n id: \"cli\",\n label: \"CLI\",\n icon: UiTerminal,\n title: \"Claude Code CLI\",\n provider: \"anthropic\",\n },\n {\n id: \"cmux\",\n label: \"cmux\",\n icon: UiColumns,\n title: \"Claude multiplexer\",\n provider: \"anthropic\",\n },\n ],\n },\n {\n id: \"codex\",\n label: \"Codex\",\n provider: \"openai\",\n modes: [\n {\n id: \"api\",\n label: \"API\",\n icon: UiCloud,\n title: \"OpenAI API\",\n provider: \"openai\",\n },\n {\n id: \"agent\",\n label: \"Agent\",\n icon: UiRobotAi,\n title: \"Codex agent\",\n provider: \"openai\",\n },\n {\n id: \"cli\",\n label: \"CLI\",\n icon: UiTerminal,\n title: \"Codex CLI\",\n provider: \"openai\",\n },\n {\n id: \"cmux\",\n label: \"cmux\",\n icon: UiColumns,\n title: \"Codex multiplexer\",\n provider: \"openai\",\n },\n ],\n },\n {\n id: \"gemini\",\n label: \"Gemini\",\n provider: \"googleai\",\n modes: [\n { id: \"api\", label: \"API\", icon: UiCloud, title: \"Gemini API\" },\n { id: \"cli\", label: \"CLI\", icon: UiTerminal, title: \"Gemini CLI\" },\n ],\n },\n {\n id: \"deepseek\",\n label: \"DeepSeek\",\n provider: \"deepseek\",\n modes: [{ id: \"api\", label: \"API\", icon: UiCloud, title: \"DeepSeek API\" }],\n },\n];\n\n// One provider×mode cell as captain serves it (`/whoami`.runtimes and the prompt\n// schema document's `runtimes`), projected from its model registry. It carries\n// ids, not display text: `claude`/`api` are enough to render both, and a served\n// label would be a second place for presentation to drift.\nexport type RuntimeCatalogMode = {\n /** The canonical `spec.mode`: api | agent | cli | cmux. */\n mode: SpecRuntimeMode;\n /** \"api\" (remote, in-process) or \"cli\" (supervised local binary). */\n kind?: string | undefined;\n /** Rides the local CLI's own login; never consults an API key. */\n keyless?: boolean | undefined;\n /** The model id a picker should seed this mode with. */\n defaultModel?: string | undefined;\n /** The user switched this off in `~/.captain.yaml`. */\n disabled?: boolean | undefined;\n disabledReason?: string | undefined;\n /** Model-catalog provider used by this exact mode. */\n catalogProvider?: string | undefined;\n availability?: RuntimeAvailability | undefined;\n permissions?: RuntimePermissionCapabilities | undefined;\n /** Supported Spec fields, annotated with native CLI and protocol bindings. */\n schema: RuntimeSpecSchema;\n};\n\nexport type RuntimeCatalogFamily = {\n /** The coding-agent name: claude | codex | gemini | deepseek. */\n family: string;\n /** The canonical provider key: anthropic | openai | google | deepseek. */\n provider: string;\n /** The namespace this provider's model ids carry (`ChatModel.provider`). */\n catalogPrefix: string;\n modes: RuntimeCatalogMode[];\n};\n\nconst MODE_ICONS: Record<string, StaticIconComponent> = {\n api: UiCloud,\n agent: UiRobotAi,\n cli: UiTerminal,\n cmux: UiColumns,\n};\n\n// Mode ids are lowercase tokens; only the acronyms and the lowercase brand\n// \"cmux\" need spelling out. `agent` falls through to plain title case.\nconst MODE_LABELS: Record<string, string> = {\n api: \"API\",\n cli: \"CLI\",\n cmux: \"cmux\",\n};\n\n// Tooltip text, so \"Claude cmux\" reads as \"Claude multiplexer\".\nconst MODE_TITLES: Record<string, string> = {\n api: \"API\",\n agent: \"Agent SDK\",\n cli: \"CLI\",\n cmux: \"multiplexer\",\n};\n\n// The one brand whose title case is not just an initial capital.\nconst FAMILY_LABELS: Record<string, string> = { deepseek: \"DeepSeek\" };\n\nfunction titleCase(token: string): string {\n return token ? token.charAt(0).toUpperCase() + token.slice(1) : token;\n}\n\n// Turns the served catalog into the shared family list. Unavailable entries\n// stay present for Provider Status while runtime controls filter them out.\n//\n// The registry has one provider per family, so Claude's API mode sits beside its\n// Agent/CLI/cmux modes here rather than in a separate \"Anthropic\" family the way\n// SPEC_RUNTIME_FAMILIES splits them.\nexport function familiesFromRuntimeCatalog(\n catalog: RuntimeCatalogFamily[] | undefined,\n): SpecRuntimeFamily[] {\n if (!catalog?.length) return SPEC_RUNTIME_FAMILIES;\n const families: SpecRuntimeFamily[] = [];\n for (const entry of catalog) {\n const label = FAMILY_LABELS[entry.family] ?? titleCase(entry.family);\n const modes = entry.modes.map((mode) => ({\n id: mode.mode,\n label: MODE_LABELS[mode.mode] ?? titleCase(mode.mode),\n icon: MODE_ICONS[mode.mode],\n title: `${label} ${MODE_TITLES[mode.mode] ?? titleCase(mode.mode)}`,\n provider: mode.catalogProvider ?? entry.catalogPrefix,\n ...(mode.defaultModel ? { defaultModel: mode.defaultModel } : {}),\n ...(mode.permissions ? { permissions: mode.permissions } : {}),\n ...(mode.schema ? { schema: mode.schema } : {}),\n ...(mode.availability\n ? { availability: mode.availability }\n : mode.disabled\n ? {\n availability: {\n state: \"disabled\" as const,\n reason: `Disabled by ${\n mode.disabledReason ?? mode.mode\n } in Captain configuration.`,\n remediation: `Enable ${\n mode.disabledReason ?? mode.mode\n } on the Whoami page, then refresh.`,\n },\n }\n : {}),\n }));\n families.push({\n id: entry.family,\n label,\n provider: entry.catalogPrefix,\n modes,\n });\n }\n return families.length ? families : SPEC_RUNTIME_FAMILIES;\n}\n\nexport function familyById(\n families: SpecRuntimeFamily[],\n id: string,\n): SpecRuntimeFamily {\n const match = families.find((family) => family.id === id);\n if (match) return match;\n const first = families[0];\n if (!first) throw new Error(\"SpecRuntimeFamily catalog must not be empty\");\n return first;\n}\n\nexport function firstMode(family: SpecRuntimeFamily): SpecRuntimeModeOption {\n const mode =\n family.modes.find((candidate) => !isUnavailable(candidate.availability)) ??\n family.modes[0];\n if (!mode) {\n throw new Error(\n `SpecRuntimeFamily \"${family.id}\" must have at least one mode`,\n );\n }\n return mode;\n}\n\n// Every mode id in the catalog, first-seen order. The entry returned for an id\n// belongs to the family that declared it first, so its presentation fields may\n// differ from another family's — the id itself is family-independent.\nexport function runtimeModeOptions(\n families: SpecRuntimeFamily[],\n): SpecRuntimeModeOption[] {\n const modes = new Map<string, SpecRuntimeModeOption>();\n for (const family of families) {\n for (const mode of family.modes) {\n if (!modes.has(mode.id)) modes.set(mode.id, mode);\n }\n }\n return [...modes.values()];\n}\n\n// One phrasing for \"this family does not offer that mode\", shared by every\n// runtime presentation so the same state never reads two ways.\nexport function unsupportedModeTitle(family: SpecRuntimeFamily): string {\n return availabilityText(\n unsupportedAvailability(\n family.label,\n \"this\",\n family.modes\n .filter((mode) => !isUnavailable(mode.availability))\n .map((mode) => mode.label),\n ),\n )!;\n}\n\nexport function unsupportedModeAvailability(\n family: SpecRuntimeFamily,\n mode: SpecRuntimeModeOption,\n): RuntimeAvailability {\n return unsupportedAvailability(\n family.label,\n mode.label,\n family.modes\n .filter((candidate) => !isUnavailable(candidate.availability))\n .map((candidate) => candidate.label),\n );\n}\n\n// The mode a family will actually run for a requested id, falling back to its\n// first available one. The answer is a `spec.mode` value.\nexport function modeForFamily(\n families: SpecRuntimeFamily[],\n familyId: string,\n modeId: string,\n): string {\n const family = familyById(families, familyId);\n const requested = family.modes.find((candidate) => candidate.id === modeId);\n const mode =\n requested && !isUnavailable(requested.availability)\n ? requested\n : firstMode(family);\n if (isUnavailable(mode.availability)) {\n throw new Error(\n `SpecRuntimeFamily \"${family.id}\" has no available runtime modes`,\n );\n }\n return mode.id;\n}\n\nexport function selectionForMode(\n families: SpecRuntimeFamily[],\n mode: string | undefined,\n preferredFamily?: string | undefined,\n): { family: string; mode: string } {\n const target = (mode ?? \"\").toLowerCase();\n const preferred = families.find((family) => family.id === preferredFamily);\n const preferredMode = preferred?.modes.find(\n (entry) => entry.id.toLowerCase() === target,\n );\n if (preferred && preferredMode) {\n return { family: preferred.id, mode: preferredMode.id };\n }\n for (const family of families) {\n for (const entry of family.modes) {\n if (entry.id.toLowerCase() === target) {\n return { family: family.id, mode: entry.id };\n }\n }\n }\n const first = familyById(families, \"\");\n return { family: first.id, mode: firstMode(first).id };\n}\n\nexport function familyForModel(\n families: SpecRuntimeFamily[],\n models: ChatModel[],\n modelId: string | undefined,\n): SpecRuntimeFamily | undefined {\n if (!modelId) return undefined;\n const selected = models.find(\n (model) =>\n model.id === modelId ||\n model.runtime?.model === modelId ||\n model.runtime?.id === modelId,\n );\n if (!selected) return undefined;\n return families.find(\n (family) =>\n family.provider === selected.provider ||\n family.modes.some((mode) => mode.provider === selected.provider),\n );\n}\n\nexport function selectionForRuntime(\n families: SpecRuntimeFamily[],\n mode: string | undefined,\n modelId: string | undefined,\n models: ChatModel[],\n preferredFamily?: string | undefined,\n): { family: string; mode: string } {\n return selectionForMode(\n families,\n mode,\n familyForModel(families, models, modelId)?.id ?? preferredFamily,\n );\n}\n\nexport function familyForMode(\n families: SpecRuntimeFamily[],\n mode: string | undefined,\n preferredFamily?: string | undefined,\n): SpecRuntimeFamily | undefined {\n if (preferredFamily) {\n const family = families.find((entry) => entry.id === preferredFamily);\n if (family?.modes.some((entry) => entry.id === mode)) return family;\n }\n const target = (mode ?? \"\").toLowerCase();\n return families.find((family) =>\n family.modes.some((entry) => entry.id.toLowerCase() === target),\n );\n}\n\n// The mode option a `spec.mode` names, or undefined when the catalog does not\n// declare it. Unlike `selectionForMode` this does not fall back to the first\n// family, so a summary can stay silent about a runtime it cannot identify.\nexport function modeOptionFor(\n families: SpecRuntimeFamily[],\n mode: string | undefined,\n preferredFamily?: string | undefined,\n): SpecRuntimeModeOption | undefined {\n const target = (mode ?? \"\").toLowerCase();\n if (!target) return undefined;\n const ordered = preferredFamily\n ? [\n ...families.filter((family) => family.id === preferredFamily),\n ...families.filter((family) => family.id !== preferredFamily),\n ]\n : families;\n for (const family of ordered) {\n const entry = family.modes.find(\n (candidate) => candidate.id.toLowerCase() === target,\n );\n if (entry) return entry;\n }\n return undefined;\n}\n\n// `mode` is provider-independent, so a family is needed for a full label.\nexport function labelForMode(\n mode: string | undefined,\n families: SpecRuntimeFamily[] = SPEC_RUNTIME_FAMILIES,\n): string {\n const target = (mode ?? \"\").toLowerCase();\n for (const family of families) {\n for (const entry of family.modes) {\n if (entry.id.toLowerCase() === target) {\n return `${family.label} ${entry.label}`;\n }\n }\n }\n return \"Prompt default\";\n}\n\n/** Lists selectable models for one provider family. */\nexport function modelsForFamily(\n models: ChatModel[],\n family: SpecRuntimeFamily | undefined,\n mode?: string | undefined,\n): ChatModel[] {\n if (!family) return models.filter(isSelectableModel);\n const provider =\n family.modes.find((entry) => entry.id === mode)?.provider ??\n family.provider;\n return models.filter(\n (model) => isSelectableModel(model) && model.provider === provider,\n );\n}\n\n/** Reports whether the first matching catalog identity belongs to the target family. */\nexport function modelBelongsToFamily(\n modelId: string | undefined,\n models: ChatModel[],\n family: SpecRuntimeFamily | undefined,\n mode?: string | undefined,\n): boolean {\n if (!modelId) return true;\n const selected = models.find(\n (model) =>\n isSelectableModel(model) &&\n (model.id === modelId ||\n model.runtime?.model === modelId ||\n model.runtime?.id === modelId),\n );\n if (!selected) return false;\n const provider =\n family?.modes.find((entry) => entry.id === mode)?.provider ??\n family?.provider;\n return (\n (!provider || selected.provider === provider) &&\n (!selected.runtime?.mode || selected.runtime.mode === mode)\n );\n}\n\n/** Resolves a target mode row, using a sole shared row as fallback. */\nexport function modelForFamily(\n modelId: string | undefined,\n models: ChatModel[],\n family: SpecRuntimeFamily | undefined,\n mode?: string | undefined,\n): ChatModel | undefined {\n if (!modelId) return undefined;\n const matches = modelsForFamily(models, family, mode).filter(\n (model) =>\n model.id === modelId ||\n model.runtime?.model === modelId ||\n model.runtime?.id === modelId,\n );\n return (\n matches.find(\n (model) => !mode || !model.runtime?.mode || model.runtime.mode === mode,\n ) ?? (matches.length === 1 ? matches[0] : undefined)\n );\n}\n"],"names":["_a","_b"],"mappings":"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"}
1
+ {"version":3,"file":"runtime-mode.js","sources":["../../../src/data/runtime/runtime-mode.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\nimport { UiCloud, UiColumns, UiRobotAi, UiTerminal } from \"../../icons\";\nimport type { JsonSchemaProperty } from \"../../components/json-schema-form-types\";\nimport type { ChatModel, RuntimeAvailability } from \"../chat/types\";\nimport {\n availabilityText,\n isSelectableModel,\n isUnavailable,\n unsupportedAvailability,\n} from \"./availability\";\nimport {\n familyForModel,\n isSpecRuntimeMode,\n type SpecRuntimeMode,\n} from \"../../lib/runtime-family\";\nexport {\n familyForModel,\n isSpecRuntimeMode,\n modeOptionFor,\n runtimeModeFromModel,\n SPEC_RUNTIME_MODES,\n type SpecRuntimeMode,\n} from \"../../lib/runtime-family\";\n\n// A runtime has two independent axes: the model selects a provider family and\n// `spec.mode` selects api | agent | cli | cmux. The mode never contains a\n// provider name. This file used to call that axis `backend`, which is also what\n// captain called the composite adapter id it once served — so a value read from\n// one and posted back as the other type-checked and ran the wrong runtime.\n\nexport function runtimeModelError(\n model: string | undefined,\n): string | undefined {\n for (const raw of (model ?? \"\").split(\",\")) {\n const compact = raw.trim();\n if (!compact || !compact.includes(\":\")) continue;\n const parts = compact.split(\":\").map((part) => part.trim());\n const [mode, name, effort] = parts;\n if (!isSpecRuntimeMode(mode)) {\n return `Invalid model configuration: mode ${JSON.stringify(mode)} in model ${JSON.stringify(compact)}. Expected api, agent, cli, or cmux.`;\n }\n if (!name || parts.length > 3) {\n return `Invalid model configuration: model ${JSON.stringify(compact)}. Expected mode:model[:effort].`;\n }\n if (\n effort !== undefined &&\n ![\"low\", \"medium\", \"high\", \"xhigh\", \"max\", \"ultra\"].includes(effort)\n ) {\n return `Invalid model configuration: effort ${JSON.stringify(effort)} in model ${JSON.stringify(compact)}.`;\n }\n }\n return undefined;\n}\n\nexport function runtimeModeError(\n families: SpecRuntimeFamily[],\n mode: string | undefined,\n familyId?: string | undefined,\n): string | undefined {\n if (!mode) return undefined;\n if (!isSpecRuntimeMode(mode)) {\n return `Invalid model configuration: mode ${JSON.stringify(mode)}. Expected api, agent, cli, or cmux.`;\n }\n const family = familyId\n ? families.find((entry) => entry.id === familyId)\n : undefined;\n if (family && !family.modes.some((entry) => entry.id === mode)) {\n return `Invalid model configuration: mode ${JSON.stringify(mode)} is not available for ${family.label}.`;\n }\n if (!families.some((entry) => entry.modes.some((m) => m.id === mode))) {\n return `Invalid model configuration: mode ${JSON.stringify(mode)} is missing from the runtime catalog.`;\n }\n return undefined;\n}\n\nexport type SpecRuntimeModeOption = {\n /** The canonical `spec.mode`: api | agent | cli | cmux. */\n id: string;\n label: string;\n icon?: StaticIconComponent | undefined;\n title?: string | undefined;\n provider?: string | undefined;\n defaultModel?: string | undefined;\n availability?: RuntimeAvailability | undefined;\n permissions?: RuntimePermissionCapabilities | undefined;\n schema?: RuntimeSpecSchema | undefined;\n};\n\nexport type RuntimeArgumentImplementation = \"mapped\" | \"managed\";\n\nexport type RuntimeArgumentMapping = {\n name: string;\n implementation: RuntimeArgumentImplementation;\n description?: string | undefined;\n};\n\nexport type RuntimeSpecSchema = JsonSchemaProperty & {\n \"x-clicky-arguments\"?: RuntimeArgumentMapping[] | undefined;\n \"x-clicky-managed-arguments\"?: RuntimeArgumentMapping[] | undefined;\n};\n\nexport type RuntimePermissionSupportKind =\n | \"native\"\n | \"approximated\"\n | \"requires-broker\"\n | \"unsupported\";\n\nexport type RuntimePermissionSupport = {\n kind: RuntimePermissionSupportKind;\n effects?:\n | {\n flag?: string | undefined;\n sandbox?: string | undefined;\n approval?: string | undefined;\n note?: string | undefined;\n }\n | undefined;\n};\n\nexport type RuntimePermissionCapabilities = {\n modes: Record<string, RuntimePermissionSupport>;\n toolPolicies: Record<string, Record<string, RuntimePermissionSupport>>;\n resources: Record<string, Record<string, RuntimePermissionSupport>>;\n tools?: string[] | undefined;\n};\n\nexport type SpecRuntimeFamily = {\n id: string;\n label: string;\n /** The model-catalog provider (`ChatModel.provider`) whose models this family runs. */\n provider: string;\n /** Namespace used by fully-qualified model ids when it differs from provider. */\n catalogPrefix?: string | undefined;\n modes: SpecRuntimeModeOption[];\n};\n\n// Offline catalog for stories and tests. Live hosts should pass Captain's\n// registry projection; both use the same provider + mode structure.\nexport const SPEC_RUNTIME_FAMILIES: SpecRuntimeFamily[] = [\n {\n id: \"claude\",\n label: \"Claude\",\n provider: \"anthropic\",\n modes: [\n {\n id: \"api\",\n label: \"API\",\n icon: UiCloud,\n title: \"Anthropic API\",\n provider: \"anthropic\",\n },\n {\n id: \"agent\",\n label: \"Agent\",\n icon: UiRobotAi,\n title: \"Claude Agent SDK\",\n provider: \"anthropic\",\n },\n {\n id: \"cli\",\n label: \"CLI\",\n icon: UiTerminal,\n title: \"Claude Code CLI\",\n provider: \"anthropic\",\n },\n {\n id: \"cmux\",\n label: \"cmux\",\n icon: UiColumns,\n title: \"Claude multiplexer\",\n provider: \"anthropic\",\n },\n ],\n },\n {\n id: \"codex\",\n label: \"Codex\",\n provider: \"openai\",\n modes: [\n {\n id: \"api\",\n label: \"API\",\n icon: UiCloud,\n title: \"OpenAI API\",\n provider: \"openai\",\n },\n {\n id: \"agent\",\n label: \"Agent\",\n icon: UiRobotAi,\n title: \"Codex agent\",\n provider: \"openai\",\n },\n {\n id: \"cli\",\n label: \"CLI\",\n icon: UiTerminal,\n title: \"Codex CLI\",\n provider: \"openai\",\n },\n {\n id: \"cmux\",\n label: \"cmux\",\n icon: UiColumns,\n title: \"Codex multiplexer\",\n provider: \"openai\",\n },\n ],\n },\n {\n id: \"gemini\",\n label: \"Gemini\",\n provider: \"google\",\n catalogPrefix: \"googleai\",\n modes: [\n { id: \"api\", label: \"API\", icon: UiCloud, title: \"Gemini API\" },\n { id: \"cli\", label: \"CLI\", icon: UiTerminal, title: \"Gemini CLI\" },\n ],\n },\n {\n id: \"deepseek\",\n label: \"DeepSeek\",\n provider: \"deepseek\",\n modes: [{ id: \"api\", label: \"API\", icon: UiCloud, title: \"DeepSeek API\" }],\n },\n];\n\n// One provider×mode cell as captain serves it (`/whoami`.runtimes and the prompt\n// schema document's `runtimes`), projected from its model registry. It carries\n// ids, not display text: `claude`/`api` are enough to render both, and a served\n// label would be a second place for presentation to drift.\nexport type RuntimeCatalogMode = {\n /** The canonical `spec.mode`: api | agent | cli | cmux. */\n mode: SpecRuntimeMode;\n /** \"api\" (remote, in-process) or \"cli\" (supervised local binary). */\n kind?: string | undefined;\n /** Rides the local CLI's own login; never consults an API key. */\n keyless?: boolean | undefined;\n /** The model id a picker should seed this mode with. */\n defaultModel?: string | undefined;\n /** The user switched this off in `~/.captain.yaml`. */\n disabled?: boolean | undefined;\n disabledReason?: string | undefined;\n /** Model-catalog provider used by this exact mode. */\n catalogProvider?: string | undefined;\n availability?: RuntimeAvailability | undefined;\n permissions?: RuntimePermissionCapabilities | undefined;\n /** Supported Spec fields, annotated with native CLI and protocol bindings. */\n schema: RuntimeSpecSchema;\n};\n\nexport type RuntimeCatalogFamily = {\n /** The coding-agent name: claude | codex | gemini | deepseek. */\n family: string;\n /** The canonical provider key: anthropic | openai | google | deepseek. */\n provider: string;\n /** The namespace used in fully-qualified model ids. */\n catalogPrefix: string;\n modes: RuntimeCatalogMode[];\n};\n\nconst MODE_ICONS: Record<string, StaticIconComponent> = {\n api: UiCloud,\n agent: UiRobotAi,\n cli: UiTerminal,\n cmux: UiColumns,\n};\n\n// Mode ids are lowercase tokens; only the acronyms and the lowercase brand\n// \"cmux\" need spelling out. `agent` falls through to plain title case.\nconst MODE_LABELS: Record<string, string> = {\n api: \"API\",\n cli: \"CLI\",\n cmux: \"cmux\",\n};\n\n// Tooltip text, so \"Claude cmux\" reads as \"Claude multiplexer\".\nconst MODE_TITLES: Record<string, string> = {\n api: \"API\",\n agent: \"Agent SDK\",\n cli: \"CLI\",\n cmux: \"multiplexer\",\n};\n\n// The one brand whose title case is not just an initial capital.\nconst FAMILY_LABELS: Record<string, string> = { deepseek: \"DeepSeek\" };\n\nfunction titleCase(token: string): string {\n return token ? token.charAt(0).toUpperCase() + token.slice(1) : token;\n}\n\n// Turns the served catalog into the shared family list. Unavailable entries\n// stay present for Provider Status while runtime controls filter them out.\n//\n// The registry has one provider per family, so Claude's API mode sits beside its\n// Agent/CLI/cmux modes here rather than in a separate \"Anthropic\" family the way\n// SPEC_RUNTIME_FAMILIES splits them.\nexport function familiesFromRuntimeCatalog(\n catalog: RuntimeCatalogFamily[] | undefined,\n): SpecRuntimeFamily[] {\n if (!catalog?.length) return SPEC_RUNTIME_FAMILIES;\n const families: SpecRuntimeFamily[] = [];\n for (const entry of catalog) {\n const label = FAMILY_LABELS[entry.family] ?? titleCase(entry.family);\n const modes = entry.modes.map((mode) => ({\n id: mode.mode,\n label: MODE_LABELS[mode.mode] ?? titleCase(mode.mode),\n icon: MODE_ICONS[mode.mode],\n title: `${label} ${MODE_TITLES[mode.mode] ?? titleCase(mode.mode)}`,\n provider: mode.catalogProvider ?? entry.provider,\n ...(mode.defaultModel ? { defaultModel: mode.defaultModel } : {}),\n ...(mode.permissions ? { permissions: mode.permissions } : {}),\n ...(mode.schema ? { schema: mode.schema } : {}),\n ...(mode.availability\n ? { availability: mode.availability }\n : mode.disabled\n ? {\n availability: {\n state: \"disabled\" as const,\n reason: `Disabled by ${\n mode.disabledReason ?? mode.mode\n } in Captain configuration.`,\n remediation: `Enable ${\n mode.disabledReason ?? mode.mode\n } on the Whoami page, then refresh.`,\n },\n }\n : {}),\n }));\n families.push({\n id: entry.family,\n label,\n provider: entry.provider,\n catalogPrefix: entry.catalogPrefix,\n modes,\n });\n }\n return families.length ? families : SPEC_RUNTIME_FAMILIES;\n}\n\nexport function familyById(\n families: SpecRuntimeFamily[],\n id: string,\n): SpecRuntimeFamily {\n const match = families.find((family) => family.id === id);\n if (match) return match;\n const first = families[0];\n if (!first) throw new Error(\"SpecRuntimeFamily catalog must not be empty\");\n return first;\n}\n\nexport function firstMode(family: SpecRuntimeFamily): SpecRuntimeModeOption {\n const mode =\n family.modes.find((candidate) => !isUnavailable(candidate.availability)) ??\n family.modes[0];\n if (!mode) {\n throw new Error(\n `SpecRuntimeFamily \"${family.id}\" must have at least one mode`,\n );\n }\n return mode;\n}\n\n// Every mode id in the catalog, first-seen order. The entry returned for an id\n// belongs to the family that declared it first, so its presentation fields may\n// differ from another family's — the id itself is family-independent.\nexport function runtimeModeOptions(\n families: SpecRuntimeFamily[],\n): SpecRuntimeModeOption[] {\n const modes = new Map<string, SpecRuntimeModeOption>();\n for (const family of families) {\n for (const mode of family.modes) {\n if (!modes.has(mode.id)) modes.set(mode.id, mode);\n }\n }\n return [...modes.values()];\n}\n\n// One phrasing for \"this family does not offer that mode\", shared by every\n// runtime presentation so the same state never reads two ways.\nexport function unsupportedModeTitle(family: SpecRuntimeFamily): string {\n return availabilityText(\n unsupportedAvailability(\n family.label,\n \"this\",\n family.modes\n .filter((mode) => !isUnavailable(mode.availability))\n .map((mode) => mode.label),\n ),\n )!;\n}\n\nexport function unsupportedModeAvailability(\n family: SpecRuntimeFamily,\n mode: SpecRuntimeModeOption,\n): RuntimeAvailability {\n return unsupportedAvailability(\n family.label,\n mode.label,\n family.modes\n .filter((candidate) => !isUnavailable(candidate.availability))\n .map((candidate) => candidate.label),\n );\n}\n\n// The mode a family will actually run for a requested id, falling back to its\n// first available one. The answer is a `spec.mode` value.\nexport function modeForFamily(\n families: SpecRuntimeFamily[],\n familyId: string,\n modeId: string,\n): string {\n const family = familyById(families, familyId);\n const requested = family.modes.find((candidate) => candidate.id === modeId);\n const mode =\n requested && !isUnavailable(requested.availability)\n ? requested\n : firstMode(family);\n if (isUnavailable(mode.availability)) {\n throw new Error(\n `SpecRuntimeFamily \"${family.id}\" has no available runtime modes`,\n );\n }\n return mode.id;\n}\n\nexport function selectionForMode(\n families: SpecRuntimeFamily[],\n mode: string | undefined,\n preferredFamily?: string | undefined,\n): { family: string; mode: string } {\n const target = (mode ?? \"\").toLowerCase();\n const preferred = families.find((family) => family.id === preferredFamily);\n const preferredMode = preferred?.modes.find(\n (entry) => entry.id.toLowerCase() === target,\n );\n if (preferred && preferredMode) {\n return { family: preferred.id, mode: preferredMode.id };\n }\n for (const family of families) {\n for (const entry of family.modes) {\n if (entry.id.toLowerCase() === target) {\n return { family: family.id, mode: entry.id };\n }\n }\n }\n const first = familyById(families, \"\");\n return { family: first.id, mode: firstMode(first).id };\n}\n\nexport function selectionForRuntime(\n families: SpecRuntimeFamily[],\n mode: string | undefined,\n modelId: string | undefined,\n models: ChatModel[],\n preferredFamily?: string | undefined,\n): { family: string; mode: string } {\n return selectionForMode(\n families,\n mode,\n familyForModel(families, models, modelId)?.id ?? preferredFamily,\n );\n}\n\nexport function familyForMode(\n families: SpecRuntimeFamily[],\n mode: string | undefined,\n preferredFamily?: string | undefined,\n): SpecRuntimeFamily | undefined {\n if (preferredFamily) {\n const family = families.find((entry) => entry.id === preferredFamily);\n if (family?.modes.some((entry) => entry.id === mode)) return family;\n }\n const target = (mode ?? \"\").toLowerCase();\n return families.find((family) =>\n family.modes.some((entry) => entry.id.toLowerCase() === target),\n );\n}\n\n// The mode option a `spec.mode` names, or undefined when the catalog does not\n// declare it. Unlike `selectionForMode` this does not fall back to the first\n// family, so a summary can stay silent about a runtime it cannot identify.\n// `mode` is provider-independent, so a family is needed for a full label.\nexport function labelForMode(\n mode: string | undefined,\n families: SpecRuntimeFamily[] = SPEC_RUNTIME_FAMILIES,\n): string {\n const target = (mode ?? \"\").toLowerCase();\n for (const family of families) {\n for (const entry of family.modes) {\n if (entry.id.toLowerCase() === target) {\n return `${family.label} ${entry.label}`;\n }\n }\n }\n return \"Prompt default\";\n}\n\n/** Lists selectable models for one provider family. */\nexport function modelsForFamily(\n models: ChatModel[],\n family: SpecRuntimeFamily | undefined,\n mode?: string | undefined,\n): ChatModel[] {\n if (!family) return models.filter(isSelectableModel);\n const provider =\n family.modes.find((entry) => entry.id === mode)?.provider ??\n family.provider;\n return models.filter(\n (model) => isSelectableModel(model) && model.provider === provider,\n );\n}\n\n/** Reports whether the first matching catalog identity belongs to the target family. */\nexport function modelBelongsToFamily(\n modelId: string | undefined,\n models: ChatModel[],\n family: SpecRuntimeFamily | undefined,\n mode?: string | undefined,\n): boolean {\n if (!modelId) return true;\n const selected = models.find(\n (model) =>\n isSelectableModel(model) &&\n (model.id === modelId ||\n model.runtime?.model === modelId ||\n model.runtime?.id === modelId),\n );\n if (!selected) return false;\n const provider =\n family?.modes.find((entry) => entry.id === mode)?.provider ??\n family?.provider;\n return (\n (!provider || selected.provider === provider) &&\n (!selected.runtime?.mode || selected.runtime.mode === mode)\n );\n}\n\n/** Resolves a target mode row, using a sole shared row as fallback. */\nexport function modelForFamily(\n modelId: string | undefined,\n models: ChatModel[],\n family: SpecRuntimeFamily | undefined,\n mode?: string | undefined,\n): ChatModel | undefined {\n if (!modelId) return undefined;\n const matches = modelsForFamily(models, family, mode).filter(\n (model) =>\n model.id === modelId ||\n model.runtime?.model === modelId ||\n model.runtime?.id === modelId,\n );\n return (\n matches.find(\n (model) => !mode || !model.runtime?.mode || model.runtime.mode === mode,\n ) ?? (matches.length === 1 ? matches[0] : undefined)\n );\n}\n"],"names":["_a","_b"],"mappings":"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"}
@@ -19,6 +19,7 @@ function toRegistry(adapters) {
19
19
  }
20
20
  function TestRunner({
21
21
  tests,
22
+ allTests,
22
23
  selected,
23
24
  filters,
24
25
  expandAll,
@@ -86,9 +87,10 @@ function TestRunner({
86
87
  registry
87
88
  ]
88
89
  );
89
- const frameworks = react.useMemo(() => status.collectFrameworks(tests), [tests]);
90
- const filterCounts = react.useMemo(() => status.aggregateStatusCounts(tests), [tests]);
91
- const hasContent = tests.length > 0;
90
+ const summaryTests = allTests ?? tests;
91
+ const frameworks = react.useMemo(() => status.collectFrameworks(summaryTests), [summaryTests]);
92
+ const filterCounts = react.useMemo(() => status.aggregateStatusCounts(summaryTests), [summaryTests]);
93
+ const hasContent = summaryTests.length > 0;
92
94
  return /* @__PURE__ */ jsxRuntime.jsx(context.TestRunnerProvider, { value: ctx, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("flex h-full min-h-0 flex-col bg-background", className), children: [
93
95
  !hideHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border bg-card px-density-4 py-density-3", children: [
94
96
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
@@ -104,7 +106,7 @@ function TestRunner({
104
106
  showSummary && /* @__PURE__ */ jsxRuntime.jsx(
105
107
  TestRunSummary.TestRunSummary,
106
108
  {
107
- tests,
109
+ tests: summaryTests,
108
110
  startTime,
109
111
  endTime,
110
112
  done,
@@ -1 +1 @@
1
- {"version":3,"file":"TestRunner.cjs","sources":["../../../src/data/test-runner/TestRunner.tsx"],"sourcesContent":["import { useMemo, type ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport { SplitPane } from \"../../layout/SplitPane\";\nimport { cn } from \"../../lib/utils\";\nimport { UiBeaker } from \"../../icons\";\nimport type { RunMeta, SnapshotStatus, Test } from \"./types\";\nimport { aggregateStatusCounts, collectFrameworks } from \"./status\";\nimport { type TestFilters } from \"./filterState\";\nimport {\n createTestRunnerRegistry,\n type TestNodeAdapter,\n TestNodeAdapterRegistry,\n} from \"./adapter\";\nimport { TestRunnerProvider, type TestRunnerContext } from \"./context\";\nimport { TestTree } from \"./TestTree\";\nimport { TestDetailPanel } from \"./TestDetailPanel\";\nimport { TestRunSummary } from \"./TestRunSummary\";\nimport { TestFilterBar } from \"./TestFilterBar\";\n\nexport type TestRunnerProps = {\n tests: Test[];\n selected: Test | null;\n filters: TestFilters;\n expandAll: boolean | null;\n done: boolean;\n runMeta?: RunMeta;\n status?: SnapshotStatus;\n /** Free-form status line shown next to the title (e.g. \"Running tests...\"). */\n statusText?: string;\n now?: number;\n busy?: { rerun?: boolean; stop?: boolean };\n\n /** Controlled active detail-tab id; omit to let the detail pane own tab state. */\n activeTab?: string;\n /** Called with the picked tab id when `activeTab` is controlled. */\n onTabChange?: (tabId: string) => void;\n\n onSelect: (node: Test | null) => void;\n onFiltersChange: (next: TestFilters) => void;\n onExpandAllChange: (next: boolean | null) => void;\n onRerun?: (node: Test) => void;\n onStop?: (node: Test) => void;\n\n /** Domain node adapters, or a pre-built registry. Defaults to default-only. */\n adapters?: TestNodeAdapter[] | TestNodeAdapterRegistry;\n /**\n * Header title. Defaults (when omitted) to the \"Test Results\" beaker heading.\n * Pass `null` to render no title — e.g. a host that owns the title in its own\n * dialog/page header and embeds the runner below it.\n */\n title?: ReactNode;\n /**\n * Render the built-in run summary (counts + progress) in the header. Defaults\n * to true; pass false when the host shows the summary itself (e.g. in a dialog\n * header) to avoid duplicating it.\n */\n showSummary?: boolean;\n /** Extra header content (e.g. export/download controls owned by the host). */\n headerSlot?: ReactNode;\n /**\n * Suppresses the entire built-in header bar (title, summary, filter row).\n * Defaults to false; pass true when a host renders its own combined header\n * (e.g. a dialog header that already embeds `TestRunSummary` and filters) so\n * the runner doesn't render a second bordered bar underneath it.\n */\n hideHeader?: boolean;\n /** Initial left-pane width percentage. */\n defaultSplit?: number;\n startTime?: number | null;\n endTime?: number | null;\n className?: string;\n};\n\nfunction toRegistry(\n adapters: TestNodeAdapter[] | TestNodeAdapterRegistry | undefined,\n): TestNodeAdapterRegistry {\n if (adapters instanceof TestNodeAdapterRegistry) return adapters;\n return createTestRunnerRegistry(adapters ?? []);\n}\n\n/**\n * Top-level, pure-presentational test runner: a summary/filter header over a\n * resizable tree + detail split. All data and handlers flow in via props and\n * are exposed to sub-components through a single `TestRunnerContext`. Domain\n * rendering is pluggable via node adapters; no fetch/SSE/routing lives here.\n */\nexport function TestRunner({\n tests,\n selected,\n filters,\n expandAll,\n done,\n runMeta,\n status,\n statusText,\n now,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters,\n title,\n showSummary = true,\n headerSlot,\n hideHeader = false,\n defaultSplit = 45,\n startTime,\n endTime,\n className,\n}: TestRunnerProps) {\n const registry = useMemo(() => toRegistry(adapters), [adapters]);\n\n const ctx: TestRunnerContext = useMemo(\n () => ({\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy: busy ?? {},\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters: registry,\n }),\n [\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n registry,\n ],\n );\n\n const frameworks = useMemo(() => collectFrameworks(tests), [tests]);\n const filterCounts = useMemo(() => aggregateStatusCounts(tests), [tests]);\n const hasContent = tests.length > 0;\n\n return (\n <TestRunnerProvider value={ctx}>\n <div className={cn(\"flex h-full min-h-0 flex-col bg-background\", className)}>\n {!hideHeader && (\n <div className=\"border-b border-border bg-card px-density-4 py-density-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n {title === undefined ? (\n <h1 className=\"inline-flex items-center gap-1.5 text-lg font-bold\">\n <Icon icon={UiBeaker} className=\"text-primary\" />\n Test Results\n </h1>\n ) : (\n title\n )}\n {statusText && <span className=\"text-sm text-muted-foreground\">{statusText}</span>}\n </div>\n <div className=\"flex items-center gap-3\">\n {headerSlot}\n {showSummary && (\n <TestRunSummary\n tests={tests}\n startTime={startTime}\n endTime={endTime}\n done={done}\n now={now}\n runMeta={runMeta}\n />\n )}\n </div>\n </div>\n {hasContent && (\n <div className=\"mt-2\">\n <TestFilterBar\n filters={filters}\n onChange={onFiltersChange}\n counts={filterCounts}\n frameworks={frameworks}\n />\n </div>\n )}\n </div>\n )}\n\n <SplitPane\n className=\"min-h-0 flex-1\"\n defaultSplit={defaultSplit}\n minLeft={25}\n minRight={30}\n leftClass=\"border-r-2 border-border bg-muted/30\"\n left={<TestTree />}\n right={<TestDetailPanel />}\n />\n </div>\n </TestRunnerProvider>\n );\n}\n"],"names":["TestNodeAdapterRegistry","createTestRunnerRegistry","status","useMemo","collectFrameworks","aggregateStatusCounts","jsx","TestRunnerProvider","jsxs","cn","Icon","UiBeaker","TestRunSummary","TestFilterBar","SplitPane","TestTree","TestDetailPanel"],"mappings":"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"}
1
+ {"version":3,"file":"TestRunner.cjs","sources":["../../../src/data/test-runner/TestRunner.tsx"],"sourcesContent":["import { useMemo, type ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport { SplitPane } from \"../../layout/SplitPane\";\nimport { cn } from \"../../lib/utils\";\nimport { UiBeaker } from \"../../icons\";\nimport type { RunMeta, SnapshotStatus, Test } from \"./types\";\nimport { aggregateStatusCounts, collectFrameworks } from \"./status\";\nimport { type TestFilters } from \"./filterState\";\nimport {\n createTestRunnerRegistry,\n type TestNodeAdapter,\n TestNodeAdapterRegistry,\n} from \"./adapter\";\nimport { TestRunnerProvider, type TestRunnerContext } from \"./context\";\nimport { TestTree } from \"./TestTree\";\nimport { TestDetailPanel } from \"./TestDetailPanel\";\nimport { TestRunSummary } from \"./TestRunSummary\";\nimport { TestFilterBar } from \"./TestFilterBar\";\n\nexport type TestRunnerProps = {\n tests: Test[];\n /**\n * The full, unfiltered forest driving the filter bar's pills/counts and the\n * header summary — falls back to `tests` when omitted (every existing\n * caller pre-filters `tests` itself). Pass this explicitly when `tests` is a\n * filtered subset of a larger report, so toggling a status filter (e.g.\n * excluding the only failed node) can't make its own pill — or the whole\n * filter bar, once every pill's count reads zero — disappear.\n */\n allTests?: Test[];\n selected: Test | null;\n filters: TestFilters;\n expandAll: boolean | null;\n done: boolean;\n runMeta?: RunMeta;\n status?: SnapshotStatus;\n /** Free-form status line shown next to the title (e.g. \"Running tests...\"). */\n statusText?: string;\n now?: number;\n busy?: { rerun?: boolean; stop?: boolean };\n\n /** Controlled active detail-tab id; omit to let the detail pane own tab state. */\n activeTab?: string;\n /** Called with the picked tab id when `activeTab` is controlled. */\n onTabChange?: (tabId: string) => void;\n\n onSelect: (node: Test | null) => void;\n onFiltersChange: (next: TestFilters) => void;\n onExpandAllChange: (next: boolean | null) => void;\n onRerun?: (node: Test) => void;\n onStop?: (node: Test) => void;\n\n /** Domain node adapters, or a pre-built registry. Defaults to default-only. */\n adapters?: TestNodeAdapter[] | TestNodeAdapterRegistry;\n /**\n * Header title. Defaults (when omitted) to the \"Test Results\" beaker heading.\n * Pass `null` to render no title — e.g. a host that owns the title in its own\n * dialog/page header and embeds the runner below it.\n */\n title?: ReactNode;\n /**\n * Render the built-in run summary (counts + progress) in the header. Defaults\n * to true; pass false when the host shows the summary itself (e.g. in a dialog\n * header) to avoid duplicating it.\n */\n showSummary?: boolean;\n /** Extra header content (e.g. export/download controls owned by the host). */\n headerSlot?: ReactNode;\n /**\n * Suppresses the entire built-in header bar (title, summary, filter row).\n * Defaults to false; pass true when a host renders its own combined header\n * (e.g. a dialog header that already embeds `TestRunSummary` and filters) so\n * the runner doesn't render a second bordered bar underneath it.\n */\n hideHeader?: boolean;\n /** Initial left-pane width percentage. */\n defaultSplit?: number;\n startTime?: number | null;\n endTime?: number | null;\n className?: string;\n};\n\nfunction toRegistry(\n adapters: TestNodeAdapter[] | TestNodeAdapterRegistry | undefined,\n): TestNodeAdapterRegistry {\n if (adapters instanceof TestNodeAdapterRegistry) return adapters;\n return createTestRunnerRegistry(adapters ?? []);\n}\n\n/**\n * Top-level, pure-presentational test runner: a summary/filter header over a\n * resizable tree + detail split. All data and handlers flow in via props and\n * are exposed to sub-components through a single `TestRunnerContext`. Domain\n * rendering is pluggable via node adapters; no fetch/SSE/routing lives here.\n */\nexport function TestRunner({\n tests,\n allTests,\n selected,\n filters,\n expandAll,\n done,\n runMeta,\n status,\n statusText,\n now,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters,\n title,\n showSummary = true,\n headerSlot,\n hideHeader = false,\n defaultSplit = 45,\n startTime,\n endTime,\n className,\n}: TestRunnerProps) {\n const registry = useMemo(() => toRegistry(adapters), [adapters]);\n\n const ctx: TestRunnerContext = useMemo(\n () => ({\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy: busy ?? {},\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters: registry,\n }),\n [\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n registry,\n ],\n );\n\n const summaryTests = allTests ?? tests;\n const frameworks = useMemo(() => collectFrameworks(summaryTests), [summaryTests]);\n const filterCounts = useMemo(() => aggregateStatusCounts(summaryTests), [summaryTests]);\n const hasContent = summaryTests.length > 0;\n\n return (\n <TestRunnerProvider value={ctx}>\n <div className={cn(\"flex h-full min-h-0 flex-col bg-background\", className)}>\n {!hideHeader && (\n <div className=\"border-b border-border bg-card px-density-4 py-density-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n {title === undefined ? (\n <h1 className=\"inline-flex items-center gap-1.5 text-lg font-bold\">\n <Icon icon={UiBeaker} className=\"text-primary\" />\n Test Results\n </h1>\n ) : (\n title\n )}\n {statusText && <span className=\"text-sm text-muted-foreground\">{statusText}</span>}\n </div>\n <div className=\"flex items-center gap-3\">\n {headerSlot}\n {showSummary && (\n <TestRunSummary\n tests={summaryTests}\n startTime={startTime}\n endTime={endTime}\n done={done}\n now={now}\n runMeta={runMeta}\n />\n )}\n </div>\n </div>\n {hasContent && (\n <div className=\"mt-2\">\n <TestFilterBar\n filters={filters}\n onChange={onFiltersChange}\n counts={filterCounts}\n frameworks={frameworks}\n />\n </div>\n )}\n </div>\n )}\n\n <SplitPane\n className=\"min-h-0 flex-1\"\n defaultSplit={defaultSplit}\n minLeft={25}\n minRight={30}\n leftClass=\"border-r-2 border-border bg-muted/30\"\n left={<TestTree />}\n right={<TestDetailPanel />}\n />\n </div>\n </TestRunnerProvider>\n );\n}\n"],"names":["TestNodeAdapterRegistry","createTestRunnerRegistry","status","useMemo","collectFrameworks","aggregateStatusCounts","jsx","TestRunnerProvider","jsxs","cn","Icon","UiBeaker","TestRunSummary","TestFilterBar","SplitPane","TestTree","TestDetailPanel"],"mappings":"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"}
@@ -4,6 +4,15 @@ import { TestFilters } from './filterState';
4
4
  import { TestNodeAdapter, TestNodeAdapterRegistry } from './adapter';
5
5
  export type TestRunnerProps = {
6
6
  tests: Test[];
7
+ /**
8
+ * The full, unfiltered forest driving the filter bar's pills/counts and the
9
+ * header summary — falls back to `tests` when omitted (every existing
10
+ * caller pre-filters `tests` itself). Pass this explicitly when `tests` is a
11
+ * filtered subset of a larger report, so toggling a status filter (e.g.
12
+ * excluding the only failed node) can't make its own pill — or the whole
13
+ * filter bar, once every pill's count reads zero — disappear.
14
+ */
15
+ allTests?: Test[];
7
16
  selected: Test | null;
8
17
  filters: TestFilters;
9
18
  expandAll: boolean | null;
@@ -61,5 +70,5 @@ export type TestRunnerProps = {
61
70
  * are exposed to sub-components through a single `TestRunnerContext`. Domain
62
71
  * rendering is pluggable via node adapters; no fetch/SSE/routing lives here.
63
72
  */
64
- export declare function TestRunner({ tests, selected, filters, expandAll, done, runMeta, status, statusText, now, busy, activeTab, onTabChange, onSelect, onFiltersChange, onExpandAllChange, onRerun, onStop, adapters, title, showSummary, headerSlot, hideHeader, defaultSplit, startTime, endTime, className, }: TestRunnerProps): import("react").JSX.Element;
73
+ export declare function TestRunner({ tests, allTests, selected, filters, expandAll, done, runMeta, status, statusText, now, busy, activeTab, onTabChange, onSelect, onFiltersChange, onExpandAllChange, onRerun, onStop, adapters, title, showSummary, headerSlot, hideHeader, defaultSplit, startTime, endTime, className, }: TestRunnerProps): import("react").JSX.Element;
65
74
  //# sourceMappingURL=TestRunner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TestRunner.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestRunner.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAKhD,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE7D,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAEL,KAAK,eAAe,EACpB,uBAAuB,EACxB,MAAM,WAAW,CAAC;AAOnB,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAE3C,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtC,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IACtC,eAAe,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,iBAAiB,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAE9B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,uBAAuB,CAAC;IACvD;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AASF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,OAAO,EACP,SAAS,EACT,IAAI,EACJ,OAAO,EACP,MAAM,EACN,UAAU,EACV,GAAG,EACH,IAAI,EACJ,SAAS,EACT,WAAW,EACX,QAAQ,EACR,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,KAAK,EACL,WAAkB,EAClB,UAAU,EACV,UAAkB,EAClB,YAAiB,EACjB,SAAS,EACT,OAAO,EACP,SAAS,GACV,EAAE,eAAe,+BAwGjB"}
1
+ {"version":3,"file":"TestRunner.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestRunner.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAKhD,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE7D,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAEL,KAAK,eAAe,EACpB,uBAAuB,EACxB,MAAM,WAAW,CAAC;AAOnB,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC;IAClB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,WAAW,CAAC;IACrB,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAE3C,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEtC,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IACtC,eAAe,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,iBAAiB,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAE9B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,eAAe,EAAE,GAAG,uBAAuB,CAAC;IACvD;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AASF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,SAAS,EACT,IAAI,EACJ,OAAO,EACP,MAAM,EACN,UAAU,EACV,GAAG,EACH,IAAI,EACJ,SAAS,EACT,WAAW,EACX,QAAQ,EACR,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,KAAK,EACL,WAAkB,EAClB,UAAU,EACV,UAAkB,EAClB,YAAiB,EACjB,SAAS,EACT,OAAO,EACP,SAAS,GACV,EAAE,eAAe,+BAyGjB"}
@@ -17,6 +17,7 @@ function toRegistry(adapters) {
17
17
  }
18
18
  function TestRunner({
19
19
  tests,
20
+ allTests,
20
21
  selected,
21
22
  filters,
22
23
  expandAll,
@@ -84,9 +85,10 @@ function TestRunner({
84
85
  registry
85
86
  ]
86
87
  );
87
- const frameworks = useMemo(() => collectFrameworks(tests), [tests]);
88
- const filterCounts = useMemo(() => aggregateStatusCounts(tests), [tests]);
89
- const hasContent = tests.length > 0;
88
+ const summaryTests = allTests ?? tests;
89
+ const frameworks = useMemo(() => collectFrameworks(summaryTests), [summaryTests]);
90
+ const filterCounts = useMemo(() => aggregateStatusCounts(summaryTests), [summaryTests]);
91
+ const hasContent = summaryTests.length > 0;
90
92
  return /* @__PURE__ */ jsx(TestRunnerProvider, { value: ctx, children: /* @__PURE__ */ jsxs("div", { className: cn("flex h-full min-h-0 flex-col bg-background", className), children: [
91
93
  !hideHeader && /* @__PURE__ */ jsxs("div", { className: "border-b border-border bg-card px-density-4 py-density-3", children: [
92
94
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
@@ -102,7 +104,7 @@ function TestRunner({
102
104
  showSummary && /* @__PURE__ */ jsx(
103
105
  TestRunSummary,
104
106
  {
105
- tests,
107
+ tests: summaryTests,
106
108
  startTime,
107
109
  endTime,
108
110
  done,
@@ -1 +1 @@
1
- {"version":3,"file":"TestRunner.js","sources":["../../../src/data/test-runner/TestRunner.tsx"],"sourcesContent":["import { useMemo, type ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport { SplitPane } from \"../../layout/SplitPane\";\nimport { cn } from \"../../lib/utils\";\nimport { UiBeaker } from \"../../icons\";\nimport type { RunMeta, SnapshotStatus, Test } from \"./types\";\nimport { aggregateStatusCounts, collectFrameworks } from \"./status\";\nimport { type TestFilters } from \"./filterState\";\nimport {\n createTestRunnerRegistry,\n type TestNodeAdapter,\n TestNodeAdapterRegistry,\n} from \"./adapter\";\nimport { TestRunnerProvider, type TestRunnerContext } from \"./context\";\nimport { TestTree } from \"./TestTree\";\nimport { TestDetailPanel } from \"./TestDetailPanel\";\nimport { TestRunSummary } from \"./TestRunSummary\";\nimport { TestFilterBar } from \"./TestFilterBar\";\n\nexport type TestRunnerProps = {\n tests: Test[];\n selected: Test | null;\n filters: TestFilters;\n expandAll: boolean | null;\n done: boolean;\n runMeta?: RunMeta;\n status?: SnapshotStatus;\n /** Free-form status line shown next to the title (e.g. \"Running tests...\"). */\n statusText?: string;\n now?: number;\n busy?: { rerun?: boolean; stop?: boolean };\n\n /** Controlled active detail-tab id; omit to let the detail pane own tab state. */\n activeTab?: string;\n /** Called with the picked tab id when `activeTab` is controlled. */\n onTabChange?: (tabId: string) => void;\n\n onSelect: (node: Test | null) => void;\n onFiltersChange: (next: TestFilters) => void;\n onExpandAllChange: (next: boolean | null) => void;\n onRerun?: (node: Test) => void;\n onStop?: (node: Test) => void;\n\n /** Domain node adapters, or a pre-built registry. Defaults to default-only. */\n adapters?: TestNodeAdapter[] | TestNodeAdapterRegistry;\n /**\n * Header title. Defaults (when omitted) to the \"Test Results\" beaker heading.\n * Pass `null` to render no title — e.g. a host that owns the title in its own\n * dialog/page header and embeds the runner below it.\n */\n title?: ReactNode;\n /**\n * Render the built-in run summary (counts + progress) in the header. Defaults\n * to true; pass false when the host shows the summary itself (e.g. in a dialog\n * header) to avoid duplicating it.\n */\n showSummary?: boolean;\n /** Extra header content (e.g. export/download controls owned by the host). */\n headerSlot?: ReactNode;\n /**\n * Suppresses the entire built-in header bar (title, summary, filter row).\n * Defaults to false; pass true when a host renders its own combined header\n * (e.g. a dialog header that already embeds `TestRunSummary` and filters) so\n * the runner doesn't render a second bordered bar underneath it.\n */\n hideHeader?: boolean;\n /** Initial left-pane width percentage. */\n defaultSplit?: number;\n startTime?: number | null;\n endTime?: number | null;\n className?: string;\n};\n\nfunction toRegistry(\n adapters: TestNodeAdapter[] | TestNodeAdapterRegistry | undefined,\n): TestNodeAdapterRegistry {\n if (adapters instanceof TestNodeAdapterRegistry) return adapters;\n return createTestRunnerRegistry(adapters ?? []);\n}\n\n/**\n * Top-level, pure-presentational test runner: a summary/filter header over a\n * resizable tree + detail split. All data and handlers flow in via props and\n * are exposed to sub-components through a single `TestRunnerContext`. Domain\n * rendering is pluggable via node adapters; no fetch/SSE/routing lives here.\n */\nexport function TestRunner({\n tests,\n selected,\n filters,\n expandAll,\n done,\n runMeta,\n status,\n statusText,\n now,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters,\n title,\n showSummary = true,\n headerSlot,\n hideHeader = false,\n defaultSplit = 45,\n startTime,\n endTime,\n className,\n}: TestRunnerProps) {\n const registry = useMemo(() => toRegistry(adapters), [adapters]);\n\n const ctx: TestRunnerContext = useMemo(\n () => ({\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy: busy ?? {},\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters: registry,\n }),\n [\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n registry,\n ],\n );\n\n const frameworks = useMemo(() => collectFrameworks(tests), [tests]);\n const filterCounts = useMemo(() => aggregateStatusCounts(tests), [tests]);\n const hasContent = tests.length > 0;\n\n return (\n <TestRunnerProvider value={ctx}>\n <div className={cn(\"flex h-full min-h-0 flex-col bg-background\", className)}>\n {!hideHeader && (\n <div className=\"border-b border-border bg-card px-density-4 py-density-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n {title === undefined ? (\n <h1 className=\"inline-flex items-center gap-1.5 text-lg font-bold\">\n <Icon icon={UiBeaker} className=\"text-primary\" />\n Test Results\n </h1>\n ) : (\n title\n )}\n {statusText && <span className=\"text-sm text-muted-foreground\">{statusText}</span>}\n </div>\n <div className=\"flex items-center gap-3\">\n {headerSlot}\n {showSummary && (\n <TestRunSummary\n tests={tests}\n startTime={startTime}\n endTime={endTime}\n done={done}\n now={now}\n runMeta={runMeta}\n />\n )}\n </div>\n </div>\n {hasContent && (\n <div className=\"mt-2\">\n <TestFilterBar\n filters={filters}\n onChange={onFiltersChange}\n counts={filterCounts}\n frameworks={frameworks}\n />\n </div>\n )}\n </div>\n )}\n\n <SplitPane\n className=\"min-h-0 flex-1\"\n defaultSplit={defaultSplit}\n minLeft={25}\n minRight={30}\n leftClass=\"border-r-2 border-border bg-muted/30\"\n left={<TestTree />}\n right={<TestDetailPanel />}\n />\n </div>\n </TestRunnerProvider>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TestRunner.js","sources":["../../../src/data/test-runner/TestRunner.tsx"],"sourcesContent":["import { useMemo, type ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport { SplitPane } from \"../../layout/SplitPane\";\nimport { cn } from \"../../lib/utils\";\nimport { UiBeaker } from \"../../icons\";\nimport type { RunMeta, SnapshotStatus, Test } from \"./types\";\nimport { aggregateStatusCounts, collectFrameworks } from \"./status\";\nimport { type TestFilters } from \"./filterState\";\nimport {\n createTestRunnerRegistry,\n type TestNodeAdapter,\n TestNodeAdapterRegistry,\n} from \"./adapter\";\nimport { TestRunnerProvider, type TestRunnerContext } from \"./context\";\nimport { TestTree } from \"./TestTree\";\nimport { TestDetailPanel } from \"./TestDetailPanel\";\nimport { TestRunSummary } from \"./TestRunSummary\";\nimport { TestFilterBar } from \"./TestFilterBar\";\n\nexport type TestRunnerProps = {\n tests: Test[];\n /**\n * The full, unfiltered forest driving the filter bar's pills/counts and the\n * header summary — falls back to `tests` when omitted (every existing\n * caller pre-filters `tests` itself). Pass this explicitly when `tests` is a\n * filtered subset of a larger report, so toggling a status filter (e.g.\n * excluding the only failed node) can't make its own pill — or the whole\n * filter bar, once every pill's count reads zero — disappear.\n */\n allTests?: Test[];\n selected: Test | null;\n filters: TestFilters;\n expandAll: boolean | null;\n done: boolean;\n runMeta?: RunMeta;\n status?: SnapshotStatus;\n /** Free-form status line shown next to the title (e.g. \"Running tests...\"). */\n statusText?: string;\n now?: number;\n busy?: { rerun?: boolean; stop?: boolean };\n\n /** Controlled active detail-tab id; omit to let the detail pane own tab state. */\n activeTab?: string;\n /** Called with the picked tab id when `activeTab` is controlled. */\n onTabChange?: (tabId: string) => void;\n\n onSelect: (node: Test | null) => void;\n onFiltersChange: (next: TestFilters) => void;\n onExpandAllChange: (next: boolean | null) => void;\n onRerun?: (node: Test) => void;\n onStop?: (node: Test) => void;\n\n /** Domain node adapters, or a pre-built registry. Defaults to default-only. */\n adapters?: TestNodeAdapter[] | TestNodeAdapterRegistry;\n /**\n * Header title. Defaults (when omitted) to the \"Test Results\" beaker heading.\n * Pass `null` to render no title — e.g. a host that owns the title in its own\n * dialog/page header and embeds the runner below it.\n */\n title?: ReactNode;\n /**\n * Render the built-in run summary (counts + progress) in the header. Defaults\n * to true; pass false when the host shows the summary itself (e.g. in a dialog\n * header) to avoid duplicating it.\n */\n showSummary?: boolean;\n /** Extra header content (e.g. export/download controls owned by the host). */\n headerSlot?: ReactNode;\n /**\n * Suppresses the entire built-in header bar (title, summary, filter row).\n * Defaults to false; pass true when a host renders its own combined header\n * (e.g. a dialog header that already embeds `TestRunSummary` and filters) so\n * the runner doesn't render a second bordered bar underneath it.\n */\n hideHeader?: boolean;\n /** Initial left-pane width percentage. */\n defaultSplit?: number;\n startTime?: number | null;\n endTime?: number | null;\n className?: string;\n};\n\nfunction toRegistry(\n adapters: TestNodeAdapter[] | TestNodeAdapterRegistry | undefined,\n): TestNodeAdapterRegistry {\n if (adapters instanceof TestNodeAdapterRegistry) return adapters;\n return createTestRunnerRegistry(adapters ?? []);\n}\n\n/**\n * Top-level, pure-presentational test runner: a summary/filter header over a\n * resizable tree + detail split. All data and handlers flow in via props and\n * are exposed to sub-components through a single `TestRunnerContext`. Domain\n * rendering is pluggable via node adapters; no fetch/SSE/routing lives here.\n */\nexport function TestRunner({\n tests,\n allTests,\n selected,\n filters,\n expandAll,\n done,\n runMeta,\n status,\n statusText,\n now,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters,\n title,\n showSummary = true,\n headerSlot,\n hideHeader = false,\n defaultSplit = 45,\n startTime,\n endTime,\n className,\n}: TestRunnerProps) {\n const registry = useMemo(() => toRegistry(adapters), [adapters]);\n\n const ctx: TestRunnerContext = useMemo(\n () => ({\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy: busy ?? {},\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n adapters: registry,\n }),\n [\n tests,\n selected,\n runMeta,\n status,\n done,\n now,\n filters,\n expandAll,\n busy,\n activeTab,\n onTabChange,\n onSelect,\n onFiltersChange,\n onExpandAllChange,\n onRerun,\n onStop,\n registry,\n ],\n );\n\n const summaryTests = allTests ?? tests;\n const frameworks = useMemo(() => collectFrameworks(summaryTests), [summaryTests]);\n const filterCounts = useMemo(() => aggregateStatusCounts(summaryTests), [summaryTests]);\n const hasContent = summaryTests.length > 0;\n\n return (\n <TestRunnerProvider value={ctx}>\n <div className={cn(\"flex h-full min-h-0 flex-col bg-background\", className)}>\n {!hideHeader && (\n <div className=\"border-b border-border bg-card px-density-4 py-density-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n {title === undefined ? (\n <h1 className=\"inline-flex items-center gap-1.5 text-lg font-bold\">\n <Icon icon={UiBeaker} className=\"text-primary\" />\n Test Results\n </h1>\n ) : (\n title\n )}\n {statusText && <span className=\"text-sm text-muted-foreground\">{statusText}</span>}\n </div>\n <div className=\"flex items-center gap-3\">\n {headerSlot}\n {showSummary && (\n <TestRunSummary\n tests={summaryTests}\n startTime={startTime}\n endTime={endTime}\n done={done}\n now={now}\n runMeta={runMeta}\n />\n )}\n </div>\n </div>\n {hasContent && (\n <div className=\"mt-2\">\n <TestFilterBar\n filters={filters}\n onChange={onFiltersChange}\n counts={filterCounts}\n frameworks={frameworks}\n />\n </div>\n )}\n </div>\n )}\n\n <SplitPane\n className=\"min-h-0 flex-1\"\n defaultSplit={defaultSplit}\n minLeft={25}\n minRight={30}\n leftClass=\"border-r-2 border-border bg-muted/30\"\n left={<TestTree />}\n right={<TestDetailPanel />}\n />\n </div>\n </TestRunnerProvider>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const utils = require("../../lib/utils.cjs");
6
+ const adapters = require("./adapters.cjs");
7
+ const verifyReportTests = require("./verifyReportTests.cjs");
8
+ const filterState = require("../test-runner/filterState.cjs");
9
+ const status = require("../test-runner/status.cjs");
10
+ const TestRunner = require("../test-runner/TestRunner.cjs");
11
+ const DEFAULT_ADAPTERS = adapters.verificationAdapters();
12
+ function selectionKey(node) {
13
+ return node.task_id ?? node.name;
14
+ }
15
+ function findBySelectionKey(nodes, key) {
16
+ for (const node of nodes) {
17
+ if (selectionKey(node) === key) return node;
18
+ if (node.children) {
19
+ const found = findBySelectionKey(node.children, key);
20
+ if (found) return found;
21
+ }
22
+ }
23
+ return null;
24
+ }
25
+ function VerificationResults({
26
+ report,
27
+ done,
28
+ title = null,
29
+ className,
30
+ adapters: adapters2 = DEFAULT_ADAPTERS,
31
+ emptyText = "No verification has run yet",
32
+ selected: controlledSelected,
33
+ onSelect: controlledOnSelect,
34
+ filters: controlledFilters,
35
+ onFiltersChange: controlledOnFiltersChange
36
+ }) {
37
+ const tests = react.useMemo(() => report ? verifyReportTests.verifyReportTests(report) : [], [report]);
38
+ const [selectedKey, setSelectedKey] = react.useState(null);
39
+ const [internalFilters, setInternalFilters] = react.useState(() => filterState.emptyTestFilters());
40
+ const [expandAll, setExpandAll] = react.useState(null);
41
+ const filtersControlled = controlledFilters !== void 0;
42
+ const filters = filtersControlled ? controlledFilters : internalFilters;
43
+ const setFilters = (next) => {
44
+ if (filtersControlled) controlledOnFiltersChange == null ? void 0 : controlledOnFiltersChange(next);
45
+ else setInternalFilters(next);
46
+ };
47
+ const selectionControlled = controlledSelected !== void 0;
48
+ const uncontrolledSelected = react.useMemo(
49
+ () => selectedKey ? findBySelectionKey(tests, selectedKey) : null,
50
+ [tests, selectedKey]
51
+ );
52
+ const selected = selectionControlled ? controlledSelected : uncontrolledSelected;
53
+ const setSelected = (node) => {
54
+ if (selectionControlled) controlledOnSelect == null ? void 0 : controlledOnSelect(node);
55
+ else setSelectedKey(node ? selectionKey(node) : null);
56
+ };
57
+ const visible = react.useMemo(
58
+ () => status.filterTests(tests, filters.status, filters.framework),
59
+ [tests, filters]
60
+ );
61
+ const startTime = (report == null ? void 0 : report.started_at) ? Date.parse(report.started_at) : void 0;
62
+ const endTime = (report == null ? void 0 : report.finished_at) ? Date.parse(report.finished_at) : void 0;
63
+ const verdict = report && (report.reason || report.feedback) ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 space-y-2 border-b border-border px-3 py-2", children: [
64
+ report.reason && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-foreground", children: report.reason }),
65
+ report.feedback && /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "max-h-40 overflow-auto whitespace-pre-wrap rounded bg-muted p-2 font-mono text-[11px]", children: report.feedback })
66
+ ] }) : null;
67
+ if (!report || tests.length === 0) {
68
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("flex flex-col", className), children: [
69
+ verdict,
70
+ !verdict && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 py-4 text-xs text-muted-foreground", children: emptyText })
71
+ ] });
72
+ }
73
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("flex h-[30rem] min-h-80 flex-col", className), children: [
74
+ verdict,
75
+ /* @__PURE__ */ jsxRuntime.jsx(
76
+ TestRunner.TestRunner,
77
+ {
78
+ className: "min-h-0 flex-1",
79
+ tests: visible,
80
+ allTests: tests,
81
+ selected,
82
+ filters,
83
+ expandAll,
84
+ done: done ?? report.state !== "running",
85
+ status: { running: report.state === "running" },
86
+ ...report.state === "running" ? { statusText: "Running verification…" } : {},
87
+ ...startTime !== void 0 ? { startTime } : {},
88
+ ...endTime !== void 0 ? { endTime } : {},
89
+ title,
90
+ adapters: adapters2,
91
+ onSelect: setSelected,
92
+ onFiltersChange: setFilters,
93
+ onExpandAllChange: setExpandAll
94
+ }
95
+ )
96
+ ] });
97
+ }
98
+ exports.VerificationResults = VerificationResults;
99
+ //# sourceMappingURL=VerificationResults.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VerificationResults.cjs","sources":["../../../src/data/verification/VerificationResults.tsx"],"sourcesContent":["// Props-only VerificationResults: renders a captain VerifyReport through the\n// shared TestRunner, so both the captain webapp and gavel pr/ui can drop it in\n// without forking a data-fetching or routing dependency. Ported from gavel's\n// VerificationFixtureResults.tsx.\n\nimport { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n emptyTestFilters,\n filterTests,\n TestRunner,\n type Test,\n type TestFilters,\n type TestNodeAdapterRegistry,\n} from \"../test-runner\";\nimport { verificationAdapters } from \"./adapters\";\nimport { verifyReportTests } from \"./verifyReportTests\";\nimport type { VerifyReport } from \"./verify-report\";\n\nexport type VerificationResultsProps = {\n report: VerifyReport | null;\n /** Overrides the run-complete state. Defaults to `report.state !== \"running\"`. */\n done?: boolean;\n /** Header title, passed through to TestRunner. Defaults to no title. */\n title?: ReactNode | null;\n className?: string;\n adapters?: TestNodeAdapterRegistry;\n emptyText?: string;\n /**\n * Controlled selection — omit to let the component own selection state\n * (keyed by a stable task_id/name so the same row stays selected across a\n * re-created report of the same shape, e.g. after a live-update refresh).\n * Pass both this and `onSelect` for a host that persists selection at the\n * route level.\n */\n selected?: Test | null;\n onSelect?: (node: Test | null) => void;\n /** Controlled status/framework filters — omit to let the component own filter state. */\n filters?: TestFilters;\n onFiltersChange?: (next: TestFilters) => void;\n};\n\nconst DEFAULT_ADAPTERS = verificationAdapters();\n\n/**\n * A node's identity across a re-created forest: its own `task_id` when\n * present, else its name. Object identity can't be used — `verifyReportTests`\n * builds a brand-new `Test[]` from every report, so the previously-selected\n * object never appears in a fresh forest even when the underlying node is\n * unchanged.\n */\nfunction selectionKey(node: Test): string {\n return node.task_id ?? node.name;\n}\n\nfunction findBySelectionKey(nodes: Test[], key: string): Test | null {\n for (const node of nodes) {\n if (selectionKey(node) === key) return node;\n if (node.children) {\n const found = findBySelectionKey(node.children, key);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport function VerificationResults({\n report,\n done,\n title = null,\n className,\n adapters = DEFAULT_ADAPTERS,\n emptyText = \"No verification has run yet\",\n selected: controlledSelected,\n onSelect: controlledOnSelect,\n filters: controlledFilters,\n onFiltersChange: controlledOnFiltersChange,\n}: VerificationResultsProps) {\n const tests = useMemo(() => (report ? verifyReportTests(report) : []), [report]);\n\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n const [internalFilters, setInternalFilters] = useState<TestFilters>(() => emptyTestFilters());\n const [expandAll, setExpandAll] = useState<boolean | null>(null);\n\n const filtersControlled = controlledFilters !== undefined;\n const filters = filtersControlled ? controlledFilters : internalFilters;\n const setFilters = (next: TestFilters) => {\n if (filtersControlled) controlledOnFiltersChange?.(next);\n else setInternalFilters(next);\n };\n\n const selectionControlled = controlledSelected !== undefined;\n const uncontrolledSelected = useMemo(\n () => (selectedKey ? findBySelectionKey(tests, selectedKey) : null),\n [tests, selectedKey],\n );\n const selected = selectionControlled ? controlledSelected : uncontrolledSelected;\n const setSelected = (node: Test | null) => {\n if (selectionControlled) controlledOnSelect?.(node);\n else setSelectedKey(node ? selectionKey(node) : null);\n };\n\n const visible = useMemo(\n () => filterTests(tests, filters.status, filters.framework),\n [tests, filters],\n );\n\n const startTime = report?.started_at ? Date.parse(report.started_at) : undefined;\n const endTime = report?.finished_at ? Date.parse(report.finished_at) : undefined;\n\n // A cmd/AI verifier's reason and feedback are the only place its verdict\n // survives once its nodes are empty (e.g. an error before any check ran), so\n // they're shown above the runner whenever present — not only in that empty\n // case — since a partial pass can carry a reason alongside real test nodes.\n const verdict =\n report && (report.reason || report.feedback) ? (\n <div className=\"shrink-0 space-y-2 border-b border-border px-3 py-2\">\n {report.reason && <p className=\"text-xs text-foreground\">{report.reason}</p>}\n {report.feedback && (\n <pre className=\"max-h-40 overflow-auto whitespace-pre-wrap rounded bg-muted p-2 font-mono text-[11px]\">\n {report.feedback}\n </pre>\n )}\n </div>\n ) : null;\n\n if (!report || tests.length === 0) {\n return (\n <div className={cn(\"flex flex-col\", className)}>\n {verdict}\n {!verdict && <p className=\"px-3 py-4 text-xs text-muted-foreground\">{emptyText}</p>}\n </div>\n );\n }\n\n return (\n <div className={cn(\"flex h-[30rem] min-h-80 flex-col\", className)}>\n {verdict}\n <TestRunner\n className=\"min-h-0 flex-1\"\n tests={visible}\n allTests={tests}\n selected={selected}\n filters={filters}\n expandAll={expandAll}\n done={done ?? report.state !== \"running\"}\n status={{ running: report.state === \"running\" }}\n {...(report.state === \"running\" ? { statusText: \"Running verification…\" } : {})}\n {...(startTime !== undefined ? { startTime } : {})}\n {...(endTime !== undefined ? { endTime } : {})}\n title={title}\n adapters={adapters}\n onSelect={setSelected}\n onFiltersChange={setFilters}\n onExpandAllChange={setExpandAll}\n />\n </div>\n );\n}\n"],"names":["verificationAdapters","adapters","useMemo","verifyReportTests","useState","emptyTestFilters","filterTests","jsxs","jsx","cn","TestRunner"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { ReactNode } from '../../../../../node_modules/@types/react/index.d.ts';
2
+ import { Test, TestFilters, TestNodeAdapterRegistry } from '../test-runner';
3
+ import { VerifyReport } from './verify-report';
4
+ export type VerificationResultsProps = {
5
+ report: VerifyReport | null;
6
+ /** Overrides the run-complete state. Defaults to `report.state !== "running"`. */
7
+ done?: boolean;
8
+ /** Header title, passed through to TestRunner. Defaults to no title. */
9
+ title?: ReactNode | null;
10
+ className?: string;
11
+ adapters?: TestNodeAdapterRegistry;
12
+ emptyText?: string;
13
+ /**
14
+ * Controlled selection — omit to let the component own selection state
15
+ * (keyed by a stable task_id/name so the same row stays selected across a
16
+ * re-created report of the same shape, e.g. after a live-update refresh).
17
+ * Pass both this and `onSelect` for a host that persists selection at the
18
+ * route level.
19
+ */
20
+ selected?: Test | null;
21
+ onSelect?: (node: Test | null) => void;
22
+ /** Controlled status/framework filters — omit to let the component own filter state. */
23
+ filters?: TestFilters;
24
+ onFiltersChange?: (next: TestFilters) => void;
25
+ };
26
+ export declare function VerificationResults({ report, done, title, className, adapters, emptyText, selected: controlledSelected, onSelect: controlledOnSelect, filters: controlledFilters, onFiltersChange: controlledOnFiltersChange, }: VerificationResultsProps): import("react").JSX.Element;
27
+ //# sourceMappingURL=VerificationResults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VerificationResults.d.ts","sourceRoot":"","sources":["../../../src/data/verification/VerificationResults.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE1D,OAAO,EAIL,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,KAAK,uBAAuB,EAC7B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,kFAAkF;IAClF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IACvC,wFAAwF;IACxF,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;CAC/C,CAAC;AA0BF,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,IAAI,EACJ,KAAY,EACZ,SAAS,EACT,QAA2B,EAC3B,SAAyC,EACzC,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,iBAAiB,EAC1B,eAAe,EAAE,yBAAyB,GAC3C,EAAE,wBAAwB,+BAiF1B"}
@@ -0,0 +1,99 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useMemo, useState } from "react";
3
+ import { cn } from "../../lib/utils.js";
4
+ import { verificationAdapters } from "./adapters.js";
5
+ import { verifyReportTests } from "./verifyReportTests.js";
6
+ import { emptyTestFilters } from "../test-runner/filterState.js";
7
+ import { filterTests } from "../test-runner/status.js";
8
+ import { TestRunner } from "../test-runner/TestRunner.js";
9
+ const DEFAULT_ADAPTERS = verificationAdapters();
10
+ function selectionKey(node) {
11
+ return node.task_id ?? node.name;
12
+ }
13
+ function findBySelectionKey(nodes, key) {
14
+ for (const node of nodes) {
15
+ if (selectionKey(node) === key) return node;
16
+ if (node.children) {
17
+ const found = findBySelectionKey(node.children, key);
18
+ if (found) return found;
19
+ }
20
+ }
21
+ return null;
22
+ }
23
+ function VerificationResults({
24
+ report,
25
+ done,
26
+ title = null,
27
+ className,
28
+ adapters = DEFAULT_ADAPTERS,
29
+ emptyText = "No verification has run yet",
30
+ selected: controlledSelected,
31
+ onSelect: controlledOnSelect,
32
+ filters: controlledFilters,
33
+ onFiltersChange: controlledOnFiltersChange
34
+ }) {
35
+ const tests = useMemo(() => report ? verifyReportTests(report) : [], [report]);
36
+ const [selectedKey, setSelectedKey] = useState(null);
37
+ const [internalFilters, setInternalFilters] = useState(() => emptyTestFilters());
38
+ const [expandAll, setExpandAll] = useState(null);
39
+ const filtersControlled = controlledFilters !== void 0;
40
+ const filters = filtersControlled ? controlledFilters : internalFilters;
41
+ const setFilters = (next) => {
42
+ if (filtersControlled) controlledOnFiltersChange == null ? void 0 : controlledOnFiltersChange(next);
43
+ else setInternalFilters(next);
44
+ };
45
+ const selectionControlled = controlledSelected !== void 0;
46
+ const uncontrolledSelected = useMemo(
47
+ () => selectedKey ? findBySelectionKey(tests, selectedKey) : null,
48
+ [tests, selectedKey]
49
+ );
50
+ const selected = selectionControlled ? controlledSelected : uncontrolledSelected;
51
+ const setSelected = (node) => {
52
+ if (selectionControlled) controlledOnSelect == null ? void 0 : controlledOnSelect(node);
53
+ else setSelectedKey(node ? selectionKey(node) : null);
54
+ };
55
+ const visible = useMemo(
56
+ () => filterTests(tests, filters.status, filters.framework),
57
+ [tests, filters]
58
+ );
59
+ const startTime = (report == null ? void 0 : report.started_at) ? Date.parse(report.started_at) : void 0;
60
+ const endTime = (report == null ? void 0 : report.finished_at) ? Date.parse(report.finished_at) : void 0;
61
+ const verdict = report && (report.reason || report.feedback) ? /* @__PURE__ */ jsxs("div", { className: "shrink-0 space-y-2 border-b border-border px-3 py-2", children: [
62
+ report.reason && /* @__PURE__ */ jsx("p", { className: "text-xs text-foreground", children: report.reason }),
63
+ report.feedback && /* @__PURE__ */ jsx("pre", { className: "max-h-40 overflow-auto whitespace-pre-wrap rounded bg-muted p-2 font-mono text-[11px]", children: report.feedback })
64
+ ] }) : null;
65
+ if (!report || tests.length === 0) {
66
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", className), children: [
67
+ verdict,
68
+ !verdict && /* @__PURE__ */ jsx("p", { className: "px-3 py-4 text-xs text-muted-foreground", children: emptyText })
69
+ ] });
70
+ }
71
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex h-[30rem] min-h-80 flex-col", className), children: [
72
+ verdict,
73
+ /* @__PURE__ */ jsx(
74
+ TestRunner,
75
+ {
76
+ className: "min-h-0 flex-1",
77
+ tests: visible,
78
+ allTests: tests,
79
+ selected,
80
+ filters,
81
+ expandAll,
82
+ done: done ?? report.state !== "running",
83
+ status: { running: report.state === "running" },
84
+ ...report.state === "running" ? { statusText: "Running verification…" } : {},
85
+ ...startTime !== void 0 ? { startTime } : {},
86
+ ...endTime !== void 0 ? { endTime } : {},
87
+ title,
88
+ adapters,
89
+ onSelect: setSelected,
90
+ onFiltersChange: setFilters,
91
+ onExpandAllChange: setExpandAll
92
+ }
93
+ )
94
+ ] });
95
+ }
96
+ export {
97
+ VerificationResults
98
+ };
99
+ //# sourceMappingURL=VerificationResults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VerificationResults.js","sources":["../../../src/data/verification/VerificationResults.tsx"],"sourcesContent":["// Props-only VerificationResults: renders a captain VerifyReport through the\n// shared TestRunner, so both the captain webapp and gavel pr/ui can drop it in\n// without forking a data-fetching or routing dependency. Ported from gavel's\n// VerificationFixtureResults.tsx.\n\nimport { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n emptyTestFilters,\n filterTests,\n TestRunner,\n type Test,\n type TestFilters,\n type TestNodeAdapterRegistry,\n} from \"../test-runner\";\nimport { verificationAdapters } from \"./adapters\";\nimport { verifyReportTests } from \"./verifyReportTests\";\nimport type { VerifyReport } from \"./verify-report\";\n\nexport type VerificationResultsProps = {\n report: VerifyReport | null;\n /** Overrides the run-complete state. Defaults to `report.state !== \"running\"`. */\n done?: boolean;\n /** Header title, passed through to TestRunner. Defaults to no title. */\n title?: ReactNode | null;\n className?: string;\n adapters?: TestNodeAdapterRegistry;\n emptyText?: string;\n /**\n * Controlled selection — omit to let the component own selection state\n * (keyed by a stable task_id/name so the same row stays selected across a\n * re-created report of the same shape, e.g. after a live-update refresh).\n * Pass both this and `onSelect` for a host that persists selection at the\n * route level.\n */\n selected?: Test | null;\n onSelect?: (node: Test | null) => void;\n /** Controlled status/framework filters — omit to let the component own filter state. */\n filters?: TestFilters;\n onFiltersChange?: (next: TestFilters) => void;\n};\n\nconst DEFAULT_ADAPTERS = verificationAdapters();\n\n/**\n * A node's identity across a re-created forest: its own `task_id` when\n * present, else its name. Object identity can't be used — `verifyReportTests`\n * builds a brand-new `Test[]` from every report, so the previously-selected\n * object never appears in a fresh forest even when the underlying node is\n * unchanged.\n */\nfunction selectionKey(node: Test): string {\n return node.task_id ?? node.name;\n}\n\nfunction findBySelectionKey(nodes: Test[], key: string): Test | null {\n for (const node of nodes) {\n if (selectionKey(node) === key) return node;\n if (node.children) {\n const found = findBySelectionKey(node.children, key);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport function VerificationResults({\n report,\n done,\n title = null,\n className,\n adapters = DEFAULT_ADAPTERS,\n emptyText = \"No verification has run yet\",\n selected: controlledSelected,\n onSelect: controlledOnSelect,\n filters: controlledFilters,\n onFiltersChange: controlledOnFiltersChange,\n}: VerificationResultsProps) {\n const tests = useMemo(() => (report ? verifyReportTests(report) : []), [report]);\n\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n const [internalFilters, setInternalFilters] = useState<TestFilters>(() => emptyTestFilters());\n const [expandAll, setExpandAll] = useState<boolean | null>(null);\n\n const filtersControlled = controlledFilters !== undefined;\n const filters = filtersControlled ? controlledFilters : internalFilters;\n const setFilters = (next: TestFilters) => {\n if (filtersControlled) controlledOnFiltersChange?.(next);\n else setInternalFilters(next);\n };\n\n const selectionControlled = controlledSelected !== undefined;\n const uncontrolledSelected = useMemo(\n () => (selectedKey ? findBySelectionKey(tests, selectedKey) : null),\n [tests, selectedKey],\n );\n const selected = selectionControlled ? controlledSelected : uncontrolledSelected;\n const setSelected = (node: Test | null) => {\n if (selectionControlled) controlledOnSelect?.(node);\n else setSelectedKey(node ? selectionKey(node) : null);\n };\n\n const visible = useMemo(\n () => filterTests(tests, filters.status, filters.framework),\n [tests, filters],\n );\n\n const startTime = report?.started_at ? Date.parse(report.started_at) : undefined;\n const endTime = report?.finished_at ? Date.parse(report.finished_at) : undefined;\n\n // A cmd/AI verifier's reason and feedback are the only place its verdict\n // survives once its nodes are empty (e.g. an error before any check ran), so\n // they're shown above the runner whenever present — not only in that empty\n // case — since a partial pass can carry a reason alongside real test nodes.\n const verdict =\n report && (report.reason || report.feedback) ? (\n <div className=\"shrink-0 space-y-2 border-b border-border px-3 py-2\">\n {report.reason && <p className=\"text-xs text-foreground\">{report.reason}</p>}\n {report.feedback && (\n <pre className=\"max-h-40 overflow-auto whitespace-pre-wrap rounded bg-muted p-2 font-mono text-[11px]\">\n {report.feedback}\n </pre>\n )}\n </div>\n ) : null;\n\n if (!report || tests.length === 0) {\n return (\n <div className={cn(\"flex flex-col\", className)}>\n {verdict}\n {!verdict && <p className=\"px-3 py-4 text-xs text-muted-foreground\">{emptyText}</p>}\n </div>\n );\n }\n\n return (\n <div className={cn(\"flex h-[30rem] min-h-80 flex-col\", className)}>\n {verdict}\n <TestRunner\n className=\"min-h-0 flex-1\"\n tests={visible}\n allTests={tests}\n selected={selected}\n filters={filters}\n expandAll={expandAll}\n done={done ?? report.state !== \"running\"}\n status={{ running: report.state === \"running\" }}\n {...(report.state === \"running\" ? { statusText: \"Running verification…\" } : {})}\n {...(startTime !== undefined ? { startTime } : {})}\n {...(endTime !== undefined ? { endTime } : {})}\n title={title}\n adapters={adapters}\n onSelect={setSelected}\n onFiltersChange={setFilters}\n onExpandAllChange={setExpandAll}\n />\n </div>\n );\n}\n"],"names":[],"mappings":"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"}