@stigmer/react 3.1.1 → 3.1.2

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 (426) hide show
  1. package/composer/SessionComposer.d.ts +24 -1
  2. package/composer/SessionComposer.d.ts.map +1 -1
  3. package/composer/SessionComposer.js +19 -8
  4. package/composer/SessionComposer.js.map +1 -1
  5. package/execution/ArtifactContentRenderer.d.ts +11 -1
  6. package/execution/ArtifactContentRenderer.d.ts.map +1 -1
  7. package/execution/ArtifactContentRenderer.js +39 -15
  8. package/execution/ArtifactContentRenderer.js.map +1 -1
  9. package/execution/FilePathContext.d.ts +8 -1
  10. package/execution/FilePathContext.d.ts.map +1 -1
  11. package/execution/FilePathContext.js.map +1 -1
  12. package/execution/FilePathLink.d.ts.map +1 -1
  13. package/execution/FilePathLink.js +21 -6
  14. package/execution/FilePathLink.js.map +1 -1
  15. package/execution/MessageEntry.d.ts +29 -0
  16. package/execution/MessageEntry.d.ts.map +1 -1
  17. package/execution/MessageEntry.js +29 -5
  18. package/execution/MessageEntry.js.map +1 -1
  19. package/execution/MessageThread.d.ts +76 -13
  20. package/execution/MessageThread.d.ts.map +1 -1
  21. package/execution/MessageThread.js +178 -24
  22. package/execution/MessageThread.js.map +1 -1
  23. package/execution/PlanArtifactCard.d.ts +27 -18
  24. package/execution/PlanArtifactCard.d.ts.map +1 -1
  25. package/execution/PlanArtifactCard.js +13 -23
  26. package/execution/PlanArtifactCard.js.map +1 -1
  27. package/execution/PlanDocumentMessage.d.ts +32 -0
  28. package/execution/PlanDocumentMessage.d.ts.map +1 -0
  29. package/execution/PlanDocumentMessage.js +37 -0
  30. package/execution/PlanDocumentMessage.js.map +1 -0
  31. package/execution/PlanStreamingCard.d.ts +45 -0
  32. package/execution/PlanStreamingCard.d.ts.map +1 -0
  33. package/execution/PlanStreamingCard.js +35 -0
  34. package/execution/PlanStreamingCard.js.map +1 -0
  35. package/execution/index.d.ts +5 -1
  36. package/execution/index.d.ts.map +1 -1
  37. package/execution/index.js +2 -0
  38. package/execution/index.js.map +1 -1
  39. package/execution/useCreateAgentExecution.d.ts +10 -0
  40. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  41. package/execution/useCreateAgentExecution.js +5 -1
  42. package/execution/useCreateAgentExecution.js.map +1 -1
  43. package/github/decodeGitHubContent.d.ts +29 -0
  44. package/github/decodeGitHubContent.d.ts.map +1 -0
  45. package/github/decodeGitHubContent.js +72 -0
  46. package/github/decodeGitHubContent.js.map +1 -0
  47. package/github/index.d.ts +1 -0
  48. package/github/index.d.ts.map +1 -1
  49. package/github/index.js +1 -0
  50. package/github/index.js.map +1 -1
  51. package/github/useGitHubFileReader.d.ts +26 -0
  52. package/github/useGitHubFileReader.d.ts.map +1 -0
  53. package/github/useGitHubFileReader.js +106 -0
  54. package/github/useGitHubFileReader.js.map +1 -0
  55. package/github/useGitHubTreeLister.d.ts.map +1 -1
  56. package/github/useGitHubTreeLister.js +6 -2
  57. package/github/useGitHubTreeLister.js.map +1 -1
  58. package/index.d.ts +9 -9
  59. package/index.d.ts.map +1 -1
  60. package/index.js +5 -5
  61. package/index.js.map +1 -1
  62. package/internal/ResizableSplit.d.ts +72 -22
  63. package/internal/ResizableSplit.d.ts.map +1 -1
  64. package/internal/ResizableSplit.js +96 -38
  65. package/internal/ResizableSplit.js.map +1 -1
  66. package/internal/VirtualizedThread.d.ts +5 -3
  67. package/internal/VirtualizedThread.d.ts.map +1 -1
  68. package/internal/VirtualizedThread.js +6 -4
  69. package/internal/VirtualizedThread.js.map +1 -1
  70. package/internal/file-icons/index.d.ts +17 -0
  71. package/internal/file-icons/index.d.ts.map +1 -0
  72. package/internal/file-icons/index.js +60 -0
  73. package/internal/file-icons/index.js.map +1 -0
  74. package/internal/file-tree/FileTreeNode.d.ts +18 -1
  75. package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
  76. package/internal/file-tree/FileTreeNode.js +11 -2
  77. package/internal/file-tree/FileTreeNode.js.map +1 -1
  78. package/internal/markdown-components.d.ts +38 -1
  79. package/internal/markdown-components.d.ts.map +1 -1
  80. package/internal/markdown-components.js +86 -11
  81. package/internal/markdown-components.js.map +1 -1
  82. package/{workflow → internal}/motion-preference.d.ts +7 -4
  83. package/internal/motion-preference.d.ts.map +1 -0
  84. package/{workflow → internal}/motion-preference.js +7 -4
  85. package/internal/motion-preference.js.map +1 -0
  86. package/internal/store/index.d.ts +33 -0
  87. package/internal/store/index.d.ts.map +1 -1
  88. package/internal/store/index.js +59 -0
  89. package/internal/store/index.js.map +1 -1
  90. package/internal/store/workspace-editors-store.d.ts +145 -0
  91. package/internal/store/workspace-editors-store.d.ts.map +1 -0
  92. package/internal/store/workspace-editors-store.js +208 -0
  93. package/internal/store/workspace-editors-store.js.map +1 -0
  94. package/internal/store/workspace-file-selection-store.d.ts +38 -0
  95. package/internal/store/workspace-file-selection-store.d.ts.map +1 -0
  96. package/internal/store/workspace-file-selection-store.js +62 -0
  97. package/internal/store/workspace-file-selection-store.js.map +1 -0
  98. package/internal/useRevealLine.d.ts +49 -0
  99. package/internal/useRevealLine.d.ts.map +1 -0
  100. package/internal/useRevealLine.js +43 -0
  101. package/internal/useRevealLine.js.map +1 -0
  102. package/library/detect-plan-artifact.d.ts +21 -0
  103. package/library/detect-plan-artifact.d.ts.map +1 -1
  104. package/library/detect-plan-artifact.js +20 -0
  105. package/library/detect-plan-artifact.js.map +1 -1
  106. package/library/detect-streaming-plan.d.ts +45 -0
  107. package/library/detect-streaming-plan.d.ts.map +1 -0
  108. package/library/detect-streaming-plan.js +83 -0
  109. package/library/detect-streaming-plan.js.map +1 -0
  110. package/library/index.d.ts +4 -1
  111. package/library/index.d.ts.map +1 -1
  112. package/library/index.js +2 -1
  113. package/library/index.js.map +1 -1
  114. package/package.json +4 -4
  115. package/session/NewSessionViewer.d.ts +19 -4
  116. package/session/NewSessionViewer.d.ts.map +1 -1
  117. package/session/NewSessionViewer.js +52 -25
  118. package/session/NewSessionViewer.js.map +1 -1
  119. package/session/PlanEditor.d.ts +55 -0
  120. package/session/PlanEditor.d.ts.map +1 -0
  121. package/session/PlanEditor.js +88 -0
  122. package/session/PlanEditor.js.map +1 -0
  123. package/session/PlanStreamingDocument.d.ts +30 -0
  124. package/session/PlanStreamingDocument.d.ts.map +1 -0
  125. package/session/PlanStreamingDocument.js +37 -0
  126. package/session/PlanStreamingDocument.js.map +1 -0
  127. package/session/SessionPanelChip.d.ts +26 -0
  128. package/session/SessionPanelChip.d.ts.map +1 -0
  129. package/session/SessionPanelChip.js +40 -0
  130. package/session/SessionPanelChip.js.map +1 -0
  131. package/session/SessionViewer.d.ts +34 -7
  132. package/session/SessionViewer.d.ts.map +1 -1
  133. package/session/SessionViewer.js +315 -33
  134. package/session/SessionViewer.js.map +1 -1
  135. package/session/{inspector → facets}/ArtifactsTab.d.ts +10 -2
  136. package/session/facets/ArtifactsTab.d.ts.map +1 -0
  137. package/session/{inspector → facets}/ArtifactsTab.js +8 -3
  138. package/session/facets/ArtifactsTab.js.map +1 -0
  139. package/session/{inspector → facets}/ChangesTab.d.ts +3 -3
  140. package/session/facets/ChangesTab.d.ts.map +1 -0
  141. package/session/{inspector → facets}/ChangesTab.js +3 -3
  142. package/session/facets/ChangesTab.js.map +1 -0
  143. package/session/facets/InspectTab.d.ts.map +1 -0
  144. package/session/facets/InspectTab.js.map +1 -0
  145. package/session/{inspector → facets}/SetupTab.d.ts +11 -2
  146. package/session/facets/SetupTab.d.ts.map +1 -0
  147. package/session/{inspector → facets}/SetupTab.js +4 -3
  148. package/session/facets/SetupTab.js.map +1 -0
  149. package/session/{inspector → facets}/UsageTab.d.ts +1 -1
  150. package/session/facets/UsageTab.d.ts.map +1 -0
  151. package/session/{inspector → facets}/UsageTab.js +1 -1
  152. package/session/facets/UsageTab.js.map +1 -0
  153. package/session/{inspector → facets}/index.d.ts +0 -6
  154. package/session/facets/index.d.ts.map +1 -0
  155. package/session/{inspector → facets}/index.js +0 -3
  156. package/session/facets/index.js.map +1 -0
  157. package/session/index.d.ts +11 -2
  158. package/session/index.d.ts.map +1 -1
  159. package/session/index.js +15 -2
  160. package/session/index.js.map +1 -1
  161. package/session/plan-document.d.ts +9 -0
  162. package/session/plan-document.d.ts.map +1 -0
  163. package/session/plan-document.js +17 -0
  164. package/session/plan-document.js.map +1 -0
  165. package/session/useOpenFileChange.d.ts +20 -0
  166. package/session/useOpenFileChange.d.ts.map +1 -0
  167. package/session/useOpenFileChange.js +31 -0
  168. package/session/useOpenFileChange.js.map +1 -0
  169. package/session/usePlanDraft.d.ts +52 -0
  170. package/session/usePlanDraft.d.ts.map +1 -0
  171. package/session/usePlanDraft.js +63 -0
  172. package/session/usePlanDraft.js.map +1 -0
  173. package/session/useSessionConversation.d.ts +6 -0
  174. package/session/useSessionConversation.d.ts.map +1 -1
  175. package/session/useSessionConversation.js +1 -0
  176. package/session/useSessionConversation.js.map +1 -1
  177. package/session/useSessionPageFlow.d.ts.map +1 -1
  178. package/session/useSessionPageFlow.js +1 -0
  179. package/session/useSessionPageFlow.js.map +1 -1
  180. package/session/useSessionPanel.d.ts +120 -0
  181. package/session/useSessionPanel.d.ts.map +1 -0
  182. package/session/useSessionPanel.js +130 -0
  183. package/session/useSessionPanel.js.map +1 -0
  184. package/session/useSessionRailViews.d.ts +45 -0
  185. package/session/useSessionRailViews.d.ts.map +1 -0
  186. package/session/useSessionRailViews.js +105 -0
  187. package/session/useSessionRailViews.js.map +1 -0
  188. package/src/composer/SessionComposer.tsx +52 -10
  189. package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
  190. package/src/execution/ArtifactContentRenderer.tsx +101 -24
  191. package/src/execution/FilePathContext.tsx +8 -1
  192. package/src/execution/FilePathLink.tsx +22 -6
  193. package/src/execution/MessageEntry.tsx +111 -1
  194. package/src/execution/MessageThread.tsx +291 -36
  195. package/src/execution/PlanArtifactCard.tsx +63 -31
  196. package/src/execution/PlanDocumentMessage.tsx +96 -0
  197. package/src/execution/PlanStreamingCard.tsx +137 -0
  198. package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
  199. package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
  200. package/src/execution/__tests__/MessageThread.test.tsx +101 -0
  201. package/src/execution/__tests__/PlanArtifactCard.test.tsx +66 -12
  202. package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
  203. package/src/execution/__tests__/PlanStreamingCard.test.tsx +49 -0
  204. package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +504 -22
  205. package/src/execution/__tests__/message-entry.test.tsx +48 -0
  206. package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
  207. package/src/execution/index.ts +7 -1
  208. package/src/execution/useCreateAgentExecution.ts +16 -1
  209. package/src/github/__tests__/decodeGitHubContent.test.ts +102 -0
  210. package/src/github/__tests__/useGitHubFileReader.test.ts +183 -0
  211. package/src/github/decodeGitHubContent.ts +83 -0
  212. package/src/github/index.ts +1 -0
  213. package/src/github/useGitHubFileReader.ts +152 -0
  214. package/src/github/useGitHubTreeLister.ts +6 -2
  215. package/src/index.ts +63 -9
  216. package/src/internal/ResizableSplit.tsx +184 -51
  217. package/src/internal/VirtualizedThread.tsx +12 -4
  218. package/src/internal/__tests__/ResizableSplit.test.tsx +125 -3
  219. package/src/internal/__tests__/markdown-components.test.tsx +68 -0
  220. package/src/internal/__tests__/useRevealLine.test.tsx +97 -0
  221. package/src/internal/file-icons/__tests__/file-icons.test.tsx +35 -0
  222. package/src/internal/file-icons/index.tsx +137 -0
  223. package/src/internal/file-tree/FileTreeNode.tsx +43 -3
  224. package/src/internal/file-tree/__tests__/FileTreeNode-explorer.test.tsx +86 -0
  225. package/src/internal/markdown-components.tsx +116 -11
  226. package/src/{workflow → internal}/motion-preference.ts +7 -4
  227. package/src/internal/store/__tests__/workspace-editors-store.test.ts +216 -0
  228. package/src/internal/store/__tests__/workspace-file-selection-store.test.ts +118 -0
  229. package/src/internal/store/index.ts +94 -0
  230. package/src/internal/store/workspace-editors-store.ts +315 -0
  231. package/src/internal/store/workspace-file-selection-store.ts +88 -0
  232. package/src/internal/useRevealLine.ts +81 -0
  233. package/src/library/__tests__/detect-plan-artifact.test.ts +48 -0
  234. package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
  235. package/src/library/detect-plan-artifact.ts +35 -0
  236. package/src/library/detect-streaming-plan.ts +108 -0
  237. package/src/library/index.ts +5 -0
  238. package/src/session/NewSessionViewer.tsx +123 -55
  239. package/src/session/PlanEditor.tsx +361 -0
  240. package/src/session/PlanStreamingDocument.tsx +97 -0
  241. package/src/session/SessionPanelChip.tsx +103 -0
  242. package/src/session/SessionViewer.tsx +617 -90
  243. package/src/session/__tests__/NewSessionViewer.test.tsx +148 -0
  244. package/src/session/__tests__/PlanEditor.test.tsx +217 -0
  245. package/src/session/__tests__/PlanStreamingDocument.test.tsx +50 -0
  246. package/src/session/__tests__/SessionPanelChip.test.tsx +42 -0
  247. package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +9 -4
  248. package/src/session/__tests__/SessionViewer-transcriptFileOpen.test.tsx +205 -0
  249. package/src/session/__tests__/audienceWiring.test.tsx +55 -19
  250. package/src/session/__tests__/useOpenFileChange.test.tsx +82 -0
  251. package/src/session/__tests__/usePlanDraft.test.ts +102 -0
  252. package/src/session/__tests__/useSessionPanel.test.ts +298 -0
  253. package/src/session/__tests__/useSessionRailViews.test.tsx +124 -0
  254. package/src/session/{inspector → facets}/ArtifactsTab.tsx +27 -5
  255. package/src/session/{inspector → facets}/ChangesTab.tsx +3 -3
  256. package/src/session/{inspector → facets}/SetupTab.tsx +13 -1
  257. package/src/session/{inspector → facets}/UsageTab.tsx +1 -1
  258. package/src/session/{inspector → facets}/__tests__/ArtifactsTab.test.tsx +35 -1
  259. package/src/session/facets/__tests__/SetupTab.test.tsx +44 -0
  260. package/src/session/{inspector → facets}/index.ts +0 -16
  261. package/src/session/index.ts +30 -13
  262. package/src/session/plan-document.ts +19 -0
  263. package/src/session/useOpenFileChange.ts +53 -0
  264. package/src/session/usePlanDraft.ts +109 -0
  265. package/src/session/useSessionConversation.ts +7 -0
  266. package/src/session/useSessionPageFlow.ts +1 -0
  267. package/src/session/useSessionPanel.ts +288 -0
  268. package/src/session/useSessionRailViews.tsx +200 -0
  269. package/src/workflow/WorkflowExecutionGraph.tsx +1 -1
  270. package/src/workflow/index.ts +1 -1
  271. package/src/workflow/useFollowExecution.ts +1 -1
  272. package/src/workspace/EditorTabs.tsx +145 -0
  273. package/src/workspace/ExplorerTree.tsx +247 -0
  274. package/src/workspace/FileViewer.tsx +516 -0
  275. package/src/workspace/WorkspaceContentSearch.tsx +478 -0
  276. package/src/workspace/WorkspaceContentSearcher.ts +70 -0
  277. package/src/workspace/WorkspaceFileLister.ts +11 -0
  278. package/src/workspace/WorkspaceFileReader.ts +57 -0
  279. package/src/workspace/WorkspaceFileSearch.tsx +429 -0
  280. package/src/workspace/WorkspaceSurface.tsx +781 -0
  281. package/src/workspace/__tests__/EditorTabs.test.tsx +100 -0
  282. package/src/workspace/__tests__/ExplorerTree.test.tsx +152 -0
  283. package/src/workspace/__tests__/FileViewer.test.tsx +421 -0
  284. package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +196 -0
  285. package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +206 -0
  286. package/src/workspace/__tests__/WorkspaceSurface.test.tsx +348 -0
  287. package/src/workspace/__tests__/findChangeForSelection.test.ts +132 -0
  288. package/src/workspace/__tests__/matchContentPreview.test.ts +55 -0
  289. package/src/workspace/__tests__/matchWorkspaceFiles.test.ts +104 -0
  290. package/src/workspace/__tests__/resolveWorkspaceFileSelection.test.ts +135 -0
  291. package/src/workspace/__tests__/useWorkspaceContentSearch.test.tsx +196 -0
  292. package/src/workspace/__tests__/useWorkspaceFileContent.test.tsx +190 -0
  293. package/src/workspace/__tests__/useWorkspaceFileSearch.test.tsx +162 -0
  294. package/src/workspace/findChangeForSelection.ts +61 -0
  295. package/src/workspace/index.ts +56 -2
  296. package/src/workspace/matchContentPreview.ts +51 -0
  297. package/src/workspace/matchWorkspaceFiles.ts +86 -0
  298. package/src/workspace/resolveWorkspaceFileSelection.ts +119 -0
  299. package/src/workspace/useWorkspaceContentSearch.ts +228 -0
  300. package/src/workspace/useWorkspaceFileContent.ts +129 -0
  301. package/src/workspace/useWorkspaceFileSearch.ts +184 -0
  302. package/src/workspace/useWorkspaceFiles.ts +27 -27
  303. package/src/workspace/workspaceListingCache.ts +93 -0
  304. package/styles.css +1 -1
  305. package/workflow/WorkflowExecutionGraph.js +1 -1
  306. package/workflow/WorkflowExecutionGraph.js.map +1 -1
  307. package/workflow/index.d.ts +1 -1
  308. package/workflow/index.d.ts.map +1 -1
  309. package/workflow/index.js +1 -1
  310. package/workflow/index.js.map +1 -1
  311. package/workflow/useFollowExecution.js +1 -1
  312. package/workflow/useFollowExecution.js.map +1 -1
  313. package/workspace/EditorTabs.d.ts +29 -0
  314. package/workspace/EditorTabs.d.ts.map +1 -0
  315. package/workspace/EditorTabs.js +66 -0
  316. package/workspace/EditorTabs.js.map +1 -0
  317. package/workspace/ExplorerTree.d.ts +32 -0
  318. package/workspace/ExplorerTree.d.ts.map +1 -0
  319. package/workspace/ExplorerTree.js +45 -0
  320. package/workspace/ExplorerTree.js.map +1 -0
  321. package/workspace/FileViewer.d.ts +93 -0
  322. package/workspace/FileViewer.d.ts.map +1 -0
  323. package/workspace/FileViewer.js +182 -0
  324. package/workspace/FileViewer.js.map +1 -0
  325. package/workspace/WorkspaceContentSearch.d.ts +41 -0
  326. package/workspace/WorkspaceContentSearch.d.ts.map +1 -0
  327. package/workspace/WorkspaceContentSearch.js +195 -0
  328. package/workspace/WorkspaceContentSearch.js.map +1 -0
  329. package/workspace/WorkspaceContentSearcher.d.ts +59 -0
  330. package/workspace/WorkspaceContentSearcher.d.ts.map +1 -0
  331. package/workspace/WorkspaceContentSearcher.js +7 -0
  332. package/workspace/WorkspaceContentSearcher.js.map +1 -0
  333. package/workspace/WorkspaceFileLister.d.ts +11 -0
  334. package/workspace/WorkspaceFileLister.d.ts.map +1 -1
  335. package/workspace/WorkspaceFileReader.d.ts +48 -0
  336. package/workspace/WorkspaceFileReader.d.ts.map +1 -0
  337. package/workspace/WorkspaceFileReader.js +11 -0
  338. package/workspace/WorkspaceFileReader.js.map +1 -0
  339. package/workspace/WorkspaceFileSearch.d.ts +32 -0
  340. package/workspace/WorkspaceFileSearch.d.ts.map +1 -0
  341. package/workspace/WorkspaceFileSearch.js +155 -0
  342. package/workspace/WorkspaceFileSearch.js.map +1 -0
  343. package/workspace/WorkspaceSurface.d.ts +151 -0
  344. package/workspace/WorkspaceSurface.d.ts.map +1 -0
  345. package/workspace/WorkspaceSurface.js +184 -0
  346. package/workspace/WorkspaceSurface.js.map +1 -0
  347. package/workspace/findChangeForSelection.d.ts +19 -0
  348. package/workspace/findChangeForSelection.d.ts.map +1 -0
  349. package/workspace/findChangeForSelection.js +46 -0
  350. package/workspace/findChangeForSelection.js.map +1 -0
  351. package/workspace/index.d.ts +24 -2
  352. package/workspace/index.d.ts.map +1 -1
  353. package/workspace/index.js +13 -1
  354. package/workspace/index.js.map +1 -1
  355. package/workspace/matchContentPreview.d.ts +21 -0
  356. package/workspace/matchContentPreview.d.ts.map +1 -0
  357. package/workspace/matchContentPreview.js +36 -0
  358. package/workspace/matchContentPreview.js.map +1 -0
  359. package/workspace/matchWorkspaceFiles.d.ts +30 -0
  360. package/workspace/matchWorkspaceFiles.d.ts.map +1 -0
  361. package/workspace/matchWorkspaceFiles.js +58 -0
  362. package/workspace/matchWorkspaceFiles.js.map +1 -0
  363. package/workspace/resolveWorkspaceFileSelection.d.ts +19 -0
  364. package/workspace/resolveWorkspaceFileSelection.d.ts.map +1 -0
  365. package/workspace/resolveWorkspaceFileSelection.js +115 -0
  366. package/workspace/resolveWorkspaceFileSelection.js.map +1 -0
  367. package/workspace/useWorkspaceContentSearch.d.ts +69 -0
  368. package/workspace/useWorkspaceContentSearch.d.ts.map +1 -0
  369. package/workspace/useWorkspaceContentSearch.js +154 -0
  370. package/workspace/useWorkspaceContentSearch.js.map +1 -0
  371. package/workspace/useWorkspaceFileContent.d.ts +73 -0
  372. package/workspace/useWorkspaceFileContent.d.ts.map +1 -0
  373. package/workspace/useWorkspaceFileContent.js +57 -0
  374. package/workspace/useWorkspaceFileContent.js.map +1 -0
  375. package/workspace/useWorkspaceFileSearch.d.ts +61 -0
  376. package/workspace/useWorkspaceFileSearch.d.ts.map +1 -0
  377. package/workspace/useWorkspaceFileSearch.js +119 -0
  378. package/workspace/useWorkspaceFileSearch.js.map +1 -0
  379. package/workspace/useWorkspaceFiles.d.ts +13 -5
  380. package/workspace/useWorkspaceFiles.d.ts.map +1 -1
  381. package/workspace/useWorkspaceFiles.js +18 -19
  382. package/workspace/useWorkspaceFiles.js.map +1 -1
  383. package/workspace/workspaceListingCache.d.ts +47 -0
  384. package/workspace/workspaceListingCache.d.ts.map +1 -0
  385. package/workspace/workspaceListingCache.js +55 -0
  386. package/workspace/workspaceListingCache.js.map +1 -0
  387. package/session/inspector/ArtifactsTab.d.ts.map +0 -1
  388. package/session/inspector/ArtifactsTab.js.map +0 -1
  389. package/session/inspector/ChangesTab.d.ts.map +0 -1
  390. package/session/inspector/ChangesTab.js.map +0 -1
  391. package/session/inspector/InspectTab.d.ts.map +0 -1
  392. package/session/inspector/InspectTab.js.map +0 -1
  393. package/session/inspector/SessionInspector.d.ts +0 -64
  394. package/session/inspector/SessionInspector.d.ts.map +0 -1
  395. package/session/inspector/SessionInspector.js +0 -53
  396. package/session/inspector/SessionInspector.js.map +0 -1
  397. package/session/inspector/SetupTab.d.ts.map +0 -1
  398. package/session/inspector/SetupTab.js.map +0 -1
  399. package/session/inspector/UsageTab.d.ts.map +0 -1
  400. package/session/inspector/UsageTab.js.map +0 -1
  401. package/session/inspector/WorkspaceTab.d.ts +0 -35
  402. package/session/inspector/WorkspaceTab.d.ts.map +0 -1
  403. package/session/inspector/WorkspaceTab.js +0 -75
  404. package/session/inspector/WorkspaceTab.js.map +0 -1
  405. package/session/inspector/index.d.ts.map +0 -1
  406. package/session/inspector/index.js.map +0 -1
  407. package/session/inspector/useSessionInspector.d.ts +0 -49
  408. package/session/inspector/useSessionInspector.d.ts.map +0 -1
  409. package/session/inspector/useSessionInspector.js +0 -122
  410. package/session/inspector/useSessionInspector.js.map +0 -1
  411. package/src/session/inspector/SessionInspector.tsx +0 -162
  412. package/src/session/inspector/WorkspaceTab.tsx +0 -245
  413. package/src/session/inspector/__tests__/useSessionInspector.test.ts +0 -251
  414. package/src/session/inspector/useSessionInspector.ts +0 -178
  415. package/src/workspace/WorkspaceEntryFiles.tsx +0 -196
  416. package/workflow/motion-preference.d.ts.map +0 -1
  417. package/workflow/motion-preference.js.map +0 -1
  418. package/workspace/WorkspaceEntryFiles.d.ts +0 -22
  419. package/workspace/WorkspaceEntryFiles.d.ts.map +0 -1
  420. package/workspace/WorkspaceEntryFiles.js +0 -58
  421. package/workspace/WorkspaceEntryFiles.js.map +0 -1
  422. /package/session/{inspector → facets}/InspectTab.d.ts +0 -0
  423. /package/session/{inspector → facets}/InspectTab.js +0 -0
  424. /package/src/{workflow → internal}/__tests__/motion-preference.test.ts +0 -0
  425. /package/src/session/{inspector → facets}/InspectTab.tsx +0 -0
  426. /package/src/session/{inspector → facets}/__tests__/ChangesTab.test.tsx +0 -0
