@stigmer/react 3.1.1 → 3.1.3

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 (483) hide show
  1. package/composer/SessionComposer.d.ts +25 -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/ArtifactPreviewModal.d.ts +5 -5
  10. package/execution/ArtifactPreviewModal.js +4 -4
  11. package/execution/ArtifactPreviewModal.js.map +1 -1
  12. package/execution/FileChangeProgressBar.d.ts +47 -0
  13. package/execution/FileChangeProgressBar.d.ts.map +1 -0
  14. package/execution/FileChangeProgressBar.js +49 -0
  15. package/execution/FileChangeProgressBar.js.map +1 -0
  16. package/execution/FileChangesView.d.ts.map +1 -1
  17. package/execution/FileChangesView.js +19 -4
  18. package/execution/FileChangesView.js.map +1 -1
  19. package/execution/FilePathContext.d.ts +8 -1
  20. package/execution/FilePathContext.d.ts.map +1 -1
  21. package/execution/FilePathContext.js.map +1 -1
  22. package/execution/FilePathLink.d.ts.map +1 -1
  23. package/execution/FilePathLink.js +21 -6
  24. package/execution/FilePathLink.js.map +1 -1
  25. package/execution/FileReviewAtoms.d.ts +27 -0
  26. package/execution/FileReviewAtoms.d.ts.map +1 -0
  27. package/execution/FileReviewAtoms.js +64 -0
  28. package/execution/FileReviewAtoms.js.map +1 -0
  29. package/execution/FileReviewCard.d.ts +2 -2
  30. package/execution/FileReviewCard.d.ts.map +1 -1
  31. package/execution/FileReviewCard.js +32 -62
  32. package/execution/FileReviewCard.js.map +1 -1
  33. package/execution/MessageEntry.d.ts +20 -0
  34. package/execution/MessageEntry.d.ts.map +1 -1
  35. package/execution/MessageEntry.js +19 -5
  36. package/execution/MessageEntry.js.map +1 -1
  37. package/execution/MessageThread.d.ts +75 -13
  38. package/execution/MessageThread.d.ts.map +1 -1
  39. package/execution/MessageThread.js +195 -27
  40. package/execution/MessageThread.js.map +1 -1
  41. package/execution/PlanArtifactCard.d.ts +36 -21
  42. package/execution/PlanArtifactCard.d.ts.map +1 -1
  43. package/execution/PlanArtifactCard.js +39 -25
  44. package/execution/PlanArtifactCard.js.map +1 -1
  45. package/execution/PlanCompletionCard.d.ts +4 -4
  46. package/execution/PlanCompletionCard.d.ts.map +1 -1
  47. package/execution/PlanCompletionCard.js +4 -4
  48. package/execution/PlanCompletionCard.js.map +1 -1
  49. package/execution/PlanDocumentMessage.d.ts +32 -0
  50. package/execution/PlanDocumentMessage.d.ts.map +1 -0
  51. package/execution/PlanDocumentMessage.js +37 -0
  52. package/execution/PlanDocumentMessage.js.map +1 -0
  53. package/execution/PlanStreamingCard.d.ts +50 -0
  54. package/execution/PlanStreamingCard.d.ts.map +1 -0
  55. package/execution/PlanStreamingCard.js +40 -0
  56. package/execution/PlanStreamingCard.js.map +1 -0
  57. package/execution/index.d.ts +9 -1
  58. package/execution/index.d.ts.map +1 -1
  59. package/execution/index.js +4 -0
  60. package/execution/index.js.map +1 -1
  61. package/execution/use-build-from-plan-hotkey.d.ts +1 -1
  62. package/execution/use-build-from-plan-hotkey.js +1 -1
  63. package/execution/useArtifactCopy.d.ts +51 -0
  64. package/execution/useArtifactCopy.d.ts.map +1 -0
  65. package/execution/useArtifactCopy.js +75 -0
  66. package/execution/useArtifactCopy.js.map +1 -0
  67. package/execution/useArtifactDownload.d.ts.map +1 -1
  68. package/execution/useArtifactDownload.js +17 -5
  69. package/execution/useArtifactDownload.js.map +1 -1
  70. package/execution/useCreateAgentExecution.d.ts +12 -0
  71. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  72. package/execution/useCreateAgentExecution.js +5 -1
  73. package/execution/useCreateAgentExecution.js.map +1 -1
  74. package/github/decodeGitHubContent.d.ts +29 -0
  75. package/github/decodeGitHubContent.d.ts.map +1 -0
  76. package/github/decodeGitHubContent.js +72 -0
  77. package/github/decodeGitHubContent.js.map +1 -0
  78. package/github/index.d.ts +1 -0
  79. package/github/index.d.ts.map +1 -1
  80. package/github/index.js +1 -0
  81. package/github/index.js.map +1 -1
  82. package/github/useGitHubFileReader.d.ts +26 -0
  83. package/github/useGitHubFileReader.d.ts.map +1 -0
  84. package/github/useGitHubFileReader.js +106 -0
  85. package/github/useGitHubFileReader.js.map +1 -0
  86. package/github/useGitHubTreeLister.d.ts.map +1 -1
  87. package/github/useGitHubTreeLister.js +6 -2
  88. package/github/useGitHubTreeLister.js.map +1 -1
  89. package/index.d.ts +9 -9
  90. package/index.d.ts.map +1 -1
  91. package/index.js +5 -5
  92. package/index.js.map +1 -1
  93. package/internal/ResizableSplit.d.ts +72 -22
  94. package/internal/ResizableSplit.d.ts.map +1 -1
  95. package/internal/ResizableSplit.js +96 -38
  96. package/internal/ResizableSplit.js.map +1 -1
  97. package/internal/VirtualizedThread.d.ts +5 -3
  98. package/internal/VirtualizedThread.d.ts.map +1 -1
  99. package/internal/VirtualizedThread.js +6 -4
  100. package/internal/VirtualizedThread.js.map +1 -1
  101. package/internal/file-icons/index.d.ts +17 -0
  102. package/internal/file-icons/index.d.ts.map +1 -0
  103. package/internal/file-icons/index.js +60 -0
  104. package/internal/file-icons/index.js.map +1 -0
  105. package/internal/file-tree/FileTreeNode.d.ts +18 -1
  106. package/internal/file-tree/FileTreeNode.d.ts.map +1 -1
  107. package/internal/file-tree/FileTreeNode.js +11 -2
  108. package/internal/file-tree/FileTreeNode.js.map +1 -1
  109. package/internal/markdown-components.d.ts +38 -1
  110. package/internal/markdown-components.d.ts.map +1 -1
  111. package/internal/markdown-components.js +86 -11
  112. package/internal/markdown-components.js.map +1 -1
  113. package/{workflow → internal}/motion-preference.d.ts +7 -4
  114. package/internal/motion-preference.d.ts.map +1 -0
  115. package/{workflow → internal}/motion-preference.js +7 -4
  116. package/internal/motion-preference.js.map +1 -0
  117. package/internal/store/index.d.ts +33 -0
  118. package/internal/store/index.d.ts.map +1 -1
  119. package/internal/store/index.js +59 -0
  120. package/internal/store/index.js.map +1 -1
  121. package/internal/store/workspace-editors-store.d.ts +145 -0
  122. package/internal/store/workspace-editors-store.d.ts.map +1 -0
  123. package/internal/store/workspace-editors-store.js +208 -0
  124. package/internal/store/workspace-editors-store.js.map +1 -0
  125. package/internal/store/workspace-file-selection-store.d.ts +38 -0
  126. package/internal/store/workspace-file-selection-store.d.ts.map +1 -0
  127. package/internal/store/workspace-file-selection-store.js +62 -0
  128. package/internal/store/workspace-file-selection-store.js.map +1 -0
  129. package/internal/useRevealLine.d.ts +49 -0
  130. package/internal/useRevealLine.d.ts.map +1 -0
  131. package/internal/useRevealLine.js +43 -0
  132. package/internal/useRevealLine.js.map +1 -0
  133. package/library/detect-plan-artifact.d.ts +43 -4
  134. package/library/detect-plan-artifact.d.ts.map +1 -1
  135. package/library/detect-plan-artifact.js +45 -5
  136. package/library/detect-plan-artifact.js.map +1 -1
  137. package/library/detect-streaming-plan.d.ts +45 -0
  138. package/library/detect-streaming-plan.d.ts.map +1 -0
  139. package/library/detect-streaming-plan.js +83 -0
  140. package/library/detect-streaming-plan.js.map +1 -0
  141. package/library/index.d.ts +4 -1
  142. package/library/index.d.ts.map +1 -1
  143. package/library/index.js +2 -1
  144. package/library/index.js.map +1 -1
  145. package/package.json +4 -4
  146. package/session/NewSessionViewer.d.ts +19 -4
  147. package/session/NewSessionViewer.d.ts.map +1 -1
  148. package/session/NewSessionViewer.js +52 -25
  149. package/session/NewSessionViewer.js.map +1 -1
  150. package/session/PlanEditor.d.ts +55 -0
  151. package/session/PlanEditor.d.ts.map +1 -0
  152. package/session/PlanEditor.js +88 -0
  153. package/session/PlanEditor.js.map +1 -0
  154. package/session/PlanStreamingDocument.d.ts +30 -0
  155. package/session/PlanStreamingDocument.d.ts.map +1 -0
  156. package/session/PlanStreamingDocument.js +37 -0
  157. package/session/PlanStreamingDocument.js.map +1 -0
  158. package/session/SessionPanelChip.d.ts +26 -0
  159. package/session/SessionPanelChip.d.ts.map +1 -0
  160. package/session/SessionPanelChip.js +40 -0
  161. package/session/SessionPanelChip.js.map +1 -0
  162. package/session/SessionViewer.d.ts +34 -7
  163. package/session/SessionViewer.d.ts.map +1 -1
  164. package/session/SessionViewer.js +334 -33
  165. package/session/SessionViewer.js.map +1 -1
  166. package/session/{inspector → facets}/ArtifactsTab.d.ts +10 -2
  167. package/session/facets/ArtifactsTab.d.ts.map +1 -0
  168. package/session/{inspector → facets}/ArtifactsTab.js +8 -3
  169. package/session/facets/ArtifactsTab.js.map +1 -0
  170. package/session/{inspector → facets}/ChangesTab.d.ts +3 -3
  171. package/session/facets/ChangesTab.d.ts.map +1 -0
  172. package/session/{inspector → facets}/ChangesTab.js +3 -3
  173. package/session/facets/ChangesTab.js.map +1 -0
  174. package/session/facets/InspectTab.d.ts.map +1 -0
  175. package/session/facets/InspectTab.js.map +1 -0
  176. package/session/{inspector → facets}/SetupTab.d.ts +11 -2
  177. package/session/facets/SetupTab.d.ts.map +1 -0
  178. package/session/{inspector → facets}/SetupTab.js +4 -3
  179. package/session/facets/SetupTab.js.map +1 -0
  180. package/session/{inspector → facets}/UsageTab.d.ts +1 -1
  181. package/session/facets/UsageTab.d.ts.map +1 -0
  182. package/session/{inspector → facets}/UsageTab.js +1 -1
  183. package/session/facets/UsageTab.js.map +1 -0
  184. package/session/{inspector → facets}/index.d.ts +0 -6
  185. package/session/facets/index.d.ts.map +1 -0
  186. package/session/{inspector → facets}/index.js +0 -3
  187. package/session/facets/index.js.map +1 -0
  188. package/session/index.d.ts +11 -2
  189. package/session/index.d.ts.map +1 -1
  190. package/session/index.js +15 -2
  191. package/session/index.js.map +1 -1
  192. package/session/plan-document.d.ts +21 -0
  193. package/session/plan-document.d.ts.map +1 -0
  194. package/session/plan-document.js +28 -0
  195. package/session/plan-document.js.map +1 -0
  196. package/session/useOpenFileChange.d.ts +20 -0
  197. package/session/useOpenFileChange.d.ts.map +1 -0
  198. package/session/useOpenFileChange.js +31 -0
  199. package/session/useOpenFileChange.js.map +1 -0
  200. package/session/usePlanDraft.d.ts +52 -0
  201. package/session/usePlanDraft.d.ts.map +1 -0
  202. package/session/usePlanDraft.js +63 -0
  203. package/session/usePlanDraft.js.map +1 -0
  204. package/session/useSessionConversation.d.ts +14 -1
  205. package/session/useSessionConversation.d.ts.map +1 -1
  206. package/session/useSessionConversation.js +20 -2
  207. package/session/useSessionConversation.js.map +1 -1
  208. package/session/useSessionPageFlow.d.ts.map +1 -1
  209. package/session/useSessionPageFlow.js +1 -0
  210. package/session/useSessionPageFlow.js.map +1 -1
  211. package/session/useSessionPanel.d.ts +120 -0
  212. package/session/useSessionPanel.d.ts.map +1 -0
  213. package/session/useSessionPanel.js +130 -0
  214. package/session/useSessionPanel.js.map +1 -0
  215. package/session/useSessionRailViews.d.ts +45 -0
  216. package/session/useSessionRailViews.d.ts.map +1 -0
  217. package/session/useSessionRailViews.js +105 -0
  218. package/session/useSessionRailViews.js.map +1 -0
  219. package/src/composer/SessionComposer.tsx +53 -10
  220. package/src/composer/__tests__/SessionComposer-contract.test.tsx +58 -4
  221. package/src/execution/ArtifactContentRenderer.tsx +101 -24
  222. package/src/execution/ArtifactPreviewModal.tsx +9 -9
  223. package/src/execution/FileChangeProgressBar.tsx +121 -0
  224. package/src/execution/FileChangesView.tsx +18 -4
  225. package/src/execution/FilePathContext.tsx +8 -1
  226. package/src/execution/FilePathLink.tsx +22 -6
  227. package/src/execution/FileReviewAtoms.tsx +89 -0
  228. package/src/execution/FileReviewCard.tsx +57 -90
  229. package/src/execution/MessageEntry.tsx +49 -1
  230. package/src/execution/MessageThread.tsx +308 -39
  231. package/src/execution/PlanArtifactCard.tsx +174 -64
  232. package/src/execution/PlanCompletionCard.tsx +5 -5
  233. package/src/execution/PlanDocumentMessage.tsx +96 -0
  234. package/src/execution/PlanStreamingCard.tsx +141 -0
  235. package/src/execution/__tests__/ArtifactContentRenderer.test.tsx +80 -1
  236. package/src/execution/__tests__/ArtifactPreviewModal.test.tsx +6 -6
  237. package/src/execution/__tests__/FileChangeProgressBar.test.tsx +125 -0
  238. package/src/execution/__tests__/FilePathLink.test.tsx +87 -0
  239. package/src/execution/__tests__/FileReviewCard.test.tsx +66 -7
  240. package/src/execution/__tests__/MessageThread.test.tsx +102 -1
  241. package/src/execution/__tests__/PlanArtifactCard.test.tsx +114 -26
  242. package/src/execution/__tests__/PlanCompletionCard.test.tsx +2 -2
  243. package/src/execution/__tests__/PlanDocumentMessage.test.tsx +55 -0
  244. package/src/execution/__tests__/PlanStreamingCard.test.tsx +56 -0
  245. package/src/execution/__tests__/buildThreadItems-plan-completion.test.ts +600 -22
  246. package/src/execution/__tests__/message-entry.test.tsx +17 -0
  247. package/src/execution/__tests__/useArtifactCopy.test.tsx +90 -0
  248. package/src/execution/__tests__/useArtifactDownload.test.tsx +2 -0
  249. package/src/execution/__tests__/useCreateAgentExecution.test.tsx +85 -0
  250. package/src/execution/index.ts +13 -1
  251. package/src/execution/use-build-from-plan-hotkey.ts +1 -1
  252. package/src/execution/useArtifactCopy.ts +109 -0
  253. package/src/execution/useArtifactDownload.ts +17 -5
  254. package/src/execution/useCreateAgentExecution.ts +18 -1
  255. package/src/github/__tests__/decodeGitHubContent.test.ts +102 -0
  256. package/src/github/__tests__/useGitHubFileReader.test.ts +183 -0
  257. package/src/github/decodeGitHubContent.ts +83 -0
  258. package/src/github/index.ts +1 -0
  259. package/src/github/useGitHubFileReader.ts +152 -0
  260. package/src/github/useGitHubTreeLister.ts +6 -2
  261. package/src/index.ts +69 -9
  262. package/src/internal/ResizableSplit.tsx +184 -51
  263. package/src/internal/VirtualizedThread.tsx +12 -4
  264. package/src/internal/__tests__/ResizableSplit.test.tsx +125 -3
  265. package/src/internal/__tests__/markdown-components.test.tsx +68 -0
  266. package/src/internal/__tests__/useRevealLine.test.tsx +97 -0
  267. package/src/internal/file-icons/__tests__/file-icons.test.tsx +35 -0
  268. package/src/internal/file-icons/index.tsx +137 -0
  269. package/src/internal/file-tree/FileTreeNode.tsx +56 -5
  270. package/src/internal/file-tree/__tests__/FileTreeNode-explorer.test.tsx +86 -0
  271. package/src/internal/markdown-components.tsx +116 -11
  272. package/src/{workflow → internal}/motion-preference.ts +7 -4
  273. package/src/internal/store/__tests__/workspace-editors-store.test.ts +216 -0
  274. package/src/internal/store/__tests__/workspace-file-selection-store.test.ts +118 -0
  275. package/src/internal/store/index.ts +94 -0
  276. package/src/internal/store/workspace-editors-store.ts +315 -0
  277. package/src/internal/store/workspace-file-selection-store.ts +88 -0
  278. package/src/internal/useRevealLine.ts +81 -0
  279. package/src/library/__tests__/detect-plan-artifact.test.ts +69 -0
  280. package/src/library/__tests__/detect-streaming-plan.test.ts +234 -0
  281. package/src/library/detect-plan-artifact.ts +62 -5
  282. package/src/library/detect-streaming-plan.ts +108 -0
  283. package/src/library/index.ts +7 -0
  284. package/src/session/NewSessionViewer.tsx +123 -55
  285. package/src/session/PlanEditor.tsx +361 -0
  286. package/src/session/PlanStreamingDocument.tsx +97 -0
  287. package/src/session/SessionPanelChip.tsx +103 -0
  288. package/src/session/SessionViewer.tsx +655 -96
  289. package/src/session/__tests__/NewSessionViewer.test.tsx +148 -0
  290. package/src/session/__tests__/PlanEditor.test.tsx +217 -0
  291. package/src/session/__tests__/PlanStreamingDocument.test.tsx +50 -0
  292. package/src/session/__tests__/SessionPanelChip.test.tsx +42 -0
  293. package/src/session/__tests__/SessionViewer-fileReviewDock.test.tsx +66 -4
  294. package/src/session/__tests__/SessionViewer-transcriptFileOpen.test.tsx +205 -0
  295. package/src/session/__tests__/audienceWiring.test.tsx +55 -19
  296. package/src/session/__tests__/useOpenFileChange.test.tsx +82 -0
  297. package/src/session/__tests__/usePlanDraft.test.ts +102 -0
  298. package/src/session/__tests__/useSessionConversation.test.tsx +44 -0
  299. package/src/session/__tests__/useSessionPanel.test.ts +298 -0
  300. package/src/session/__tests__/useSessionRailViews.test.tsx +124 -0
  301. package/src/session/{inspector → facets}/ArtifactsTab.tsx +27 -5
  302. package/src/session/{inspector → facets}/ChangesTab.tsx +3 -3
  303. package/src/session/{inspector → facets}/SetupTab.tsx +13 -1
  304. package/src/session/{inspector → facets}/UsageTab.tsx +1 -1
  305. package/src/session/{inspector → facets}/__tests__/ArtifactsTab.test.tsx +42 -8
  306. package/src/session/facets/__tests__/SetupTab.test.tsx +44 -0
  307. package/src/session/{inspector → facets}/index.ts +0 -16
  308. package/src/session/index.ts +30 -13
  309. package/src/session/plan-document.ts +30 -0
  310. package/src/session/useOpenFileChange.ts +53 -0
  311. package/src/session/usePlanDraft.ts +109 -0
  312. package/src/session/useSessionConversation.ts +38 -3
  313. package/src/session/useSessionPageFlow.ts +1 -0
  314. package/src/session/useSessionPanel.ts +288 -0
  315. package/src/session/useSessionRailViews.tsx +200 -0
  316. package/src/workflow/WorkflowExecutionGraph.tsx +1 -1
  317. package/src/workflow/index.ts +1 -1
  318. package/src/workflow/useFollowExecution.ts +1 -1
  319. package/src/workspace/EditorTabs.tsx +174 -0
  320. package/src/workspace/ExplorerTree.tsx +253 -0
  321. package/src/workspace/FileViewer.tsx +537 -0
  322. package/src/workspace/WorkspaceContentSearch.tsx +502 -0
  323. package/src/workspace/WorkspaceContentSearcher.ts +70 -0
  324. package/src/workspace/WorkspaceEditor.tsx +19 -16
  325. package/src/workspace/WorkspaceFileLister.ts +11 -0
  326. package/src/workspace/WorkspaceFileReader.ts +57 -0
  327. package/src/workspace/WorkspaceFileSearch.tsx +452 -0
  328. package/src/workspace/WorkspaceSurface.tsx +839 -0
  329. package/src/workspace/__tests__/EditorTabs.test.tsx +102 -0
  330. package/src/workspace/__tests__/ExplorerTree.test.tsx +204 -0
  331. package/src/workspace/__tests__/FileViewer.test.tsx +439 -0
  332. package/src/workspace/__tests__/WorkspaceContentSearch.test.tsx +229 -0
  333. package/src/workspace/__tests__/WorkspaceEditor-initialPanel.test.tsx +19 -0
  334. package/src/workspace/__tests__/WorkspaceFileSearch.test.tsx +227 -0
  335. package/src/workspace/__tests__/WorkspaceSurface.test.tsx +418 -0
  336. package/src/workspace/__tests__/a11y/harness.tsx +140 -0
  337. package/src/workspace/__tests__/a11y/mock-capabilities.ts +138 -0
  338. package/src/workspace/__tests__/a11y/workspace-editor.a11y.test.tsx +65 -0
  339. package/src/workspace/__tests__/a11y/workspace-explorer-search.a11y.test.tsx +112 -0
  340. package/src/workspace/__tests__/a11y/workspace-viewer-tabs.a11y.test.tsx +69 -0
  341. package/src/workspace/__tests__/findChangeForSelection.test.ts +132 -0
  342. package/src/workspace/__tests__/matchContentPreview.test.ts +55 -0
  343. package/src/workspace/__tests__/matchWorkspaceFiles.test.ts +104 -0
  344. package/src/workspace/__tests__/resolveWorkspaceFileSelection.test.ts +135 -0
  345. package/src/workspace/__tests__/useWorkspaceContentSearch.test.tsx +196 -0
  346. package/src/workspace/__tests__/useWorkspaceFileContent.test.tsx +190 -0
  347. package/src/workspace/__tests__/useWorkspaceFileSearch.test.tsx +162 -0
  348. package/src/workspace/findChangeForSelection.ts +61 -0
  349. package/src/workspace/index.ts +56 -2
  350. package/src/workspace/matchContentPreview.ts +51 -0
  351. package/src/workspace/matchWorkspaceFiles.ts +86 -0
  352. package/src/workspace/resolveWorkspaceFileSelection.ts +119 -0
  353. package/src/workspace/useWorkspaceContentSearch.ts +228 -0
  354. package/src/workspace/useWorkspaceFileContent.ts +129 -0
  355. package/src/workspace/useWorkspaceFileSearch.ts +184 -0
  356. package/src/workspace/useWorkspaceFiles.ts +27 -27
  357. package/src/workspace/workspaceListingCache.ts +93 -0
  358. package/styles.css +1 -1
  359. package/workflow/WorkflowExecutionGraph.js +1 -1
  360. package/workflow/WorkflowExecutionGraph.js.map +1 -1
  361. package/workflow/index.d.ts +1 -1
  362. package/workflow/index.d.ts.map +1 -1
  363. package/workflow/index.js +1 -1
  364. package/workflow/index.js.map +1 -1
  365. package/workflow/useFollowExecution.js +1 -1
  366. package/workflow/useFollowExecution.js.map +1 -1
  367. package/workspace/EditorTabs.d.ts +47 -0
  368. package/workspace/EditorTabs.d.ts.map +1 -0
  369. package/workspace/EditorTabs.js +78 -0
  370. package/workspace/EditorTabs.js.map +1 -0
  371. package/workspace/ExplorerTree.d.ts +32 -0
  372. package/workspace/ExplorerTree.d.ts.map +1 -0
  373. package/workspace/ExplorerTree.js +49 -0
  374. package/workspace/ExplorerTree.js.map +1 -0
  375. package/workspace/FileViewer.d.ts +93 -0
  376. package/workspace/FileViewer.d.ts.map +1 -0
  377. package/workspace/FileViewer.js +193 -0
  378. package/workspace/FileViewer.js.map +1 -0
  379. package/workspace/WorkspaceContentSearch.d.ts +41 -0
  380. package/workspace/WorkspaceContentSearch.d.ts.map +1 -0
  381. package/workspace/WorkspaceContentSearch.js +216 -0
  382. package/workspace/WorkspaceContentSearch.js.map +1 -0
  383. package/workspace/WorkspaceContentSearcher.d.ts +59 -0
  384. package/workspace/WorkspaceContentSearcher.d.ts.map +1 -0
  385. package/workspace/WorkspaceContentSearcher.js +7 -0
  386. package/workspace/WorkspaceContentSearcher.js.map +1 -0
  387. package/workspace/WorkspaceEditor.d.ts.map +1 -1
  388. package/workspace/WorkspaceEditor.js +8 -10
  389. package/workspace/WorkspaceEditor.js.map +1 -1
  390. package/workspace/WorkspaceFileLister.d.ts +11 -0
  391. package/workspace/WorkspaceFileLister.d.ts.map +1 -1
  392. package/workspace/WorkspaceFileReader.d.ts +48 -0
  393. package/workspace/WorkspaceFileReader.d.ts.map +1 -0
  394. package/workspace/WorkspaceFileReader.js +11 -0
  395. package/workspace/WorkspaceFileReader.js.map +1 -0
  396. package/workspace/WorkspaceFileSearch.d.ts +32 -0
  397. package/workspace/WorkspaceFileSearch.d.ts.map +1 -0
  398. package/workspace/WorkspaceFileSearch.js +175 -0
  399. package/workspace/WorkspaceFileSearch.js.map +1 -0
  400. package/workspace/WorkspaceSurface.d.ts +151 -0
  401. package/workspace/WorkspaceSurface.d.ts.map +1 -0
  402. package/workspace/WorkspaceSurface.js +220 -0
  403. package/workspace/WorkspaceSurface.js.map +1 -0
  404. package/workspace/findChangeForSelection.d.ts +19 -0
  405. package/workspace/findChangeForSelection.d.ts.map +1 -0
  406. package/workspace/findChangeForSelection.js +46 -0
  407. package/workspace/findChangeForSelection.js.map +1 -0
  408. package/workspace/index.d.ts +24 -2
  409. package/workspace/index.d.ts.map +1 -1
  410. package/workspace/index.js +13 -1
  411. package/workspace/index.js.map +1 -1
  412. package/workspace/matchContentPreview.d.ts +21 -0
  413. package/workspace/matchContentPreview.d.ts.map +1 -0
  414. package/workspace/matchContentPreview.js +36 -0
  415. package/workspace/matchContentPreview.js.map +1 -0
  416. package/workspace/matchWorkspaceFiles.d.ts +30 -0
  417. package/workspace/matchWorkspaceFiles.d.ts.map +1 -0
  418. package/workspace/matchWorkspaceFiles.js +58 -0
  419. package/workspace/matchWorkspaceFiles.js.map +1 -0
  420. package/workspace/resolveWorkspaceFileSelection.d.ts +19 -0
  421. package/workspace/resolveWorkspaceFileSelection.d.ts.map +1 -0
  422. package/workspace/resolveWorkspaceFileSelection.js +115 -0
  423. package/workspace/resolveWorkspaceFileSelection.js.map +1 -0
  424. package/workspace/useWorkspaceContentSearch.d.ts +69 -0
  425. package/workspace/useWorkspaceContentSearch.d.ts.map +1 -0
  426. package/workspace/useWorkspaceContentSearch.js +154 -0
  427. package/workspace/useWorkspaceContentSearch.js.map +1 -0
  428. package/workspace/useWorkspaceFileContent.d.ts +73 -0
  429. package/workspace/useWorkspaceFileContent.d.ts.map +1 -0
  430. package/workspace/useWorkspaceFileContent.js +57 -0
  431. package/workspace/useWorkspaceFileContent.js.map +1 -0
  432. package/workspace/useWorkspaceFileSearch.d.ts +61 -0
  433. package/workspace/useWorkspaceFileSearch.d.ts.map +1 -0
  434. package/workspace/useWorkspaceFileSearch.js +119 -0
  435. package/workspace/useWorkspaceFileSearch.js.map +1 -0
  436. package/workspace/useWorkspaceFiles.d.ts +13 -5
  437. package/workspace/useWorkspaceFiles.d.ts.map +1 -1
  438. package/workspace/useWorkspaceFiles.js +18 -19
  439. package/workspace/useWorkspaceFiles.js.map +1 -1
  440. package/workspace/workspaceListingCache.d.ts +47 -0
  441. package/workspace/workspaceListingCache.d.ts.map +1 -0
  442. package/workspace/workspaceListingCache.js +55 -0
  443. package/workspace/workspaceListingCache.js.map +1 -0
  444. package/session/inspector/ArtifactsTab.d.ts.map +0 -1
  445. package/session/inspector/ArtifactsTab.js.map +0 -1
  446. package/session/inspector/ChangesTab.d.ts.map +0 -1
  447. package/session/inspector/ChangesTab.js.map +0 -1
  448. package/session/inspector/InspectTab.d.ts.map +0 -1
  449. package/session/inspector/InspectTab.js.map +0 -1
  450. package/session/inspector/SessionInspector.d.ts +0 -64
  451. package/session/inspector/SessionInspector.d.ts.map +0 -1
  452. package/session/inspector/SessionInspector.js +0 -53
  453. package/session/inspector/SessionInspector.js.map +0 -1
  454. package/session/inspector/SetupTab.d.ts.map +0 -1
  455. package/session/inspector/SetupTab.js.map +0 -1
  456. package/session/inspector/UsageTab.d.ts.map +0 -1
  457. package/session/inspector/UsageTab.js.map +0 -1
  458. package/session/inspector/WorkspaceTab.d.ts +0 -35
  459. package/session/inspector/WorkspaceTab.d.ts.map +0 -1
  460. package/session/inspector/WorkspaceTab.js +0 -75
  461. package/session/inspector/WorkspaceTab.js.map +0 -1
  462. package/session/inspector/index.d.ts.map +0 -1
  463. package/session/inspector/index.js.map +0 -1
  464. package/session/inspector/useSessionInspector.d.ts +0 -49
  465. package/session/inspector/useSessionInspector.d.ts.map +0 -1
  466. package/session/inspector/useSessionInspector.js +0 -122
  467. package/session/inspector/useSessionInspector.js.map +0 -1
  468. package/src/session/inspector/SessionInspector.tsx +0 -162
  469. package/src/session/inspector/WorkspaceTab.tsx +0 -245
  470. package/src/session/inspector/__tests__/useSessionInspector.test.ts +0 -251
  471. package/src/session/inspector/useSessionInspector.ts +0 -178
  472. package/src/workspace/WorkspaceEntryFiles.tsx +0 -196
  473. package/workflow/motion-preference.d.ts.map +0 -1
  474. package/workflow/motion-preference.js.map +0 -1
  475. package/workspace/WorkspaceEntryFiles.d.ts +0 -22
  476. package/workspace/WorkspaceEntryFiles.d.ts.map +0 -1
  477. package/workspace/WorkspaceEntryFiles.js +0 -58
  478. package/workspace/WorkspaceEntryFiles.js.map +0 -1
  479. /package/session/{inspector → facets}/InspectTab.d.ts +0 -0
  480. /package/session/{inspector → facets}/InspectTab.js +0 -0
  481. /package/src/{workflow → internal}/__tests__/motion-preference.test.ts +0 -0
  482. /package/src/session/{inspector → facets}/InspectTab.tsx +0 -0
  483. /package/src/session/{inspector → facets}/__tests__/ChangesTab.test.tsx +0 -0
