@dxos/plugin-github 0.7.4 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (628) hide show
  1. package/LICENSE +102 -5
  2. package/PLUGIN.mdl +784 -0
  3. package/dist/lib/GitHubCapabilities.mjs +10 -0
  4. package/dist/lib/GitHubCapabilities.mjs.map +1 -0
  5. package/dist/lib/GitHubEvents.mjs +15 -0
  6. package/dist/lib/GitHubEvents.mjs.map +1 -0
  7. package/dist/lib/GitHubOperation.mjs +358 -0
  8. package/dist/lib/GitHubOperation.mjs.map +1 -0
  9. package/dist/lib/GitHubPlugin.mjs +16 -0
  10. package/dist/lib/GitHubPlugin.mjs.map +1 -0
  11. package/dist/lib/Walkthrough.mjs +59 -0
  12. package/dist/lib/Walkthrough.mjs.map +1 -0
  13. package/dist/lib/capabilities.browser.mjs +54 -0
  14. package/dist/lib/capabilities.browser.mjs.map +1 -0
  15. package/dist/lib/capabilities.mjs +54 -0
  16. package/dist/lib/capabilities.mjs.map +1 -0
  17. package/dist/lib/capabilities.node.mjs +30 -0
  18. package/dist/lib/capabilities.node.mjs.map +1 -0
  19. package/dist/lib/capabilities.tauri.mjs +54 -0
  20. package/dist/lib/capabilities.tauri.mjs.map +1 -0
  21. package/dist/lib/capabilities.workerd.mjs +30 -0
  22. package/dist/lib/capabilities.workerd.mjs.map +1 -0
  23. package/dist/lib/chunk-ImportPullRequestDialog.mjs +116 -0
  24. package/dist/lib/chunk-ImportPullRequestDialog.mjs.map +1 -0
  25. package/dist/lib/chunk-PLUGIN.mjs +6 -0
  26. package/dist/lib/chunk-PLUGIN.mjs.map +1 -0
  27. package/dist/lib/chunk-PullRequestArticle.mjs +1486 -0
  28. package/dist/lib/chunk-PullRequestArticle.mjs.map +1 -0
  29. package/dist/lib/chunk-PullRequestArticle2.mjs +2 -0
  30. package/dist/lib/chunk-PullRequestCardMenu.mjs +123 -0
  31. package/dist/lib/chunk-PullRequestCardMenu.mjs.map +1 -0
  32. package/dist/lib/chunk-PullRequestsArticle.mjs +594 -0
  33. package/dist/lib/chunk-PullRequestsArticle.mjs.map +1 -0
  34. package/dist/lib/chunk-WalkthroughArticle.mjs +26 -0
  35. package/dist/lib/chunk-WalkthroughArticle.mjs.map +1 -0
  36. package/dist/lib/chunk-add-pull-request-comment.mjs +19 -0
  37. package/dist/lib/chunk-add-pull-request-comment.mjs.map +1 -0
  38. package/dist/lib/chunk-add-pull-request-review-comment.mjs +25 -0
  39. package/dist/lib/chunk-add-pull-request-review-comment.mjs.map +1 -0
  40. package/dist/lib/chunk-app-graph-builder.mjs +39 -0
  41. package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
  42. package/dist/lib/chunk-connector.mjs +70 -0
  43. package/dist/lib/chunk-connector.mjs.map +1 -0
  44. package/dist/lib/chunk-constants.mjs +11 -0
  45. package/dist/lib/chunk-constants.mjs.map +1 -0
  46. package/dist/lib/chunk-errors.mjs +29 -0
  47. package/dist/lib/chunk-errors.mjs.map +1 -0
  48. package/dist/lib/chunk-generate-walkthrough.mjs +86 -0
  49. package/dist/lib/chunk-generate-walkthrough.mjs.map +1 -0
  50. package/dist/lib/chunk-generate.mjs +719 -0
  51. package/dist/lib/chunk-generate.mjs.map +1 -0
  52. package/dist/lib/chunk-get-pull-request-diff.mjs +25 -0
  53. package/dist/lib/chunk-get-pull-request-diff.mjs.map +1 -0
  54. package/dist/lib/chunk-get-pull-request-status.mjs +29 -0
  55. package/dist/lib/chunk-get-pull-request-status.mjs.map +1 -0
  56. package/dist/lib/chunk-get-repositories.mjs +32 -0
  57. package/dist/lib/chunk-get-repositories.mjs.map +1 -0
  58. package/dist/lib/chunk-github-api.mjs +375 -0
  59. package/dist/lib/chunk-github-api.mjs.map +1 -0
  60. package/dist/lib/chunk-github-link.mjs +59 -0
  61. package/dist/lib/chunk-github-link.mjs.map +1 -0
  62. package/dist/lib/chunk-import-pull-request-from-snapshot.mjs +25 -0
  63. package/dist/lib/chunk-import-pull-request-from-snapshot.mjs.map +1 -0
  64. package/dist/lib/chunk-import-pull-request.mjs +96 -0
  65. package/dist/lib/chunk-import-pull-request.mjs.map +1 -0
  66. package/dist/lib/chunk-link-resolver.mjs +109 -0
  67. package/dist/lib/chunk-link-resolver.mjs.map +1 -0
  68. package/dist/lib/chunk-markdown-extension.mjs +92 -0
  69. package/dist/lib/chunk-markdown-extension.mjs.map +1 -0
  70. package/dist/lib/chunk-materialize-target.mjs +36 -0
  71. package/dist/lib/chunk-materialize-target.mjs.map +1 -0
  72. package/dist/lib/chunk-operation-handler.mjs +12 -0
  73. package/dist/lib/chunk-operation-handler.mjs.map +1 -0
  74. package/dist/lib/chunk-page-action.mjs +22 -0
  75. package/dist/lib/chunk-page-action.mjs.map +1 -0
  76. package/dist/lib/chunk-pull-request.mjs +58 -0
  77. package/dist/lib/chunk-pull-request.mjs.map +1 -0
  78. package/dist/lib/chunk-pull-request2.mjs +110 -0
  79. package/dist/lib/chunk-pull-request2.mjs.map +1 -0
  80. package/dist/lib/chunk-react-surface.mjs +233 -0
  81. package/dist/lib/chunk-react-surface.mjs.map +1 -0
  82. package/dist/lib/chunk-rolldown-runtime.mjs +13 -0
  83. package/dist/lib/chunk-schema.mjs +15 -0
  84. package/dist/lib/chunk-schema.mjs.map +1 -0
  85. package/dist/lib/chunk-skill-definition.mjs +10 -0
  86. package/dist/lib/chunk-skill-definition.mjs.map +1 -0
  87. package/dist/lib/chunk-submit-pull-request-approval.mjs +56 -0
  88. package/dist/lib/chunk-submit-pull-request-approval.mjs.map +1 -0
  89. package/dist/lib/chunk-sync-pull-request.mjs +24 -0
  90. package/dist/lib/chunk-sync-pull-request.mjs.map +1 -0
  91. package/dist/lib/chunk-sync.mjs +481 -0
  92. package/dist/lib/chunk-sync.mjs.map +1 -0
  93. package/dist/lib/chunk-useOpenObject.mjs +43 -0
  94. package/dist/lib/chunk-useOpenObject.mjs.map +1 -0
  95. package/dist/lib/extensions.mjs +132 -0
  96. package/dist/lib/extensions.mjs.map +1 -0
  97. package/dist/lib/index.mjs +4 -0
  98. package/dist/lib/meta.mjs +47 -0
  99. package/dist/lib/meta.mjs.map +1 -0
  100. package/dist/lib/ns/Extensions.mjs +18 -0
  101. package/dist/lib/ns/Extensions.mjs.map +1 -0
  102. package/dist/lib/operations.mjs +22 -0
  103. package/dist/lib/operations.mjs.map +1 -0
  104. package/dist/lib/plugin.mjs +9 -0
  105. package/dist/lib/plugin.mjs.map +1 -0
  106. package/dist/lib/skills.mjs +44 -0
  107. package/dist/lib/skills.mjs.map +1 -0
  108. package/dist/lib/testing.mjs +189 -0
  109. package/dist/lib/testing.mjs.map +1 -0
  110. package/dist/lib/translations.mjs +136 -0
  111. package/dist/lib/translations.mjs.map +1 -0
  112. package/dist/lib/types.mjs +5 -0
  113. package/dist/types/dx.config.d.ts +28 -0
  114. package/dist/types/dx.config.d.ts.map +1 -0
  115. package/dist/types/src/Extensions.d.ts +2 -0
  116. package/dist/types/src/Extensions.d.ts.map +1 -0
  117. package/dist/types/src/GitHubPlugin.d.ts +37 -0
  118. package/dist/types/src/GitHubPlugin.d.ts.map +1 -0
  119. package/dist/types/src/GitHubPlugin.workerd.test.d.ts +2 -0
  120. package/dist/types/src/GitHubPlugin.workerd.test.d.ts.map +1 -0
  121. package/dist/types/src/approval.d.ts +21 -0
  122. package/dist/types/src/approval.d.ts.map +1 -0
  123. package/dist/types/src/approval.test.d.ts +2 -0
  124. package/dist/types/src/approval.test.d.ts.map +1 -0
  125. package/dist/types/src/capabilities/app-graph-builder.d.ts +9 -0
  126. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  127. package/dist/types/src/capabilities/connector.d.ts +17 -0
  128. package/dist/types/src/capabilities/connector.d.ts.map +1 -0
  129. package/dist/types/src/capabilities/gen/browser.d.ts +13 -0
  130. package/dist/types/src/capabilities/gen/browser.d.ts.map +1 -0
  131. package/dist/types/src/capabilities/gen/node.d.ts +13 -0
  132. package/dist/types/src/capabilities/gen/node.d.ts.map +1 -0
  133. package/dist/types/src/capabilities/gen/tauri.d.ts +13 -0
  134. package/dist/types/src/capabilities/gen/tauri.d.ts.map +1 -0
  135. package/dist/types/src/capabilities/gen/workerd.d.ts +13 -0
  136. package/dist/types/src/capabilities/gen/workerd.d.ts.map +1 -0
  137. package/dist/types/src/capabilities/index.d.ts +13 -0
  138. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  139. package/dist/types/src/capabilities/link-resolver.d.ts +10 -0
  140. package/dist/types/src/capabilities/link-resolver.d.ts.map +1 -0
  141. package/dist/types/src/capabilities/markdown-extension.d.ts +14 -0
  142. package/dist/types/src/capabilities/markdown-extension.d.ts.map +1 -0
  143. package/dist/types/src/capabilities/operation-handler.d.ts +5 -0
  144. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  145. package/dist/types/src/capabilities/page-action.d.ts +5 -0
  146. package/dist/types/src/capabilities/page-action.d.ts.map +1 -0
  147. package/dist/types/src/capabilities/react-surface.d.ts +5 -0
  148. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  149. package/dist/types/src/capabilities/schema.d.ts +12 -0
  150. package/dist/types/src/capabilities/schema.d.ts.map +1 -0
  151. package/dist/types/src/capabilities/skill-definition.d.ts +5 -0
  152. package/dist/types/src/capabilities/skill-definition.d.ts.map +1 -0
  153. package/dist/types/src/cards/GitHubCard.d.ts +11 -0
  154. package/dist/types/src/cards/GitHubCard.d.ts.map +1 -0
  155. package/dist/types/src/cards/GitHubCard.stories.d.ts +45 -0
  156. package/dist/types/src/cards/GitHubCard.stories.d.ts.map +1 -0
  157. package/dist/types/src/cards/PullRequestCard.d.ts +9 -0
  158. package/dist/types/src/cards/PullRequestCard.d.ts.map +1 -0
  159. package/dist/types/src/cards/index.d.ts +3 -0
  160. package/dist/types/src/cards/index.d.ts.map +1 -0
  161. package/dist/types/src/components/CommentComposer/CommentComposer.d.ts +30 -0
  162. package/dist/types/src/components/CommentComposer/CommentComposer.d.ts.map +1 -0
  163. package/dist/types/src/components/CommentComposer/index.d.ts +2 -0
  164. package/dist/types/src/components/CommentComposer/index.d.ts.map +1 -0
  165. package/dist/types/src/components/PullRequestFiles/DiffStat.d.ts +8 -0
  166. package/dist/types/src/components/PullRequestFiles/DiffStat.d.ts.map +1 -0
  167. package/dist/types/src/components/PullRequestFiles/FileTree.d.ts +17 -0
  168. package/dist/types/src/components/PullRequestFiles/FileTree.d.ts.map +1 -0
  169. package/dist/types/src/components/PullRequestFiles/PullRequestFiles.d.ts +23 -0
  170. package/dist/types/src/components/PullRequestFiles/PullRequestFiles.d.ts.map +1 -0
  171. package/dist/types/src/components/PullRequestFiles/files.d.ts +39 -0
  172. package/dist/types/src/components/PullRequestFiles/files.d.ts.map +1 -0
  173. package/dist/types/src/components/PullRequestFiles/files.test.d.ts +2 -0
  174. package/dist/types/src/components/PullRequestFiles/files.test.d.ts.map +1 -0
  175. package/dist/types/src/components/PullRequestFiles/index.d.ts +5 -0
  176. package/dist/types/src/components/PullRequestFiles/index.d.ts.map +1 -0
  177. package/dist/types/src/components/PullRequestOverview/ArtifactPill.d.ts +21 -0
  178. package/dist/types/src/components/PullRequestOverview/ArtifactPill.d.ts.map +1 -0
  179. package/dist/types/src/components/PullRequestOverview/CheckRunList.d.ts +15 -0
  180. package/dist/types/src/components/PullRequestOverview/CheckRunList.d.ts.map +1 -0
  181. package/dist/types/src/components/PullRequestOverview/PullRequestDetails.d.ts +10 -0
  182. package/dist/types/src/components/PullRequestOverview/PullRequestDetails.d.ts.map +1 -0
  183. package/dist/types/src/components/PullRequestOverview/PullRequestOverview.d.ts +16 -0
  184. package/dist/types/src/components/PullRequestOverview/PullRequestOverview.d.ts.map +1 -0
  185. package/dist/types/src/components/PullRequestOverview/RelatedCards.d.ts +28 -0
  186. package/dist/types/src/components/PullRequestOverview/RelatedCards.d.ts.map +1 -0
  187. package/dist/types/src/components/PullRequestOverview/index.d.ts +6 -0
  188. package/dist/types/src/components/PullRequestOverview/index.d.ts.map +1 -0
  189. package/dist/types/src/components/PullRequestStatus/PullRequestStatus.d.ts +20 -0
  190. package/dist/types/src/components/PullRequestStatus/PullRequestStatus.d.ts.map +1 -0
  191. package/dist/types/src/components/PullRequestStatus/index.d.ts +2 -0
  192. package/dist/types/src/components/PullRequestStatus/index.d.ts.map +1 -0
  193. package/dist/types/src/components/WalkthroughView/WalkthroughView.d.ts +18 -0
  194. package/dist/types/src/components/WalkthroughView/WalkthroughView.d.ts.map +1 -0
  195. package/dist/types/src/components/WalkthroughView/extensions.d.ts +16 -0
  196. package/dist/types/src/components/WalkthroughView/extensions.d.ts.map +1 -0
  197. package/dist/types/src/components/WalkthroughView/index.d.ts +3 -0
  198. package/dist/types/src/components/WalkthroughView/index.d.ts.map +1 -0
  199. package/dist/types/src/components/index.d.ts +5 -8
  200. package/dist/types/src/components/index.d.ts.map +1 -1
  201. package/dist/types/src/constants.d.ts +7 -0
  202. package/dist/types/src/constants.d.ts.map +1 -0
  203. package/dist/types/src/containers/ImportPullRequestDialog/ImportPullRequestDialog.d.ts +6 -0
  204. package/dist/types/src/containers/ImportPullRequestDialog/ImportPullRequestDialog.d.ts.map +1 -0
  205. package/dist/types/src/containers/ImportPullRequestDialog/index.d.ts +3 -0
  206. package/dist/types/src/containers/ImportPullRequestDialog/index.d.ts.map +1 -0
  207. package/dist/types/src/containers/PullRequestArticle/PullRequestArticle.d.ts +15 -0
  208. package/dist/types/src/containers/PullRequestArticle/PullRequestArticle.d.ts.map +1 -0
  209. package/dist/types/src/containers/PullRequestArticle/failure.d.ts +10 -0
  210. package/dist/types/src/containers/PullRequestArticle/failure.d.ts.map +1 -0
  211. package/dist/types/src/containers/PullRequestArticle/failure.test.d.ts +2 -0
  212. package/dist/types/src/containers/PullRequestArticle/failure.test.d.ts.map +1 -0
  213. package/dist/types/src/containers/PullRequestArticle/index.d.ts +2 -0
  214. package/dist/types/src/containers/PullRequestArticle/index.d.ts.map +1 -0
  215. package/dist/types/src/containers/PullRequestCardMenu/PullRequestCardMenu.d.ts +14 -0
  216. package/dist/types/src/containers/PullRequestCardMenu/PullRequestCardMenu.d.ts.map +1 -0
  217. package/dist/types/src/containers/PullRequestCardMenu/index.d.ts +2 -0
  218. package/dist/types/src/containers/PullRequestCardMenu/index.d.ts.map +1 -0
  219. package/dist/types/src/containers/PullRequestsArticle/PullRequestsArticle.d.ts +13 -0
  220. package/dist/types/src/containers/PullRequestsArticle/PullRequestsArticle.d.ts.map +1 -0
  221. package/dist/types/src/containers/PullRequestsArticle/arrange.d.ts +44 -0
  222. package/dist/types/src/containers/PullRequestsArticle/arrange.d.ts.map +1 -0
  223. package/dist/types/src/containers/PullRequestsArticle/arrange.test.d.ts +2 -0
  224. package/dist/types/src/containers/PullRequestsArticle/arrange.test.d.ts.map +1 -0
  225. package/dist/types/src/containers/PullRequestsArticle/format.d.ts +3 -0
  226. package/dist/types/src/containers/PullRequestsArticle/format.d.ts.map +1 -0
  227. package/dist/types/src/containers/PullRequestsArticle/index.d.ts +2 -0
  228. package/dist/types/src/containers/PullRequestsArticle/index.d.ts.map +1 -0
  229. package/dist/types/src/containers/WalkthroughArticle/WalkthroughArticle.d.ts +13 -0
  230. package/dist/types/src/containers/WalkthroughArticle/WalkthroughArticle.d.ts.map +1 -0
  231. package/dist/types/src/containers/WalkthroughArticle/index.d.ts +2 -0
  232. package/dist/types/src/containers/WalkthroughArticle/index.d.ts.map +1 -0
  233. package/dist/types/src/containers/index.d.ts +7 -0
  234. package/dist/types/src/containers/index.d.ts.map +1 -0
  235. package/dist/types/src/errors.d.ts +157 -0
  236. package/dist/types/src/errors.d.ts.map +1 -0
  237. package/dist/types/src/extensions/index.d.ts +3 -0
  238. package/dist/types/src/extensions/index.d.ts.map +1 -0
  239. package/dist/types/src/extensions/links.d.ts +21 -0
  240. package/dist/types/src/extensions/links.d.ts.map +1 -0
  241. package/dist/types/src/extensions/links.test.d.ts +2 -0
  242. package/dist/types/src/extensions/links.test.d.ts.map +1 -0
  243. package/dist/types/src/extensions/references.d.ts +23 -0
  244. package/dist/types/src/extensions/references.d.ts.map +1 -0
  245. package/dist/types/src/extensions/references.test.d.ts +2 -0
  246. package/dist/types/src/extensions/references.test.d.ts.map +1 -0
  247. package/dist/types/src/github-link.d.ts +29 -0
  248. package/dist/types/src/github-link.d.ts.map +1 -0
  249. package/dist/types/src/hooks/index.d.ts +5 -2
  250. package/dist/types/src/hooks/index.d.ts.map +1 -1
  251. package/dist/types/src/hooks/useOpenObject.d.ts +9 -0
  252. package/dist/types/src/hooks/useOpenObject.d.ts.map +1 -0
  253. package/dist/types/src/hooks/usePullRequestChecks.d.ts +10 -0
  254. package/dist/types/src/hooks/usePullRequestChecks.d.ts.map +1 -0
  255. package/dist/types/src/hooks/usePullRequestDiff.d.ts +12 -0
  256. package/dist/types/src/hooks/usePullRequestDiff.d.ts.map +1 -0
  257. package/dist/types/src/hooks/usePullRequestFiles.d.ts +22 -0
  258. package/dist/types/src/hooks/usePullRequestFiles.d.ts.map +1 -0
  259. package/dist/types/src/hooks/useSyncPullRequest.d.ts +10 -0
  260. package/dist/types/src/hooks/useSyncPullRequest.d.ts.map +1 -0
  261. package/dist/types/src/index.d.ts +3 -3
  262. package/dist/types/src/index.d.ts.map +1 -1
  263. package/dist/types/src/meta.d.ts +34 -11
  264. package/dist/types/src/meta.d.ts.map +1 -1
  265. package/dist/types/src/operations/add-pull-request-comment.d.ts +5 -0
  266. package/dist/types/src/operations/add-pull-request-comment.d.ts.map +1 -0
  267. package/dist/types/src/operations/add-pull-request-review-comment.d.ts +5 -0
  268. package/dist/types/src/operations/add-pull-request-review-comment.d.ts.map +1 -0
  269. package/dist/types/src/operations/generate-walkthrough.d.ts +11 -0
  270. package/dist/types/src/operations/generate-walkthrough.d.ts.map +1 -0
  271. package/dist/types/src/operations/get-pull-request-diff.d.ts +5 -0
  272. package/dist/types/src/operations/get-pull-request-diff.d.ts.map +1 -0
  273. package/dist/types/src/operations/get-pull-request-status.d.ts +5 -0
  274. package/dist/types/src/operations/get-pull-request-status.d.ts.map +1 -0
  275. package/dist/types/src/operations/get-repositories.d.ts +13 -0
  276. package/dist/types/src/operations/get-repositories.d.ts.map +1 -0
  277. package/dist/types/src/operations/import-pull-request-from-snapshot.d.ts +12 -0
  278. package/dist/types/src/operations/import-pull-request-from-snapshot.d.ts.map +1 -0
  279. package/dist/types/src/operations/import-pull-request.d.ts +63 -0
  280. package/dist/types/src/operations/import-pull-request.d.ts.map +1 -0
  281. package/dist/types/src/operations/import-pull-request.test.d.ts +2 -0
  282. package/dist/types/src/operations/import-pull-request.test.d.ts.map +1 -0
  283. package/dist/types/src/operations/index.d.ts +3 -0
  284. package/dist/types/src/operations/index.d.ts.map +1 -0
  285. package/dist/types/src/operations/materialize-target.d.ts +12 -0
  286. package/dist/types/src/operations/materialize-target.d.ts.map +1 -0
  287. package/dist/types/src/operations/pull-request.d.ts +48 -0
  288. package/dist/types/src/operations/pull-request.d.ts.map +1 -0
  289. package/dist/types/src/operations/pull-request.test.d.ts +2 -0
  290. package/dist/types/src/operations/pull-request.test.d.ts.map +1 -0
  291. package/dist/types/src/operations/submit-pull-request-approval.d.ts +5 -0
  292. package/dist/types/src/operations/submit-pull-request-approval.d.ts.map +1 -0
  293. package/dist/types/src/operations/sync-pull-request.d.ts +5 -0
  294. package/dist/types/src/operations/sync-pull-request.d.ts.map +1 -0
  295. package/dist/types/src/operations/sync.d.ts +123 -0
  296. package/dist/types/src/operations/sync.d.ts.map +1 -0
  297. package/dist/types/src/operations/sync.test.d.ts +2 -0
  298. package/dist/types/src/operations/sync.test.d.ts.map +1 -0
  299. package/dist/types/src/plugin.d.ts +4 -0
  300. package/dist/types/src/plugin.d.ts.map +1 -0
  301. package/dist/types/src/plugin.test.d.ts +2 -0
  302. package/dist/types/src/plugin.test.d.ts.map +1 -0
  303. package/dist/types/src/pull-request-body.d.ts +37 -0
  304. package/dist/types/src/pull-request-body.d.ts.map +1 -0
  305. package/dist/types/src/pull-request-body.test.d.ts +2 -0
  306. package/dist/types/src/pull-request-body.test.d.ts.map +1 -0
  307. package/dist/types/src/pull-request.d.ts +28 -0
  308. package/dist/types/src/pull-request.d.ts.map +1 -0
  309. package/dist/types/src/pull-request.test.d.ts +2 -0
  310. package/dist/types/src/pull-request.test.d.ts.map +1 -0
  311. package/dist/types/src/services/github-api.d.ts +332 -0
  312. package/dist/types/src/services/github-api.d.ts.map +1 -0
  313. package/dist/types/src/services/index.d.ts +2 -0
  314. package/dist/types/src/services/index.d.ts.map +1 -0
  315. package/dist/types/src/skills/GitHubSkill.d.ts +12 -0
  316. package/dist/types/src/skills/GitHubSkill.d.ts.map +1 -0
  317. package/dist/types/src/skills/index.d.ts +2 -0
  318. package/dist/types/src/skills/index.d.ts.map +1 -0
  319. package/dist/types/src/stories/Generate.stories.d.ts +27 -0
  320. package/dist/types/src/stories/Generate.stories.d.ts.map +1 -0
  321. package/dist/types/src/stories/Links.stories.d.ts +23 -0
  322. package/dist/types/src/stories/Links.stories.d.ts.map +1 -0
  323. package/dist/types/src/stories/PullRequestArticle.stories.d.ts +359 -0
  324. package/dist/types/src/stories/PullRequestArticle.stories.d.ts.map +1 -0
  325. package/dist/types/src/stories/PullRequestFiles.stories.d.ts +365 -0
  326. package/dist/types/src/stories/PullRequestFiles.stories.d.ts.map +1 -0
  327. package/dist/types/src/stories/PullRequestOverview.stories.d.ts +367 -0
  328. package/dist/types/src/stories/PullRequestOverview.stories.d.ts.map +1 -0
  329. package/dist/types/src/stories/PullRequestsArticle.stories.d.ts +357 -0
  330. package/dist/types/src/stories/PullRequestsArticle.stories.d.ts.map +1 -0
  331. package/dist/types/src/stories/Walkthrough.stories.d.ts +380 -0
  332. package/dist/types/src/stories/Walkthrough.stories.d.ts.map +1 -0
  333. package/dist/types/src/stories/github.d.ts +23 -0
  334. package/dist/types/src/stories/github.d.ts.map +1 -0
  335. package/dist/types/src/stories/github.test.d.ts +2 -0
  336. package/dist/types/src/stories/github.test.d.ts.map +1 -0
  337. package/dist/types/src/stories/walkthrough-fixture.d.ts +8 -0
  338. package/dist/types/src/stories/walkthrough-fixture.d.ts.map +1 -0
  339. package/dist/types/src/testing/fixtures.d.ts +14 -0
  340. package/dist/types/src/testing/fixtures.d.ts.map +1 -0
  341. package/dist/types/src/testing/index.d.ts +4 -0
  342. package/dist/types/src/testing/index.d.ts.map +1 -0
  343. package/dist/types/src/testing/plugin.d.ts +4 -0
  344. package/dist/types/src/testing/plugin.d.ts.map +1 -0
  345. package/dist/types/src/testing/pull-request-13348.d.ts +6 -0
  346. package/dist/types/src/testing/pull-request-13348.d.ts.map +1 -0
  347. package/dist/types/src/translations.d.ts +339 -53
  348. package/dist/types/src/translations.d.ts.map +1 -1
  349. package/dist/types/src/types/GitHubCapabilities.d.ts +13 -0
  350. package/dist/types/src/types/GitHubCapabilities.d.ts.map +1 -0
  351. package/dist/types/src/types/GitHubEvents.d.ts +8 -0
  352. package/dist/types/src/types/GitHubEvents.d.ts.map +1 -0
  353. package/dist/types/src/types/GitHubOperation.d.ts +270 -0
  354. package/dist/types/src/types/GitHubOperation.d.ts.map +1 -0
  355. package/dist/types/src/types/PullRequestsView.d.ts +35 -0
  356. package/dist/types/src/types/PullRequestsView.d.ts.map +1 -0
  357. package/dist/types/src/types/Walkthrough.d.ts +31 -0
  358. package/dist/types/src/types/Walkthrough.d.ts.map +1 -0
  359. package/dist/types/src/types/Walkthrough.test.d.ts +2 -0
  360. package/dist/types/src/types/Walkthrough.test.d.ts.map +1 -0
  361. package/dist/types/src/types/index.d.ts +5 -0
  362. package/dist/types/src/types/index.d.ts.map +1 -0
  363. package/dist/types/src/walkthrough/fill.d.ts +28 -0
  364. package/dist/types/src/walkthrough/fill.d.ts.map +1 -0
  365. package/dist/types/src/walkthrough/fill.test.d.ts +2 -0
  366. package/dist/types/src/walkthrough/fill.test.d.ts.map +1 -0
  367. package/dist/types/src/walkthrough/generate.d.ts +67 -0
  368. package/dist/types/src/walkthrough/generate.d.ts.map +1 -0
  369. package/dist/types/src/walkthrough/generate.test.d.ts +2 -0
  370. package/dist/types/src/walkthrough/generate.test.d.ts.map +1 -0
  371. package/dist/types/src/walkthrough/generated.d.ts +20 -0
  372. package/dist/types/src/walkthrough/generated.d.ts.map +1 -0
  373. package/dist/types/src/walkthrough/generated.test.d.ts +2 -0
  374. package/dist/types/src/walkthrough/generated.test.d.ts.map +1 -0
  375. package/dist/types/src/walkthrough/headings.d.ts +8 -0
  376. package/dist/types/src/walkthrough/headings.d.ts.map +1 -0
  377. package/dist/types/src/walkthrough/headings.test.d.ts +2 -0
  378. package/dist/types/src/walkthrough/headings.test.d.ts.map +1 -0
  379. package/dist/types/src/walkthrough/index.d.ts +9 -0
  380. package/dist/types/src/walkthrough/index.d.ts.map +1 -0
  381. package/dist/types/src/walkthrough/patch.d.ts +48 -0
  382. package/dist/types/src/walkthrough/patch.d.ts.map +1 -0
  383. package/dist/types/src/walkthrough/plan.d.ts +55 -0
  384. package/dist/types/src/walkthrough/plan.d.ts.map +1 -0
  385. package/dist/types/src/walkthrough/plan.test.d.ts +2 -0
  386. package/dist/types/src/walkthrough/plan.test.d.ts.map +1 -0
  387. package/dist/types/src/walkthrough/prompt.d.ts +33 -0
  388. package/dist/types/src/walkthrough/prompt.d.ts.map +1 -0
  389. package/dist/types/src/walkthrough/prompt.test.d.ts +2 -0
  390. package/dist/types/src/walkthrough/prompt.test.d.ts.map +1 -0
  391. package/dist/types/src/walkthrough/score.d.ts +43 -0
  392. package/dist/types/src/walkthrough/score.d.ts.map +1 -0
  393. package/dist/types/src/walkthrough/score.test.d.ts +2 -0
  394. package/dist/types/src/walkthrough/score.test.d.ts.map +1 -0
  395. package/dist/types/tsconfig.tsbuildinfo +1 -0
  396. package/dx.config.ts +39 -0
  397. package/package.json +167 -48
  398. package/src/Extensions.ts +7 -0
  399. package/src/GitHubPlugin.ts +15 -0
  400. package/src/GitHubPlugin.workerd.test.ts +23 -0
  401. package/src/approval.test.ts +40 -0
  402. package/src/approval.ts +39 -0
  403. package/src/capabilities/app-graph-builder.ts +47 -0
  404. package/src/capabilities/connector.ts +95 -0
  405. package/src/capabilities/gen/browser.ts +82 -0
  406. package/src/capabilities/gen/node.ts +43 -0
  407. package/src/capabilities/gen/tauri.ts +82 -0
  408. package/src/capabilities/gen/workerd.ts +43 -0
  409. package/src/capabilities/index.ts +71 -0
  410. package/src/capabilities/link-resolver.ts +137 -0
  411. package/src/capabilities/markdown-extension.ts +146 -0
  412. package/src/capabilities/operation-handler.ts +16 -0
  413. package/src/capabilities/page-action.ts +32 -0
  414. package/src/capabilities/react-surface.ts +98 -0
  415. package/src/capabilities/schema.ts +16 -0
  416. package/src/capabilities/skill-definition.ts +14 -0
  417. package/src/cards/GitHubCard.stories.tsx +165 -0
  418. package/src/cards/GitHubCard.tsx +93 -0
  419. package/src/cards/PullRequestCard.tsx +23 -0
  420. package/src/cards/index.ts +6 -0
  421. package/src/components/CommentComposer/CommentComposer.tsx +109 -0
  422. package/src/components/CommentComposer/index.ts +5 -0
  423. package/src/components/PullRequestFiles/DiffStat.tsx +15 -0
  424. package/src/components/PullRequestFiles/FileTree.tsx +102 -0
  425. package/src/components/PullRequestFiles/PullRequestFiles.tsx +87 -0
  426. package/src/components/PullRequestFiles/files.test.ts +59 -0
  427. package/src/components/PullRequestFiles/files.ts +115 -0
  428. package/src/components/PullRequestFiles/index.ts +8 -0
  429. package/src/components/PullRequestOverview/ArtifactPill.tsx +82 -0
  430. package/src/components/PullRequestOverview/CheckRunList.tsx +120 -0
  431. package/src/components/PullRequestOverview/PullRequestDetails.tsx +15 -0
  432. package/src/components/PullRequestOverview/PullRequestOverview.tsx +110 -0
  433. package/src/components/PullRequestOverview/RelatedCards.tsx +147 -0
  434. package/src/components/PullRequestOverview/index.ts +9 -0
  435. package/src/components/PullRequestStatus/PullRequestStatus.tsx +81 -0
  436. package/src/components/PullRequestStatus/index.ts +5 -0
  437. package/src/components/WalkthroughView/WalkthroughView.tsx +62 -0
  438. package/src/components/WalkthroughView/extensions.ts +53 -0
  439. package/src/components/WalkthroughView/index.ts +6 -0
  440. package/src/components/index.ts +6 -9
  441. package/src/constants.ts +12 -0
  442. package/src/containers/ImportPullRequestDialog/ImportPullRequestDialog.tsx +160 -0
  443. package/src/containers/ImportPullRequestDialog/index.ts +7 -0
  444. package/src/containers/PullRequestArticle/PullRequestArticle.tsx +573 -0
  445. package/src/containers/PullRequestArticle/failure.test.ts +42 -0
  446. package/src/containers/PullRequestArticle/failure.ts +16 -0
  447. package/src/containers/PullRequestArticle/index.ts +5 -0
  448. package/src/containers/PullRequestCardMenu/PullRequestCardMenu.tsx +134 -0
  449. package/src/containers/PullRequestCardMenu/index.ts +5 -0
  450. package/src/containers/PullRequestsArticle/PullRequestsArticle.tsx +361 -0
  451. package/src/containers/PullRequestsArticle/arrange.test.ts +122 -0
  452. package/src/containers/PullRequestsArticle/arrange.ts +245 -0
  453. package/src/containers/PullRequestsArticle/format.ts +31 -0
  454. package/src/containers/PullRequestsArticle/index.ts +5 -0
  455. package/src/containers/WalkthroughArticle/WalkthroughArticle.tsx +31 -0
  456. package/src/containers/WalkthroughArticle/index.ts +5 -0
  457. package/src/containers/index.ts +11 -0
  458. package/src/errors.ts +61 -0
  459. package/src/extensions/index.ts +6 -0
  460. package/src/extensions/links.test.ts +133 -0
  461. package/src/extensions/links.ts +91 -0
  462. package/src/extensions/references.test.ts +83 -0
  463. package/src/extensions/references.ts +100 -0
  464. package/src/github-link.ts +70 -0
  465. package/src/hooks/index.ts +6 -3
  466. package/src/hooks/useOpenObject.ts +48 -0
  467. package/src/hooks/usePullRequestChecks.ts +81 -0
  468. package/src/hooks/usePullRequestDiff.ts +57 -0
  469. package/src/hooks/usePullRequestFiles.ts +98 -0
  470. package/src/hooks/useSyncPullRequest.ts +51 -0
  471. package/src/index.ts +4 -6
  472. package/src/meta.ts +8 -13
  473. package/src/operations/add-pull-request-comment.ts +31 -0
  474. package/src/operations/add-pull-request-review-comment.ts +32 -0
  475. package/src/operations/generate-walkthrough.ts +124 -0
  476. package/src/operations/get-pull-request-diff.ts +37 -0
  477. package/src/operations/get-pull-request-status.ts +44 -0
  478. package/src/operations/get-repositories.ts +53 -0
  479. package/src/operations/import-pull-request-from-snapshot.ts +48 -0
  480. package/src/operations/import-pull-request.test.ts +151 -0
  481. package/src/operations/import-pull-request.ts +141 -0
  482. package/src/operations/index.ts +29 -0
  483. package/src/operations/materialize-target.ts +60 -0
  484. package/src/operations/pull-request.test.ts +120 -0
  485. package/src/operations/pull-request.ts +141 -0
  486. package/src/operations/submit-pull-request-approval.ts +41 -0
  487. package/src/operations/sync-pull-request.ts +37 -0
  488. package/src/operations/sync.test.ts +453 -0
  489. package/src/operations/sync.ts +807 -0
  490. package/src/plugin.test.ts +40 -0
  491. package/src/plugin.ts +37 -0
  492. package/src/pull-request-body.test.ts +61 -0
  493. package/src/pull-request-body.ts +144 -0
  494. package/src/pull-request.test.ts +67 -0
  495. package/src/pull-request.ts +80 -0
  496. package/src/services/github-api.ts +735 -0
  497. package/src/services/index.ts +5 -0
  498. package/src/skills/GitHubSkill.ts +46 -0
  499. package/src/skills/index.ts +5 -0
  500. package/src/stories/Generate.stories.tsx +152 -0
  501. package/src/stories/Links.stories.tsx +153 -0
  502. package/src/stories/PullRequestArticle.stories.tsx +107 -0
  503. package/src/stories/PullRequestFiles.stories.tsx +69 -0
  504. package/src/stories/PullRequestOverview.stories.tsx +113 -0
  505. package/src/stories/PullRequestsArticle.stories.tsx +170 -0
  506. package/src/stories/Walkthrough.stories.tsx +110 -0
  507. package/src/stories/github.test.ts +65 -0
  508. package/src/stories/github.ts +70 -0
  509. package/src/stories/walkthrough-fixture.ts +115 -0
  510. package/src/testing/fixtures.ts +99 -0
  511. package/src/testing/index.ts +7 -0
  512. package/src/testing/plugin.ts +25 -0
  513. package/src/testing/pull-request-13348.ts +104 -0
  514. package/src/testing/pull-request-13363.patch +2981 -0
  515. package/src/translations.ts +135 -63
  516. package/src/types/GitHubCapabilities.ts +27 -0
  517. package/src/types/GitHubEvents.ts +16 -0
  518. package/src/types/GitHubOperation.ts +371 -0
  519. package/src/types/PullRequestsView.ts +45 -0
  520. package/src/types/Walkthrough.test.ts +75 -0
  521. package/src/types/Walkthrough.ts +66 -0
  522. package/src/types/index.ts +8 -0
  523. package/src/vite-env.d.ts +15 -0
  524. package/src/walkthrough/fill.test.ts +337 -0
  525. package/src/walkthrough/fill.ts +246 -0
  526. package/src/walkthrough/generate.test.ts +219 -0
  527. package/src/walkthrough/generate.ts +248 -0
  528. package/src/walkthrough/generated.test.ts +70 -0
  529. package/src/walkthrough/generated.ts +70 -0
  530. package/src/walkthrough/headings.test.ts +40 -0
  531. package/src/walkthrough/headings.ts +39 -0
  532. package/src/walkthrough/index.ts +12 -0
  533. package/src/walkthrough/patch.ts +154 -0
  534. package/src/walkthrough/plan.test.ts +178 -0
  535. package/src/walkthrough/plan.ts +251 -0
  536. package/src/walkthrough/prompt.test.ts +100 -0
  537. package/src/walkthrough/prompt.ts +147 -0
  538. package/src/walkthrough/score.test.ts +272 -0
  539. package/src/walkthrough/score.ts +430 -0
  540. package/README.md +0 -15
  541. package/dist/lib/browser/chunk-S4MPSBA5.mjs +0 -21
  542. package/dist/lib/browser/chunk-S4MPSBA5.mjs.map +0 -7
  543. package/dist/lib/browser/index.css +0 -7
  544. package/dist/lib/browser/index.css.map +0 -7
  545. package/dist/lib/browser/index.mjs +0 -1535
  546. package/dist/lib/browser/index.mjs.map +0 -7
  547. package/dist/lib/browser/meta.json +0 -1
  548. package/dist/lib/browser/meta.mjs +0 -11
  549. package/dist/lib/browser/meta.mjs.map +0 -7
  550. package/dist/types/src/GithubPlugin.d.ts +0 -4
  551. package/dist/types/src/GithubPlugin.d.ts.map +0 -1
  552. package/dist/types/src/components/EmbeddedMain/EmbeddedMain.d.ts +0 -4
  553. package/dist/types/src/components/EmbeddedMain/EmbeddedMain.d.ts.map +0 -1
  554. package/dist/types/src/components/EmbeddedMain/GfmPreview.d.ts +0 -9
  555. package/dist/types/src/components/EmbeddedMain/GfmPreview.d.ts.map +0 -1
  556. package/dist/types/src/components/EmbeddedMain/index.d.ts +0 -2
  557. package/dist/types/src/components/EmbeddedMain/index.d.ts.map +0 -1
  558. package/dist/types/src/components/ExportDialog.d.ts +0 -8
  559. package/dist/types/src/components/ExportDialog.d.ts.map +0 -1
  560. package/dist/types/src/components/GithubApiProviders/GitHubSettings.d.ts +0 -3
  561. package/dist/types/src/components/GithubApiProviders/GitHubSettings.d.ts.map +0 -1
  562. package/dist/types/src/components/GithubApiProviders/OctokitProvider.d.ts +0 -15
  563. package/dist/types/src/components/GithubApiProviders/OctokitProvider.d.ts.map +0 -1
  564. package/dist/types/src/components/GithubApiProviders/index.d.ts +0 -3
  565. package/dist/types/src/components/GithubApiProviders/index.d.ts.map +0 -1
  566. package/dist/types/src/components/GithubEchoResolverProviders/DocumentTreeItem.d.ts +0 -6
  567. package/dist/types/src/components/GithubEchoResolverProviders/DocumentTreeItem.d.ts.map +0 -1
  568. package/dist/types/src/components/GithubEchoResolverProviders/ResolverContext.d.ts +0 -7
  569. package/dist/types/src/components/GithubEchoResolverProviders/ResolverContext.d.ts.map +0 -1
  570. package/dist/types/src/components/GithubEchoResolverProviders/ResolverDialog.d.ts +0 -6
  571. package/dist/types/src/components/GithubEchoResolverProviders/ResolverDialog.d.ts.map +0 -1
  572. package/dist/types/src/components/GithubEchoResolverProviders/ResolverProps.d.ts +0 -16
  573. package/dist/types/src/components/GithubEchoResolverProviders/ResolverProps.d.ts.map +0 -1
  574. package/dist/types/src/components/GithubEchoResolverProviders/ResolverTree.d.ts +0 -3
  575. package/dist/types/src/components/GithubEchoResolverProviders/ResolverTree.d.ts.map +0 -1
  576. package/dist/types/src/components/GithubEchoResolverProviders/SpacePickerTreeItem.d.ts +0 -11
  577. package/dist/types/src/components/GithubEchoResolverProviders/SpacePickerTreeItem.d.ts.map +0 -1
  578. package/dist/types/src/components/GithubEchoResolverProviders/index.d.ts +0 -3
  579. package/dist/types/src/components/GithubEchoResolverProviders/index.d.ts.map +0 -1
  580. package/dist/types/src/components/GithubEchoResolverProviders/spaceResolvers.d.ts +0 -6
  581. package/dist/types/src/components/GithubEchoResolverProviders/spaceResolvers.d.ts.map +0 -1
  582. package/dist/types/src/components/ImportDialog.d.ts +0 -7
  583. package/dist/types/src/components/ImportDialog.d.ts.map +0 -1
  584. package/dist/types/src/components/Issue.d.ts +0 -5
  585. package/dist/types/src/components/Issue.d.ts.map +0 -1
  586. package/dist/types/src/components/Loading/Loading.d.ts +0 -15
  587. package/dist/types/src/components/Loading/Loading.d.ts.map +0 -1
  588. package/dist/types/src/components/Loading/Loading.stories.d.ts +0 -40
  589. package/dist/types/src/components/Loading/Loading.stories.d.ts.map +0 -1
  590. package/dist/types/src/components/Loading/index.d.ts +0 -2
  591. package/dist/types/src/components/Loading/index.d.ts.map +0 -1
  592. package/dist/types/src/components/MarkdownActions.d.ts +0 -7
  593. package/dist/types/src/components/MarkdownActions.d.ts.map +0 -1
  594. package/dist/types/src/components/UrlDialog.d.ts +0 -6
  595. package/dist/types/src/components/UrlDialog.d.ts.map +0 -1
  596. package/dist/types/src/hooks/useDocGhId.d.ts +0 -6
  597. package/dist/types/src/hooks/useDocGhId.d.ts.map +0 -1
  598. package/dist/types/src/hooks/useGhIdFromUrl.d.ts +0 -2
  599. package/dist/types/src/hooks/useGhIdFromUrl.d.ts.map +0 -1
  600. package/dist/types/src/types.d.ts +0 -30
  601. package/dist/types/src/types.d.ts.map +0 -1
  602. package/src/GithubPlugin.tsx +0 -127
  603. package/src/components/EmbeddedMain/EmbeddedMain.tsx +0 -294
  604. package/src/components/EmbeddedMain/GfmPreview.tsx +0 -110
  605. package/src/components/EmbeddedMain/embedded.css +0 -3
  606. package/src/components/EmbeddedMain/index.ts +0 -5
  607. package/src/components/ExportDialog.tsx +0 -157
  608. package/src/components/GithubApiProviders/GitHubSettings.tsx +0 -72
  609. package/src/components/GithubApiProviders/OctokitProvider.tsx +0 -60
  610. package/src/components/GithubApiProviders/index.ts +0 -6
  611. package/src/components/GithubEchoResolverProviders/DocumentTreeItem.tsx +0 -26
  612. package/src/components/GithubEchoResolverProviders/ResolverContext.tsx +0 -137
  613. package/src/components/GithubEchoResolverProviders/ResolverDialog.tsx +0 -34
  614. package/src/components/GithubEchoResolverProviders/ResolverProps.ts +0 -23
  615. package/src/components/GithubEchoResolverProviders/ResolverTree.tsx +0 -86
  616. package/src/components/GithubEchoResolverProviders/SpacePickerTreeItem.tsx +0 -105
  617. package/src/components/GithubEchoResolverProviders/index.ts +0 -6
  618. package/src/components/GithubEchoResolverProviders/spaceResolvers.ts +0 -86
  619. package/src/components/ImportDialog.tsx +0 -72
  620. package/src/components/Issue.tsx +0 -62
  621. package/src/components/Loading/Loading.stories.tsx +0 -32
  622. package/src/components/Loading/Loading.tsx +0 -70
  623. package/src/components/Loading/index.ts +0 -5
  624. package/src/components/MarkdownActions.tsx +0 -136
  625. package/src/components/UrlDialog.tsx +0 -52
  626. package/src/hooks/useDocGhId.ts +0 -38
  627. package/src/hooks/useGhIdFromUrl.ts +0 -26
  628. package/src/types.ts +0 -51
