@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.
- package/LICENSE +102 -5
- package/PLUGIN.mdl +784 -0
- package/dist/lib/GitHubCapabilities.mjs +10 -0
- package/dist/lib/GitHubCapabilities.mjs.map +1 -0
- package/dist/lib/GitHubEvents.mjs +15 -0
- package/dist/lib/GitHubEvents.mjs.map +1 -0
- package/dist/lib/GitHubOperation.mjs +358 -0
- package/dist/lib/GitHubOperation.mjs.map +1 -0
- package/dist/lib/GitHubPlugin.mjs +16 -0
- package/dist/lib/GitHubPlugin.mjs.map +1 -0
- package/dist/lib/Walkthrough.mjs +59 -0
- package/dist/lib/Walkthrough.mjs.map +1 -0
- package/dist/lib/capabilities.browser.mjs +54 -0
- package/dist/lib/capabilities.browser.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +54 -0
- package/dist/lib/capabilities.mjs.map +1 -0
- package/dist/lib/capabilities.node.mjs +30 -0
- package/dist/lib/capabilities.node.mjs.map +1 -0
- package/dist/lib/capabilities.tauri.mjs +54 -0
- package/dist/lib/capabilities.tauri.mjs.map +1 -0
- package/dist/lib/capabilities.workerd.mjs +30 -0
- package/dist/lib/capabilities.workerd.mjs.map +1 -0
- package/dist/lib/chunk-ImportPullRequestDialog.mjs +116 -0
- package/dist/lib/chunk-ImportPullRequestDialog.mjs.map +1 -0
- package/dist/lib/chunk-PLUGIN.mjs +6 -0
- package/dist/lib/chunk-PLUGIN.mjs.map +1 -0
- package/dist/lib/chunk-PullRequestArticle.mjs +1486 -0
- package/dist/lib/chunk-PullRequestArticle.mjs.map +1 -0
- package/dist/lib/chunk-PullRequestArticle2.mjs +2 -0
- package/dist/lib/chunk-PullRequestCardMenu.mjs +123 -0
- package/dist/lib/chunk-PullRequestCardMenu.mjs.map +1 -0
- package/dist/lib/chunk-PullRequestsArticle.mjs +594 -0
- package/dist/lib/chunk-PullRequestsArticle.mjs.map +1 -0
- package/dist/lib/chunk-WalkthroughArticle.mjs +26 -0
- package/dist/lib/chunk-WalkthroughArticle.mjs.map +1 -0
- package/dist/lib/chunk-add-pull-request-comment.mjs +19 -0
- package/dist/lib/chunk-add-pull-request-comment.mjs.map +1 -0
- package/dist/lib/chunk-add-pull-request-review-comment.mjs +25 -0
- package/dist/lib/chunk-add-pull-request-review-comment.mjs.map +1 -0
- package/dist/lib/chunk-app-graph-builder.mjs +39 -0
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
- package/dist/lib/chunk-connector.mjs +70 -0
- package/dist/lib/chunk-connector.mjs.map +1 -0
- package/dist/lib/chunk-constants.mjs +11 -0
- package/dist/lib/chunk-constants.mjs.map +1 -0
- package/dist/lib/chunk-errors.mjs +29 -0
- package/dist/lib/chunk-errors.mjs.map +1 -0
- package/dist/lib/chunk-generate-walkthrough.mjs +86 -0
- package/dist/lib/chunk-generate-walkthrough.mjs.map +1 -0
- package/dist/lib/chunk-generate.mjs +719 -0
- package/dist/lib/chunk-generate.mjs.map +1 -0
- package/dist/lib/chunk-get-pull-request-diff.mjs +25 -0
- package/dist/lib/chunk-get-pull-request-diff.mjs.map +1 -0
- package/dist/lib/chunk-get-pull-request-status.mjs +29 -0
- package/dist/lib/chunk-get-pull-request-status.mjs.map +1 -0
- package/dist/lib/chunk-get-repositories.mjs +32 -0
- package/dist/lib/chunk-get-repositories.mjs.map +1 -0
- package/dist/lib/chunk-github-api.mjs +375 -0
- package/dist/lib/chunk-github-api.mjs.map +1 -0
- package/dist/lib/chunk-github-link.mjs +59 -0
- package/dist/lib/chunk-github-link.mjs.map +1 -0
- package/dist/lib/chunk-import-pull-request-from-snapshot.mjs +25 -0
- package/dist/lib/chunk-import-pull-request-from-snapshot.mjs.map +1 -0
- package/dist/lib/chunk-import-pull-request.mjs +96 -0
- package/dist/lib/chunk-import-pull-request.mjs.map +1 -0
- package/dist/lib/chunk-link-resolver.mjs +109 -0
- package/dist/lib/chunk-link-resolver.mjs.map +1 -0
- package/dist/lib/chunk-markdown-extension.mjs +92 -0
- package/dist/lib/chunk-markdown-extension.mjs.map +1 -0
- package/dist/lib/chunk-materialize-target.mjs +36 -0
- package/dist/lib/chunk-materialize-target.mjs.map +1 -0
- package/dist/lib/chunk-operation-handler.mjs +12 -0
- package/dist/lib/chunk-operation-handler.mjs.map +1 -0
- package/dist/lib/chunk-page-action.mjs +22 -0
- package/dist/lib/chunk-page-action.mjs.map +1 -0
- package/dist/lib/chunk-pull-request.mjs +58 -0
- package/dist/lib/chunk-pull-request.mjs.map +1 -0
- package/dist/lib/chunk-pull-request2.mjs +110 -0
- package/dist/lib/chunk-pull-request2.mjs.map +1 -0
- package/dist/lib/chunk-react-surface.mjs +233 -0
- package/dist/lib/chunk-react-surface.mjs.map +1 -0
- package/dist/lib/chunk-rolldown-runtime.mjs +13 -0
- package/dist/lib/chunk-schema.mjs +15 -0
- package/dist/lib/chunk-schema.mjs.map +1 -0
- package/dist/lib/chunk-skill-definition.mjs +10 -0
- package/dist/lib/chunk-skill-definition.mjs.map +1 -0
- package/dist/lib/chunk-submit-pull-request-approval.mjs +56 -0
- package/dist/lib/chunk-submit-pull-request-approval.mjs.map +1 -0
- package/dist/lib/chunk-sync-pull-request.mjs +24 -0
- package/dist/lib/chunk-sync-pull-request.mjs.map +1 -0
- package/dist/lib/chunk-sync.mjs +481 -0
- package/dist/lib/chunk-sync.mjs.map +1 -0
- package/dist/lib/chunk-useOpenObject.mjs +43 -0
- package/dist/lib/chunk-useOpenObject.mjs.map +1 -0
- package/dist/lib/extensions.mjs +132 -0
- package/dist/lib/extensions.mjs.map +1 -0
- package/dist/lib/index.mjs +4 -0
- package/dist/lib/meta.mjs +47 -0
- package/dist/lib/meta.mjs.map +1 -0
- package/dist/lib/ns/Extensions.mjs +18 -0
- package/dist/lib/ns/Extensions.mjs.map +1 -0
- package/dist/lib/operations.mjs +22 -0
- package/dist/lib/operations.mjs.map +1 -0
- package/dist/lib/plugin.mjs +9 -0
- package/dist/lib/plugin.mjs.map +1 -0
- package/dist/lib/skills.mjs +44 -0
- package/dist/lib/skills.mjs.map +1 -0
- package/dist/lib/testing.mjs +189 -0
- package/dist/lib/testing.mjs.map +1 -0
- package/dist/lib/translations.mjs +136 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/lib/types.mjs +5 -0
- package/dist/types/dx.config.d.ts +28 -0
- package/dist/types/dx.config.d.ts.map +1 -0
- package/dist/types/src/Extensions.d.ts +2 -0
- package/dist/types/src/Extensions.d.ts.map +1 -0
- package/dist/types/src/GitHubPlugin.d.ts +37 -0
- package/dist/types/src/GitHubPlugin.d.ts.map +1 -0
- package/dist/types/src/GitHubPlugin.workerd.test.d.ts +2 -0
- package/dist/types/src/GitHubPlugin.workerd.test.d.ts.map +1 -0
- package/dist/types/src/approval.d.ts +21 -0
- package/dist/types/src/approval.d.ts.map +1 -0
- package/dist/types/src/approval.test.d.ts +2 -0
- package/dist/types/src/approval.test.d.ts.map +1 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts +9 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/connector.d.ts +17 -0
- package/dist/types/src/capabilities/connector.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/browser.d.ts +13 -0
- package/dist/types/src/capabilities/gen/browser.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/node.d.ts +13 -0
- package/dist/types/src/capabilities/gen/node.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/tauri.d.ts +13 -0
- package/dist/types/src/capabilities/gen/tauri.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/workerd.d.ts +13 -0
- package/dist/types/src/capabilities/gen/workerd.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +13 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/link-resolver.d.ts +10 -0
- package/dist/types/src/capabilities/link-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/markdown-extension.d.ts +14 -0
- package/dist/types/src/capabilities/markdown-extension.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-handler.d.ts +5 -0
- package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
- package/dist/types/src/capabilities/page-action.d.ts +5 -0
- package/dist/types/src/capabilities/page-action.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +5 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/schema.d.ts +12 -0
- package/dist/types/src/capabilities/schema.d.ts.map +1 -0
- package/dist/types/src/capabilities/skill-definition.d.ts +5 -0
- package/dist/types/src/capabilities/skill-definition.d.ts.map +1 -0
- package/dist/types/src/cards/GitHubCard.d.ts +11 -0
- package/dist/types/src/cards/GitHubCard.d.ts.map +1 -0
- package/dist/types/src/cards/GitHubCard.stories.d.ts +45 -0
- package/dist/types/src/cards/GitHubCard.stories.d.ts.map +1 -0
- package/dist/types/src/cards/PullRequestCard.d.ts +9 -0
- package/dist/types/src/cards/PullRequestCard.d.ts.map +1 -0
- package/dist/types/src/cards/index.d.ts +3 -0
- package/dist/types/src/cards/index.d.ts.map +1 -0
- package/dist/types/src/components/CommentComposer/CommentComposer.d.ts +30 -0
- package/dist/types/src/components/CommentComposer/CommentComposer.d.ts.map +1 -0
- package/dist/types/src/components/CommentComposer/index.d.ts +2 -0
- package/dist/types/src/components/CommentComposer/index.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestFiles/DiffStat.d.ts +8 -0
- package/dist/types/src/components/PullRequestFiles/DiffStat.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestFiles/FileTree.d.ts +17 -0
- package/dist/types/src/components/PullRequestFiles/FileTree.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestFiles/PullRequestFiles.d.ts +23 -0
- package/dist/types/src/components/PullRequestFiles/PullRequestFiles.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestFiles/files.d.ts +39 -0
- package/dist/types/src/components/PullRequestFiles/files.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestFiles/files.test.d.ts +2 -0
- package/dist/types/src/components/PullRequestFiles/files.test.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestFiles/index.d.ts +5 -0
- package/dist/types/src/components/PullRequestFiles/index.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestOverview/ArtifactPill.d.ts +21 -0
- package/dist/types/src/components/PullRequestOverview/ArtifactPill.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestOverview/CheckRunList.d.ts +15 -0
- package/dist/types/src/components/PullRequestOverview/CheckRunList.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestOverview/PullRequestDetails.d.ts +10 -0
- package/dist/types/src/components/PullRequestOverview/PullRequestDetails.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestOverview/PullRequestOverview.d.ts +16 -0
- package/dist/types/src/components/PullRequestOverview/PullRequestOverview.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestOverview/RelatedCards.d.ts +28 -0
- package/dist/types/src/components/PullRequestOverview/RelatedCards.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestOverview/index.d.ts +6 -0
- package/dist/types/src/components/PullRequestOverview/index.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestStatus/PullRequestStatus.d.ts +20 -0
- package/dist/types/src/components/PullRequestStatus/PullRequestStatus.d.ts.map +1 -0
- package/dist/types/src/components/PullRequestStatus/index.d.ts +2 -0
- package/dist/types/src/components/PullRequestStatus/index.d.ts.map +1 -0
- package/dist/types/src/components/WalkthroughView/WalkthroughView.d.ts +18 -0
- package/dist/types/src/components/WalkthroughView/WalkthroughView.d.ts.map +1 -0
- package/dist/types/src/components/WalkthroughView/extensions.d.ts +16 -0
- package/dist/types/src/components/WalkthroughView/extensions.d.ts.map +1 -0
- package/dist/types/src/components/WalkthroughView/index.d.ts +3 -0
- package/dist/types/src/components/WalkthroughView/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +5 -8
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/constants.d.ts +7 -0
- package/dist/types/src/constants.d.ts.map +1 -0
- package/dist/types/src/containers/ImportPullRequestDialog/ImportPullRequestDialog.d.ts +6 -0
- package/dist/types/src/containers/ImportPullRequestDialog/ImportPullRequestDialog.d.ts.map +1 -0
- package/dist/types/src/containers/ImportPullRequestDialog/index.d.ts +3 -0
- package/dist/types/src/containers/ImportPullRequestDialog/index.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestArticle/PullRequestArticle.d.ts +15 -0
- package/dist/types/src/containers/PullRequestArticle/PullRequestArticle.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestArticle/failure.d.ts +10 -0
- package/dist/types/src/containers/PullRequestArticle/failure.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestArticle/failure.test.d.ts +2 -0
- package/dist/types/src/containers/PullRequestArticle/failure.test.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestArticle/index.d.ts +2 -0
- package/dist/types/src/containers/PullRequestArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestCardMenu/PullRequestCardMenu.d.ts +14 -0
- package/dist/types/src/containers/PullRequestCardMenu/PullRequestCardMenu.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestCardMenu/index.d.ts +2 -0
- package/dist/types/src/containers/PullRequestCardMenu/index.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestsArticle/PullRequestsArticle.d.ts +13 -0
- package/dist/types/src/containers/PullRequestsArticle/PullRequestsArticle.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestsArticle/arrange.d.ts +44 -0
- package/dist/types/src/containers/PullRequestsArticle/arrange.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestsArticle/arrange.test.d.ts +2 -0
- package/dist/types/src/containers/PullRequestsArticle/arrange.test.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestsArticle/format.d.ts +3 -0
- package/dist/types/src/containers/PullRequestsArticle/format.d.ts.map +1 -0
- package/dist/types/src/containers/PullRequestsArticle/index.d.ts +2 -0
- package/dist/types/src/containers/PullRequestsArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/WalkthroughArticle/WalkthroughArticle.d.ts +13 -0
- package/dist/types/src/containers/WalkthroughArticle/WalkthroughArticle.d.ts.map +1 -0
- package/dist/types/src/containers/WalkthroughArticle/index.d.ts +2 -0
- package/dist/types/src/containers/WalkthroughArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +7 -0
- package/dist/types/src/containers/index.d.ts.map +1 -0
- package/dist/types/src/errors.d.ts +157 -0
- package/dist/types/src/errors.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +3 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -0
- package/dist/types/src/extensions/links.d.ts +21 -0
- package/dist/types/src/extensions/links.d.ts.map +1 -0
- package/dist/types/src/extensions/links.test.d.ts +2 -0
- package/dist/types/src/extensions/links.test.d.ts.map +1 -0
- package/dist/types/src/extensions/references.d.ts +23 -0
- package/dist/types/src/extensions/references.d.ts.map +1 -0
- package/dist/types/src/extensions/references.test.d.ts +2 -0
- package/dist/types/src/extensions/references.test.d.ts.map +1 -0
- package/dist/types/src/github-link.d.ts +29 -0
- package/dist/types/src/github-link.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +5 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useOpenObject.d.ts +9 -0
- package/dist/types/src/hooks/useOpenObject.d.ts.map +1 -0
- package/dist/types/src/hooks/usePullRequestChecks.d.ts +10 -0
- package/dist/types/src/hooks/usePullRequestChecks.d.ts.map +1 -0
- package/dist/types/src/hooks/usePullRequestDiff.d.ts +12 -0
- package/dist/types/src/hooks/usePullRequestDiff.d.ts.map +1 -0
- package/dist/types/src/hooks/usePullRequestFiles.d.ts +22 -0
- package/dist/types/src/hooks/usePullRequestFiles.d.ts.map +1 -0
- package/dist/types/src/hooks/useSyncPullRequest.d.ts +10 -0
- package/dist/types/src/hooks/useSyncPullRequest.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +3 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +34 -11
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/operations/add-pull-request-comment.d.ts +5 -0
- package/dist/types/src/operations/add-pull-request-comment.d.ts.map +1 -0
- package/dist/types/src/operations/add-pull-request-review-comment.d.ts +5 -0
- package/dist/types/src/operations/add-pull-request-review-comment.d.ts.map +1 -0
- package/dist/types/src/operations/generate-walkthrough.d.ts +11 -0
- package/dist/types/src/operations/generate-walkthrough.d.ts.map +1 -0
- package/dist/types/src/operations/get-pull-request-diff.d.ts +5 -0
- package/dist/types/src/operations/get-pull-request-diff.d.ts.map +1 -0
- package/dist/types/src/operations/get-pull-request-status.d.ts +5 -0
- package/dist/types/src/operations/get-pull-request-status.d.ts.map +1 -0
- package/dist/types/src/operations/get-repositories.d.ts +13 -0
- package/dist/types/src/operations/get-repositories.d.ts.map +1 -0
- package/dist/types/src/operations/import-pull-request-from-snapshot.d.ts +12 -0
- package/dist/types/src/operations/import-pull-request-from-snapshot.d.ts.map +1 -0
- package/dist/types/src/operations/import-pull-request.d.ts +63 -0
- package/dist/types/src/operations/import-pull-request.d.ts.map +1 -0
- package/dist/types/src/operations/import-pull-request.test.d.ts +2 -0
- package/dist/types/src/operations/import-pull-request.test.d.ts.map +1 -0
- package/dist/types/src/operations/index.d.ts +3 -0
- package/dist/types/src/operations/index.d.ts.map +1 -0
- package/dist/types/src/operations/materialize-target.d.ts +12 -0
- package/dist/types/src/operations/materialize-target.d.ts.map +1 -0
- package/dist/types/src/operations/pull-request.d.ts +48 -0
- package/dist/types/src/operations/pull-request.d.ts.map +1 -0
- package/dist/types/src/operations/pull-request.test.d.ts +2 -0
- package/dist/types/src/operations/pull-request.test.d.ts.map +1 -0
- package/dist/types/src/operations/submit-pull-request-approval.d.ts +5 -0
- package/dist/types/src/operations/submit-pull-request-approval.d.ts.map +1 -0
- package/dist/types/src/operations/sync-pull-request.d.ts +5 -0
- package/dist/types/src/operations/sync-pull-request.d.ts.map +1 -0
- package/dist/types/src/operations/sync.d.ts +123 -0
- package/dist/types/src/operations/sync.d.ts.map +1 -0
- package/dist/types/src/operations/sync.test.d.ts +2 -0
- package/dist/types/src/operations/sync.test.d.ts.map +1 -0
- package/dist/types/src/plugin.d.ts +4 -0
- package/dist/types/src/plugin.d.ts.map +1 -0
- package/dist/types/src/plugin.test.d.ts +2 -0
- package/dist/types/src/plugin.test.d.ts.map +1 -0
- package/dist/types/src/pull-request-body.d.ts +37 -0
- package/dist/types/src/pull-request-body.d.ts.map +1 -0
- package/dist/types/src/pull-request-body.test.d.ts +2 -0
- package/dist/types/src/pull-request-body.test.d.ts.map +1 -0
- package/dist/types/src/pull-request.d.ts +28 -0
- package/dist/types/src/pull-request.d.ts.map +1 -0
- package/dist/types/src/pull-request.test.d.ts +2 -0
- package/dist/types/src/pull-request.test.d.ts.map +1 -0
- package/dist/types/src/services/github-api.d.ts +332 -0
- package/dist/types/src/services/github-api.d.ts.map +1 -0
- package/dist/types/src/services/index.d.ts +2 -0
- package/dist/types/src/services/index.d.ts.map +1 -0
- package/dist/types/src/skills/GitHubSkill.d.ts +12 -0
- package/dist/types/src/skills/GitHubSkill.d.ts.map +1 -0
- package/dist/types/src/skills/index.d.ts +2 -0
- package/dist/types/src/skills/index.d.ts.map +1 -0
- package/dist/types/src/stories/Generate.stories.d.ts +27 -0
- package/dist/types/src/stories/Generate.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Links.stories.d.ts +23 -0
- package/dist/types/src/stories/Links.stories.d.ts.map +1 -0
- package/dist/types/src/stories/PullRequestArticle.stories.d.ts +359 -0
- package/dist/types/src/stories/PullRequestArticle.stories.d.ts.map +1 -0
- package/dist/types/src/stories/PullRequestFiles.stories.d.ts +365 -0
- package/dist/types/src/stories/PullRequestFiles.stories.d.ts.map +1 -0
- package/dist/types/src/stories/PullRequestOverview.stories.d.ts +367 -0
- package/dist/types/src/stories/PullRequestOverview.stories.d.ts.map +1 -0
- package/dist/types/src/stories/PullRequestsArticle.stories.d.ts +357 -0
- package/dist/types/src/stories/PullRequestsArticle.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Walkthrough.stories.d.ts +380 -0
- package/dist/types/src/stories/Walkthrough.stories.d.ts.map +1 -0
- package/dist/types/src/stories/github.d.ts +23 -0
- package/dist/types/src/stories/github.d.ts.map +1 -0
- package/dist/types/src/stories/github.test.d.ts +2 -0
- package/dist/types/src/stories/github.test.d.ts.map +1 -0
- package/dist/types/src/stories/walkthrough-fixture.d.ts +8 -0
- package/dist/types/src/stories/walkthrough-fixture.d.ts.map +1 -0
- package/dist/types/src/testing/fixtures.d.ts +14 -0
- package/dist/types/src/testing/fixtures.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +4 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/plugin.d.ts +4 -0
- package/dist/types/src/testing/plugin.d.ts.map +1 -0
- package/dist/types/src/testing/pull-request-13348.d.ts +6 -0
- package/dist/types/src/testing/pull-request-13348.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +339 -53
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/GitHubCapabilities.d.ts +13 -0
- package/dist/types/src/types/GitHubCapabilities.d.ts.map +1 -0
- package/dist/types/src/types/GitHubEvents.d.ts +8 -0
- package/dist/types/src/types/GitHubEvents.d.ts.map +1 -0
- package/dist/types/src/types/GitHubOperation.d.ts +270 -0
- package/dist/types/src/types/GitHubOperation.d.ts.map +1 -0
- package/dist/types/src/types/PullRequestsView.d.ts +35 -0
- package/dist/types/src/types/PullRequestsView.d.ts.map +1 -0
- package/dist/types/src/types/Walkthrough.d.ts +31 -0
- package/dist/types/src/types/Walkthrough.d.ts.map +1 -0
- package/dist/types/src/types/Walkthrough.test.d.ts +2 -0
- package/dist/types/src/types/Walkthrough.test.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +5 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/src/walkthrough/fill.d.ts +28 -0
- package/dist/types/src/walkthrough/fill.d.ts.map +1 -0
- package/dist/types/src/walkthrough/fill.test.d.ts +2 -0
- package/dist/types/src/walkthrough/fill.test.d.ts.map +1 -0
- package/dist/types/src/walkthrough/generate.d.ts +67 -0
- package/dist/types/src/walkthrough/generate.d.ts.map +1 -0
- package/dist/types/src/walkthrough/generate.test.d.ts +2 -0
- package/dist/types/src/walkthrough/generate.test.d.ts.map +1 -0
- package/dist/types/src/walkthrough/generated.d.ts +20 -0
- package/dist/types/src/walkthrough/generated.d.ts.map +1 -0
- package/dist/types/src/walkthrough/generated.test.d.ts +2 -0
- package/dist/types/src/walkthrough/generated.test.d.ts.map +1 -0
- package/dist/types/src/walkthrough/headings.d.ts +8 -0
- package/dist/types/src/walkthrough/headings.d.ts.map +1 -0
- package/dist/types/src/walkthrough/headings.test.d.ts +2 -0
- package/dist/types/src/walkthrough/headings.test.d.ts.map +1 -0
- package/dist/types/src/walkthrough/index.d.ts +9 -0
- package/dist/types/src/walkthrough/index.d.ts.map +1 -0
- package/dist/types/src/walkthrough/patch.d.ts +48 -0
- package/dist/types/src/walkthrough/patch.d.ts.map +1 -0
- package/dist/types/src/walkthrough/plan.d.ts +55 -0
- package/dist/types/src/walkthrough/plan.d.ts.map +1 -0
- package/dist/types/src/walkthrough/plan.test.d.ts +2 -0
- package/dist/types/src/walkthrough/plan.test.d.ts.map +1 -0
- package/dist/types/src/walkthrough/prompt.d.ts +33 -0
- package/dist/types/src/walkthrough/prompt.d.ts.map +1 -0
- package/dist/types/src/walkthrough/prompt.test.d.ts +2 -0
- package/dist/types/src/walkthrough/prompt.test.d.ts.map +1 -0
- package/dist/types/src/walkthrough/score.d.ts +43 -0
- package/dist/types/src/walkthrough/score.d.ts.map +1 -0
- package/dist/types/src/walkthrough/score.test.d.ts +2 -0
- package/dist/types/src/walkthrough/score.test.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/dx.config.ts +39 -0
- package/package.json +167 -48
- package/src/Extensions.ts +7 -0
- package/src/GitHubPlugin.ts +15 -0
- package/src/GitHubPlugin.workerd.test.ts +23 -0
- package/src/approval.test.ts +40 -0
- package/src/approval.ts +39 -0
- package/src/capabilities/app-graph-builder.ts +47 -0
- package/src/capabilities/connector.ts +95 -0
- package/src/capabilities/gen/browser.ts +82 -0
- package/src/capabilities/gen/node.ts +43 -0
- package/src/capabilities/gen/tauri.ts +82 -0
- package/src/capabilities/gen/workerd.ts +43 -0
- package/src/capabilities/index.ts +71 -0
- package/src/capabilities/link-resolver.ts +137 -0
- package/src/capabilities/markdown-extension.ts +146 -0
- package/src/capabilities/operation-handler.ts +16 -0
- package/src/capabilities/page-action.ts +32 -0
- package/src/capabilities/react-surface.ts +98 -0
- package/src/capabilities/schema.ts +16 -0
- package/src/capabilities/skill-definition.ts +14 -0
- package/src/cards/GitHubCard.stories.tsx +165 -0
- package/src/cards/GitHubCard.tsx +93 -0
- package/src/cards/PullRequestCard.tsx +23 -0
- package/src/cards/index.ts +6 -0
- package/src/components/CommentComposer/CommentComposer.tsx +109 -0
- package/src/components/CommentComposer/index.ts +5 -0
- package/src/components/PullRequestFiles/DiffStat.tsx +15 -0
- package/src/components/PullRequestFiles/FileTree.tsx +102 -0
- package/src/components/PullRequestFiles/PullRequestFiles.tsx +87 -0
- package/src/components/PullRequestFiles/files.test.ts +59 -0
- package/src/components/PullRequestFiles/files.ts +115 -0
- package/src/components/PullRequestFiles/index.ts +8 -0
- package/src/components/PullRequestOverview/ArtifactPill.tsx +82 -0
- package/src/components/PullRequestOverview/CheckRunList.tsx +120 -0
- package/src/components/PullRequestOverview/PullRequestDetails.tsx +15 -0
- package/src/components/PullRequestOverview/PullRequestOverview.tsx +110 -0
- package/src/components/PullRequestOverview/RelatedCards.tsx +147 -0
- package/src/components/PullRequestOverview/index.ts +9 -0
- package/src/components/PullRequestStatus/PullRequestStatus.tsx +81 -0
- package/src/components/PullRequestStatus/index.ts +5 -0
- package/src/components/WalkthroughView/WalkthroughView.tsx +62 -0
- package/src/components/WalkthroughView/extensions.ts +53 -0
- package/src/components/WalkthroughView/index.ts +6 -0
- package/src/components/index.ts +6 -9
- package/src/constants.ts +12 -0
- package/src/containers/ImportPullRequestDialog/ImportPullRequestDialog.tsx +160 -0
- package/src/containers/ImportPullRequestDialog/index.ts +7 -0
- package/src/containers/PullRequestArticle/PullRequestArticle.tsx +573 -0
- package/src/containers/PullRequestArticle/failure.test.ts +42 -0
- package/src/containers/PullRequestArticle/failure.ts +16 -0
- package/src/containers/PullRequestArticle/index.ts +5 -0
- package/src/containers/PullRequestCardMenu/PullRequestCardMenu.tsx +134 -0
- package/src/containers/PullRequestCardMenu/index.ts +5 -0
- package/src/containers/PullRequestsArticle/PullRequestsArticle.tsx +361 -0
- package/src/containers/PullRequestsArticle/arrange.test.ts +122 -0
- package/src/containers/PullRequestsArticle/arrange.ts +245 -0
- package/src/containers/PullRequestsArticle/format.ts +31 -0
- package/src/containers/PullRequestsArticle/index.ts +5 -0
- package/src/containers/WalkthroughArticle/WalkthroughArticle.tsx +31 -0
- package/src/containers/WalkthroughArticle/index.ts +5 -0
- package/src/containers/index.ts +11 -0
- package/src/errors.ts +61 -0
- package/src/extensions/index.ts +6 -0
- package/src/extensions/links.test.ts +133 -0
- package/src/extensions/links.ts +91 -0
- package/src/extensions/references.test.ts +83 -0
- package/src/extensions/references.ts +100 -0
- package/src/github-link.ts +70 -0
- package/src/hooks/index.ts +6 -3
- package/src/hooks/useOpenObject.ts +48 -0
- package/src/hooks/usePullRequestChecks.ts +81 -0
- package/src/hooks/usePullRequestDiff.ts +57 -0
- package/src/hooks/usePullRequestFiles.ts +98 -0
- package/src/hooks/useSyncPullRequest.ts +51 -0
- package/src/index.ts +4 -6
- package/src/meta.ts +8 -13
- package/src/operations/add-pull-request-comment.ts +31 -0
- package/src/operations/add-pull-request-review-comment.ts +32 -0
- package/src/operations/generate-walkthrough.ts +124 -0
- package/src/operations/get-pull-request-diff.ts +37 -0
- package/src/operations/get-pull-request-status.ts +44 -0
- package/src/operations/get-repositories.ts +53 -0
- package/src/operations/import-pull-request-from-snapshot.ts +48 -0
- package/src/operations/import-pull-request.test.ts +151 -0
- package/src/operations/import-pull-request.ts +141 -0
- package/src/operations/index.ts +29 -0
- package/src/operations/materialize-target.ts +60 -0
- package/src/operations/pull-request.test.ts +120 -0
- package/src/operations/pull-request.ts +141 -0
- package/src/operations/submit-pull-request-approval.ts +41 -0
- package/src/operations/sync-pull-request.ts +37 -0
- package/src/operations/sync.test.ts +453 -0
- package/src/operations/sync.ts +807 -0
- package/src/plugin.test.ts +40 -0
- package/src/plugin.ts +37 -0
- package/src/pull-request-body.test.ts +61 -0
- package/src/pull-request-body.ts +144 -0
- package/src/pull-request.test.ts +67 -0
- package/src/pull-request.ts +80 -0
- package/src/services/github-api.ts +735 -0
- package/src/services/index.ts +5 -0
- package/src/skills/GitHubSkill.ts +46 -0
- package/src/skills/index.ts +5 -0
- package/src/stories/Generate.stories.tsx +152 -0
- package/src/stories/Links.stories.tsx +153 -0
- package/src/stories/PullRequestArticle.stories.tsx +107 -0
- package/src/stories/PullRequestFiles.stories.tsx +69 -0
- package/src/stories/PullRequestOverview.stories.tsx +113 -0
- package/src/stories/PullRequestsArticle.stories.tsx +170 -0
- package/src/stories/Walkthrough.stories.tsx +110 -0
- package/src/stories/github.test.ts +65 -0
- package/src/stories/github.ts +70 -0
- package/src/stories/walkthrough-fixture.ts +115 -0
- package/src/testing/fixtures.ts +99 -0
- package/src/testing/index.ts +7 -0
- package/src/testing/plugin.ts +25 -0
- package/src/testing/pull-request-13348.ts +104 -0
- package/src/testing/pull-request-13363.patch +2981 -0
- package/src/translations.ts +135 -63
- package/src/types/GitHubCapabilities.ts +27 -0
- package/src/types/GitHubEvents.ts +16 -0
- package/src/types/GitHubOperation.ts +371 -0
- package/src/types/PullRequestsView.ts +45 -0
- package/src/types/Walkthrough.test.ts +75 -0
- package/src/types/Walkthrough.ts +66 -0
- package/src/types/index.ts +8 -0
- package/src/vite-env.d.ts +15 -0
- package/src/walkthrough/fill.test.ts +337 -0
- package/src/walkthrough/fill.ts +246 -0
- package/src/walkthrough/generate.test.ts +219 -0
- package/src/walkthrough/generate.ts +248 -0
- package/src/walkthrough/generated.test.ts +70 -0
- package/src/walkthrough/generated.ts +70 -0
- package/src/walkthrough/headings.test.ts +40 -0
- package/src/walkthrough/headings.ts +39 -0
- package/src/walkthrough/index.ts +12 -0
- package/src/walkthrough/patch.ts +154 -0
- package/src/walkthrough/plan.test.ts +178 -0
- package/src/walkthrough/plan.ts +251 -0
- package/src/walkthrough/prompt.test.ts +100 -0
- package/src/walkthrough/prompt.ts +147 -0
- package/src/walkthrough/score.test.ts +272 -0
- package/src/walkthrough/score.ts +430 -0
- package/README.md +0 -15
- package/dist/lib/browser/chunk-S4MPSBA5.mjs +0 -21
- package/dist/lib/browser/chunk-S4MPSBA5.mjs.map +0 -7
- package/dist/lib/browser/index.css +0 -7
- package/dist/lib/browser/index.css.map +0 -7
- package/dist/lib/browser/index.mjs +0 -1535
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/meta.mjs +0 -11
- package/dist/lib/browser/meta.mjs.map +0 -7
- package/dist/types/src/GithubPlugin.d.ts +0 -4
- package/dist/types/src/GithubPlugin.d.ts.map +0 -1
- package/dist/types/src/components/EmbeddedMain/EmbeddedMain.d.ts +0 -4
- package/dist/types/src/components/EmbeddedMain/EmbeddedMain.d.ts.map +0 -1
- package/dist/types/src/components/EmbeddedMain/GfmPreview.d.ts +0 -9
- package/dist/types/src/components/EmbeddedMain/GfmPreview.d.ts.map +0 -1
- package/dist/types/src/components/EmbeddedMain/index.d.ts +0 -2
- package/dist/types/src/components/EmbeddedMain/index.d.ts.map +0 -1
- package/dist/types/src/components/ExportDialog.d.ts +0 -8
- package/dist/types/src/components/ExportDialog.d.ts.map +0 -1
- package/dist/types/src/components/GithubApiProviders/GitHubSettings.d.ts +0 -3
- package/dist/types/src/components/GithubApiProviders/GitHubSettings.d.ts.map +0 -1
- package/dist/types/src/components/GithubApiProviders/OctokitProvider.d.ts +0 -15
- package/dist/types/src/components/GithubApiProviders/OctokitProvider.d.ts.map +0 -1
- package/dist/types/src/components/GithubApiProviders/index.d.ts +0 -3
- package/dist/types/src/components/GithubApiProviders/index.d.ts.map +0 -1
- package/dist/types/src/components/GithubEchoResolverProviders/DocumentTreeItem.d.ts +0 -6
- package/dist/types/src/components/GithubEchoResolverProviders/DocumentTreeItem.d.ts.map +0 -1
- package/dist/types/src/components/GithubEchoResolverProviders/ResolverContext.d.ts +0 -7
- package/dist/types/src/components/GithubEchoResolverProviders/ResolverContext.d.ts.map +0 -1
- package/dist/types/src/components/GithubEchoResolverProviders/ResolverDialog.d.ts +0 -6
- package/dist/types/src/components/GithubEchoResolverProviders/ResolverDialog.d.ts.map +0 -1
- package/dist/types/src/components/GithubEchoResolverProviders/ResolverProps.d.ts +0 -16
- package/dist/types/src/components/GithubEchoResolverProviders/ResolverProps.d.ts.map +0 -1
- package/dist/types/src/components/GithubEchoResolverProviders/ResolverTree.d.ts +0 -3
- package/dist/types/src/components/GithubEchoResolverProviders/ResolverTree.d.ts.map +0 -1
- package/dist/types/src/components/GithubEchoResolverProviders/SpacePickerTreeItem.d.ts +0 -11
- package/dist/types/src/components/GithubEchoResolverProviders/SpacePickerTreeItem.d.ts.map +0 -1
- package/dist/types/src/components/GithubEchoResolverProviders/index.d.ts +0 -3
- package/dist/types/src/components/GithubEchoResolverProviders/index.d.ts.map +0 -1
- package/dist/types/src/components/GithubEchoResolverProviders/spaceResolvers.d.ts +0 -6
- package/dist/types/src/components/GithubEchoResolverProviders/spaceResolvers.d.ts.map +0 -1
- package/dist/types/src/components/ImportDialog.d.ts +0 -7
- package/dist/types/src/components/ImportDialog.d.ts.map +0 -1
- package/dist/types/src/components/Issue.d.ts +0 -5
- package/dist/types/src/components/Issue.d.ts.map +0 -1
- package/dist/types/src/components/Loading/Loading.d.ts +0 -15
- package/dist/types/src/components/Loading/Loading.d.ts.map +0 -1
- package/dist/types/src/components/Loading/Loading.stories.d.ts +0 -40
- package/dist/types/src/components/Loading/Loading.stories.d.ts.map +0 -1
- package/dist/types/src/components/Loading/index.d.ts +0 -2
- package/dist/types/src/components/Loading/index.d.ts.map +0 -1
- package/dist/types/src/components/MarkdownActions.d.ts +0 -7
- package/dist/types/src/components/MarkdownActions.d.ts.map +0 -1
- package/dist/types/src/components/UrlDialog.d.ts +0 -6
- package/dist/types/src/components/UrlDialog.d.ts.map +0 -1
- package/dist/types/src/hooks/useDocGhId.d.ts +0 -6
- package/dist/types/src/hooks/useDocGhId.d.ts.map +0 -1
- package/dist/types/src/hooks/useGhIdFromUrl.d.ts +0 -2
- package/dist/types/src/hooks/useGhIdFromUrl.d.ts.map +0 -1
- package/dist/types/src/types.d.ts +0 -30
- package/dist/types/src/types.d.ts.map +0 -1
- package/src/GithubPlugin.tsx +0 -127
- package/src/components/EmbeddedMain/EmbeddedMain.tsx +0 -294
- package/src/components/EmbeddedMain/GfmPreview.tsx +0 -110
- package/src/components/EmbeddedMain/embedded.css +0 -3
- package/src/components/EmbeddedMain/index.ts +0 -5
- package/src/components/ExportDialog.tsx +0 -157
- package/src/components/GithubApiProviders/GitHubSettings.tsx +0 -72
- package/src/components/GithubApiProviders/OctokitProvider.tsx +0 -60
- package/src/components/GithubApiProviders/index.ts +0 -6
- package/src/components/GithubEchoResolverProviders/DocumentTreeItem.tsx +0 -26
- package/src/components/GithubEchoResolverProviders/ResolverContext.tsx +0 -137
- package/src/components/GithubEchoResolverProviders/ResolverDialog.tsx +0 -34
- package/src/components/GithubEchoResolverProviders/ResolverProps.ts +0 -23
- package/src/components/GithubEchoResolverProviders/ResolverTree.tsx +0 -86
- package/src/components/GithubEchoResolverProviders/SpacePickerTreeItem.tsx +0 -105
- package/src/components/GithubEchoResolverProviders/index.ts +0 -6
- package/src/components/GithubEchoResolverProviders/spaceResolvers.ts +0 -86
- package/src/components/ImportDialog.tsx +0 -72
- package/src/components/Issue.tsx +0 -62
- package/src/components/Loading/Loading.stories.tsx +0 -32
- package/src/components/Loading/Loading.tsx +0 -70
- package/src/components/Loading/index.ts +0 -5
- package/src/components/MarkdownActions.tsx +0 -136
- package/src/components/UrlDialog.tsx +0 -52
- package/src/hooks/useDocGhId.ts +0 -38
- package/src/hooks/useGhIdFromUrl.ts +0 -26
- package/src/types.ts +0 -51
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
|
|
7
|
+
import * as Progress from '@dxos/app-toolkit/Progress';
|
|
8
|
+
import { Database, Filter, Obj, Ref } from '@dxos/echo';
|
|
9
|
+
import { PullRequest } from '@dxos/types';
|
|
10
|
+
|
|
11
|
+
import { Walkthrough } from '#types';
|
|
12
|
+
|
|
13
|
+
import { fillWalkthrough } from './fill.ts';
|
|
14
|
+
import { isGeneratedFile } from './generated.ts';
|
|
15
|
+
import { spaceHeadings } from './headings.ts';
|
|
16
|
+
import { parsePatch } from './patch.ts';
|
|
17
|
+
import {
|
|
18
|
+
CHAPTER_SYSTEM_PROMPT,
|
|
19
|
+
DEFAULT_CHAPTER_THRESHOLD_CHARS,
|
|
20
|
+
PLANNER_SYSTEM_PROMPT,
|
|
21
|
+
assembleWalkthrough,
|
|
22
|
+
buildChapterPrompt,
|
|
23
|
+
buildPlannerPrompt,
|
|
24
|
+
chapterDiff,
|
|
25
|
+
parsePlan,
|
|
26
|
+
} from './plan.ts';
|
|
27
|
+
import { SYSTEM_PROMPT, buildPrompt } from './prompt.ts';
|
|
28
|
+
|
|
29
|
+
/** What the pull request looks like on GitHub right now, as against the local mirror of it. */
|
|
30
|
+
export type RemoteFacts = {
|
|
31
|
+
title?: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
baseBranch?: string;
|
|
34
|
+
headBranch?: string;
|
|
35
|
+
/** Head SHA. Absent means the walkthrough cannot be pinned to a commit, so it is always stale. */
|
|
36
|
+
commit?: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type GenerateOptions<R = never> = {
|
|
40
|
+
pullRequest: PullRequest.PullRequest;
|
|
41
|
+
remote: RemoteFacts;
|
|
42
|
+
/** The whole unified diff, which the chunks are filled from. */
|
|
43
|
+
diff: string;
|
|
44
|
+
/** Regenerate even where a walkthrough for this head already exists. */
|
|
45
|
+
force?: boolean;
|
|
46
|
+
/** Identifier recorded on the result, so a regression can be attributed after the default moves. */
|
|
47
|
+
model: string;
|
|
48
|
+
/**
|
|
49
|
+
* Runs the model over the prompt. Injected so the decision logic can be tested without one, and
|
|
50
|
+
* generic in its requirement so the model service it needs is DECLARED by the caller rather than
|
|
51
|
+
* quietly dropped — a requirement erased here is a defect at the first real invocation.
|
|
52
|
+
*/
|
|
53
|
+
narrate: (prompt: string) => Effect.Effect<string, never, R>;
|
|
54
|
+
/** Phase reporter; `current` counts against {@link GENERATE_PHASES}. */
|
|
55
|
+
report?: (message: string, current: number) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Diff size past which the walkthrough is planned into chapters and narrated a chapter at a time.
|
|
58
|
+
* Zero forces the two-stage path; `Infinity` forces the one-shot path.
|
|
59
|
+
*/
|
|
60
|
+
chapterThresholdChars?: number;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export type GenerateResult = {
|
|
64
|
+
walkthrough: Walkthrough.Walkthrough;
|
|
65
|
+
/** How the body was written: one prompt, or a plan plus a prompt per chapter. */
|
|
66
|
+
strategy?: 'one-shot' | 'chaptered';
|
|
67
|
+
/** Whether the model ran, as against an existing walkthrough being returned unchanged. */
|
|
68
|
+
generated: boolean;
|
|
69
|
+
covered: number;
|
|
70
|
+
total: number;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/** Phases a caller's progress meter counts, so it is determinate rather than a spinner. */
|
|
74
|
+
export const GENERATE_PHASES = 5;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Decides whether to regenerate, runs the model, fills the chunks, and stores the result.
|
|
78
|
+
*
|
|
79
|
+
* Split from the operation handler so the part with the decisions in it can be tested against a real
|
|
80
|
+
* database without a network or a model: what the handler adds is two HTTP calls.
|
|
81
|
+
*/
|
|
82
|
+
export const generateWalkthrough = <R = never>({
|
|
83
|
+
pullRequest,
|
|
84
|
+
remote,
|
|
85
|
+
diff,
|
|
86
|
+
force,
|
|
87
|
+
model,
|
|
88
|
+
narrate,
|
|
89
|
+
report = () => {},
|
|
90
|
+
chapterThresholdChars = DEFAULT_CHAPTER_THRESHOLD_CHARS,
|
|
91
|
+
}: GenerateOptions<R>): Effect.Effect<GenerateResult, never, Database.Service | R> =>
|
|
92
|
+
Effect.gen(function* () {
|
|
93
|
+
const existing = yield* findWalkthrough(pullRequest);
|
|
94
|
+
|
|
95
|
+
// Regenerating against the same head cannot change the answer, so it is only work.
|
|
96
|
+
if (existing && !force && remote.commit && !Walkthrough.isStale(existing, remote.commit)) {
|
|
97
|
+
report(Progress.STATUS_COMPLETE, GENERATE_PHASES);
|
|
98
|
+
return {
|
|
99
|
+
walkthrough: existing,
|
|
100
|
+
generated: false,
|
|
101
|
+
covered: existing.covered ?? 0,
|
|
102
|
+
total: existing.total ?? 0,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
report('Writing the walkthrough', 3);
|
|
107
|
+
const facts = {
|
|
108
|
+
owner: pullRequest.owner,
|
|
109
|
+
repo: pullRequest.repo,
|
|
110
|
+
number: pullRequest.number,
|
|
111
|
+
title: remote.title ?? pullRequest.title,
|
|
112
|
+
description: remote.description ?? pullRequest.description,
|
|
113
|
+
baseBranch: remote.baseBranch ?? pullRequest.baseBranch,
|
|
114
|
+
headBranch: remote.headBranch ?? pullRequest.headBranch,
|
|
115
|
+
};
|
|
116
|
+
const chaptered =
|
|
117
|
+
diff.length > chapterThresholdChars ? yield* narrateChapters(facts, diff, narrate, report) : undefined;
|
|
118
|
+
const narration = chaptered ?? (yield* narrate(`${SYSTEM_PROMPT}\n\n---\n\n${buildPrompt({ ...facts, diff })}`));
|
|
119
|
+
|
|
120
|
+
report('Filling the chunks', 4);
|
|
121
|
+
const filled = fillWalkthrough(narration, diff);
|
|
122
|
+
const walkthrough = yield* upsert(existing, {
|
|
123
|
+
pullRequest: Ref.make(pullRequest),
|
|
124
|
+
title: Walkthrough.makeTitle(pullRequest, remote.title ?? pullRequest.title),
|
|
125
|
+
body: spaceHeadings(filled.body),
|
|
126
|
+
commit: remote.commit ?? '',
|
|
127
|
+
generatedAt: new Date().toISOString(),
|
|
128
|
+
model,
|
|
129
|
+
covered: filled.covered,
|
|
130
|
+
total: filled.total,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
report(Progress.STATUS_COMPLETE, GENERATE_PHASES);
|
|
134
|
+
return {
|
|
135
|
+
walkthrough,
|
|
136
|
+
strategy: chaptered ? ('chaptered' as const) : ('one-shot' as const),
|
|
137
|
+
generated: true,
|
|
138
|
+
covered: filled.covered,
|
|
139
|
+
total: filled.total,
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Plans the chapters, then narrates each one against its own files.
|
|
145
|
+
*
|
|
146
|
+
* Returns undefined when the plan cannot be read, so the caller falls back to one prompt rather
|
|
147
|
+
* than failing: a walkthrough of part of the change beats no walkthrough.
|
|
148
|
+
*/
|
|
149
|
+
const narrateChapters = <R>(
|
|
150
|
+
facts: Parameters<typeof buildPlannerPrompt>[0],
|
|
151
|
+
diff: string,
|
|
152
|
+
narrate: (prompt: string) => Effect.Effect<string, never, R>,
|
|
153
|
+
report: (message: string, current: number) => void,
|
|
154
|
+
): Effect.Effect<string | undefined, never, R> =>
|
|
155
|
+
Effect.gen(function* () {
|
|
156
|
+
const files = parsePatch(diff).filter((file) => !isGeneratedFile(file));
|
|
157
|
+
const planned = yield* narrate(`${PLANNER_SYSTEM_PROMPT}\n\n---\n\n${buildPlannerPrompt(facts, diff)}`);
|
|
158
|
+
const plan = parsePlan(
|
|
159
|
+
planned,
|
|
160
|
+
files.map((file) => file.path),
|
|
161
|
+
);
|
|
162
|
+
if (!plan) {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const chapters: string[] = [];
|
|
167
|
+
for (const chapter of plan.chapters) {
|
|
168
|
+
report(`Writing "${chapter.title}"`, 3);
|
|
169
|
+
// Serial rather than concurrent: a chapter is written against a document the reader meets in
|
|
170
|
+
// order, and the model's own rate limit is the binding constraint on a large change anyway.
|
|
171
|
+
const body = yield* narrate(
|
|
172
|
+
`${CHAPTER_SYSTEM_PROMPT}\n\n---\n\n${buildChapterPrompt(plan, chapter, chapterDiff(files, chapter))}`,
|
|
173
|
+
);
|
|
174
|
+
chapters.push(body);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return assembleWalkthrough(plan, chapters);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
/** The walkthrough already written for this pull request, if any. */
|
|
181
|
+
export const findWalkthrough = (
|
|
182
|
+
pullRequest: PullRequest.PullRequest,
|
|
183
|
+
): Effect.Effect<Walkthrough.Walkthrough | undefined, never, Database.Service> =>
|
|
184
|
+
Database.query(Filter.type(Walkthrough.Walkthrough, { pullRequest: Ref.make(pullRequest) })).run.pipe(
|
|
185
|
+
// Filtered by the ref rather than by loading every walkthrough and comparing: a space holds one
|
|
186
|
+
// per reviewed pull request, which is not a handful.
|
|
187
|
+
Effect.map(newestWalkthrough),
|
|
188
|
+
Effect.orDie,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* The newest of however many were written, ties broken by id.
|
|
193
|
+
*
|
|
194
|
+
* Two generations racing on one pull request both see none and both add: the check and the write
|
|
195
|
+
* are separate steps, and ECHO has neither a uniqueness constraint nor an atomic upsert to close
|
|
196
|
+
* that. Picking deterministically makes the duplicate inert instead — every reader lands on the
|
|
197
|
+
* same object, and the next regeneration updates that one in place rather than forking again. The
|
|
198
|
+
* loser stays in the space; removing it from a read path would delete another client's object.
|
|
199
|
+
*/
|
|
200
|
+
export const newestWalkthrough = (
|
|
201
|
+
walkthroughs: readonly Walkthrough.Walkthrough[],
|
|
202
|
+
): Walkthrough.Walkthrough | undefined =>
|
|
203
|
+
walkthroughs.reduce<Walkthrough.Walkthrough | undefined>((newest, walkthrough) => {
|
|
204
|
+
if (!newest) {
|
|
205
|
+
return walkthrough;
|
|
206
|
+
}
|
|
207
|
+
const left = generatedTime(walkthrough);
|
|
208
|
+
const right = generatedTime(newest);
|
|
209
|
+
if (left !== right) {
|
|
210
|
+
return left > right ? walkthrough : newest;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// The id is a ULID, so it is fixed width and orders the same on every peer.
|
|
214
|
+
return walkthrough.id > newest.id ? walkthrough : newest;
|
|
215
|
+
}, undefined);
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Parsed rather than compared as a string: `generatedAt` is an unvalidated date-time, so a value
|
|
219
|
+
* written by anything but this code can carry an offset (`+02:00`) that sorts against a `Z` value
|
|
220
|
+
* the wrong way round. An unparseable or absent one sorts oldest.
|
|
221
|
+
*/
|
|
222
|
+
const generatedTime = (walkthrough: Walkthrough.Walkthrough): number => {
|
|
223
|
+
const parsed = Date.parse(walkthrough.generatedAt ?? '');
|
|
224
|
+
return Number.isNaN(parsed) ? Number.NEGATIVE_INFINITY : parsed;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/** Replaces the body in place where one exists, so links to the walkthrough survive regeneration. */
|
|
228
|
+
const upsert = (
|
|
229
|
+
existing: Walkthrough.Walkthrough | undefined,
|
|
230
|
+
props: Obj.MakeProps<typeof Walkthrough.Walkthrough>,
|
|
231
|
+
): Effect.Effect<Walkthrough.Walkthrough, never, Database.Service> =>
|
|
232
|
+
Effect.gen(function* () {
|
|
233
|
+
if (!existing) {
|
|
234
|
+
return yield* Database.add(Walkthrough.make(props));
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// One notification for the whole replacement, rather than six — a subscriber re-rendering the
|
|
238
|
+
// document between the body and the commit would show one against the other.
|
|
239
|
+
return Obj.update(existing, (existing) => {
|
|
240
|
+
existing.title = props.title;
|
|
241
|
+
existing.body = props.body;
|
|
242
|
+
existing.commit = props.commit;
|
|
243
|
+
existing.generatedAt = props.generatedAt;
|
|
244
|
+
existing.model = props.model;
|
|
245
|
+
existing.covered = props.covered;
|
|
246
|
+
existing.total = props.total;
|
|
247
|
+
});
|
|
248
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { isBinaryPatch, isGeneratedFile, isGeneratedPath } from './generated.ts';
|
|
8
|
+
|
|
9
|
+
describe('isGeneratedPath', () => {
|
|
10
|
+
test.each([
|
|
11
|
+
'pnpm-lock.yaml',
|
|
12
|
+
'apps/site/package-lock.json',
|
|
13
|
+
'yarn.lock',
|
|
14
|
+
'Cargo.lock',
|
|
15
|
+
'go.sum',
|
|
16
|
+
'packages/core/dist/index.js',
|
|
17
|
+
'packages/core/build/bundle.css',
|
|
18
|
+
'coverage/lcov-report/index.html',
|
|
19
|
+
'vendor/lib/thing.ts',
|
|
20
|
+
'src/__snapshots__/render.test.ts',
|
|
21
|
+
'public/app.min.js',
|
|
22
|
+
'public/app.min.css',
|
|
23
|
+
'dist-info/bundle.js.map',
|
|
24
|
+
'src/render.test.ts.snap',
|
|
25
|
+
'src/types/index.d.ts',
|
|
26
|
+
'src/proto/service_pb.ts',
|
|
27
|
+
'src/proto/service.pb.go',
|
|
28
|
+
'src/proto/service_pb2.py',
|
|
29
|
+
'src/schema.gen.ts',
|
|
30
|
+
'src/theme.generated.css',
|
|
31
|
+
'assets/logo.png',
|
|
32
|
+
'assets/font.woff2',
|
|
33
|
+
'fixtures/archive.tar.gz',
|
|
34
|
+
'bin/tool.wasm',
|
|
35
|
+
'.changeset/wild-pans-argue.md',
|
|
36
|
+
'packages/thing/.changeset/quiet-moons.md',
|
|
37
|
+
])('%s is generated', (path) => {
|
|
38
|
+
expect(isGeneratedPath(path)).to.be.true;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test.each([
|
|
42
|
+
'src/index.ts',
|
|
43
|
+
'packages/core/src/query/compile.ts',
|
|
44
|
+
'docs/DESIGN.md',
|
|
45
|
+
'src/components/Button.tsx',
|
|
46
|
+
// Near misses: a file is not generated because its name contains a generated word.
|
|
47
|
+
'src/distribution.ts',
|
|
48
|
+
'src/generated-ids.ts',
|
|
49
|
+
'src/build-plan.ts',
|
|
50
|
+
'scripts/lockfile-audit.ts',
|
|
51
|
+
])('%s is not generated', (path) => {
|
|
52
|
+
expect(isGeneratedPath(path)).to.be.false;
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('isBinaryPatch', () => {
|
|
57
|
+
test('reads git’s own markers', () => {
|
|
58
|
+
expect(isBinaryPatch(['Binary files a/x.dat and b/x.dat differ'])).to.be.true;
|
|
59
|
+
expect(isBinaryPatch(['GIT binary patch', 'literal 1234'])).to.be.true;
|
|
60
|
+
expect(isBinaryPatch(['index 111..222 100644', '--- a/src/a.ts', '+++ b/src/a.ts'])).to.be.false;
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('isGeneratedFile', () => {
|
|
65
|
+
test('catches a binary the extension does not announce', () => {
|
|
66
|
+
// A file with no extension at all, which only the patch shape gives away.
|
|
67
|
+
expect(isGeneratedFile({ path: 'fixtures/corpus', preamble: ['Binary files a/x and b/x differ'] })).to.be.true;
|
|
68
|
+
expect(isGeneratedFile({ path: 'src/index.ts', preamble: ['index 111..222 100644'] })).to.be.false;
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Files a reviewer does not read, and a walkthrough should not spend prose or a fence on: machine
|
|
7
|
+
* output, vendored blobs, and anything whose diff is a consequence of another file in the same
|
|
8
|
+
* change.
|
|
9
|
+
*
|
|
10
|
+
* Detection is by path and by patch shape rather than by a `.gitattributes` lookup, because the
|
|
11
|
+
* walkthrough only ever has the patch.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Lockfiles: the largest hunk in most pull requests and the one nobody reads. */
|
|
15
|
+
const LOCKFILES = [
|
|
16
|
+
'pnpm-lock.yaml',
|
|
17
|
+
'package-lock.json',
|
|
18
|
+
'yarn.lock',
|
|
19
|
+
'bun.lockb',
|
|
20
|
+
'npm-shrinkwrap.json',
|
|
21
|
+
'Cargo.lock',
|
|
22
|
+
'poetry.lock',
|
|
23
|
+
'composer.lock',
|
|
24
|
+
'Gemfile.lock',
|
|
25
|
+
'go.sum',
|
|
26
|
+
'flake.lock',
|
|
27
|
+
'uv.lock',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
/** Directories whose contents are built, vendored or cached rather than written. */
|
|
31
|
+
const GENERATED_DIRECTORIES = /(^|\/)(dist|build|out|coverage|node_modules|vendor|__snapshots__|\.turbo)\//;
|
|
32
|
+
|
|
33
|
+
/** Suffixes that are compiled, minified, generated from a schema, or not text at all. */
|
|
34
|
+
const GENERATED_SUFFIX =
|
|
35
|
+
/(\.min\.(js|css)|\.map|\.snap|\.d\.ts|[._-]pb\.(ts|js)|\.pb\.go|_pb2\.py|\.gen\.(ts|js|go)|\.generated\.[a-z]+)$/i;
|
|
36
|
+
|
|
37
|
+
/** Binary by extension. A patch shows these as "Binary files … differ", with nothing to read. */
|
|
38
|
+
const BINARY_SUFFIX =
|
|
39
|
+
/\.(png|jpe?g|gif|webp|avif|ico|icns|bmp|tiff?|svgz|pdf|woff2?|ttf|otf|eot|zip|gz|tgz|bz2|xz|7z|rar|wasm|so|dylib|dll|exe|bin|dat|db|sqlite3?|mp[34]|mov|mp4|webm|wav|ogg|jar|class|pyc|node)$/i;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Whether a path is machine-written or unreadable.
|
|
43
|
+
*
|
|
44
|
+
* `.changeset/` entries count: the changeset is a consequence of the change the walkthrough already
|
|
45
|
+
* describes, and a section about it tells the reader nothing the rest of the document did not.
|
|
46
|
+
*/
|
|
47
|
+
export const isGeneratedPath = (path: string): boolean => {
|
|
48
|
+
const name = path.split('/').pop() ?? path;
|
|
49
|
+
return (
|
|
50
|
+
LOCKFILES.includes(name) ||
|
|
51
|
+
GENERATED_DIRECTORIES.test(path) ||
|
|
52
|
+
GENERATED_SUFFIX.test(path) ||
|
|
53
|
+
BINARY_SUFFIX.test(path) ||
|
|
54
|
+
path.startsWith('.changeset/') ||
|
|
55
|
+
path.includes('/.changeset/')
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/** A file git could not diff as text, whatever its extension says. */
|
|
60
|
+
export const isBinaryPatch = (preamble: readonly string[]): boolean =>
|
|
61
|
+
preamble.some((line) => line.startsWith('Binary files ') || line.startsWith('GIT binary patch'));
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Whether this file is one the walkthrough should leave alone.
|
|
65
|
+
*
|
|
66
|
+
* A hunk count of zero is NOT generated on its own: a rename or a mode change is still a change a
|
|
67
|
+
* reviewer has to know about, and {@link fillWalkthrough} reports it separately.
|
|
68
|
+
*/
|
|
69
|
+
export const isGeneratedFile = (file: { path: string; preamble: readonly string[] }): boolean =>
|
|
70
|
+
isGeneratedPath(file.path) || isBinaryPatch(file.preamble);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { spaceHeadings } from './headings.ts';
|
|
8
|
+
|
|
9
|
+
describe('spaceHeadings', () => {
|
|
10
|
+
test('separates a heading from the paragraph above it', () => {
|
|
11
|
+
expect(spaceHeadings('First.\n## Schema: Task gains attachments\nBody.')).to.equal(
|
|
12
|
+
'First.\n\n## Schema: Task gains attachments\nBody.',
|
|
13
|
+
);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('leaves an already separated heading and a leading heading alone', () => {
|
|
17
|
+
const markdown = '# Title\n\nWhy.\n\n## One\n\nFirst.\n';
|
|
18
|
+
expect(spaceHeadings(markdown)).to.equal(markdown);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('ignores hash lines inside a code fence', () => {
|
|
22
|
+
const markdown = 'Prose.\n\n```diff file=a.sh\n+echo\n# a shell comment\n```\n';
|
|
23
|
+
expect(spaceHeadings(markdown)).to.equal(markdown);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('a fence line with an info string does not close the fence', () => {
|
|
27
|
+
const markdown = 'Prose.\n\n```md\nText.\n```ts\n# still code\n```\nAfter.\n## Next\n';
|
|
28
|
+
expect(spaceHeadings(markdown)).to.equal('Prose.\n\n```md\nText.\n```ts\n# still code\n```\nAfter.\n\n## Next\n');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('reads CRLF lines, and keeps their line endings', () => {
|
|
32
|
+
const markdown = 'Prose.\r\n\r\n```\r\ncode\r\n```\r\nAfter.\r\n## Next\r\n';
|
|
33
|
+
expect(spaceHeadings(markdown)).to.equal('Prose.\r\n\r\n```\r\ncode\r\n```\r\nAfter.\r\n\r\n## Next\r\n');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('does not treat a hashtag as a heading', () => {
|
|
37
|
+
const markdown = 'Prose.\n#hashtag';
|
|
38
|
+
expect(spaceHeadings(markdown)).to.equal(markdown);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
const FENCE = /^\s{0,3}(`{3,}|~{3,})/;
|
|
6
|
+
/** A closing fence carries nothing after its marker: a line with an info string only opens one. */
|
|
7
|
+
const CLOSING_FENCE = /^\s{0,3}(`{3,}|~{3,})[ \t]*$/;
|
|
8
|
+
const HEADING = /^\s{0,3}#{1,6}(\s|$)/;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Puts a blank line before every heading outside a code fence.
|
|
12
|
+
*
|
|
13
|
+
* A heading may legally interrupt a paragraph, so the model and the chapter join both emit one on
|
|
14
|
+
* the very next line — which the walkthrough's source-level editor shows flush against the prose.
|
|
15
|
+
*/
|
|
16
|
+
export const spaceHeadings = (markdown: string): string => {
|
|
17
|
+
const lines = markdown.split('\n');
|
|
18
|
+
const result: string[] = [];
|
|
19
|
+
let fence: string | undefined;
|
|
20
|
+
for (const line of lines) {
|
|
21
|
+
// Split on `\n` alone, so a CRLF line keeps its `\r`: matched without it, written back with it.
|
|
22
|
+
const crlf = line.endsWith('\r');
|
|
23
|
+
const text = crlf ? line.slice(0, -1) : line;
|
|
24
|
+
const marker = text.match(FENCE)?.[1];
|
|
25
|
+
if (fence) {
|
|
26
|
+
const closer = text.match(CLOSING_FENCE)?.[1];
|
|
27
|
+
if (closer && closer[0] === fence[0] && closer.length >= fence.length) {
|
|
28
|
+
fence = undefined;
|
|
29
|
+
}
|
|
30
|
+
} else if (marker) {
|
|
31
|
+
fence = marker;
|
|
32
|
+
} else if (HEADING.test(text) && result.length > 0 && result[result.length - 1].trim() !== '') {
|
|
33
|
+
result.push(crlf ? '\r' : '');
|
|
34
|
+
}
|
|
35
|
+
result.push(line);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return result.join('\n');
|
|
39
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
export * from './fill.ts';
|
|
6
|
+
export * from './generate.ts';
|
|
7
|
+
export * from './generated.ts';
|
|
8
|
+
export * from './headings.ts';
|
|
9
|
+
export * from './patch.ts';
|
|
10
|
+
export * from './plan.ts';
|
|
11
|
+
export * from './prompt.ts';
|
|
12
|
+
export * from './score.ts';
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
/** A `@@` hunk, kept as the verbatim lines git emitted so filling a chunk is lossless. */
|
|
6
|
+
export type PatchHunk = {
|
|
7
|
+
/** The `@@ -a,b +c,d @@ section` line. */
|
|
8
|
+
header: string;
|
|
9
|
+
/** Body lines (context, additions, removals), without the header. */
|
|
10
|
+
lines: string[];
|
|
11
|
+
/** 1-based inclusive span in the file AFTER the change; `afterEnd < afterStart` for a pure removal. */
|
|
12
|
+
afterStart: number;
|
|
13
|
+
afterEnd: number;
|
|
14
|
+
/** The same span in the file BEFORE it, which is all a pure removal has. */
|
|
15
|
+
beforeStart: number;
|
|
16
|
+
beforeEnd: number;
|
|
17
|
+
added: number;
|
|
18
|
+
removed: number;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type PatchFile = {
|
|
22
|
+
/** Path after the change, or the pre-image path when the file was deleted. */
|
|
23
|
+
path: string;
|
|
24
|
+
/** Headers git emitted before the first hunk (`diff --git`, `index`, `---`, `+++`). */
|
|
25
|
+
preamble: string[];
|
|
26
|
+
hunks: PatchHunk[];
|
|
27
|
+
added: number;
|
|
28
|
+
removed: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const FILE_HEADER = /^diff --git a\/(.+?) b\/(.+)$/;
|
|
32
|
+
const HUNK_HEADER = /^@@+\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@/;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Splits a multi-file unified diff — what `GET /repos/…/pulls/N` returns under the `diff` media type
|
|
36
|
+
* — into files and hunks. Hunk bodies are carried verbatim rather than re-derived, so a chunk filled
|
|
37
|
+
* from one is byte-identical to what git produced.
|
|
38
|
+
*/
|
|
39
|
+
export const parsePatch = (patch: string): PatchFile[] => {
|
|
40
|
+
const files: PatchFile[] = [];
|
|
41
|
+
let file: PatchFile | undefined;
|
|
42
|
+
let hunk: PatchHunk | undefined;
|
|
43
|
+
|
|
44
|
+
for (const raw of patch.split('\n')) {
|
|
45
|
+
// A patch saved or served with CRLF keeps its carriage returns, and every match below is
|
|
46
|
+
// anchored: left in place they make the whole parse return nothing at all.
|
|
47
|
+
const line = raw.endsWith('\r') ? raw.slice(0, -1) : raw;
|
|
48
|
+
const header = FILE_HEADER.exec(line);
|
|
49
|
+
if (header) {
|
|
50
|
+
// `b/` is the post-image path and is `/dev/null` only in the `+++` line, never here.
|
|
51
|
+
file = { path: header[2], preamble: [line], hunks: [], added: 0, removed: 0 };
|
|
52
|
+
files.push(file);
|
|
53
|
+
hunk = undefined;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (!file) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const hunkHeader = HUNK_HEADER.exec(line);
|
|
61
|
+
if (hunkHeader) {
|
|
62
|
+
const beforeStart = Number(hunkHeader[1]);
|
|
63
|
+
const beforeCount = hunkHeader[2] === undefined ? 1 : Number(hunkHeader[2]);
|
|
64
|
+
const afterStart = Number(hunkHeader[3]);
|
|
65
|
+
const afterCount = hunkHeader[4] === undefined ? 1 : Number(hunkHeader[4]);
|
|
66
|
+
hunk = {
|
|
67
|
+
header: line,
|
|
68
|
+
lines: [],
|
|
69
|
+
afterStart,
|
|
70
|
+
afterEnd: afterStart + afterCount - 1,
|
|
71
|
+
beforeStart,
|
|
72
|
+
beforeEnd: beforeStart + beforeCount - 1,
|
|
73
|
+
added: 0,
|
|
74
|
+
removed: 0,
|
|
75
|
+
};
|
|
76
|
+
file.hunks.push(hunk);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!hunk) {
|
|
81
|
+
file.preamble.push(line);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// `` annotates the preceding line and is not a line of either version.
|
|
86
|
+
if (line.startsWith('\\')) {
|
|
87
|
+
hunk.lines.push(line);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (line.startsWith('+')) {
|
|
91
|
+
hunk.added++;
|
|
92
|
+
file.added++;
|
|
93
|
+
} else if (line.startsWith('-')) {
|
|
94
|
+
hunk.removed++;
|
|
95
|
+
file.removed++;
|
|
96
|
+
}
|
|
97
|
+
hunk.lines.push(line);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Only the LAST hunk of the LAST file can carry the transport's trailing newline, and only one of
|
|
101
|
+
// them: a blank line anywhere else is context the chunk has to keep showing.
|
|
102
|
+
const trailing = files.at(-1)?.hunks.at(-1);
|
|
103
|
+
if (trailing?.lines.at(-1) === '') {
|
|
104
|
+
trailing.lines.pop();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// A patch may name one path twice (a rename reported as delete-then-add, a malformed paste). Their
|
|
108
|
+
// hunks belong to one file, or the second silently hides the first from every fence.
|
|
109
|
+
const merged = new Map<string, PatchFile>();
|
|
110
|
+
for (const file of files) {
|
|
111
|
+
const existing = merged.get(file.path);
|
|
112
|
+
if (existing) {
|
|
113
|
+
existing.hunks.push(...file.hunks);
|
|
114
|
+
existing.added += file.added;
|
|
115
|
+
existing.removed += file.removed;
|
|
116
|
+
} else {
|
|
117
|
+
merged.set(file.path, file);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return [...merged.values()];
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/** The hunk text a diff fence holds: the `@@` header and its body, as git wrote them. */
|
|
125
|
+
export const renderHunks = (hunks: PatchHunk[]): string =>
|
|
126
|
+
hunks.map((hunk) => [hunk.header, ...hunk.lines].join('\n')).join('\n');
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Whether a hunk shows any of `[start, end]` of the post-change file.
|
|
130
|
+
*
|
|
131
|
+
* A pure removal spans nothing after the change (`afterEnd === afterStart - 1`), so it is treated as
|
|
132
|
+
* occupying the single position the lines were removed from — otherwise no range could ever select
|
|
133
|
+
* it, including the one this module's own {@link hunkRange} reports for it.
|
|
134
|
+
*/
|
|
135
|
+
export const hunkOverlaps = (hunk: PatchHunk, start: number, end: number): boolean =>
|
|
136
|
+
hunk.afterStart <= end && Math.max(hunk.afterEnd, hunk.afterStart) >= start;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* The span a set of hunks covers, for a fence's `lines=` attribute.
|
|
140
|
+
*
|
|
141
|
+
* Measured after the change, except where nothing survives it: a deleted file's post-image is empty
|
|
142
|
+
* and would otherwise read as `Lines 0`, so its range is quoted from the pre-image instead.
|
|
143
|
+
*/
|
|
144
|
+
export const hunkRange = (hunks: PatchHunk[]): string | undefined => {
|
|
145
|
+
if (hunks.length === 0) {
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
const survives = hunks.some((hunk) => hunk.afterEnd >= hunk.afterStart);
|
|
149
|
+
const start = Math.min(...hunks.map((hunk) => (survives ? hunk.afterStart : hunk.beforeStart)));
|
|
150
|
+
// `afterStart` for a pure removal, as `hunkOverlaps` does: its `afterEnd` is one BELOW its start,
|
|
151
|
+
// so a set mixing one with a live hunk would end the range before the removal it contains.
|
|
152
|
+
const end = Math.max(...hunks.map((hunk) => (survives ? Math.max(hunk.afterEnd, hunk.afterStart) : hunk.beforeEnd)));
|
|
153
|
+
return start >= end ? `${start}` : `${start}-${end}`;
|
|
154
|
+
};
|