@@ -0,0 +1,154 @@
1
+ "use client";
2
+ import { useEffect, useMemo, useRef, useState } from "react";
3
+ import { toError } from "../internal/toError.js";
4
+ /** Default debounce for content-search query changes — matches `useResourceSearch`. */
5
+ const DEFAULT_DEBOUNCE_MS = 300;
6
+ /**
7
+ * Minimum query length before a disk search fires. Content search hits the
8
+ * filesystem on every query (unlike the cached filename search), so a
9
+ * single-character query would scan the whole tree for a near-useless result.
10
+ * Two characters is a gentle, documented floor — not an arbitrary limit.
11
+ */
12
+ const DEFAULT_MIN_LENGTH = 2;
13
+ const EMPTY_GROUPS = [];
14
+ /**
15
+ * Behavior hook powering workspace-wide content (text) search.
16
+ *
17
+ * The text-grep sibling of
18
+ * {@link useWorkspaceFileSearch}: it keeps
19
+ * that hook's per-entry aggregation, error isolation, and generation guard, and
20
+ * adds the platform's canonical debounce idiom from `useResourceSearch`
21
+ * (`query`/`debouncedQuery` + `setTimeout`). The key difference is that the
22
+ * debounced query is part of the *fetch* — each keystroke hits disk via the
23
+ * injected {@link WorkspaceContentSearcher}, uncached — so a `minLength` guard
24
+ * and a debounce protect the filesystem.
25
+ *
26
+ * Prior results stay visible while a new debounced query loads (`isRefetching`
27
+ * true, results unchanged); only the very first search with nothing to show
28
+ * flips `isLoading`. This avoids a per-keystroke blank flash the cached filename
29
+ * search never had.
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * const { groups, totalMatches, isRefetching } = useWorkspaceContentSearch({
34
+ * entries: workspace.entries,
35
+ * searcher: workspaceContentSearcher,
36
+ * query,
37
+ * });
38
+ * ```
39
+ */
40
+ export function useWorkspaceContentSearch({ entries, searcher, query, debounceMs = DEFAULT_DEBOUNCE_MS, minLength = DEFAULT_MIN_LENGTH, }) {
41
+ // Settled results per entry, keyed by entry id. Retained across query changes
42
+ // and only swapped wholesale when a new generation fully resolves — so a
43
+ // reload never blanks what the user is already reading.
44
+ const [results, setResults] = useState({});
45
+ const [pending, setPending] = useState(false);
46
+ // Debounce the query into the fetch key (the `useResourceSearch` idiom).
47
+ const [debouncedQuery, setDebouncedQuery] = useState(query);
48
+ useEffect(() => {
49
+ const timer = setTimeout(() => setDebouncedQuery(query), debounceMs);
50
+ return () => clearTimeout(timer);
51
+ }, [query, debounceMs]);
52
+ // Latest entries read inside the effect without widening its dependency to the
53
+ // (possibly per-render) array identity — the effect keys on the id set instead.
54
+ const entriesRef = useRef(entries);
55
+ entriesRef.current = entries;
56
+ const entriesKey = entries.map((entry) => entry.id).join("\u0000");
57
+ // Ignore resolutions from a superseded run (id set, searcher, or query changed).
58
+ const generationRef = useRef(0);
59
+ const effectiveQuery = debouncedQuery.trim();
60
+ const belowMinLength = effectiveQuery.length < minLength;
61
+ useEffect(() => {
62
+ // No searcher or a too-short query: clear results, nothing in flight. (An
63
+ // in-flight generation is abandoned via the bumped ref.)
64
+ if (!searcher || belowMinLength) {
65
+ generationRef.current += 1;
66
+ setResults({});
67
+ setPending(false);
68
+ return;
69
+ }
70
+ const currentEntries = entriesRef.current;
71
+ const generation = ++generationRef.current;
72
+ setPending(true);
73
+ Promise.all(currentEntries.map(async (entry) => {
74
+ try {
75
+ const result = await searcher(entry, effectiveQuery);
76
+ if (result === null)
77
+ return [entry.id, { status: "unsupported" }];
78
+ return [
79
+ entry.id,
80
+ { status: "ready", matches: result.matches, truncated: result.truncated },
81
+ ];
82
+ }
83
+ catch (err) {
84
+ return [entry.id, { status: "error", error: toError(err) }];
85
+ }
86
+ })).then((settled) => {
87
+ // A newer generation started while this batch was in flight — drop it so
88
+ // stale results never overwrite fresher ones (or clobber a cleared state).
89
+ if (generationRef.current !== generation)
90
+ return;
91
+ const next = {};
92
+ for (const [id, res] of settled)
93
+ next[id] = res;
94
+ setResults(next);
95
+ setPending(false);
96
+ });
97
+ }, [entriesKey, searcher, effectiveQuery, belowMinLength]);
98
+ return useMemo(() => {
99
+ if (!searcher) {
100
+ return {
101
+ groups: EMPTY_GROUPS,
102
+ totalMatches: 0,
103
+ isLoading: false,
104
+ isRefetching: false,
105
+ isUnsupported: true,
106
+ error: null,
107
+ };
108
+ }
109
+ const groups = [];
110
+ let totalMatches = 0;
111
+ let firstError = null;
112
+ let unsupportedCount = 0;
113
+ let settledCount = 0;
114
+ for (const entry of entries) {
115
+ const state = results[entry.id];
116
+ if (!state)
117
+ continue;
118
+ settledCount += 1;
119
+ if (state.status === "unsupported") {
120
+ unsupportedCount += 1;
121
+ continue;
122
+ }
123
+ if (state.status === "error") {
124
+ if (!firstError)
125
+ firstError = state.error;
126
+ groups.push({ entry, matches: [], truncated: false, error: state.error });
127
+ continue;
128
+ }
129
+ totalMatches += state.matches.length;
130
+ // Worth showing only when it carries matches or a truncation notice.
131
+ if (state.matches.length > 0 || state.truncated) {
132
+ groups.push({
133
+ entry,
134
+ matches: state.matches,
135
+ truncated: state.truncated,
136
+ error: null,
137
+ });
138
+ }
139
+ }
140
+ const hasPriorResults = settledCount > 0;
141
+ const isUnsupported = entries.length > 0 && unsupportedCount === entries.length;
142
+ return {
143
+ groups,
144
+ totalMatches,
145
+ // First search (nothing settled yet) blanks; a reload over existing
146
+ // results keeps them visible and signals `isRefetching` instead.
147
+ isLoading: pending && !hasPriorResults,
148
+ isRefetching: pending && hasPriorResults,
149
+ isUnsupported,
150
+ error: firstError,
151
+ };
152
+ }, [entries, results, pending, searcher]);
153
+ }
154
+ //# sourceMappingURL=useWorkspaceContentSearch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWorkspaceContentSearch.js","sourceRoot":"","sources":["../../src/workspace/useWorkspaceContentSearch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import type { WorkspaceEntry } from "./useWorkspaceEntries.js";
2
+ import type { WorkspaceFileContent, WorkspaceFileReader } from "./WorkspaceFileReader.js";
3
+ /** Options for {@link useWorkspaceFileContent}. */
4
+ export interface UseWorkspaceFileContentOptions {
5
+ /** The workspace entry that owns the file, or `null` when nothing is open. */
6
+ readonly entry: WorkspaceEntry | null;
7
+ /** Repo-relative (git) or root-relative (local) path, or `null` when nothing is open. */
8
+ readonly path: string | null;
9
+ /**
10
+ * Platform-injected content reader. `undefined` when the host app injects
11
+ * no reader at all (e.g. web with no GitHub token) — surfaced as
12
+ * {@link UseWorkspaceFileContentReturn.isUnsupported}, not an error.
13
+ */
14
+ readonly reader: WorkspaceFileReader | undefined;
15
+ }
16
+ /** Return value of {@link useWorkspaceFileContent}. */
17
+ export interface UseWorkspaceFileContentReturn {
18
+ /**
19
+ * The decoded file content (+ metadata), or `null` while the request is
20
+ * in-flight, skipped, failed, or the substrate is unsupported. A present
21
+ * object with `text === null` is a real file that is binary, too large, or
22
+ * undecodable — distinct from `isUnsupported`.
23
+ */
24
+ readonly content: WorkspaceFileContent | null;
25
+ /** `true` only on the first load, before any content has arrived. */
26
+ readonly isLoading: boolean;
27
+ /** `true` while a background refetch is in flight and stale content is shown. */
28
+ readonly isRefetching: boolean;
29
+ /** Error from the last failed read (a reader throw), or `null` when healthy. */
30
+ readonly error: Error | null;
31
+ /**
32
+ * `true` when no reader can serve this file — either no reader was injected
33
+ * or the reader reported the entry's substrate as unsupported (git-on-desktop,
34
+ * local-on-web, missing token). This is the honest "not available here" state,
35
+ * never an error.
36
+ */
37
+ readonly isUnsupported: boolean;
38
+ /** Imperatively re-read the current file. Stale content stays visible. */
39
+ readonly refetch: () => void;
40
+ }
41
+ /**
42
+ * Behavior hook that reads a single workspace file's content on demand.
43
+ *
44
+ * The byte-reading peer of {@link useWorkspaceFiles}
45
+ * (which lists the tree), built on the same {@link useFetch} engine as the
46
+ * content-fetch family ({@link useArtifactContent},
47
+ * `useToolOutputContent`, `useFileChangeContent`) so it inherits their
48
+ * stale-while-revalidate, cancellation, and `refetch` semantics for free.
49
+ *
50
+ * Deliberately passes **no** `cacheKey`: file bodies (up to
51
+ * {@link MAX_WORKSPACE_FILE_READ_BYTES})
52
+ * do not belong in the cross-mount metadata cache, which is sized for small,
53
+ * hot resources. Re-opening a file re-reads it — the correct trade for a
54
+ * read-only viewer.
55
+ *
56
+ * Maps the reader's two failure axes onto distinct states:
57
+ * - reader resolves `null` (unsupported substrate) -> {@link UseWorkspaceFileContentReturn.isUnsupported}
58
+ * - reader **throws** (404, network, unreadable) -> {@link UseWorkspaceFileContentReturn.error}
59
+ *
60
+ * Pass `null` for `entry`/`path` (or an `undefined` reader) to stay idle —
61
+ * the established `useFetch` convention.
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * const { content, isLoading, error, isUnsupported } = useWorkspaceFileContent({
66
+ * entry,
67
+ * path: "src/index.ts",
68
+ * reader: workspaceFileReader,
69
+ * });
70
+ * ```
71
+ */
72
+ export declare function useWorkspaceFileContent({ entry, path, reader, }: UseWorkspaceFileContentOptions): UseWorkspaceFileContentReturn;
73
+ //# sourceMappingURL=useWorkspaceFileContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWorkspaceFileContent.d.ts","sourceRoot":"","sources":["../../src/workspace/useWorkspaceFileContent.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AAElC,mDAAmD;AACnD,MAAM,WAAW,8BAA8B;IAC7C,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,CAAC;CAClD;AAED,uDAAuD;AACvD,MAAM,WAAW,6BAA6B;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC9C,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAcD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,IAAI,EACJ,MAAM,GACP,EAAE,8BAA8B,GAAG,6BAA6B,CA+BhE"}
@@ -0,0 +1,57 @@
1
+ "use client";
2
+ import { useMemo } from "react";
3
+ import { useFetch } from "../internal/useFetch.js";
4
+ const EMPTY_CONTENT = { content: null };
5
+ /**
6
+ * Behavior hook that reads a single workspace file's content on demand.
7
+ *
8
+ * The byte-reading peer of {@link useWorkspaceFiles}
9
+ * (which lists the tree), built on the same {@link useFetch} engine as the
10
+ * content-fetch family ({@link useArtifactContent},
11
+ * `useToolOutputContent`, `useFileChangeContent`) so it inherits their
12
+ * stale-while-revalidate, cancellation, and `refetch` semantics for free.
13
+ *
14
+ * Deliberately passes **no** `cacheKey`: file bodies (up to
15
+ * {@link MAX_WORKSPACE_FILE_READ_BYTES})
16
+ * do not belong in the cross-mount metadata cache, which is sized for small,
17
+ * hot resources. Re-opening a file re-reads it — the correct trade for a
18
+ * read-only viewer.
19
+ *
20
+ * Maps the reader's two failure axes onto distinct states:
21
+ * - reader resolves `null` (unsupported substrate) -> {@link UseWorkspaceFileContentReturn.isUnsupported}
22
+ * - reader **throws** (404, network, unreadable) -> {@link UseWorkspaceFileContentReturn.error}
23
+ *
24
+ * Pass `null` for `entry`/`path` (or an `undefined` reader) to stay idle —
25
+ * the established `useFetch` convention.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * const { content, isLoading, error, isUnsupported } = useWorkspaceFileContent({
30
+ * entry,
31
+ * path: "src/index.ts",
32
+ * reader: workspaceFileReader,
33
+ * });
34
+ * ```
35
+ */
36
+ export function useWorkspaceFileContent({ entry, path, reader, }) {
37
+ // The fetch runs only when a reader, an entry, and a path are all present.
38
+ const enabled = !!(reader && entry && path);
39
+ const { data, isLoading, isRefetching, error, refetch } = useFetch(enabled
40
+ ? () => reader(entry, path).then((c) => ({ content: c }))
41
+ : null,
42
+ // Identity deps: a change to any of these is a different file to read.
43
+ [entry?.id ?? null, path ?? null, reader], EMPTY_CONTENT);
44
+ // Unsupported = no reader at all, or a completed fetch that resolved to null
45
+ // (the reader's "this substrate isn't mine" signal). In-flight and error
46
+ // states are excluded so the viewer shows loading/error, not "unavailable".
47
+ const isUnsupported = !reader || (enabled && !isLoading && !error && data.content === null);
48
+ return useMemo(() => ({
49
+ content: data.content,
50
+ isLoading,
51
+ isRefetching,
52
+ error,
53
+ isUnsupported,
54
+ refetch,
55
+ }), [data.content, isLoading, isRefetching, error, isUnsupported, refetch]);
56
+ }
57
+ //# sourceMappingURL=useWorkspaceFileContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWorkspaceFileContent.js","sourceRoot":"","sources":["../../src/workspace/useWorkspaceFileContent.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAyDnD,MAAM,aAAa,GAAoB,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,KAAK,EACL,IAAI,EACJ,MAAM,GACyB;IAC/B,2EAA2E;IAC3E,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC;IAE5C,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,GACrD,QAAQ,CACN,OAAO;QACL,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QACzD,CAAC,CAAC,IAAI;IACR,uEAAuE;IACvE,CAAC,KAAK,EAAE,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,MAAM,CAAC,EACzC,aAAa,CACd,CAAC;IAEJ,6EAA6E;IAC7E,yEAAyE;IACzE,4EAA4E;IAC5E,MAAM,aAAa,GACjB,CAAC,MAAM,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;IAExE,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,CAAC;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,SAAS;QACT,YAAY;QACZ,KAAK;QACL,aAAa;QACb,OAAO;KACR,CAAC,EACF,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,CACvE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,61 @@
1
+ import type { WorkspaceEntry } from "./useWorkspaceEntries.js";
2
+ import type { WorkspaceFileLister } from "./WorkspaceFileLister.js";
3
+ import { type WorkspaceFileMatch } from "./matchWorkspaceFiles.js";
4
+ /** Options for {@link useWorkspaceFileSearch}. */
5
+ export interface UseWorkspaceFileSearchOptions {
6
+ /** All workspace entries to search across. */
7
+ readonly entries: readonly WorkspaceEntry[];
8
+ /** Platform-injected file lister. `undefined` → nothing is searchable. */
9
+ readonly lister: WorkspaceFileLister | undefined;
10
+ /** Current search query. Empty/whitespace yields no matches (search shows a hint). */
11
+ readonly query: string;
12
+ }
13
+ /** Matches (and per-entry status) for one workspace entry. */
14
+ export interface WorkspaceFileSearchGroup {
15
+ /** The workspace entry these matches belong to. */
16
+ readonly entry: WorkspaceEntry;
17
+ /** Ranked matches within this entry, best-first. */
18
+ readonly matches: readonly WorkspaceFileMatch[];
19
+ /** `true` when this entry's listing was truncated (repository too large). */
20
+ readonly truncated: boolean;
21
+ /** Listing error for this entry, if any (isolated — other entries still resolve). */
22
+ readonly error: Error | null;
23
+ }
24
+ /** Return value of {@link useWorkspaceFileSearch}. */
25
+ export interface UseWorkspaceFileSearchReturn {
26
+ /** Entries with something to show (matches, an error, or a truncation notice). */
27
+ readonly groups: readonly WorkspaceFileSearchGroup[];
28
+ /** Total matches across all groups (for a "showing N of M" affordance). */
29
+ readonly totalMatches: number;
30
+ /** `true` while any entry's listing is still loading. */
31
+ readonly isLoading: boolean;
32
+ /** `true` when no substrate can be searched (no lister, or every entry unsupported). */
33
+ readonly isUnsupported: boolean;
34
+ /** First per-entry error, for a top-level fallback message. `null` when none. */
35
+ readonly error: Error | null;
36
+ }
37
+ /**
38
+ * Behavior hook powering workspace-wide filename/path search.
39
+ *
40
+ * Loads each entry's listing through the shared
41
+ * {@link loadEntryFiles} cache (warm from
42
+ * Files browsing → usually free), then ranks matches per entry with the pure
43
+ * {@link matchWorkspaceFiles}. Fetching is keyed by the set of entry ids, so a
44
+ * query change re-ranks the already-loaded listings without re-fetching. Errors
45
+ * are isolated per entry (one failing repo never blanks the rest), and a stale
46
+ * generation's late resolutions are ignored.
47
+ *
48
+ * Meant to be consumed by a component mounted only while Search is active
49
+ * (`WorkspaceFileSearch`), so the Files view incurs no search fetching.
50
+ *
51
+ * @example
52
+ * ```tsx
53
+ * const { groups, totalMatches, isLoading } = useWorkspaceFileSearch({
54
+ * entries: workspace.entries,
55
+ * lister: workspaceFileLister,
56
+ * query,
57
+ * });
58
+ * ```
59
+ */
60
+ export declare function useWorkspaceFileSearch({ entries, lister, query, }: UseWorkspaceFileSearchOptions): UseWorkspaceFileSearchReturn;
61
+ //# sourceMappingURL=useWorkspaceFileSearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWorkspaceFileSearch.d.ts","sourceRoot":"","sources":["../../src/workspace/useWorkspaceFileSearch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAExF,kDAAkD;AAClD,MAAM,WAAW,6BAA6B;IAC5C,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACjD,sFAAsF;IACtF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,8DAA8D;AAC9D,MAAM,WAAW,wBAAwB;IACvC,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAChD,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,qFAAqF;IACrF,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CAC9B;AAED,sDAAsD;AACtD,MAAM,WAAW,4BAA4B;IAC3C,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,SAAS,wBAAwB,EAAE,CAAC;IACrD,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,wFAAwF;IACxF,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CAC9B;AAWD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,OAAO,EACP,MAAM,EACN,KAAK,GACN,EAAE,6BAA6B,GAAG,4BAA4B,CAsG9D"}
@@ -0,0 +1,119 @@
1
+ "use client";
2
+ import { useEffect, useMemo, useRef, useState } from "react";
3
+ import { toError } from "../internal/toError.js";
4
+ import { loadEntryFiles } from "./workspaceListingCache.js";
5
+ import { matchWorkspaceFiles } from "./matchWorkspaceFiles.js";
6
+ const EMPTY_GROUPS = [];
7
+ /**
8
+ * Behavior hook powering workspace-wide filename/path search.
9
+ *
10
+ * Loads each entry's listing through the shared
11
+ * {@link loadEntryFiles} cache (warm from
12
+ * Files browsing → usually free), then ranks matches per entry with the pure
13
+ * {@link matchWorkspaceFiles}. Fetching is keyed by the set of entry ids, so a
14
+ * query change re-ranks the already-loaded listings without re-fetching. Errors
15
+ * are isolated per entry (one failing repo never blanks the rest), and a stale
16
+ * generation's late resolutions are ignored.
17
+ *
18
+ * Meant to be consumed by a component mounted only while Search is active
19
+ * (`WorkspaceFileSearch`), so the Files view incurs no search fetching.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * const { groups, totalMatches, isLoading } = useWorkspaceFileSearch({
24
+ * entries: workspace.entries,
25
+ * lister: workspaceFileLister,
26
+ * query,
27
+ * });
28
+ * ```
29
+ */
30
+ export function useWorkspaceFileSearch({ entries, lister, query, }) {
31
+ const [states, setStates] = useState({});
32
+ // Latest entries read inside the effect without widening its dependency to the
33
+ // (possibly per-render) array identity — the effect keys on the id set instead.
34
+ const entriesRef = useRef(entries);
35
+ entriesRef.current = entries;
36
+ const entriesKey = entries.map((entry) => entry.id).join("\u0000");
37
+ // Ignore resolutions from a superseded entry set (id set or lister changed).
38
+ const generationRef = useRef(0);
39
+ useEffect(() => {
40
+ if (!lister) {
41
+ setStates({});
42
+ return;
43
+ }
44
+ const currentEntries = entriesRef.current;
45
+ const generation = ++generationRef.current;
46
+ // Seed loading for not-yet-known entries; drop states for removed ones.
47
+ setStates((prev) => {
48
+ const next = {};
49
+ for (const entry of currentEntries) {
50
+ next[entry.id] = prev[entry.id] ?? { status: "loading" };
51
+ }
52
+ return next;
53
+ });
54
+ for (const entry of currentEntries) {
55
+ loadEntryFiles(entry, lister)
56
+ .then((listing) => {
57
+ if (generationRef.current !== generation)
58
+ return;
59
+ setStates((prev) => ({
60
+ ...prev,
61
+ [entry.id]: listing === null
62
+ ? { status: "unsupported" }
63
+ : { status: "ready", listing },
64
+ }));
65
+ })
66
+ .catch((err) => {
67
+ if (generationRef.current !== generation)
68
+ return;
69
+ setStates((prev) => ({
70
+ ...prev,
71
+ [entry.id]: { status: "error", error: toError(err) },
72
+ }));
73
+ });
74
+ }
75
+ }, [entriesKey, lister]);
76
+ return useMemo(() => {
77
+ if (!lister) {
78
+ return {
79
+ groups: EMPTY_GROUPS,
80
+ totalMatches: 0,
81
+ isLoading: false,
82
+ isUnsupported: true,
83
+ error: null,
84
+ };
85
+ }
86
+ const groups = [];
87
+ let totalMatches = 0;
88
+ let isLoading = false;
89
+ let firstError = null;
90
+ let unsupportedCount = 0;
91
+ for (const entry of entries) {
92
+ const state = states[entry.id];
93
+ if (!state || state.status === "loading") {
94
+ isLoading = true;
95
+ continue;
96
+ }
97
+ if (state.status === "unsupported") {
98
+ unsupportedCount += 1;
99
+ continue;
100
+ }
101
+ const error = state.status === "error" ? state.error ?? null : null;
102
+ if (error && !firstError)
103
+ firstError = error;
104
+ const truncated = state.listing?.truncated ?? false;
105
+ const matches = state.listing
106
+ ? matchWorkspaceFiles(state.listing.files, query)
107
+ : [];
108
+ totalMatches += matches.length;
109
+ // A group is worth showing only when it carries matches, an error, or a
110
+ // truncation notice — otherwise it is silent.
111
+ if (matches.length > 0 || error || truncated) {
112
+ groups.push({ entry, matches, truncated, error });
113
+ }
114
+ }
115
+ const isUnsupported = entries.length > 0 && unsupportedCount === entries.length;
116
+ return { groups, totalMatches, isLoading, isUnsupported, error: firstError };
117
+ }, [entries, states, query, lister]);
118
+ }
119
+ //# sourceMappingURL=useWorkspaceFileSearch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWorkspaceFileSearch.js","sourceRoot":"","sources":["../../src/workspace/useWorkspaceFileSearch.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type TreeNode } from "../internal/file-tree/index.js";
1
+ import type { TreeNode } from "../internal/file-tree/index.js";
2
2
  import type { WorkspaceEntry } from "./useWorkspaceEntries.js";