@@ -0,0 +1,59 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { describe, test } from 'vitest';
6
+
7
+ import { parsePatch } from '../../walkthrough/patch.ts';
8
+ import { buildFileTree, diffFence, fileSignature, flattenFiles } from './files.ts';
9
+
10
+ const patch = (path: string, line: string) =>
11
+ [`diff --git a/${path} b/${path}`, `--- a/${path}`, `+++ b/${path}`, '@@ -1,1 +1,1 @@', '-old', `+${line}`].join(
12
+ '\n',
13
+ );
14
+
15
+ describe('buildFileTree', () => {
16
+ test('folds single-child directories and lists directories before files', ({ expect }) => {
17
+ const files = parsePatch(
18
+ [
19
+ patch('packages/core/echo/src/Filter.ts', 'a'),
20
+ patch('packages/core/echo/src/Query.ts', 'b'),
21
+ patch('packages/core/echo/package.json', 'c'),
22
+ patch('README.md', 'd'),
23
+ ].join('\n'),
24
+ );
25
+ const tree = buildFileTree(files);
26
+ expect(tree.children.map((node) => node.name)).toEqual(['packages/core/echo', 'README.md']);
27
+ expect(tree.children[0].children.map((node) => node.name)).toEqual(['src', 'package.json']);
28
+ expect(tree.children[0].added).toBe(3);
29
+ expect(flattenFiles(tree).map((file) => file.path)).toEqual([
30
+ 'packages/core/echo/src/Filter.ts',
31
+ 'packages/core/echo/src/Query.ts',
32
+ 'packages/core/echo/package.json',
33
+ 'README.md',
34
+ ]);
35
+ });
36
+ });
37
+
38
+ describe('buildFileTree, replaced paths', () => {
39
+ test('keeps a directory that replaced a file of the same name', ({ expect }) => {
40
+ const files = parsePatch([patch('docs/a', 'x'), patch('docs/a/b.md', 'y')].join('\n'));
41
+ expect(flattenFiles(buildFileTree(files)).map((file) => file.path)).toEqual(['docs/a/b.md', 'docs/a']);
42
+ });
43
+ });
44
+
45
+ describe('diffFence', () => {
46
+ test('outgrows any backtick run in the body', ({ expect }) => {
47
+ const [file] = parsePatch(patch('docs/README.md', '````ts'));
48
+ expect(diffFence(file).startsWith('`````diff file=docs/README.md\n@@ -1,1 +1,1 @@')).toBe(true);
49
+ });
50
+ });
51
+
52
+ describe('fileSignature', () => {
53
+ test('moves when the change does', ({ expect }) => {
54
+ const [first] = parsePatch(patch('a.ts', 'one'));
55
+ const [second] = parsePatch(patch('a.ts', 'two'));
56
+ expect(fileSignature(first)).toBe(fileSignature(parsePatch(patch('a.ts', 'one'))[0]));
57
+ expect(fileSignature(first)).not.toBe(fileSignature(second));
58
+ });
59
+ });
@@ -0,0 +1,115 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type PatchFile, renderHunks } from '../../walkthrough/patch.ts';
6
+
7
+ /** A node of the changed-file tree: a directory (with children) or a changed file (with its patch). */
8
+ export type FileNode = {
9
+ /**
10
+ * A generated id rather than the path: the tree joins ids into row paths with a separator a file
11
+ * name may itself contain (`+page.svelte`).
12
+ */
13
+ id: string;
14
+ /** The full path of the file or directory; the synthetic root's is empty. */
15
+ path: string;
16
+ /** What the row shows: a base name, or a run of directories that each hold only one child. */
17
+ name: string;
18
+ file?: PatchFile;
19
+ children: FileNode[];
20
+ added: number;
21
+ removed: number;
22
+ };
23
+
24
+ /** Id of the synthetic root the tree model anchors its top-level rows to; never rendered. */
25
+ export const FILE_TREE_ROOT = 'root';
26
+
27
+ /**
28
+ * The changed files as a directory tree, directories before files and each alphabetical — the order
29
+ * GitHub's own file tree uses. A directory whose only child is another directory is folded into one
30
+ * row (`src/components`), since a chain of single-entry folders is depth without information.
31
+ */
32
+ export const buildFileTree = (files: readonly PatchFile[]): FileNode => {
33
+ let count = 0;
34
+ const nextId = () => `node-${++count}`;
35
+ const root: FileNode = { id: FILE_TREE_ROOT, path: '', name: '', children: [], added: 0, removed: 0 };
36
+ for (const file of files) {
37
+ const segments = file.path.split('/');
38
+ let parent = root;
39
+ for (let index = 0; index < segments.length - 1; index++) {
40
+ const path = segments.slice(0, index + 1).join('/');
41
+ // Directories only: a change can replace a file with a directory of the same name.
42
+ let directory = parent.children.find((child) => !child.file && child.path === path);
43
+ if (!directory) {
44
+ directory = { id: nextId(), path, name: segments[index], children: [], added: 0, removed: 0 };
45
+ parent.children.push(directory);
46
+ }
47
+ parent = directory;
48
+ }
49
+ parent.children.push({
50
+ id: nextId(),
51
+ path: file.path,
52
+ name: segments.at(-1) ?? file.path,
53
+ file,
54
+ children: [],
55
+ added: file.added,
56
+ removed: file.removed,
57
+ });
58
+ }
59
+
60
+ const finish = (node: FileNode): FileNode => {
61
+ const children = node.children.map(finish).sort(compareNodes);
62
+ let folded: FileNode = {
63
+ ...node,
64
+ children,
65
+ added: node.file ? node.added : children.reduce((sum, child) => sum + child.added, 0),
66
+ removed: node.file ? node.removed : children.reduce((sum, child) => sum + child.removed, 0),
67
+ };
68
+ while (folded !== root && !folded.file && folded.children.length === 1 && !folded.children[0].file) {
69
+ const [only] = folded.children;
70
+ folded = { ...only, name: `${folded.name}/${only.name}` };
71
+ }
72
+ return folded;
73
+ };
74
+
75
+ return finish(root);
76
+ };
77
+
78
+ const compareNodes = (left: FileNode, right: FileNode): number =>
79
+ Number(!!left.file) - Number(!!right.file) || left.name.localeCompare(right.name);
80
+
81
+ /** The files in the order the tree lists them, which is the order previous/next walks. */
82
+ export const flattenFiles = (node: FileNode): PatchFile[] =>
83
+ node.file ? [node.file] : node.children.flatMap(flattenFiles);
84
+
85
+ /**
86
+ * One file's change as the ```diff fence the walkthrough renders, so the files view shows a file
87
+ * exactly as a walkthrough chunk would. The fence is one backtick longer than any run in the body:
88
+ * a context line of a markdown file can itself be a fence, which would otherwise close this one.
89
+ */
90
+ export const diffFence = (file: PatchFile): string => {
91
+ const body = renderHunks(file.hunks);
92
+ const longest = Math.max(0, ...(body.match(/`+/g) ?? []).map((run) => run.length));
93
+ const fence = '`'.repeat(Math.max(3, longest + 1));
94
+ return `${fence}diff file=${file.path}\n${body}\n${fence}`;
95
+ };
96
+
97
+ /**
98
+ * A short digest of a file's change. A file is reviewed at a signature: when a push changes the
99
+ * file its signature moves and the check falls away, as GitHub's "Viewed" does.
100
+ */
101
+ export const fileSignature = (file: PatchFile): string => {
102
+ // FNV-1a over the hunk text; collisions only cost a stale check, never correctness.
103
+ let hash = 0x811c9dc5;
104
+ for (const hunk of file.hunks) {
105
+ for (const line of [hunk.header, ...hunk.lines]) {
106
+ for (let index = 0; index < line.length; index++) {
107
+ hash ^= line.charCodeAt(index);
108
+ hash = Math.imul(hash, 0x01000193);
109
+ }
110
+ hash ^= 10;
111
+ hash = Math.imul(hash, 0x01000193);
112
+ }
113
+ }
114
+ return (hash >>> 0).toString(36);
115
+ };
@@ -0,0 +1,8 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './DiffStat.tsx';
6
+ export * from './files.ts';
7
+ export * from './FileTree.tsx';
8
+ export * from './PullRequestFiles.tsx';
@@ -0,0 +1,82 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React, { type ReactNode } from 'react';
6
+
7
+ import * as Button from '@dxos/react-ui/Button';
8
+ import * as Popover from '@dxos/react-ui/Popover';
9
+
10
+ import { type ArtifactKind, type ArtifactLink } from '../../pull-request-body.ts';
11
+
12
+ /** The leading icon for each kind of artifact. */
13
+ export const artifactIcon: Record<ArtifactKind, string> = {
14
+ video: 'ph--film-strip--regular',
15
+ image: 'ph--image--regular',
16
+ file: 'ph--file--regular',
17
+ };
18
+
19
+ /** The image or video itself, or nothing for a file the browser cannot show inline. */
20
+ export const ArtifactMedia = ({ artifact, classNames }: { artifact: ArtifactLink; classNames?: string }) =>
21
+ artifact.kind === 'video' ? (
22
+ <video
23
+ src={artifact.url}
24
+ controls
25
+ muted
26
+ playsInline
27
+ preload='metadata'
28
+ className={['block w-full bg-black rounded-sm', classNames].filter(Boolean).join(' ')}
29
+ data-testid='pull-request.artifact.video'
30
+ />
31
+ ) : artifact.kind === 'image' ? (
32
+ <img
33
+ src={artifact.url}
34
+ alt={artifact.label ?? artifact.name}
35
+ loading='lazy'
36
+ className={['block w-full object-contain rounded-sm', classNames].filter(Boolean).join(' ')}
37
+ data-testid='pull-request.artifact.image'
38
+ />
39
+ ) : null;
40
+
41
+ export type ArtifactPillProps = {
42
+ artifact: ArtifactLink;
43
+ /** The link's text; the file name when it was written bare. */
44
+ children?: ReactNode;
45
+ };
46
+
47
+ /**
48
+ * An artifact link as a pill that previews its image or video in place, so a reader sees the demo
49
+ * without leaving the pull request. The outline matches the anchor chip a GitHub link becomes, so
50
+ * the body's links read as one kind of thing.
51
+ */
52
+ export const ArtifactPill = ({ artifact, children }: ArtifactPillProps) => {
53
+ const label = typeof children === 'string' && children !== artifact.url ? children : artifact.name;
54
+ if (artifact.kind === 'file') {
55
+ return (
56
+ <a href={artifact.url} target='_blank' rel='noopener noreferrer' className='dx-tag-anchor'>
57
+ {label}
58
+ </a>
59
+ );
60
+ }
61
+
62
+ return (
63
+ <Popover.Root autoFocus={false}>
64
+ <Popover.Trigger asChild>
65
+ <Button.Root
66
+ hue='neutral'
67
+ size='sm'
68
+ classNames='bg-input-surface text-fg font-normal ring-inset ring ring-neutral-border hover:bg-hover-surface hover:ring-info-border align-baseline'
69
+ icon={artifactIcon[artifact.kind]}
70
+ iconClassNames={artifact.kind === 'video' ? 'text-violet-500' : 'text-sky-500'}
71
+ label={label}
72
+ data-testid='pull-request.artifact.pill'
73
+ />
74
+ </Popover.Trigger>
75
+ <Popover.Content classNames='w-[min(40rem,90vw)]'>
76
+ <Popover.Body classNames='p-1'>
77
+ <ArtifactMedia artifact={artifact} />
78
+ </Popover.Body>
79
+ </Popover.Content>
80
+ </Popover.Root>
81
+ );
82
+ };
@@ -0,0 +1,120 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React, { useMemo } from 'react';
6
+
7
+ import { Listbox } from '@dxos/react-ui-list';
8
+ import * as Hooks from '@dxos/react-ui/Hooks';
9
+ import * as Status from '@dxos/react-ui/Status';
10
+
11
+ import { meta } from '#meta';
12
+ import { type GitHubOperation } from '#types';
13
+
14
+ const outcomeIcon: Record<GitHubOperation.CheckOutcome, { icon: string; classNames: string }> = {
15
+ failure: { icon: 'ph--x-circle--fill', classNames: 'text-error-text' },
16
+ pending: { icon: 'ph--circle-notch--regular', classNames: 'text-warning-text animate-spin' },
17
+ success: { icon: 'ph--check-circle--fill', classNames: 'text-success-text' },
18
+ neutral: { icon: 'ph--minus-circle--regular', classNames: 'text-fg-muted' },
19
+ skipped: { icon: 'ph--prohibit--regular', classNames: 'text-fg-muted' },
20
+ };
21
+
22
+ // What needs attention first: a failure is the reason to open the list, a running check the next.
23
+ const outcomeOrder: GitHubOperation.CheckOutcome[] = ['failure', 'pending', 'success', 'neutral', 'skipped'];
24
+
25
+ /** `4m 12s`, or undefined for a run that has not both started and finished. */
26
+ export const formatDuration = (startedAt?: string, completedAt?: string): string | undefined => {
27
+ if (!startedAt || !completedAt) {
28
+ return undefined;
29
+ }
30
+ const seconds = Math.max(0, Math.round((Date.parse(completedAt) - Date.parse(startedAt)) / 1000));
31
+ if (Number.isNaN(seconds)) {
32
+ return undefined;
33
+ }
34
+ const minutes = Math.floor(seconds / 60);
35
+ return minutes > 0 ? `${minutes}m ${seconds % 60}s` : `${seconds}s`;
36
+ };
37
+
38
+ /** Sorts runs by what needs attention, then by name so shards read in order. */
39
+ export const sortCheckRuns = (runs: readonly GitHubOperation.CheckRun[]): GitHubOperation.CheckRun[] =>
40
+ [...runs].sort(
41
+ (a, b) =>
42
+ outcomeOrder.indexOf(a.outcome) - outcomeOrder.indexOf(b.outcome) ||
43
+ a.name.localeCompare(b.name, undefined, { numeric: true }),
44
+ );
45
+
46
+ export type CheckRunListProps = {
47
+ /** Undefined while the status is loading. */
48
+ runs?: readonly GitHubOperation.CheckRun[];
49
+ };
50
+
51
+ /** Every check on the head commit: its outcome, how long it took, and its logs a click away. */
52
+ export const CheckRunList = ({ runs }: CheckRunListProps) => {
53
+ const { t } = Hooks.useTranslation(meta.profile.key);
54
+ const sorted = useMemo(() => (runs ? sortCheckRuns(runs) : undefined), [runs]);
55
+ const summary = useCheckSummary(runs);
56
+
57
+ if (!sorted || sorted.length === 0) {
58
+ return <Status.Empty>{t(sorted ? 'no-checks.message' : 'checks-loading.message')}</Status.Empty>;
59
+ }
60
+
61
+ return (
62
+ <Listbox.Root items={sorted.map((run) => ({ value: `${run.name}-${run.url ?? ''}`, label: run.name }))}>
63
+ <Listbox.Content aria-label={summary} data-testid='pull-request.checks'>
64
+ {sorted.map((run) => {
65
+ const { icon, classNames } = outcomeIcon[run.outcome];
66
+ const duration = formatDuration(run.startedAt, run.completedAt);
67
+ // GitHub's own word when it says more than the outcome: `timed out` rather than `failed`.
68
+ const detail =
69
+ run.conclusion && run.conclusion !== run.outcome && run.conclusion !== 'failure'
70
+ ? run.conclusion.replace(/_/g, ' ')
71
+ : undefined;
72
+ const outcome =
73
+ run.outcome === 'skipped'
74
+ ? t('check-outcome.skipped.label')
75
+ : (duration ?? t(`check-outcome.${run.outcome}.label`));
76
+ const url = run.url;
77
+ return (
78
+ <Listbox.Item
79
+ key={`${run.name}-${url ?? ''}`}
80
+ id={`${run.name}-${url ?? ''}`}
81
+ data-outcome={run.outcome}
82
+ data-testid='pull-request.check'
83
+ onClick={url ? () => window.open(url, '_blank', 'noopener,noreferrer') : undefined}
84
+ >
85
+ <Listbox.ItemIcon icon={icon} classNames={classNames} />
86
+ <Listbox.ItemText>{run.name}</Listbox.ItemText>
87
+ <Listbox.ItemDescription>{[detail, outcome].filter(Boolean).join(' · ')}</Listbox.ItemDescription>
88
+ </Listbox.Item>
89
+ );
90
+ })}
91
+ </Listbox.Content>
92
+ </Listbox.Root>
93
+ );
94
+ };
95
+
96
+ /** The label the checks section carries: the counts once there are runs to count. */
97
+ export const useCheckSummary = (runs?: readonly GitHubOperation.CheckRun[]): string => {
98
+ const { t } = Hooks.useTranslation(meta.profile.key);
99
+ return useMemo(() => {
100
+ if (!runs || runs.length === 0) {
101
+ return t('checks.label');
102
+ }
103
+ const counts: Record<GitHubOperation.CheckOutcome, number> = {
104
+ success: 0,
105
+ failure: 0,
106
+ pending: 0,
107
+ skipped: 0,
108
+ neutral: 0,
109
+ };
110
+ for (const run of runs) {
111
+ counts[run.outcome]++;
112
+ }
113
+ return t('checks-summary.label', {
114
+ passed: counts.success + counts.neutral,
115
+ failed: counts.failure,
116
+ pending: counts.pending,
117
+ skipped: counts.skipped,
118
+ });
119
+ }, [runs, t]);
120
+ };
@@ -0,0 +1,15 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Schema from 'effect/Schema';
6
+
7
+ /** What the overview's details section shows, as a read-only form: one row per fact about the pull request. */
8
+ export const PullRequestDetailsSchema = Schema.Struct({
9
+ reference: Schema.String.annotate({ title: 'Pull request' }),
10
+ state: Schema.optional(Schema.String.annotate({ title: 'State' })),
11
+ checks: Schema.optional(Schema.String.annotate({ title: 'Checks' })),
12
+ branches: Schema.optional(Schema.String.annotate({ title: 'Branches' })),
13
+ });
14
+
15
+ export type PullRequestDetailsValues = Schema.Schema.Type<typeof PullRequestDetailsSchema>;
@@ -0,0 +1,110 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React, { useMemo } from 'react';
6
+
7
+ import * as Hooks from '@dxos/app-framework/Hooks';
8
+ import { DxAnchor } from '@dxos/lit-ui/react';
9
+ import * as PreviewCapabilities from '@dxos/plugin-preview/PreviewCapabilities';
10
+ import { Form } from '@dxos/react-ui-form';
11
+ import { MarkdownLink, MarkdownView, type MarkdownViewProps } from '@dxos/react-ui-markdown';
12
+ import * as UiHooks from '@dxos/react-ui/Hooks';
13
+ import * as Icon from '@dxos/react-ui/Icon';
14
+ import * as Status from '@dxos/react-ui/Status';
15
+
16
+ import { meta } from '#meta';
17
+ import { type GitHubOperation } from '#types';
18
+
19
+ import { parseArtifactLink, parsePullRequestBody } from '../../pull-request-body.ts';
20
+ import { ArtifactPill } from './ArtifactPill.tsx';
21
+ import { CheckRunList, useCheckSummary } from './CheckRunList.tsx';
22
+ import { PullRequestDetailsSchema, type PullRequestDetailsValues } from './PullRequestDetails.tsx';
23
+ import { RelatedCards, useRelatedItems } from './RelatedCards.tsx';
24
+
25
+ export type PullRequestOverviewProps = {
26
+ /** The pull request's description as written on GitHub, footers included. */
27
+ body?: string;
28
+ details: PullRequestDetailsValues;
29
+ /** Undefined while the status is loading. */
30
+ runs?: readonly GitHubOperation.CheckRun[];
31
+ };
32
+
33
+ /**
34
+ * A pull request as its author presented it: the description, the facts about it, what it links to
35
+ * beyond the diff, and every check on its head commit.
36
+ */
37
+ export const PullRequestOverview = ({ body, details, runs }: PullRequestOverviewProps) => {
38
+ const { t } = UiHooks.useTranslation(meta.profile.key);
39
+ const parsed = useMemo(() => parsePullRequestBody(body), [body]);
40
+ const components = useBodyComponents();
41
+ const related = useRelatedItems(parsed);
42
+ const checkSummary = useCheckSummary(runs);
43
+
44
+ // One form hosts the whole tab, so the description and every section share its viewport's column
45
+ // rather than each nesting a gutter of its own.
46
+ return (
47
+ <Form.Root schema={PullRequestDetailsSchema} values={details} layout='static' readonly>
48
+ <Form.Viewport scroll width='document'>
49
+ <Form.Content>
50
+ {parsed.markdown ? (
51
+ <MarkdownView content={parsed.markdown} components={components} data-testid='pull-request.body' />
52
+ ) : (
53
+ <Status.Empty>{t('no-description.message')}</Status.Empty>
54
+ )}
55
+ <Form.FieldSet label={t('details.label')} data-testid='pull-request.details'>
56
+ <Form.Fields />
57
+ </Form.FieldSet>
58
+ {related.length > 0 && (
59
+ <Form.FieldSet label={t('related.label')}>
60
+ <RelatedCards items={related} />
61
+ </Form.FieldSet>
62
+ )}
63
+ <Form.FieldSet label={checkSummary}>
64
+ <CheckRunList runs={runs} />
65
+ </Form.FieldSet>
66
+ </Form.Content>
67
+ </Form.Viewport>
68
+ </Form.Root>
69
+ );
70
+ };
71
+
72
+ /**
73
+ * Links in the body as pills: an artifact previews its media in place, and a link a preview
74
+ * resolver answers (another pull request, an issue) becomes the anchor chip the editor makes of it.
75
+ */
76
+ const useBodyComponents = (): MarkdownViewProps['components'] => {
77
+ const resolvers = Hooks.useCapabilities(PreviewCapabilities.LinkResolver);
78
+ return useMemo(
79
+ () => ({
80
+ a: ({ children, href, node: _node, ...props }) => {
81
+ const artifact = href ? parseArtifactLink(href) : undefined;
82
+ if (artifact) {
83
+ return <ArtifactPill artifact={artifact}>{children}</ArtifactPill>;
84
+ }
85
+ const all = resolvers.flat();
86
+ if (!href || !PreviewCapabilities.isPreviewLink(all, href)) {
87
+ return (
88
+ <MarkdownLink href={href} {...props}>
89
+ {children}
90
+ </MarkdownLink>
91
+ );
92
+ }
93
+ const icon = PreviewCapabilities.linkIcon(all, href);
94
+ return (
95
+ <DxAnchor eid={href} className='dx-tag-anchor'>
96
+ {icon && (
97
+ <Icon.Icon
98
+ icon={icon.icon}
99
+ size='md'
100
+ classNames={['inline-block align-[-0.125em] me-1', icon.classNames]}
101
+ />
102
+ )}
103
+ {children === href ? (PreviewCapabilities.linkLabel(all, href) ?? children) : children}
104
+ </DxAnchor>
105
+ );
106
+ },
107
+ }),
108
+ [resolvers],
109
+ );
110
+ };
@@ -0,0 +1,147 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React, { useMemo } from 'react';
6
+
7
+ import { Masonry } from '@dxos/react-ui-masonry';
8
+ import * as Button from '@dxos/react-ui/Button';
9
+ import * as Card from '@dxos/react-ui/Card';
10
+ import * as Hooks from '@dxos/react-ui/Hooks';
11
+ import * as Icon from '@dxos/react-ui/Icon';
12
+ import * as Layout from '@dxos/react-ui/Layout';
13
+
14
+ import { meta } from '#meta';
15
+
16
+ import { type ArtifactLink, type PullRequestBody } from '../../pull-request-body.ts';
17
+ import { ArtifactMedia, artifactIcon } from './ArtifactPill.tsx';
18
+
19
+ /** One tile of the related grid: a demo artifact, or a link out of the pull request. */
20
+ export type RelatedItem =
21
+ | { kind: 'artifact'; id: string; artifact: ArtifactLink }
22
+ | { kind: 'link'; id: string; icon: string; iconClassNames?: string; title: string; href?: string; detail?: string };
23
+
24
+ export type RelatedCardsProps = Pick<PullRequestBody, 'artifacts' | 'claudeCode' | 'previewUrl'>;
25
+
26
+ /** What {@link RelatedCards} would show; empty when the pull request links to nothing beyond its diff. */
27
+ export const useRelatedItems = ({ artifacts, claudeCode, previewUrl }: RelatedCardsProps): RelatedItem[] => {
28
+ const { t } = Hooks.useTranslation(meta.profile.key);
29
+ return useMemo(() => {
30
+ const items: RelatedItem[] = artifacts.map((artifact) => ({ kind: 'artifact', id: artifact.url, artifact }));
31
+ if (previewUrl) {
32
+ items.push({
33
+ kind: 'link',
34
+ id: 'preview',
35
+ icon: 'ph--rocket-launch--regular',
36
+ iconClassNames: 'text-success-text',
37
+ title: t('preview-deployment.label'),
38
+ href: previewUrl,
39
+ detail: hostOf(previewUrl),
40
+ });
41
+ }
42
+ if (claudeCode) {
43
+ items.push({
44
+ kind: 'link',
45
+ id: 'claude',
46
+ icon: 'px--anthropic--regular',
47
+ iconClassNames: 'text-warning-text',
48
+ title: claudeCode.sessionUrl ? t('claude-session.label') : t('claude-generated.label'),
49
+ href: claudeCode.sessionUrl,
50
+ detail: claudeCode.sessionUrl?.split('/').at(-1),
51
+ });
52
+ }
53
+ return items;
54
+ }, [artifacts, claudeCode, previewUrl, t]);
55
+ };
56
+
57
+ /**
58
+ * What the pull request points at beyond its diff, one card each — its demo media, the preview
59
+ * deployment built from it, and the session that wrote it — in the masonry grid related objects
60
+ * use everywhere else. Renders inside its host's scroller rather than owning one.
61
+ */
62
+ export const RelatedCards = ({ items }: { items: readonly RelatedItem[] }) => (
63
+ <Masonry.Root Tile={RelatedCard} centered={false}>
64
+ <Masonry.Viewport items={items} getId={(item: RelatedItem) => item.id} scroll={false} />
65
+ </Masonry.Root>
66
+ );
67
+
68
+ const RelatedCard = ({ data: item }: { data: RelatedItem }) => {
69
+ const { t } = Hooks.useTranslation(meta.profile.key);
70
+ if (item.kind === 'link') {
71
+ return (
72
+ <Card.Root data-testid={`pull-request.related.${item.id}`}>
73
+ <CardHeading icon={item.icon} iconClassNames={item.iconClassNames} title={item.title} href={item.href} />
74
+ {item.detail && (
75
+ <Card.Row>
76
+ <Card.Text variant='muted' truncate>
77
+ {item.detail}
78
+ </Card.Text>
79
+ </Card.Row>
80
+ )}
81
+ </Card.Root>
82
+ );
83
+ }
84
+
85
+ const { artifact } = item;
86
+ return (
87
+ <Card.Root data-testid='pull-request.related.artifact'>
88
+ <CardHeading
89
+ icon={artifactIcon[artifact.kind]}
90
+ title={artifact.label ?? t(`artifact-${artifact.kind}.label`)}
91
+ href={artifact.url}
92
+ />
93
+ <Card.Row>
94
+ <Card.Text variant='muted' truncate>
95
+ {artifact.name}
96
+ </Card.Text>
97
+ </Card.Row>
98
+ {artifact.kind !== 'file' && (
99
+ <Card.Body>
100
+ {/* `col-span-3` spans the card's gutters, as `Card.Poster` does; the body is `display: contents`. */}
101
+ <ArtifactMedia artifact={artifact} classNames='col-span-3 aspect-video max-h-[200px] object-cover' />
102
+ </Card.Body>
103
+ )}
104
+ </Card.Root>
105
+ );
106
+ };
107
+
108
+ const CardHeading = ({
109
+ icon,
110
+ iconClassNames,
111
+ title,
112
+ href,
113
+ }: {
114
+ icon: string;
115
+ iconClassNames?: string;
116
+ title: string;
117
+ href?: string;
118
+ }) => {
119
+ const { t } = Hooks.useTranslation(meta.profile.key);
120
+ return (
121
+ <Card.Header>
122
+ <Layout.Block>
123
+ <Icon.Icon icon={icon} classNames={iconClassNames} />
124
+ </Layout.Block>
125
+ <Card.Title>{title}</Card.Title>
126
+ {href && (
127
+ <Layout.Block rail='end'>
128
+ <Button.Root
129
+ iconOnly
130
+ variant='ghost'
131
+ icon='ph--arrow-square-out--regular'
132
+ label={t('open-link.label')}
133
+ onClick={() => window.open(href, '_blank', 'noopener,noreferrer')}
134
+ />
135
+ </Layout.Block>
136
+ )}
137
+ </Card.Header>
138
+ );
139
+ };
140
+
141
+ const hostOf = (url: string): string => {
142
+ try {
143
+ return new URL(url).host;
144
+ } catch {
145
+ return url;
146
+ }
147
+ };
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './ArtifactPill.tsx';
6
+ export * from './CheckRunList.tsx';
7
+ export * from './PullRequestDetails.tsx';
8
+ export * from './PullRequestOverview.tsx';
9
+ export * from './RelatedCards.tsx';