@@ -0,0 +1,183 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { renderHook } from "@testing-library/react";
3
+ import { useGitHubFileReader } from "../useGitHubFileReader";
4
+ import type { WorkspaceEntry } from "../../workspace/useWorkspaceEntries";
5
+
6
+ function gitEntry(overrides?: Partial<WorkspaceEntry>): WorkspaceEntry {
7
+ return {
8
+ id: "ws-1",
9
+ name: "acme/api",
10
+ type: "git",
11
+ gitUrl: "https://github.com/acme/api",
12
+ gitBranch: "main",
13
+ ...overrides,
14
+ };
15
+ }
16
+
17
+ function localEntry(): WorkspaceEntry {
18
+ return {
19
+ id: "ws-2",
20
+ name: "/Users/dev/project",
21
+ type: "local",
22
+ localPath: "/Users/dev/project",
23
+ };
24
+ }
25
+
26
+ function b64(s: string): string {
27
+ return Buffer.from(s, "utf-8").toString("base64");
28
+ }
29
+
30
+ function jsonResponse(body: unknown, status = 200): Response {
31
+ return new Response(JSON.stringify(body), { status });
32
+ }
33
+
34
+ describe("useGitHubFileReader", () => {
35
+ const originalFetch = globalThis.fetch;
36
+
37
+ beforeEach(() => {
38
+ globalThis.fetch = vi.fn();
39
+ });
40
+
41
+ afterEach(() => {
42
+ globalThis.fetch = originalFetch;
43
+ });
44
+
45
+ it("returns undefined when token is null", () => {
46
+ const { result } = renderHook(() => useGitHubFileReader(null));
47
+ expect(result.current).toBeUndefined();
48
+ });
49
+
50
+ it("returns a reader function when a token is provided", () => {
51
+ const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
52
+ expect(typeof result.current).toBe("function");
53
+ });
54
+
55
+ it("returns null for non-git entries without fetching", async () => {
56
+ const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
57
+ const content = await result.current!(localEntry(), "src/index.ts");
58
+ expect(content).toBeNull();
59
+ expect(globalThis.fetch).not.toHaveBeenCalled();
60
+ });
61
+
62
+ it("returns null for non-GitHub git URLs", async () => {
63
+ const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
64
+ const content = await result.current!(
65
+ gitEntry({ gitUrl: "https://gitlab.com/acme/api" }),
66
+ "src/index.ts",
67
+ );
68
+ expect(content).toBeNull();
69
+ expect(globalThis.fetch).not.toHaveBeenCalled();
70
+ });
71
+
72
+ it("decodes a base64 text file from the Contents API", async () => {
73
+ vi.mocked(globalThis.fetch).mockResolvedValue(
74
+ jsonResponse({ encoding: "base64", size: 12, content: b64("Hello World!"), sha: "s1" }),
75
+ );
76
+
77
+ const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
78
+ const content = await result.current!(gitEntry(), "src/index.ts");
79
+
80
+ expect(globalThis.fetch).toHaveBeenCalledWith(
81
+ "https://api.github.com/repos/acme/api/contents/src/index.ts?ref=main",
82
+ { headers: { Authorization: "Bearer ghp_abc" } },
83
+ );
84
+ expect(content).toEqual({
85
+ text: "Hello World!",
86
+ isBinary: false,
87
+ size: 12,
88
+ encoding: "utf-8",
89
+ });
90
+ });
91
+
92
+ it("encodes the path per segment and the branch", async () => {
93
+ vi.mocked(globalThis.fetch).mockResolvedValue(
94
+ jsonResponse({ encoding: "base64", size: 1, content: b64("x"), sha: "s1" }),
95
+ );
96
+
97
+ const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
98
+ await result.current!(
99
+ gitEntry({ gitBranch: "feat/my branch" }),
100
+ "src/a b/c#d.ts",
101
+ );
102
+
103
+ expect(globalThis.fetch).toHaveBeenCalledWith(
104
+ "https://api.github.com/repos/acme/api/contents/src/a%20b/c%23d.ts?ref=feat%2Fmy%20branch",
105
+ expect.anything(),
106
+ );
107
+ });
108
+
109
+ it("defaults to the main branch when gitBranch is undefined", async () => {
110
+ vi.mocked(globalThis.fetch).mockResolvedValue(
111
+ jsonResponse({ encoding: "base64", size: 1, content: b64("x"), sha: "s1" }),
112
+ );
113
+
114
+ const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
115
+ await result.current!(gitEntry({ gitBranch: undefined }), "f.ts");
116
+
117
+ expect(globalThis.fetch).toHaveBeenCalledWith(
118
+ expect.stringContaining("?ref=main"),
119
+ expect.anything(),
120
+ );
121
+ });
122
+
123
+ it("throws on a non-OK response (404 = failed to load, not unsupported)", async () => {
124
+ vi.mocked(globalThis.fetch).mockResolvedValue(new Response("nope", { status: 404 }));
125
+
126
+ const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
127
+ await expect(result.current!(gitEntry(), "missing.ts")).rejects.toThrow("HTTP 404");
128
+ });
129
+
130
+ it("throws when the path is a directory (Contents API returns an array)", async () => {
131
+ vi.mocked(globalThis.fetch).mockResolvedValue(jsonResponse([{ name: "index.ts" }]));
132
+
133
+ const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
134
+ await expect(result.current!(gitEntry(), "src")).rejects.toThrow("is a directory");
135
+ });
136
+
137
+ it("falls back to the Blob API when Contents returns encoding:none", async () => {
138
+ const big = "x".repeat(2_000_000); // > 1 MB, ≤ 10 MB ceiling
139
+ vi.mocked(globalThis.fetch)
140
+ .mockResolvedValueOnce(
141
+ jsonResponse({ encoding: "none", size: big.length, content: "", sha: "blobsha" }),
142
+ )
143
+ .mockResolvedValueOnce(
144
+ jsonResponse({ encoding: "base64", size: big.length, content: b64(big) }),
145
+ );
146
+
147
+ const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
148
+ const content = await result.current!(gitEntry(), "big.txt");
149
+
150
+ expect(vi.mocked(globalThis.fetch).mock.calls[1][0]).toBe(
151
+ "https://api.github.com/repos/acme/api/git/blobs/blobsha",
152
+ );
153
+ expect(content!.size).toBe(big.length);
154
+ expect(content!.truncated).toBe(true);
155
+ expect(content!.text).toHaveLength(1_048_576);
156
+ });
157
+
158
+ it("reports files above the blob ceiling as too-large without downloading", async () => {
159
+ const hugeSize = 50 * 1024 * 1024; // 50 MB > 10 MB ceiling
160
+ vi.mocked(globalThis.fetch).mockResolvedValue(
161
+ jsonResponse({ encoding: "none", size: hugeSize, content: "", sha: "blobsha" }),
162
+ );
163
+
164
+ const { result } = renderHook(() => useGitHubFileReader("ghp_abc"));
165
+ const content = await result.current!(gitEntry(), "huge.bin");
166
+
167
+ expect(globalThis.fetch).toHaveBeenCalledTimes(1); // no blob download
168
+ expect(content).toEqual({
169
+ text: null,
170
+ isBinary: false,
171
+ size: hugeSize,
172
+ encoding: "none",
173
+ truncated: true,
174
+ });
175
+ });
176
+
177
+ it("returns a stable reader reference across renders", () => {
178
+ const { result, rerender } = renderHook(() => useGitHubFileReader("ghp_abc"));
179
+ const first = result.current;
180
+ rerender();
181
+ expect(result.current).toBe(first);
182
+ });
183
+ });
@@ -0,0 +1,83 @@
1
+ // Pure byte/text decode helpers for the GitHub file reader.
2
+ // Kept free of React and fetch so the Slice 0 spike behavior (base64 decode,
3
+ // binary detection, the 1 MB cap) is unit-testable in isolation.
4
+
5
+ import {
6
+ MAX_WORKSPACE_FILE_READ_BYTES,
7
+ type WorkspaceFileContent,
8
+ } from "../workspace/WorkspaceFileReader.js";
9
+
10
+ // Scan only the head for a NUL byte — git uses the first 8000 bytes as its
11
+ // text/binary heuristic, and scanning the whole buffer buys nothing.
12
+ const BINARY_SNIFF_BYTES = 8000;
13
+
14
+ /**
15
+ * Decode a GitHub base64 payload to raw bytes.
16
+ *
17
+ * GitHub's Contents API line-wraps its base64 with `\n` every 60 chars, and
18
+ * `atob` rejects embedded newlines in some engines — strip all ASCII
19
+ * whitespace first.
20
+ */
21
+ export function base64ToBytes(b64: string): Uint8Array {
22
+ const clean = b64.replace(/\s/g, "");
23
+ const binary = atob(clean);
24
+ return Uint8Array.from(binary, (ch) => ch.charCodeAt(0));
25
+ }
26
+
27
+ /** Detect binary content via a NUL byte in the head of the buffer. */
28
+ export function detectBinary(bytes: Uint8Array): boolean {
29
+ const limit = Math.min(bytes.length, BINARY_SNIFF_BYTES);
30
+ for (let i = 0; i < limit; i++) {
31
+ if (bytes[i] === 0) return true;
32
+ }
33
+ return false;
34
+ }
35
+
36
+ /**
37
+ * Decode bytes as strict UTF-8, returning `null` when the sequence is invalid.
38
+ * `{ fatal: true }` makes `TextDecoder` throw rather than emit replacement
39
+ * characters, so undecodable files degrade to the binary/unknown fallback
40
+ * instead of silently rendering mojibake.
41
+ */
42
+ export function bytesToText(bytes: Uint8Array): string | null {
43
+ try {
44
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Turn decoded bytes into a {@link WorkspaceFileContent}, applying binary
52
+ * detection and the shared 1 MB display cap.
53
+ *
54
+ * @param bytes the full decoded bytes as delivered by GitHub
55
+ * @param fullSize the file's true size in bytes (GitHub's `size` field), which
56
+ * may exceed `bytes.length` when the caller has already capped
57
+ * the download — reported verbatim as `size`.
58
+ */
59
+ export function normalizeGitHubContent(
60
+ bytes: Uint8Array,
61
+ fullSize: number,
62
+ ): WorkspaceFileContent {
63
+ if (detectBinary(bytes)) {
64
+ return { text: null, isBinary: true, size: fullSize, encoding: "base64" };
65
+ }
66
+
67
+ // Decode the full buffer, then cap the resulting *string* — capping the bytes
68
+ // first could split a multibyte char at the boundary and make the fatal
69
+ // decoder reject an otherwise-valid file.
70
+ const text = bytesToText(bytes);
71
+ if (text === null) {
72
+ return { text: null, isBinary: false, size: fullSize, encoding: "unknown" };
73
+ }
74
+
75
+ const truncated = bytes.length > MAX_WORKSPACE_FILE_READ_BYTES;
76
+ return {
77
+ text: truncated ? text.slice(0, MAX_WORKSPACE_FILE_READ_BYTES) : text,
78
+ isBinary: false,
79
+ size: fullSize,
80
+ encoding: "utf-8",
81
+ ...(truncated ? { truncated: true } : {}),
82
+ };
83
+ }
@@ -25,4 +25,5 @@ export {
25
25
  } from "./GitHubRepoPicker.js";
26
26
 
27
27
  export { useGitHubTreeLister } from "./useGitHubTreeLister.js";
28
+ export { useGitHubFileReader } from "./useGitHubFileReader.js";
28
29
  export { parseGitUrl, type ParsedGitRepo } from "./parseGitUrl.js";
@@ -0,0 +1,152 @@
1
+ "use client";
2
+
3
+ import { useCallback } from "react";
4
+ import type { WorkspaceEntry } from "../workspace/useWorkspaceEntries.js";
5
+ import type {
6
+ WorkspaceFileContent,
7
+ WorkspaceFileReader,
8
+ } from "../workspace/WorkspaceFileReader.js";
9
+ import { base64ToBytes, normalizeGitHubContent } from "./decodeGitHubContent.js";
10
+ import { parseGitUrl } from "./parseGitUrl.js";
11
+
12
+ const GITHUB_API = "https://api.github.com/repos";
13
+
14
+ /**
15
+ * Upper bound on files we will pull through the Blob API (Gate 1, Option B).
16
+ *
17
+ * The Contents API caps at ~1 MB and signals larger files with
18
+ * `encoding: "none"`; the Blob API then serves them in full (up to GitHub's own
19
+ * ~100 MB blob limit). Since we only ever display the first ~1 MB, downloading
20
+ * a 90 MB blob to show 1 MB is wasteful — so above this ceiling we report the
21
+ * file as too-large
22
+ * (`text: null`, `truncated: true`) using the size GitHub already told us,
23
+ * without downloading anything.
24
+ */
25
+ const BLOB_FETCH_CEILING_BYTES = 10 * 1024 * 1024; // 10 MiB
26
+
27
+ /** Single-file shape of `GET /repos/{o}/{r}/contents/{path}`. */
28
+ interface GitHubContentsFile {
29
+ readonly encoding: "base64" | "none";
30
+ readonly size: number;
31
+ readonly content: string;
32
+ readonly sha: string;
33
+ }
34
+
35
+ /** Shape of `GET /repos/{o}/{r}/git/blobs/{sha}`. */
36
+ interface GitHubBlob {
37
+ readonly encoding: "base64";
38
+ readonly size: number;
39
+ readonly content: string;
40
+ }
41
+
42
+ /** Encode a repo-relative path per segment, preserving the slashes. */
43
+ function encodePath(path: string): string {
44
+ return path.split("/").map(encodeURIComponent).join("/");
45
+ }
46
+
47
+ /**
48
+ * Creates a {@link WorkspaceFileReader} backed by the GitHub Contents API,
49
+ * with a Blob-API fallback for files above the Contents 1 MB cap.
50
+ *
51
+ * Uses the same client-side OAuth token as {@link useGitHubTreeLister}
52
+ * (`Authorization: Bearer`), inheriting its private-repo scope. Returns
53
+ * `undefined` when no token is present, mirroring the tree lister so callers
54
+ * can treat "no reader" and "no lister" identically.
55
+ *
56
+ * The reader itself:
57
+ * - Returns `null` when the entry is not a readable GitHub git repo
58
+ * (non-git entry, missing/unparseable URL) — the "unsupported here" state.
59
+ * - **Throws** on a real failure: a non-OK response, or a directory path
60
+ * (which the Contents API returns as a JSON array). Consumers surface these
61
+ * as an error, distinct from the null "unsupported" state.
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * const gitHubConnection = useGitHubConnection(org);
66
+ * const fileReader = useGitHubFileReader(gitHubConnection.token);
67
+ * <SessionViewer workspaceFileReader={fileReader} />
68
+ * ```
69
+ */
70
+ export function useGitHubFileReader(
71
+ token: string | null,
72
+ ): WorkspaceFileReader | undefined {
73
+ const reader = useCallback(
74
+ async (
75
+ entry: WorkspaceEntry,
76
+ path: string,
77
+ ): Promise<WorkspaceFileContent | null> => {
78
+ if (entry.type !== "git" || !entry.gitUrl || !token) return null;
79
+
80
+ const parsed = parseGitUrl(entry.gitUrl);
81
+ if (!parsed) return null;
82
+
83
+ const branch = entry.gitBranch || "main";
84
+ const url =
85
+ `${GITHUB_API}/${parsed.owner}/${parsed.repo}/contents/${encodePath(path)}` +
86
+ `?ref=${encodeURIComponent(branch)}`;
87
+
88
+ const resp = await fetch(url, {
89
+ headers: { Authorization: `Bearer ${token}` },
90
+ });
91
+ if (!resp.ok) {
92
+ throw new Error(
93
+ `GitHub content fetch failed for ${path} (HTTP ${resp.status})`,
94
+ );
95
+ }
96
+
97
+ const data: unknown = await resp.json();
98
+ // The Contents API returns an array for a directory — a misdirected read,
99
+ // not an unsupported substrate, so fail loudly rather than return null.
100
+ if (Array.isArray(data)) {
101
+ throw new Error(`Cannot read "${path}": path is a directory`);
102
+ }
103
+
104
+ const file = data as GitHubContentsFile;
105
+ if (file.encoding === "base64") {
106
+ return normalizeGitHubContent(base64ToBytes(file.content), file.size);
107
+ }
108
+
109
+ // encoding: "none" is GitHub's signal that the file exceeds the Contents
110
+ // API's ~1 MB cap; the bytes live only behind the Blob API.
111
+ return readViaBlob(parsed, file, token);
112
+ },
113
+ [token],
114
+ );
115
+
116
+ if (!token) return undefined;
117
+ return reader;
118
+ }
119
+
120
+ /**
121
+ * Gate 1 / Option B — size-gated blob fetch for files the Contents API refused
122
+ * (`encoding: "none"`). Isolated so the large-file policy can change without
123
+ * touching the reader's control flow.
124
+ */
125
+ async function readViaBlob(
126
+ parsed: { owner: string; repo: string },
127
+ file: GitHubContentsFile,
128
+ token: string,
129
+ ): Promise<WorkspaceFileContent> {
130
+ // Above the ceiling we never download — GitHub already told us the size, so
131
+ // report it as too-large-to-preview without spending the bandwidth.
132
+ if (file.size > BLOB_FETCH_CEILING_BYTES) {
133
+ return {
134
+ text: null,
135
+ isBinary: false,
136
+ size: file.size,
137
+ encoding: "none",
138
+ truncated: true,
139
+ };
140
+ }
141
+
142
+ const url = `${GITHUB_API}/${parsed.owner}/${parsed.repo}/git/blobs/${file.sha}`;
143
+ const resp = await fetch(url, {
144
+ headers: { Authorization: `Bearer ${token}` },
145
+ });
146
+ if (!resp.ok) {
147
+ throw new Error(`GitHub blob fetch failed for ${file.sha} (HTTP ${resp.status})`);
148
+ }
149
+
150
+ const blob: GitHubBlob = await resp.json();
151
+ return normalizeGitHubContent(base64ToBytes(blob.content), blob.size);
152
+ }
@@ -22,12 +22,16 @@ interface GitHubTreeResponse {
22
22
  }
23
23
 
24
24
  /**
25
- * Sentinel entry appended to the listing when the GitHub API indicates
26
- * that the tree was truncated (repository exceeds the API's entry limit).
25
+ * Advisory entry appended to the listing when the GitHub API indicates that the
26
+ * tree was truncated (repository exceeds the API's entry limit). Flagged with
27
+ * `notice: true` so generic consumers treat it as a "results incomplete" banner
28
+ * rather than an openable file (see `workspaceListingCache`) — never a tree leaf,
29
+ * never a search hit.
27
30
  */
28
31
  const TRUNCATION_MARKER: WorkspaceFileEntry = {
29
32
  path: "... (tree truncated by GitHub — repository has too many files)",
30
33
  isDirectory: false,
34
+ notice: true,
31
35
  };
32
36
 
33
37
  /**
package/src/index.ts CHANGED
@@ -66,23 +66,58 @@ export type {
66
66
  export {
67
67
  useWorkspaceEntries,
68
68
  useWorkspaceFiles,
69
+ useWorkspaceFileContent,
70
+ useWorkspaceFileSearch,
71
+ useWorkspaceContentSearch,
69
72
  useWorkspaceSources,
73
+ MAX_WORKSPACE_FILE_READ_BYTES,
70
74
  WorkspaceEditor,
71
- WorkspaceEntryFiles,
75
+ WorkspaceFileSearch,
76
+ WorkspaceContentSearch,
72
77
  WorkspaceSummary,
78
+ FileViewer,
79
+ WorkspaceSurface,
80
+ ExplorerTree,
81
+ virtualEntryId,
82
+ isVirtualEntryId,
73
83
  } from "./workspace/index.js";
74
84
  export type {
75
85
  WorkspaceEntry,
76
86
  WorkspaceFileEntry,
77
87
  WorkspaceFileLister,
88
+ WorkspaceFileContent,
89
+ WorkspaceFileReader,
78
90
  UseWorkspaceEntriesReturn,
79
91
  UseWorkspaceFilesOptions,
80
92
  UseWorkspaceFilesReturn,
81
- WorkspaceEntryFilesProps,
93
+ UseWorkspaceFileContentOptions,
94
+ UseWorkspaceFileContentReturn,
95
+ UseWorkspaceFileSearchOptions,
96
+ UseWorkspaceFileSearchReturn,
97
+ WorkspaceFileSearchGroup,
98
+ WorkspaceFileMatch,
99
+ WorkspaceFileSearchProps,
100
+ WorkspaceContentMatch,
101
+ WorkspaceContentSearchResult,
102
+ WorkspaceContentSearcher,
103
+ UseWorkspaceContentSearchOptions,
104
+ UseWorkspaceContentSearchReturn,
105
+ WorkspaceContentSearchGroup,
106
+ WorkspaceContentSearchProps,
107
+ FileViewerProps,
108
+ FileViewerHandle,
109
+ SelectedWorkspaceFile,
82
110
  UseWorkspaceSourcesOptions,
83
111
  UseWorkspaceSourcesReturn,
84
112
  WorkspaceEditorProps,
85
113
  WorkspaceSummaryProps,
114
+ WorkspaceSurfaceProps,
115
+ SurfaceRailView,
116
+ SurfaceVirtualDocument,
117
+ ExplorerTreeProps,
118
+ OpenEditor,
119
+ OpenFileOptions,
120
+ RevealTarget,
86
121
  } from "./workspace/index.js";
87
122
 
88
123
  // Session — data hooks, behavior hooks, utilities (Session aggregate + conversation lifecycle)
@@ -112,9 +147,13 @@ export {
112
147
  resolvedSubject,
113
148
  SessionViewer,
114
149
  NewSessionViewer,
115
- SessionInspector,
116
- useSessionInspector,
117
- buildVisibleTabs,
150
+ useSessionPanel,
151
+ usePlanDraft,
152
+ planDraftKey,
153
+ PlanEditor,
154
+ PlanStreamingDocument,
155
+ PLAN_DOCUMENT_ENTRY_ID,
156
+ PLAN_DOCUMENT_PATH,
118
157
  SetupTab,
119
158
  } from "./session/index.js";
120
159
  export type {
@@ -152,13 +191,14 @@ export type {
152
191
  SearchResultGroup,
153
192
  SessionViewerProps,
154
193
  NewSessionViewerProps,
194
+ SessionPanelController,
195
+ UseSessionPanelOptions,
196
+ PlanDraftController,
197
+ PlanEditorProps,
198
+ PlanStreamingDocumentProps,
155
199
  ExecutionTargetOption,
156
200
  RuntimeEnvProvider,
157
201
  SessionAudience,
158
- SessionInspectorProps,
159
- SessionInspectorTabId,
160
- UseSessionInspectorOptions,
161
- UseSessionInspectorReturn,
162
202
  SetupTabProps,
163
203
  SetupTabMutationCallbacks,
164
204
  SelectedThreadItem,
@@ -208,6 +248,9 @@ export {
208
248
  SummarizationBadge,
209
249
  SummarizationCard,
210
250
  PlanCompletionCard,
251
+ PlanArtifactCard,
252
+ PlanStreamingCard,
253
+ PlanDocumentMessage,
211
254
  useContextWindow,
212
255
  formatCost,
213
256
  formatTokenCount,
@@ -224,6 +267,7 @@ export {
224
267
  resolveToolCategoryFromKind,
225
268
  toolKindToCategoryInfo,
226
269
  defaultDisclosureForCategory,
270
+ extractPrimaryArg,
227
271
  McpToolDetail,
228
272
  parseMcpResult,
229
273
  formatDuration,
@@ -239,6 +283,7 @@ export {
239
283
  ApprovalCardBody,
240
284
  FileReviewCard,
241
285
  FileReviewDock,
286
+ FileChangeProgressBar,
242
287
  ApprovalContext,
243
288
  useApproval,
244
289
  FileReviewContext,
@@ -263,6 +308,7 @@ export {
263
308
  useArtifactContent,
264
309
  useArtifactDownloadUrl,
265
310
  useArtifactDownload,
311
+ useArtifactCopy,
266
312
  useToolOutputContent,
267
313
  useFileChangeContent,
268
314
  execIdFromStorageKey,
@@ -302,6 +348,9 @@ export type {
302
348
  SummarizationBadgeProps,
303
349
  SummarizationCardProps,
304
350
  PlanCompletionCardProps,
351
+ PlanArtifactCardProps,
352
+ PlanStreamingCardProps,
353
+ PlanDocumentMessageProps,
305
354
  ContextHealth,
306
355
  SummarizationEventView,
307
356
  UseContextWindowReturn,
@@ -320,6 +369,7 @@ export type {
320
369
  SubAgentSectionProps,
321
370
  MessageEntryProps,
322
371
  MessageThreadProps,
372
+ ThreadContentColumn,
323
373
  ThreadSkeletonProps,
324
374
  FollowUpInputProps,
325
375
  ApprovalCardProps,
@@ -327,6 +377,7 @@ export type {
327
377
  ApprovalCardBodyProps,
328
378
  FileReviewCardProps,
329
379
  FileReviewDockProps,
380
+ FileChangeProgressBarProps,
330
381
  ApprovalContextValue,
331
382
  UseApprovalResult,
332
383
  FileReviewContextValue,
@@ -349,6 +400,7 @@ export type {
349
400
  UseArtifactDownloadUrlReturn,
350
401
  UseArtifactDownloadUrlOptions,
351
402
  UseArtifactDownloadReturn,
403
+ UseArtifactCopyReturn,
352
404
  UseToolOutputContentReturn,
353
405
  ToolOutputRefLike,
354
406
  UseFileChangeContentReturn,
@@ -519,6 +571,7 @@ export {
519
571
  useGitHubRepos,
520
572
  useGitHubSearch,
521
573
  useGitHubTreeLister,
574
+ useGitHubFileReader,
522
575
  parseGitUrl,
523
576
  GitHubRepoPicker,
524
577
  GITHUB_CALLBACK_MESSAGE_TYPE,
@@ -931,7 +984,12 @@ export {
931
984
  detectSkillPackage,
932
985
  useDetectSkillPackage,
933
986
  isPlanArtifact,
987
+ isPlanArtifactName,
934
988
  findPlanArtifact,
989
+ findLatestSessionPlan,
990
+ findStreamingPlan,
991
+ PLAN_ARTIFACT_NAME,
992
+ PLAN_ARTIFACT_SUFFIX,
935
993
  parseResourceYaml,
936
994
  serializeAgentYaml,
937
995
  serializeMcpServerYaml,
@@ -954,6 +1012,8 @@ export type {
954
1012
  StigmerResourceKind,
955
1013
  StigmerResourceDetection,
956
1014
  SkillPackageDetection,
1015
+ SessionPlan,
1016
+ StreamingPlan,
957
1017
  UseDetectSkillPackageReturn,
958
1018
  ParsedResource,
959
1019
  UseApplyResourceReturn,