3
3
  import type { WorkspaceFileLister } from "./WorkspaceFileLister.js";
4
4
  /** Options for {@link useWorkspaceFiles}. */
@@ -16,6 +16,12 @@ export interface UseWorkspaceFilesReturn {
16
16
  readonly isLoading: boolean;
17
17
  /** Error from the lister, if any. */
18
18
  readonly error: Error | null;
19
+ /**
20
+ * `true` when the listing was truncated by the backend (repository too large).
21
+ * The advisory entry is excluded from `tree`; callers render an incomplete-results
22
+ * banner from this flag instead (DD-11).
23
+ */
24
+ readonly truncated: boolean;
19
25
  /** Re-fetch the file listing for the current entry (cache-bust). */
20
26
  readonly refresh: () => void;
21
27
  }
@@ -23,16 +29,18 @@ export interface UseWorkspaceFilesReturn {
23
29
  * Behavior hook that fetches and caches a file listing for a single
24
30
  * workspace entry, converting it into a {@link TreeNode} hierarchy.
25
31
  *
26
- * - Calls the platform-injected `lister` when the entry changes.
27
- * - Caches results per `entry.id` so tab switches and re-expands
28
- * are instant without re-fetching.
32
+ * - Calls the platform-injected `lister` (via the shared
33
+ * {@link loadEntryFiles} cache) when the
34
+ * entry changes.
35
+ * - Reads the shared listing cache so tab switches, re-expands, and the search
36
+ * surface are instant without re-fetching (one cache, keyed by `entry.id`).
29
37
  * - Returns an empty tree and skips the call when `lister` is
30
38
  * `undefined` (graceful degradation — DD-011 opt-in).
31
39
  * - Memoizes the return value for referential stability (DD-010).
32
40
  *
33
41
  * @example
34
42
  * ```tsx
35
- * const { tree, isLoading, error, refresh } = useWorkspaceFiles({
43
+ * const { tree, isLoading, error, truncated, refresh } = useWorkspaceFiles({
36
44
  * entry: selectedEntry,
37
45
  * lister: workspaceFileLister,
38
46
  * });
@@ -1 +1 @@
1
- {"version":3,"file":"useWorkspaceFiles.d.ts","sourceRoot":"","sources":["../../src/workspace/useWorkspaceFiles.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAE9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAsB,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAExF,6CAA6C;AAC7C,MAAM,WAAW,wBAAwB;IACvC,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,sGAAsG;IACtG,QAAQ,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,CAAC;CAClD;AAED,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;IACnC,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAiBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,MAAM,GACP,EAAE,wBAAwB,GAAG,uBAAuB,CAsEpD"}
1
+ {"version":3,"file":"useWorkspaceFiles.d.ts","sourceRoot":"","sources":["../../src/workspace/useWorkspaceFiles.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAGpE,6CAA6C;AAC7C,MAAM,WAAW,wBAAwB;IACvC,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,sGAAsG;IACtG,QAAQ,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,CAAC;CAClD;AAED,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;IACnC,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAID;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,MAAM,GACP,EAAE,wBAAwB,GAAG,uBAAuB,CA0EpD"}
@@ -1,29 +1,24 @@
1
1
  "use client";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
- import { buildFileTree } from "../internal/file-tree/index.js";
4
3
  import { toError } from "../internal/toError.js";
4
+ import { loadEntryFiles, peekEntryListing } from "./workspaceListingCache.js";
5
5
  const EMPTY_TREE = [];
6
- /**
7
- * Module-level cache shared across all component instances. This ensures
8
- * that switching between tabs (e.g., Workspace tab unmount/remount) doesn't
9
- * re-fetch file listings that were already loaded. Entries are keyed by
10
- * the workspace entry's stable ID.
11
- */
12
- const sharedCache = new Map();
13
6
  /**
14
7
  * Behavior hook that fetches and caches a file listing for a single
15
8
  * workspace entry, converting it into a {@link TreeNode} hierarchy.
16
9
  *
17
- * - Calls the platform-injected `lister` when the entry changes.
18
- * - Caches results per `entry.id` so tab switches and re-expands
19
- * are instant without re-fetching.
10
+ * - Calls the platform-injected `lister` (via the shared
11
+ * {@link loadEntryFiles} cache) when the
12
+ * entry changes.
13
+ * - Reads the shared listing cache so tab switches, re-expands, and the search
14
+ * surface are instant without re-fetching (one cache, keyed by `entry.id`).
20
15
  * - Returns an empty tree and skips the call when `lister` is
21
16
  * `undefined` (graceful degradation — DD-011 opt-in).
22
17
  * - Memoizes the return value for referential stability (DD-010).
23
18
  *
24
19
  * @example
25
20
  * ```tsx
26
- * const { tree, isLoading, error, refresh } = useWorkspaceFiles({
21
+ * const { tree, isLoading, error, truncated, refresh } = useWorkspaceFiles({
27
22
  * entry: selectedEntry,
28
23
  * lister: workspaceFileLister,
29
24
  * });
@@ -33,14 +28,16 @@ export function useWorkspaceFiles({ entry, lister, }) {
33
28
  const [isLoading, setIsLoading] = useState(false);
34
29
  const [error, setError] = useState(null);
35
30
  const [tree, setTree] = useState(EMPTY_TREE);
31
+ const [truncated, setTruncated] = useState(false);
36
32
  const fetchIdRef = useRef(0);
37
33
  const fetchFiles = useCallback(async (target, bustCache) => {
38
34
  if (!lister)
39
35
  return;
40
36
  if (!bustCache) {
41
- const cached = sharedCache.get(target.id);
37
+ const cached = peekEntryListing(target.id);
42
38
  if (cached) {
43
39
  setTree(cached.tree);
40
+ setTruncated(cached.truncated);
44
41
  setError(null);
45
42
  setIsLoading(false);
46
43
  return;
@@ -50,17 +47,17 @@ export function useWorkspaceFiles({ entry, lister, }) {
50
47
  setIsLoading(true);
51
48
  setError(null);
52
49
  try {
53
- const files = await lister(target);
50
+ const listing = await loadEntryFiles(target, lister, { bustCache });
54
51
  if (fetchIdRef.current !== id)
55
52
  return;
56
- if (files === null) {
53
+ if (listing === null) {
57
54
  setTree(EMPTY_TREE);
55
+ setTruncated(false);
58
56
  setIsLoading(false);
59
57
  return;
60
58
  }
61
- const built = buildFileTree(files.filter((f) => !f.isDirectory));
62
- sharedCache.set(target.id, { files, tree: built });
63
- setTree(built);
59
+ setTree(listing.tree);
60
+ setTruncated(listing.truncated);
64
61
  setIsLoading(false);
65
62
  }
66
63
  catch (err) {
@@ -68,12 +65,14 @@ export function useWorkspaceFiles({ entry, lister, }) {
68
65
  return;
69
66
  setError(toError(err));
70
67
  setTree(EMPTY_TREE);
68
+ setTruncated(false);
71
69
  setIsLoading(false);
72
70
  }
73
71
  }, [lister]);
74
72
  useEffect(() => {
75
73
  if (!entry || !lister) {
76
74
  setTree(EMPTY_TREE);
75
+ setTruncated(false);
77
76
  setIsLoading(false);
78
77
  setError(null);
79
78
  return;
@@ -85,6 +84,6 @@ export function useWorkspaceFiles({ entry, lister, }) {
85
84
  fetchFiles(entry, true);
86
85
  }
87
86
  }, [entry, lister, fetchFiles]);
88
- return useMemo(() => ({ tree, isLoading, error, refresh }), [tree, isLoading, error, refresh]);
87
+ return useMemo(() => ({ tree, isLoading, error, truncated, refresh }), [tree, isLoading, error, truncated, refresh]);
89
88
  }
90
89
  //# sourceMappingURL=useWorkspaceFiles.js.map