@dxos/plugin-github 0.14.0 → 0.16.0-next-60712ab191a99ba90316cc4be753e9e11b17100a

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 (86) hide show
  1. package/dist/lib/GitHubCapabilities.mjs +1 -10
  2. package/dist/lib/GitHubEvents.mjs +1 -15
  3. package/dist/lib/GitHubOperation.mjs +1 -384
  4. package/dist/lib/GitHubPlugin.mjs +1 -16
  5. package/dist/lib/Walkthrough.mjs +1 -59
  6. package/dist/lib/capabilities.browser.mjs +1 -2
  7. package/dist/lib/capabilities.browser.mjs.map +1 -1
  8. package/dist/lib/capabilities.mjs +1 -2
  9. package/dist/lib/capabilities.mjs.map +1 -1
  10. package/dist/lib/capabilities.tauri.mjs +1 -2
  11. package/dist/lib/capabilities.tauri.mjs.map +1 -1
  12. package/dist/lib/chunk-Extensions.mjs +18 -0
  13. package/dist/lib/chunk-Extensions.mjs.map +1 -0
  14. package/dist/lib/chunk-GitHubCapabilities.mjs +10 -0
  15. package/dist/lib/chunk-GitHubCapabilities.mjs.map +1 -0
  16. package/dist/lib/chunk-GitHubEvents.mjs +15 -0
  17. package/dist/lib/chunk-GitHubEvents.mjs.map +1 -0
  18. package/dist/lib/chunk-GitHubOperation.mjs +386 -0
  19. package/dist/lib/chunk-GitHubOperation.mjs.map +1 -0
  20. package/dist/lib/chunk-GitHubPlugin.mjs +16 -0
  21. package/dist/lib/chunk-GitHubPlugin.mjs.map +1 -0
  22. package/dist/lib/chunk-ImportPullRequestDialog.mjs.map +1 -1
  23. package/dist/lib/chunk-PLUGIN.mjs +1 -1
  24. package/dist/lib/chunk-PullRequestArticle.mjs +33 -10
  25. package/dist/lib/chunk-PullRequestArticle.mjs.map +1 -1
  26. package/dist/lib/chunk-PullRequestArticle2.mjs +1 -2
  27. package/dist/lib/chunk-PullRequestCardMenu.mjs +1 -1
  28. package/dist/lib/chunk-PullRequestsArticle.mjs +3 -3
  29. package/dist/lib/chunk-PullRequestsArticle.mjs.map +1 -1
  30. package/dist/lib/chunk-Walkthrough.mjs +59 -0
  31. package/dist/lib/chunk-Walkthrough.mjs.map +1 -0
  32. package/dist/lib/chunk-WalkthroughArticle.mjs +1 -1
  33. package/dist/lib/chunk-add-pull-request-comment.mjs.map +1 -1
  34. package/dist/lib/chunk-add-pull-request-review-comment.mjs.map +1 -1
  35. package/dist/lib/chunk-connector.mjs.map +1 -1
  36. package/dist/lib/chunk-generate-walkthrough.mjs.map +1 -1
  37. package/dist/lib/chunk-get-pull-request-diff.mjs.map +1 -1
  38. package/dist/lib/chunk-get-pull-request-status.mjs.map +1 -1
  39. package/dist/lib/chunk-get-repositories.mjs.map +1 -1
  40. package/dist/lib/chunk-github-api.mjs +1 -0
  41. package/dist/lib/chunk-github-api.mjs.map +1 -1
  42. package/dist/lib/chunk-import-pull-request.mjs.map +1 -1
  43. package/dist/lib/chunk-link-resolver.mjs.map +1 -1
  44. package/dist/lib/chunk-pull-request2.mjs +1 -0
  45. package/dist/lib/chunk-pull-request2.mjs.map +1 -1
  46. package/dist/lib/chunk-react-surface.mjs +4 -4
  47. package/dist/lib/chunk-react-surface.mjs.map +1 -1
  48. package/dist/lib/chunk-submit-pull-request-approval.mjs.map +1 -1
  49. package/dist/lib/chunk-sync.mjs.map +1 -1
  50. package/dist/lib/index.mjs +2 -2
  51. package/dist/lib/meta.mjs.map +1 -1
  52. package/dist/lib/ns/Extensions.mjs +2 -16
  53. package/dist/lib/types.mjs +4 -4
  54. package/dist/types/src/capabilities/gen/browser.d.ts.map +1 -1
  55. package/dist/types/src/capabilities/gen/tauri.d.ts.map +1 -1
  56. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  57. package/dist/types/src/cards/GitHubCard.d.ts.map +1 -1
  58. package/dist/types/src/components/PullRequestOverview/CheckRunList.d.ts +1 -1
  59. package/dist/types/src/components/PullRequestOverview/CheckRunList.d.ts.map +1 -1
  60. package/dist/types/src/components/PullRequestOverview/PullRequestOverview.d.ts.map +1 -1
  61. package/dist/types/src/operations/pull-request.d.ts.map +1 -1
  62. package/dist/types/src/services/github-api.d.ts +1 -0
  63. package/dist/types/src/services/github-api.d.ts.map +1 -1
  64. package/dist/types/src/stories/PullRequestOverview.stories.d.ts +2 -0
  65. package/dist/types/src/stories/PullRequestOverview.stories.d.ts.map +1 -1
  66. package/dist/types/src/types/GitHubOperation.d.ts +3 -0
  67. package/dist/types/src/types/GitHubOperation.d.ts.map +1 -1
  68. package/dist/types/tsconfig.tsbuildinfo +1 -1
  69. package/package.json +47 -47
  70. package/src/capabilities/gen/browser.ts +1 -3
  71. package/src/capabilities/gen/tauri.ts +1 -3
  72. package/src/capabilities/index.ts +1 -4
  73. package/src/cards/GitHubCard.tsx +7 -3
  74. package/src/components/PullRequestOverview/CheckRunList.tsx +34 -6
  75. package/src/components/PullRequestOverview/PullRequestOverview.tsx +5 -1
  76. package/src/containers/PullRequestsArticle/PullRequestsArticle.tsx +12 -10
  77. package/src/operations/pull-request.ts +1 -0
  78. package/src/services/github-api.ts +1 -0
  79. package/src/stories/PullRequestOverview.stories.tsx +20 -0
  80. package/src/types/GitHubOperation.ts +2 -0
  81. package/dist/lib/GitHubCapabilities.mjs.map +0 -1
  82. package/dist/lib/GitHubEvents.mjs.map +0 -1
  83. package/dist/lib/GitHubOperation.mjs.map +0 -1
  84. package/dist/lib/GitHubPlugin.mjs.map +0 -1
  85. package/dist/lib/Walkthrough.mjs.map +0 -1
  86. package/dist/lib/ns/Extensions.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-GitHubCapabilities.mjs","names":[],"sources":["../../src/types/GitHubCapabilities.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport type * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport type * as PreviewCapabilities from '@dxos/plugin-preview/PreviewCapabilities';\nimport { type Issue, type PullRequest, type Repo } from '@dxos/types';\n\nimport { meta } from '#meta';\n\nimport { type GitHubLink } from '../extensions/index.ts';\n\n/**\n * Where a previewed link's repository, pull request or issue comes from. The plugin's default fetches it from\n * the GitHub API with the space's connection token (anonymously when there is none); a host that\n * contributes one — a story, a test, an offline build — replaces the fetch.\n */\nexport type GitHubLinkSource = (\n link: GitHubLink,\n context: PreviewCapabilities.PreviewLinkContext,\n) => Effect.Effect<Repo.Repo | Issue.Issue | PullRequest.PullRequest | undefined>;\n\nexport const LinkSource = Capability.make<GitHubLinkSource>()(`${meta.profile.key}.capability.linkSource`);\n"],"mappings":";;;;;AA0BA,IAAa,aAAa,WAAW,KAAuB,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,uBAAuB"}
@@ -0,0 +1,15 @@
1
+ import { t as __exportAll } from "./chunk-rolldown-runtime.mjs";
2
+ import { meta } from "#meta";
3
+ import * as ActivationEvent from "@dxos/app-framework/ActivationEvent";
4
+ //#region src/types/GitHubEvents.ts
5
+ var GitHubEvents_exports = /* @__PURE__ */ __exportAll({ Start: () => Start });
6
+ /**
7
+ * The feature's start event: the plugin's start-gated modules (and cross-plugin
8
+ * contributions consumed by this feature) activate here. Fired on demand and by the
9
+ * host's idle trickle.
10
+ */
11
+ var Start = ActivationEvent.pluginStart(meta.profile.key);
12
+ //#endregion
13
+ export { Start as n, GitHubEvents_exports as t };
14
+
15
+ //# sourceMappingURL=chunk-GitHubEvents.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-GitHubEvents.mjs","names":[],"sources":["../../src/types/GitHubEvents.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as ActivationEvent from '@dxos/app-framework/ActivationEvent';\n\nimport { meta } from '#meta';\n\n/**\n * The feature's start event: the plugin's start-gated modules (and cross-plugin\n * contributions consumed by this feature) activate here. Fired on demand and by the\n * host's idle trickle.\n */\nexport const Start = ActivationEvent.pluginStart(meta.profile.key);\n"],"mappings":";;;;;;;;;;AAeA,IAAa,QAAQ,gBAAgB,YAAY,KAAK,QAAQ,GAAG"}
@@ -0,0 +1,386 @@
1
+ import { t as __exportAll } from "./chunk-rolldown-runtime.mjs";
2
+ import { t as Walkthrough } from "./chunk-Walkthrough.mjs";
3
+ import * as ConnectorSpec from "@dxos/plugin-connector/ConnectorSpec";
4
+ import * as Operation from "@dxos/compute/Operation";
5
+ import { PullRequest } from "@dxos/types";
6
+ import { DXN, Database, Obj, Ref } from "@dxos/echo";
7
+ import * as Schema from "effect/Schema";
8
+ import { AiService } from "@dxos/ai";
9
+ import * as Trace from "@dxos/compute/Trace";
10
+ import * as PageAction from "@dxos/plugin-crx/PageAction";
11
+ //#region src/types/GitHubOperation.ts
12
+ var GitHubOperation_exports = /* @__PURE__ */ __exportAll({
13
+ AddPullRequestComment: () => AddPullRequestComment,
14
+ AddPullRequestReviewComment: () => AddPullRequestReviewComment,
15
+ CheckCounts: () => CheckCounts,
16
+ CheckOutcome: () => CheckOutcome,
17
+ CheckRun: () => CheckRun,
18
+ CiState: () => CiState,
19
+ GenerateWalkthrough: () => GenerateWalkthrough,
20
+ GetGitHubRepositories: () => GetGitHubRepositories,
21
+ GetPullRequestDiff: () => GetPullRequestDiff,
22
+ GetPullRequestStatus: () => GetPullRequestStatus,
23
+ ImportPullRequest: () => ImportPullRequest,
24
+ ImportPullRequestFromSnapshot: () => ImportPullRequestFromSnapshot,
25
+ MaterializeGitHubTarget: () => MaterializeGitHubTarget,
26
+ RefreshPullRequests: () => RefreshPullRequests,
27
+ ReviewState: () => ReviewState,
28
+ SubmitPullRequestApproval: () => SubmitPullRequestApproval,
29
+ SyncGitHubRepositories: () => SyncGitHubRepositories,
30
+ SyncOptions: () => SyncOptions,
31
+ SyncPullRequest: () => SyncPullRequest,
32
+ createWalkthroughProgressKey: () => createWalkthroughProgressKey
33
+ });
34
+ /**
35
+ * Discovery only — list GitHub repositories the connection's token can see.
36
+ * Returns one descriptor per repo across all the user's orgs (and personal
37
+ * account). Read-only: NEVER materializes local objects — materialization is
38
+ * handled by the connector's `materializeTarget` when a `Cursor` is created.
39
+ *
40
+ * Orgs and their members are NOT presented as sync targets — they are
41
+ * auto-synced as part of the sync of any repo they own.
42
+ */
43
+ var GetGitHubRepositories = Operation.make({
44
+ meta: {
45
+ key: DXN.make("org.dxos.operation.github.getRepositories"),
46
+ name: "Get GitHub Repositories",
47
+ description: "List GitHub repositories reachable from a connection without materializing local objects.",
48
+ icon: "ph--github-logo--regular"
49
+ },
50
+ input: ConnectorSpec.GetSyncTargetsInput,
51
+ output: ConnectorSpec.GetSyncTargetsOutput
52
+ });
53
+ /**
54
+ * Find-or-create the empty local root Project for a selected GitHub repo so a
55
+ * cursor can reference it as its `spec.target`. Keyed by the repo's
56
+ * GitHub foreign id (`remoteTarget.id`), so it is idempotent across re-selection.
57
+ */
58
+ var MaterializeGitHubTarget = Operation.make({
59
+ meta: {
60
+ key: DXN.make("org.dxos.operation.github.materializeTarget"),
61
+ name: "Materialize GitHub Target",
62
+ description: "Create the empty local root Project bound to a selected GitHub repository.",
63
+ icon: "ph--github-logo--regular"
64
+ },
65
+ input: ConnectorSpec.MaterializeTargetInput,
66
+ output: ConnectorSpec.MaterializeTargetOutput
67
+ });
68
+ /**
69
+ * Per-target options. `maxDaysBack` caps how far back issues/PRs are pulled
70
+ * (mirrors the Gmail mailbox `daysBack`). Default — when unset — is "sync
71
+ * everything ever opened or edited."
72
+ */
73
+ var SyncOptions = Schema.Struct({ maxDaysBack: Schema.Number.annotate({
74
+ title: "Sync history (days)",
75
+ description: "Pull issues and PRs updated within this many days. Leave empty to sync everything."
76
+ }).pipe(Schema.optional) });
77
+ /**
78
+ * Reconcile GitHub data for every repo bound to a connection (one cursor per repo).
79
+ *
80
+ * Pull-then-push per bound repo: auto-upsert its owning org + members,
81
+ * three-way merge the repo as a Project and its issues/PRs as Tasks (respecting
82
+ * `maxDaysBack` if set), then push diverged Project/Task fields back to GitHub.
83
+ * Sync state (`lastTick`/`lastError`/`spec.snapshots`) is written onto each binding.
84
+ */
85
+ var SyncGitHubRepositories = Operation.make({
86
+ meta: {
87
+ key: DXN.make("org.dxos.operation.github.syncRepositories"),
88
+ name: "Sync GitHub Repositories",
89
+ description: "Reconcile every bound GitHub repo plus its owning org, members, issues, PRs, and comments.",
90
+ icon: "ph--arrows-clockwise--regular"
91
+ },
92
+ input: ConnectorSpec.SyncInput,
93
+ output: Schema.Struct({ pulled: Schema.Struct({
94
+ organizations: Schema.Number,
95
+ people: Schema.Number,
96
+ projects: Schema.Number,
97
+ tasks: Schema.Number,
98
+ comments: Schema.Number
99
+ }) })
100
+ }).pipe(Operation.visible);
101
+ /**
102
+ * Import a pull request named by a github.com URL or `owner/repo#123` into the space, so it can be
103
+ * opened, reviewed and walked through without waiting for a sync of the whole repository.
104
+ *
105
+ * Idempotent by coordinates — a pull request the space already holds is returned as it stands
106
+ * rather than duplicated.
107
+ */
108
+ var ImportPullRequest = Operation.make({
109
+ meta: {
110
+ key: DXN.make("org.dxos.operation.github.importPullRequest"),
111
+ name: "Import Pull Request",
112
+ description: "Add a pull request to the space, named by its URL or as owner/repo#number.",
113
+ icon: "ph--git-pull-request--regular"
114
+ },
115
+ services: [Database.Service],
116
+ input: Schema.Struct({
117
+ /** A github.com pull request URL, or `owner/repo#123`. */
118
+ reference: Schema.String }),
119
+ output: Schema.Struct({
120
+ pullRequest: Ref.Ref(PullRequest.PullRequest),
121
+ /** False where the space already held the pull request, which is then returned unchanged. */
122
+ imported: Schema.Boolean
123
+ }),
124
+ types: [PullRequest.PullRequest]
125
+ }).pipe(Operation.visible, Operation.mutation("write"));
126
+ /**
127
+ * Import the pull request the browser extension is looking at, named by the page's own URL.
128
+ *
129
+ * Separate from {@link ImportPullRequest} because the extension bridge invokes every page action
130
+ * with the fixed `{ snapshot, target }` shape and reads an `{ id }` back. Nothing is extracted from
131
+ * the page: the URL in the snapshot's source names the pull request, and GitHub is the authority on
132
+ * everything else.
133
+ */
134
+ var ImportPullRequestFromSnapshot = Operation.make({
135
+ meta: {
136
+ key: DXN.make("org.dxos.operation.github.importPullRequestFromSnapshot"),
137
+ name: "Open pull request in Composer",
138
+ description: "Import the pull request a browser page shows, named by that page's URL.",
139
+ icon: "ph--git-pull-request--regular"
140
+ },
141
+ input: Schema.Struct({
142
+ snapshot: PageAction.Snapshot,
143
+ target: Database.Database.annotate({ description: "The database to add the pull request to." })
144
+ }),
145
+ output: Schema.Struct({ id: Schema.String }),
146
+ types: [PullRequest.PullRequest]
147
+ }).pipe(Operation.mutation("write"));
148
+ /**
149
+ * Generate a walkthrough of a pull request: one markdown document narrating the change in reading
150
+ * order, with its diff chunks spliced in from the patch itself.
151
+ *
152
+ * Idempotent by commit — a walkthrough already generated for the pull request's head is returned
153
+ * unchanged unless `force` says otherwise, since the answer cannot have changed.
154
+ */
155
+ var GenerateWalkthrough = Operation.make({
156
+ meta: {
157
+ key: DXN.make("org.dxos.operation.github.generateWalkthrough"),
158
+ name: "Generate Walkthrough",
159
+ description: "Narrate a pull request as one markdown document, with the change's diffs embedded in it.",
160
+ icon: "ph--path--regular"
161
+ },
162
+ input: Schema.Struct({
163
+ pullRequest: Ref.Ref(PullRequest.PullRequest),
164
+ /** Regenerate even where a walkthrough for this head already exists. */
165
+ force: Schema.Boolean.pipe(Schema.optional)
166
+ }),
167
+ output: Schema.Struct({
168
+ walkthrough: Ref.Ref(Walkthrough),
169
+ /** Whether the model ran, as against an existing walkthrough being returned unchanged. */
170
+ generated: Schema.Boolean,
171
+ /** Hunks the prose accounts for, over the patch's total. */
172
+ covered: Schema.Number,
173
+ total: Schema.Number
174
+ }),
175
+ types: [Walkthrough, PullRequest.PullRequest],
176
+ services: [Trace.TraceService, AiService.AiService]
177
+ }).pipe(Operation.visible);
178
+ /**
179
+ * Submit an approving review on a pull request, as the space's GitHub connection.
180
+ *
181
+ * Falls back to a marked conversation comment where GitHub refuses the review — the author's own
182
+ * pull request, or a token with no review permission — so the approval is still recorded and still
183
+ * detectable by an agent deciding whether the pull request is good to land.
184
+ */
185
+ var SubmitPullRequestApproval = Operation.make({
186
+ meta: {
187
+ key: DXN.make("org.dxos.operation.github.submitPullRequestApproval"),
188
+ name: "Submit Pull Request Approval",
189
+ description: "Submit an approving review on a pull request, or record the approval as a comment.",
190
+ icon: "ph--check-circle--regular"
191
+ },
192
+ input: Schema.Struct({
193
+ pullRequest: Ref.Ref(PullRequest.PullRequest),
194
+ /** Optional review summary. */
195
+ body: Schema.String.pipe(Schema.optional)
196
+ }),
197
+ output: Schema.Struct({
198
+ /** Set where the approving review was accepted. */
199
+ reviewId: Schema.Number.pipe(Schema.optional),
200
+ /** Set instead where the approval was recorded as a comment. */
201
+ commentId: Schema.Number.pipe(Schema.optional),
202
+ url: Schema.String.pipe(Schema.optional),
203
+ /** Whether the approval is a comment rather than a review. */
204
+ commented: Schema.Boolean
205
+ }),
206
+ types: [PullRequest.PullRequest]
207
+ });
208
+ /** Post a conversation comment on a pull request, as the space's GitHub connection. */
209
+ var AddPullRequestComment = Operation.make({
210
+ meta: {
211
+ key: DXN.make("org.dxos.operation.github.addPullRequestComment"),
212
+ name: "Add Pull Request Comment",
213
+ description: "Post a comment on a pull request.",
214
+ icon: "ph--chat-text--regular"
215
+ },
216
+ input: Schema.Struct({
217
+ pullRequest: Ref.Ref(PullRequest.PullRequest),
218
+ body: Schema.String
219
+ }),
220
+ output: Schema.Struct({
221
+ commentId: Schema.Number,
222
+ url: Schema.String.pipe(Schema.optional)
223
+ }),
224
+ types: [PullRequest.PullRequest]
225
+ });
226
+ /** Post a review comment on one line of a pull request's diff, as the space's GitHub connection. */
227
+ var AddPullRequestReviewComment = Operation.make({
228
+ meta: {
229
+ key: DXN.make("org.dxos.operation.github.addPullRequestReviewComment"),
230
+ name: "Add Pull Request Review Comment",
231
+ description: "Post a review comment on a line of a pull request diff.",
232
+ icon: "ph--chat-centered-text--regular"
233
+ },
234
+ input: Schema.Struct({
235
+ pullRequest: Ref.Ref(PullRequest.PullRequest),
236
+ body: Schema.String,
237
+ /** Head SHA the line numbers refer to; a walkthrough's `commit`. */
238
+ commit: Schema.String,
239
+ path: Schema.String,
240
+ line: Schema.Number,
241
+ /** `LEFT` for the removed side, `RIGHT` for added and context lines. */
242
+ side: Schema.Literals(["LEFT", "RIGHT"])
243
+ }),
244
+ output: Schema.Struct({
245
+ commentId: Schema.Number,
246
+ url: Schema.String.pipe(Schema.optional)
247
+ }),
248
+ types: [PullRequest.PullRequest]
249
+ });
250
+ /**
251
+ * Re-read a stored pull request from GitHub and write back whatever has changed — its title, state,
252
+ * description, branches and size — so the object in the space does not go stale between syncs.
253
+ */
254
+ var SyncPullRequest = Operation.make({
255
+ meta: {
256
+ key: DXN.make("org.dxos.operation.github.syncPullRequest"),
257
+ name: "Sync Pull Request",
258
+ description: "Refresh a stored pull request from GitHub.",
259
+ icon: "ph--arrows-clockwise--regular"
260
+ },
261
+ input: Schema.Struct({ pullRequest: Ref.Ref(PullRequest.PullRequest) }),
262
+ output: Schema.Struct({
263
+ /** Names of the fields that changed; empty where the stored pull request was already current. */
264
+ updated: Schema.Array(Schema.String) }),
265
+ types: [PullRequest.PullRequest]
266
+ }).pipe(Operation.mutation("write"));
267
+ /**
268
+ * Refresh every pull request in the space that is still in flight (open or draft) from GitHub.
269
+ *
270
+ * Run on a schedule by the space's refresh trigger (see `ensureRefreshTrigger`), so pull requests the
271
+ * user is not looking at still track their state; one unreachable pull request does not fail the rest.
272
+ */
273
+ var RefreshPullRequests = Operation.make({
274
+ meta: {
275
+ key: DXN.make("org.dxos.operation.github.refreshPullRequests"),
276
+ name: "Refresh Pull Requests",
277
+ description: "Refresh every open pull request in the space from GitHub.",
278
+ icon: "ph--arrows-clockwise--regular"
279
+ },
280
+ services: [Database.Service],
281
+ input: Schema.Struct({}),
282
+ output: Schema.Struct({
283
+ /** Open pull requests read from GitHub. */
284
+ checked: Schema.Number,
285
+ /** Of those, the ones whose stored fields changed. */
286
+ updated: Schema.Number,
287
+ /** Of those, the ones GitHub could not be read for. */
288
+ failed: Schema.Number
289
+ }),
290
+ types: [PullRequest.PullRequest]
291
+ }).pipe(Operation.mutation("write"));
292
+ /** Aggregate outcome of a commit's check runs; `none` when the commit has no checks at all. */
293
+ var CiState = Schema.Literals([
294
+ "success",
295
+ "failure",
296
+ "pending",
297
+ "none"
298
+ ]);
299
+ var CheckCounts = Schema.Struct({
300
+ total: Schema.Number,
301
+ passed: Schema.Number,
302
+ failed: Schema.Number,
303
+ pending: Schema.Number
304
+ });
305
+ /**
306
+ * Where the reviews stand, from each reviewer's latest verdict: any outstanding request for changes
307
+ * outweighs approvals, and `none` means no reviewer has approved or asked for changes.
308
+ */
309
+ var ReviewState = Schema.Literals([
310
+ "approved",
311
+ "changes_requested",
312
+ "none"
313
+ ]);
314
+ /** How one check run ended, folded to what a reader acts on; `skipped` is neither passing nor failing. */
315
+ var CheckOutcome = Schema.Literals([
316
+ "success",
317
+ "failure",
318
+ "pending",
319
+ "skipped",
320
+ "neutral"
321
+ ]);
322
+ /** One check run on the head commit, as the article lists it. */
323
+ var CheckRun = Schema.Struct({
324
+ /** GitHub's id for the run; two runs can share a name and a URL. */
325
+ id: Schema.Number.pipe(Schema.optional),
326
+ name: Schema.String,
327
+ outcome: CheckOutcome,
328
+ /** GitHub's own `conclusion` (`timed_out`, `cancelled`, …), kept for the label when it says more than the outcome. */
329
+ conclusion: Schema.String.pipe(Schema.optional),
330
+ /** Where the run's logs live: the provider's page when it has one, else GitHub's. */
331
+ url: Schema.String.pipe(Schema.optional),
332
+ startedAt: Schema.String.pipe(Schema.optional),
333
+ completedAt: Schema.String.pipe(Schema.optional)
334
+ });
335
+ /** Read a pull request's live state and the CI outcome of its head commit from GitHub. */
336
+ var GetPullRequestStatus = Operation.make({
337
+ meta: {
338
+ key: DXN.make("org.dxos.operation.github.getPullRequestStatus"),
339
+ name: "Get Pull Request Status",
340
+ description: "Read a pull request's state, its review verdict and the CI status of its head commit.",
341
+ icon: "ph--git-pull-request--regular"
342
+ },
343
+ input: Schema.Struct({ pullRequest: Ref.Ref(PullRequest.PullRequest) }),
344
+ output: Schema.Struct({
345
+ state: PullRequest.State,
346
+ title: Schema.String,
347
+ commit: Schema.String.pipe(Schema.optional),
348
+ /** The live description, which may have changed since the pull request was imported. */
349
+ body: Schema.String.pipe(Schema.optional),
350
+ ci: CiState,
351
+ checks: CheckCounts,
352
+ runs: Schema.Array(CheckRun),
353
+ review: ReviewState,
354
+ /** Reviewers whose latest verdict is an approval. */
355
+ approvals: Schema.Number
356
+ }),
357
+ types: [PullRequest.PullRequest]
358
+ });
359
+ /**
360
+ * Read a pull request's whole change as a unified diff, with the head commit it was taken at so a
361
+ * line comment on it anchors to the lines the reader saw.
362
+ */
363
+ var GetPullRequestDiff = Operation.make({
364
+ meta: {
365
+ key: DXN.make("org.dxos.operation.github.getPullRequestDiff"),
366
+ name: "Get Pull Request Diff",
367
+ description: "Read a pull request's changed files as a unified diff.",
368
+ icon: "ph--git-diff--regular"
369
+ },
370
+ input: Schema.Struct({ pullRequest: Ref.Ref(PullRequest.PullRequest) }),
371
+ output: Schema.Struct({
372
+ commit: Schema.String.pipe(Schema.optional),
373
+ diff: Schema.String
374
+ }),
375
+ types: [PullRequest.PullRequest]
376
+ });
377
+ /**
378
+ * Progress key for {@link GenerateWalkthrough}, derived from the pull request rather than passed, so
379
+ * the UI can watch a run it did not start. The absolute URI form is required: a hydration-dependent
380
+ * one would not match the key the producer mints.
381
+ */
382
+ var createWalkthroughProgressKey = (pullRequest) => Obj.getURI(pullRequest, { prefer: "absolute" }).toString() + "#walkthrough";
383
+ //#endregion
384
+ export { SubmitPullRequestApproval as _, CheckRun as a, SyncPullRequest as b, GetGitHubRepositories as c, GitHubOperation_exports as d, ImportPullRequest as f, ReviewState as g, RefreshPullRequests as h, CheckOutcome as i, GetPullRequestDiff as l, MaterializeGitHubTarget as m, AddPullRequestReviewComment as n, CiState as o, ImportPullRequestFromSnapshot as p, CheckCounts as r, GenerateWalkthrough as s, AddPullRequestComment as t, GetPullRequestStatus as u, SyncGitHubRepositories as v, createWalkthroughProgressKey as x, SyncOptions as y };
385
+
386
+ //# sourceMappingURL=chunk-GitHubOperation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-GitHubOperation.mjs","names":["Walkthrough.Walkthrough"],"sources":["../../src/types/GitHubOperation.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as Schema from 'effect/Schema';\n\nimport { AiService } from '@dxos/ai';\nimport * as Operation from '@dxos/compute/Operation';\nimport * as Trace from '@dxos/compute/Trace';\nimport { Database, DXN, Obj, Ref } from '@dxos/echo';\n// Referenced in the emitted .d.ts of the operations (via `ConnectorSpec`'s schemas); importing it\n// lets TypeScript name it (TS2883).\n// eslint-disable-next-line unused-imports/no-unused-imports\nimport { Connection } from '@dxos/link';\nimport * as ConnectorSpec from '@dxos/plugin-connector/ConnectorSpec';\nimport * as PageAction from '@dxos/plugin-crx/PageAction';\nimport { PullRequest } from '@dxos/types';\n\nimport * as Walkthrough from './Walkthrough.ts';\n\n/**\n * Discovery only — list GitHub repositories the connection's token can see.\n * Returns one descriptor per repo across all the user's orgs (and personal\n * account). Read-only: NEVER materializes local objects — materialization is\n * handled by the connector's `materializeTarget` when a `Cursor` is created.\n *\n * Orgs and their members are NOT presented as sync targets — they are\n * auto-synced as part of the sync of any repo they own.\n */\nexport const GetGitHubRepositories = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.getRepositories'),\n name: 'Get GitHub Repositories',\n description: 'List GitHub repositories reachable from a connection without materializing local objects.',\n icon: 'ph--github-logo--regular',\n },\n input: ConnectorSpec.GetSyncTargetsInput,\n output: ConnectorSpec.GetSyncTargetsOutput,\n});\n\n/**\n * Find-or-create the empty local root Project for a selected GitHub repo so a\n * cursor can reference it as its `spec.target`. Keyed by the repo's\n * GitHub foreign id (`remoteTarget.id`), so it is idempotent across re-selection.\n */\nexport const MaterializeGitHubTarget = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.materializeTarget'),\n name: 'Materialize GitHub Target',\n description: 'Create the empty local root Project bound to a selected GitHub repository.',\n icon: 'ph--github-logo--regular',\n },\n input: ConnectorSpec.MaterializeTargetInput,\n output: ConnectorSpec.MaterializeTargetOutput,\n});\n\n/**\n * Per-target options. `maxDaysBack` caps how far back issues/PRs are pulled\n * (mirrors the Gmail mailbox `daysBack`). Default — when unset — is \"sync\n * everything ever opened or edited.\"\n */\nexport const SyncOptions = Schema.Struct({\n maxDaysBack: Schema.Number.annotate({\n title: 'Sync history (days)',\n description: 'Pull issues and PRs updated within this many days. Leave empty to sync everything.',\n }).pipe(Schema.optional),\n});\n\nexport interface SyncOptions extends Schema.Schema.Type<typeof SyncOptions> {}\n\n/**\n * Reconcile GitHub data for every repo bound to a connection (one cursor per repo).\n *\n * Pull-then-push per bound repo: auto-upsert its owning org + members,\n * three-way merge the repo as a Project and its issues/PRs as Tasks (respecting\n * `maxDaysBack` if set), then push diverged Project/Task fields back to GitHub.\n * Sync state (`lastTick`/`lastError`/`spec.snapshots`) is written onto each binding.\n */\nexport const SyncGitHubRepositories = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.syncRepositories'),\n name: 'Sync GitHub Repositories',\n description: 'Reconcile every bound GitHub repo plus its owning org, members, issues, PRs, and comments.',\n icon: 'ph--arrows-clockwise--regular',\n },\n input: ConnectorSpec.SyncInput,\n output: Schema.Struct({\n pulled: Schema.Struct({\n organizations: Schema.Number,\n people: Schema.Number,\n projects: Schema.Number,\n tasks: Schema.Number,\n comments: Schema.Number,\n }),\n }),\n}).pipe(Operation.visible);\n\n/**\n * Import a pull request named by a github.com URL or `owner/repo#123` into the space, so it can be\n * opened, reviewed and walked through without waiting for a sync of the whole repository.\n *\n * Idempotent by coordinates — a pull request the space already holds is returned as it stands\n * rather than duplicated.\n */\nexport const ImportPullRequest = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.importPullRequest'),\n name: 'Import Pull Request',\n description: 'Add a pull request to the space, named by its URL or as owner/repo#number.',\n icon: 'ph--git-pull-request--regular',\n },\n services: [Database.Service],\n input: Schema.Struct({\n /** A github.com pull request URL, or `owner/repo#123`. */\n reference: Schema.String,\n }),\n output: Schema.Struct({\n pullRequest: Ref.Ref(PullRequest.PullRequest),\n /** False where the space already held the pull request, which is then returned unchanged. */\n imported: Schema.Boolean,\n }),\n types: [PullRequest.PullRequest],\n}).pipe(Operation.visible, Operation.mutation('write'));\n\n/**\n * Import the pull request the browser extension is looking at, named by the page's own URL.\n *\n * Separate from {@link ImportPullRequest} because the extension bridge invokes every page action\n * with the fixed `{ snapshot, target }` shape and reads an `{ id }` back. Nothing is extracted from\n * the page: the URL in the snapshot's source names the pull request, and GitHub is the authority on\n * everything else.\n */\nexport const ImportPullRequestFromSnapshot = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.importPullRequestFromSnapshot'),\n name: 'Open pull request in Composer',\n description: \"Import the pull request a browser page shows, named by that page's URL.\",\n icon: 'ph--git-pull-request--regular',\n },\n input: Schema.Struct({\n snapshot: PageAction.Snapshot,\n target: Database.Database.annotate({ description: 'The database to add the pull request to.' }),\n }),\n output: Schema.Struct({\n id: Schema.String,\n }),\n types: [PullRequest.PullRequest],\n}).pipe(Operation.mutation('write'));\n\n/**\n * Generate a walkthrough of a pull request: one markdown document narrating the change in reading\n * order, with its diff chunks spliced in from the patch itself.\n *\n * Idempotent by commit — a walkthrough already generated for the pull request's head is returned\n * unchanged unless `force` says otherwise, since the answer cannot have changed.\n */\nexport const GenerateWalkthrough = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.generateWalkthrough'),\n name: 'Generate Walkthrough',\n description: \"Narrate a pull request as one markdown document, with the change's diffs embedded in it.\",\n icon: 'ph--path--regular',\n },\n input: Schema.Struct({\n pullRequest: Ref.Ref(PullRequest.PullRequest),\n /** Regenerate even where a walkthrough for this head already exists. */\n force: Schema.Boolean.pipe(Schema.optional),\n }),\n output: Schema.Struct({\n walkthrough: Ref.Ref(Walkthrough.Walkthrough),\n /** Whether the model ran, as against an existing walkthrough being returned unchanged. */\n generated: Schema.Boolean,\n /** Hunks the prose accounts for, over the patch's total. */\n covered: Schema.Number,\n total: Schema.Number,\n }),\n types: [Walkthrough.Walkthrough, PullRequest.PullRequest],\n // `AiService` must be declared, not merely provided: the invoker builds the runtime from THIS list\n // and `Layer.orDie` clears a layer's error channel, never its requirement.\n services: [Trace.TraceService, AiService.AiService],\n}).pipe(Operation.visible);\n\n/**\n * Submit an approving review on a pull request, as the space's GitHub connection.\n *\n * Falls back to a marked conversation comment where GitHub refuses the review — the author's own\n * pull request, or a token with no review permission — so the approval is still recorded and still\n * detectable by an agent deciding whether the pull request is good to land.\n */\nexport const SubmitPullRequestApproval = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.submitPullRequestApproval'),\n name: 'Submit Pull Request Approval',\n description: 'Submit an approving review on a pull request, or record the approval as a comment.',\n icon: 'ph--check-circle--regular',\n },\n input: Schema.Struct({\n pullRequest: Ref.Ref(PullRequest.PullRequest),\n /** Optional review summary. */\n body: Schema.String.pipe(Schema.optional),\n }),\n output: Schema.Struct({\n /** Set where the approving review was accepted. */\n reviewId: Schema.Number.pipe(Schema.optional),\n /** Set instead where the approval was recorded as a comment. */\n commentId: Schema.Number.pipe(Schema.optional),\n url: Schema.String.pipe(Schema.optional),\n /** Whether the approval is a comment rather than a review. */\n commented: Schema.Boolean,\n }),\n types: [PullRequest.PullRequest],\n});\n\n/** Post a conversation comment on a pull request, as the space's GitHub connection. */\nexport const AddPullRequestComment = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.addPullRequestComment'),\n name: 'Add Pull Request Comment',\n description: 'Post a comment on a pull request.',\n icon: 'ph--chat-text--regular',\n },\n input: Schema.Struct({\n pullRequest: Ref.Ref(PullRequest.PullRequest),\n body: Schema.String,\n }),\n output: Schema.Struct({\n commentId: Schema.Number,\n url: Schema.String.pipe(Schema.optional),\n }),\n types: [PullRequest.PullRequest],\n});\n\n/** Post a review comment on one line of a pull request's diff, as the space's GitHub connection. */\nexport const AddPullRequestReviewComment = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.addPullRequestReviewComment'),\n name: 'Add Pull Request Review Comment',\n description: 'Post a review comment on a line of a pull request diff.',\n icon: 'ph--chat-centered-text--regular',\n },\n input: Schema.Struct({\n pullRequest: Ref.Ref(PullRequest.PullRequest),\n body: Schema.String,\n /** Head SHA the line numbers refer to; a walkthrough's `commit`. */\n commit: Schema.String,\n path: Schema.String,\n line: Schema.Number,\n /** `LEFT` for the removed side, `RIGHT` for added and context lines. */\n side: Schema.Literals(['LEFT', 'RIGHT']),\n }),\n output: Schema.Struct({\n commentId: Schema.Number,\n url: Schema.String.pipe(Schema.optional),\n }),\n types: [PullRequest.PullRequest],\n});\n\n/**\n * Re-read a stored pull request from GitHub and write back whatever has changed — its title, state,\n * description, branches and size — so the object in the space does not go stale between syncs.\n */\nexport const SyncPullRequest = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.syncPullRequest'),\n name: 'Sync Pull Request',\n description: 'Refresh a stored pull request from GitHub.',\n icon: 'ph--arrows-clockwise--regular',\n },\n input: Schema.Struct({\n pullRequest: Ref.Ref(PullRequest.PullRequest),\n }),\n output: Schema.Struct({\n /** Names of the fields that changed; empty where the stored pull request was already current. */\n updated: Schema.Array(Schema.String),\n }),\n types: [PullRequest.PullRequest],\n}).pipe(Operation.mutation('write'));\n\n/**\n * Refresh every pull request in the space that is still in flight (open or draft) from GitHub.\n *\n * Run on a schedule by the space's refresh trigger (see `ensureRefreshTrigger`), so pull requests the\n * user is not looking at still track their state; one unreachable pull request does not fail the rest.\n */\nexport const RefreshPullRequests = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.refreshPullRequests'),\n name: 'Refresh Pull Requests',\n description: 'Refresh every open pull request in the space from GitHub.',\n icon: 'ph--arrows-clockwise--regular',\n },\n services: [Database.Service],\n input: Schema.Struct({}),\n output: Schema.Struct({\n /** Open pull requests read from GitHub. */\n checked: Schema.Number,\n /** Of those, the ones whose stored fields changed. */\n updated: Schema.Number,\n /** Of those, the ones GitHub could not be read for. */\n failed: Schema.Number,\n }),\n types: [PullRequest.PullRequest],\n}).pipe(Operation.mutation('write'));\n\n/** Aggregate outcome of a commit's check runs; `none` when the commit has no checks at all. */\nexport const CiState = Schema.Literals(['success', 'failure', 'pending', 'none']);\nexport type CiState = Schema.Schema.Type<typeof CiState>;\n\nexport const CheckCounts = Schema.Struct({\n total: Schema.Number,\n passed: Schema.Number,\n failed: Schema.Number,\n pending: Schema.Number,\n});\nexport interface CheckCounts extends Schema.Schema.Type<typeof CheckCounts> {}\n\n/**\n * Where the reviews stand, from each reviewer's latest verdict: any outstanding request for changes\n * outweighs approvals, and `none` means no reviewer has approved or asked for changes.\n */\nexport const ReviewState = Schema.Literals(['approved', 'changes_requested', 'none']);\nexport type ReviewState = Schema.Schema.Type<typeof ReviewState>;\n\n/** How one check run ended, folded to what a reader acts on; `skipped` is neither passing nor failing. */\nexport const CheckOutcome = Schema.Literals(['success', 'failure', 'pending', 'skipped', 'neutral']);\nexport type CheckOutcome = Schema.Schema.Type<typeof CheckOutcome>;\n\n/** One check run on the head commit, as the article lists it. */\nexport const CheckRun = Schema.Struct({\n /** GitHub's id for the run; two runs can share a name and a URL. */\n id: Schema.Number.pipe(Schema.optional),\n name: Schema.String,\n outcome: CheckOutcome,\n /** GitHub's own `conclusion` (`timed_out`, `cancelled`, …), kept for the label when it says more than the outcome. */\n conclusion: Schema.String.pipe(Schema.optional),\n /** Where the run's logs live: the provider's page when it has one, else GitHub's. */\n url: Schema.String.pipe(Schema.optional),\n startedAt: Schema.String.pipe(Schema.optional),\n completedAt: Schema.String.pipe(Schema.optional),\n});\nexport interface CheckRun extends Schema.Schema.Type<typeof CheckRun> {}\n\n/** Read a pull request's live state and the CI outcome of its head commit from GitHub. */\nexport const GetPullRequestStatus = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.getPullRequestStatus'),\n name: 'Get Pull Request Status',\n description: \"Read a pull request's state, its review verdict and the CI status of its head commit.\",\n icon: 'ph--git-pull-request--regular',\n },\n input: Schema.Struct({\n pullRequest: Ref.Ref(PullRequest.PullRequest),\n }),\n output: Schema.Struct({\n state: PullRequest.State,\n title: Schema.String,\n commit: Schema.String.pipe(Schema.optional),\n /** The live description, which may have changed since the pull request was imported. */\n body: Schema.String.pipe(Schema.optional),\n ci: CiState,\n checks: CheckCounts,\n runs: Schema.Array(CheckRun),\n review: ReviewState,\n /** Reviewers whose latest verdict is an approval. */\n approvals: Schema.Number,\n }),\n types: [PullRequest.PullRequest],\n});\n\n/**\n * Read a pull request's whole change as a unified diff, with the head commit it was taken at so a\n * line comment on it anchors to the lines the reader saw.\n */\nexport const GetPullRequestDiff = Operation.make({\n meta: {\n key: DXN.make('org.dxos.operation.github.getPullRequestDiff'),\n name: 'Get Pull Request Diff',\n description: \"Read a pull request's changed files as a unified diff.\",\n icon: 'ph--git-diff--regular',\n },\n input: Schema.Struct({\n pullRequest: Ref.Ref(PullRequest.PullRequest),\n }),\n output: Schema.Struct({\n commit: Schema.String.pipe(Schema.optional),\n diff: Schema.String,\n }),\n types: [PullRequest.PullRequest],\n});\n\n/**\n * Progress key for {@link GenerateWalkthrough}, derived from the pull request rather than passed, so\n * the UI can watch a run it did not start. The absolute URI form is required: a hydration-dependent\n * one would not match the key the producer mints.\n */\nexport const createWalkthroughProgressKey = (pullRequest: PullRequest.PullRequest): string =>\n Obj.getURI(pullRequest, { prefer: 'absolute' }).toString() + '#walkthrough';\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { t as __exportAll } from "./chunk-rolldown-runtime.mjs";
2
+ import { meta } from "#meta";
3
+ import * as Plugin from "@dxos/app-framework/Plugin";
4
+ //#region src/GitHubPlugin.ts
5
+ var GitHubPlugin_exports = /* @__PURE__ */ __exportAll({
6
+ make: () => make,
7
+ meta: () => meta$1
8
+ });
9
+ /** Plugin metadata, available without loading the plugin body. */
10
+ var meta$1 = meta;
11
+ /** Constructs the plugin; the body loads on first enable. */
12
+ var make = Plugin.lazy(meta$1, () => import("#plugin"));
13
+ //#endregion
14
+ export { make as n, meta$1 as r, GitHubPlugin_exports as t };
15
+
16
+ //# sourceMappingURL=chunk-GitHubPlugin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-GitHubPlugin.mjs","names":["meta","pluginMeta"],"sources":["../../src/GitHubPlugin.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as Plugin from '@dxos/app-framework/Plugin';\n\nimport { meta as pluginMeta } from '#meta';\n\n/** Plugin metadata, available without loading the plugin body. */\nexport const meta = pluginMeta;\n\n/** Constructs the plugin; the body loads on first enable. */\nexport const make = Plugin.lazy(meta, () => import('#plugin'));\n"],"mappings":";;;;;;;;;AAWA,IAAaA,SAAOC;;AAGpB,IAAa,OAAO,OAAO,KAAKD,cAAY,OAAO,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"chunk-ImportPullRequestDialog.mjs","names":[],"sources":["../../src/containers/ImportPullRequestDialog/ImportPullRequestDialog.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\nimport React, { useCallback } from 'react';\n\nimport * as Hooks from '@dxos/app-framework/Hooks';\nimport * as ToolkitHooks from '@dxos/app-toolkit/Hooks';\nimport * as LayoutOperation from '@dxos/app-toolkit/LayoutOperation';\nimport { log } from '@dxos/log';\nimport { Form } from '@dxos/react-ui-form';\nimport * as Dialog from '@dxos/react-ui/Dialog';\nimport * as UiHooks from '@dxos/react-ui/Hooks';\nimport * as SystemButton from '@dxos/react-ui/SystemButton';\n\nimport { meta } from '#meta';\nimport { GitHubOperation } from '#types';\n\nimport { GitHubRepoInaccessibleError } from '../../errors.ts';\nimport { parsePullRequestReference } from '../../extensions/index.ts';\nimport { useOpenObject } from '../../hooks/index.ts';\nimport { GitHubApi } from '../../services/index.ts';\n\nconst ImportPullRequestForm = Schema.Struct({\n reference: Schema.String.pipe(\n // Validated here as well as in the operation: a typo should be answered by the field the user is\n // looking at, not by a toast after a round trip to GitHub.\n Schema.check(\n Schema.makeFilter(\n (value: string) =>\n parsePullRequestReference(value) !== undefined || 'Paste a pull request link or owner/repo#number.',\n ),\n ),\n Schema.annotate({ title: 'Pull request', description: 'https://github.com/owner/repo/pull/123 or owner/repo#123' }),\n ),\n});\n\ntype ImportPullRequestForm = Schema.Schema.Type<typeof ImportPullRequestForm>;\n\n/**\n * The status `GitHubRepoInaccessibleError` recorded, for the case the HTTP failure has already been\n * folded into it and `GitHubApi.responseStatus` no longer sees a response.\n */\nconst readStatus = (error: unknown): number | undefined => {\n if (!GitHubRepoInaccessibleError.is(error)) {\n return undefined;\n }\n const status = error.context.status;\n return typeof status === 'number' ? status : undefined;\n};\n\n/**\n * Names the failure the user can act on. A rejected credential and a repository the connection\n * cannot see both read as \"not found\" from the API, but only the first is fixed by reconnecting —\n * and a space with no connection at all is fixed by making one.\n */\nconst importFailureKey = (error: unknown): string => {\n if (!GitHubRepoInaccessibleError.is(error)) {\n return 'import-pull-request-failed.title';\n }\n if (error.context.tokenStatus === 401) {\n return 'import-pull-request-token-rejected.title';\n }\n return error.context.connected === true\n ? 'import-pull-request-inaccessible.title'\n : 'import-pull-request-not-connected.title';\n};\n\n/**\n * Imports a pull request the user names, into the space they are working in, and opens it.\n *\n * The space is the active one rather than a chosen one: the command is reached from wherever the\n * user already is, and a picker would ask a question they have already answered.\n */\nexport const ImportPullRequestDialog = () => {\n const { t } = UiHooks.useTranslation(meta.profile.key);\n const { invokePromise } = Hooks.useOperationInvoker();\n const openObject = useOpenObject();\n const space = ToolkitHooks.useActiveSpace();\n\n const handleCancel = useCallback(async () => {\n await invokePromise(LayoutOperation.UpdateDialog, { state: false });\n }, [invokePromise]);\n\n const handleSave = useCallback(\n async ({ reference }: ImportPullRequestForm) => {\n if (!space) {\n // The command is reachable from the root, which has no space of its own; saying so beats a\n // button that appears to do nothing.\n await invokePromise(LayoutOperation.AddToast, {\n id: `${meta.profile.key}.import-pull-request`,\n icon: 'ph--warning--regular',\n title: ['import-pull-request-no-space.title', { ns: meta.profile.key }],\n });\n return;\n }\n\n const { data, error } = await invokePromise(\n GitHubOperation.ImportPullRequest,\n { reference: reference.trim() },\n { spaceId: space.db.spaceId },\n );\n\n const pullRequest = data?.pullRequest.target;\n if (error || !pullRequest) {\n const status = GitHubApi.responseStatus(error) ?? readStatus(error);\n // A minified build serialises the invoker's error as a bare, headerless stack, so the name and\n // the HTTP status it carries are logged explicitly — without them a feedback bundle names the\n // failure without saying what it was.\n log.warn('pull request import failed', { reference, errorName: error?.name, status, err: error });\n await invokePromise(LayoutOperation.AddToast, {\n id: `${meta.profile.key}.import-pull-request`,\n icon: 'ph--warning--regular',\n title: [importFailureKey(error), { ns: meta.profile.key }],\n // The status is what separates a reference the user should re-check from a connection they\n // should repair, and it is otherwise visible only in the logs.\n description: status ? `${reference} — HTTP ${status}` : reference,\n });\n return;\n }\n\n // Closed only on success: a failed import keeps the reference the user typed, which is the\n // thing they would otherwise have to find again.\n await invokePromise(LayoutOperation.UpdateDialog, { state: false });\n await openObject(pullRequest);\n },\n [invokePromise, openObject, space],\n );\n\n return (\n <Dialog.Content>\n {/* The form spans the dialog, so its actions sit in the footer while reading the form's context. */}\n <Form.Root\n autoFocus\n schema={ImportPullRequestForm}\n defaultValues={{ reference: '' }}\n onSave={handleSave}\n onCancel={handleCancel}\n >\n <Dialog.Header>\n <Dialog.Title>{t('import-pull-request-dialog.title')}</Dialog.Title>\n <Dialog.CloseTrigger asChild>\n <SystemButton.Close />\n </Dialog.CloseTrigger>\n </Dialog.Header>\n <Dialog.Body>\n <Form.Content>\n <Form.Fields />\n </Form.Content>\n </Dialog.Body>\n <Dialog.Footer>\n <Form.Actions submitLabel={t('import-pull-request-submit.label')} />\n </Dialog.Footer>\n </Form.Root>\n </Dialog.Content>\n );\n};\n\nImportPullRequestDialog.displayName = 'ImportPullRequestDialog';\n"],"mappings":"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"}
1
+ {"version":3,"file":"chunk-ImportPullRequestDialog.mjs","names":["GitHubApi.responseStatus"],"sources":["../../src/containers/ImportPullRequestDialog/ImportPullRequestDialog.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\nimport React, { useCallback } from 'react';\n\nimport * as Hooks from '@dxos/app-framework/Hooks';\nimport * as ToolkitHooks from '@dxos/app-toolkit/Hooks';\nimport * as LayoutOperation from '@dxos/app-toolkit/LayoutOperation';\nimport { log } from '@dxos/log';\nimport { Form } from '@dxos/react-ui-form';\nimport * as Dialog from '@dxos/react-ui/Dialog';\nimport * as UiHooks from '@dxos/react-ui/Hooks';\nimport * as SystemButton from '@dxos/react-ui/SystemButton';\n\nimport { meta } from '#meta';\nimport { GitHubOperation } from '#types';\n\nimport { GitHubRepoInaccessibleError } from '../../errors.ts';\nimport { parsePullRequestReference } from '../../extensions/index.ts';\nimport { useOpenObject } from '../../hooks/index.ts';\nimport { GitHubApi } from '../../services/index.ts';\n\nconst ImportPullRequestForm = Schema.Struct({\n reference: Schema.String.pipe(\n // Validated here as well as in the operation: a typo should be answered by the field the user is\n // looking at, not by a toast after a round trip to GitHub.\n Schema.check(\n Schema.makeFilter(\n (value: string) =>\n parsePullRequestReference(value) !== undefined || 'Paste a pull request link or owner/repo#number.',\n ),\n ),\n Schema.annotate({ title: 'Pull request', description: 'https://github.com/owner/repo/pull/123 or owner/repo#123' }),\n ),\n});\n\ntype ImportPullRequestForm = Schema.Schema.Type<typeof ImportPullRequestForm>;\n\n/**\n * The status `GitHubRepoInaccessibleError` recorded, for the case the HTTP failure has already been\n * folded into it and `GitHubApi.responseStatus` no longer sees a response.\n */\nconst readStatus = (error: unknown): number | undefined => {\n if (!GitHubRepoInaccessibleError.is(error)) {\n return undefined;\n }\n const status = error.context.status;\n return typeof status === 'number' ? status : undefined;\n};\n\n/**\n * Names the failure the user can act on. A rejected credential and a repository the connection\n * cannot see both read as \"not found\" from the API, but only the first is fixed by reconnecting —\n * and a space with no connection at all is fixed by making one.\n */\nconst importFailureKey = (error: unknown): string => {\n if (!GitHubRepoInaccessibleError.is(error)) {\n return 'import-pull-request-failed.title';\n }\n if (error.context.tokenStatus === 401) {\n return 'import-pull-request-token-rejected.title';\n }\n return error.context.connected === true\n ? 'import-pull-request-inaccessible.title'\n : 'import-pull-request-not-connected.title';\n};\n\n/**\n * Imports a pull request the user names, into the space they are working in, and opens it.\n *\n * The space is the active one rather than a chosen one: the command is reached from wherever the\n * user already is, and a picker would ask a question they have already answered.\n */\nexport const ImportPullRequestDialog = () => {\n const { t } = UiHooks.useTranslation(meta.profile.key);\n const { invokePromise } = Hooks.useOperationInvoker();\n const openObject = useOpenObject();\n const space = ToolkitHooks.useActiveSpace();\n\n const handleCancel = useCallback(async () => {\n await invokePromise(LayoutOperation.UpdateDialog, { state: false });\n }, [invokePromise]);\n\n const handleSave = useCallback(\n async ({ reference }: ImportPullRequestForm) => {\n if (!space) {\n // The command is reachable from the root, which has no space of its own; saying so beats a\n // button that appears to do nothing.\n await invokePromise(LayoutOperation.AddToast, {\n id: `${meta.profile.key}.import-pull-request`,\n icon: 'ph--warning--regular',\n title: ['import-pull-request-no-space.title', { ns: meta.profile.key }],\n });\n return;\n }\n\n const { data, error } = await invokePromise(\n GitHubOperation.ImportPullRequest,\n { reference: reference.trim() },\n { spaceId: space.db.spaceId },\n );\n\n const pullRequest = data?.pullRequest.target;\n if (error || !pullRequest) {\n const status = GitHubApi.responseStatus(error) ?? readStatus(error);\n // A minified build serialises the invoker's error as a bare, headerless stack, so the name and\n // the HTTP status it carries are logged explicitly — without them a feedback bundle names the\n // failure without saying what it was.\n log.warn('pull request import failed', { reference, errorName: error?.name, status, err: error });\n await invokePromise(LayoutOperation.AddToast, {\n id: `${meta.profile.key}.import-pull-request`,\n icon: 'ph--warning--regular',\n title: [importFailureKey(error), { ns: meta.profile.key }],\n // The status is what separates a reference the user should re-check from a connection they\n // should repair, and it is otherwise visible only in the logs.\n description: status ? `${reference} — HTTP ${status}` : reference,\n });\n return;\n }\n\n // Closed only on success: a failed import keeps the reference the user typed, which is the\n // thing they would otherwise have to find again.\n await invokePromise(LayoutOperation.UpdateDialog, { state: false });\n await openObject(pullRequest);\n },\n [invokePromise, openObject, space],\n );\n\n return (\n <Dialog.Content>\n {/* The form spans the dialog, so its actions sit in the footer while reading the form's context. */}\n <Form.Root\n autoFocus\n schema={ImportPullRequestForm}\n defaultValues={{ reference: '' }}\n onSave={handleSave}\n onCancel={handleCancel}\n >\n <Dialog.Header>\n <Dialog.Title>{t('import-pull-request-dialog.title')}</Dialog.Title>\n <Dialog.CloseTrigger asChild>\n <SystemButton.Close />\n </Dialog.CloseTrigger>\n </Dialog.Header>\n <Dialog.Body>\n <Form.Content>\n <Form.Fields />\n </Form.Content>\n </Dialog.Body>\n <Dialog.Footer>\n <Form.Actions submitLabel={t('import-pull-request-submit.label')} />\n </Dialog.Footer>\n </Form.Root>\n </Dialog.Content>\n );\n};\n\nImportPullRequestDialog.displayName = 'ImportPullRequestDialog';\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  //#region PLUGIN.mdl?raw
2
2
  var PLUGIN_default = "---\nid: org.dxos.plugin.github\nname: GitHubPlugin\nversion: 0.1.0\n---\n\nBidirectional GitHub integration for DXOS Composer.\n\nConnects one or more GitHub OAuth integrations to a space and keeps\norganizations, people, repositories, issues, and pull requests\nsynchronized with ECHO. Users select repositories as sync targets; owning\norganizations and their members are pulled automatically. Local edits to\nissue title, description, and open/closed status are pushed back to GitHub\nvia snapshot-diff reconciliation.\n\n## Extensions\n\nThe following extension dialects are used in this document.\nEach extension is defined in the Appendix or resolved via its URI.\n\n| Term | URI |\n|-------------|--------------------------------|\n| `type` | `org.dxos.mdl.type@1.0` |\n| `feat` | `org.dxos.mdl.feat@1.0` |\n| `scenario` | `org.dxos.mdl.scenario@1.0` |\n| `component` | `org.dxos.mdl.component@1.0` |\n| `op` | `org.dxos.mdl.op@1.1` |\n| `test` | `org.dxos.mdl.test@1.0` |\n\n## Types\n\n```mdl\ntype SyncTargetDescriptor\n desc: Lightweight descriptor returned by GetGitHubRepositories; never stored in ECHO directly.\n fields:\n id: string # stringified GitHub numeric repo id\n name: string # full_name e.g. \"acme/anvil\"\n description?: string\n```\n\n```mdl\ntype SyncOptions\n desc: Per-target sync tuning knobs stored on Integration.targets[i].options.\n fields:\n maxDaysBack?: number # pull issues/PRs updated within this many days; omit for full history\n```\n\n```mdl\ntype GitHubUser\n desc: Subset of the GitHub REST user object consumed by the sync service.\n fields:\n id: number\n login: string\n name?: string\n email?: string\n avatar_url?: string\n html_url?: string\n```\n\n```mdl\ntype GitHubOrg\n desc: Subset of the GitHub REST org object.\n fields:\n id: number\n login: string\n name?: string\n description?: string\n blog?: string\n avatar_url?: string\n html_url?: string\n```\n\n```mdl\ntype GitHubRepo\n desc: Subset of the GitHub REST repo object.\n fields:\n id: number\n name: string\n full_name: string\n description?: string\n html_url?: string\n archived?: boolean\n owner: GitHubUser # owner.login used to derive org lookup\n```\n\n```mdl\ntype GitHubIssue\n desc: Subset of the GitHub REST issue object; PRs appear here with a non-null pull_request field.\n fields:\n id: number\n number: number\n title: string\n body?: string\n state: open | closed\n assignees?: GitHubUser[]\n labels?: GitHubLabel[]\n pull_request?: GitHubPullRef # non-null → this item is a PR\n created_at?: string\n updated_at?: string\n closed_at?: string\n```\n\n```mdl\ntype GitHubLabel\n fields:\n name: string\n```\n\n```mdl\ntype GitHubPullRef\n desc: Minimal PR marker stored inline on a GitHubIssue.\n fields:\n url: string\n merged_at?: string\n```\n\n```mdl\ntype GitHubComment\n fields:\n id: number\n body?: string\n user?: GitHubUser\n created_at?: string\n updated_at?: string\n html_url?: string\n```\n\n```mdl\ntype ProjectSnapshot\n desc: Fields recorded on Integration.snapshots after each pull; used to detect local divergence on push.\n fields:\n name: string # recorded but push is intentionally disabled\n description: string\n```\n\n```mdl\ntype TaskSnapshot\n desc: Fields recorded on Integration.snapshots after each pull; used to detect local divergence on push.\n fields:\n title: string\n description: string\n status: todo | done # collapsed from GitHub open/closed\n```\n\n```mdl\ntype SyncResult\n desc: Counters returned by SyncGitHubRepositories.\n fields:\n pulled:\n organizations: number\n people: number\n projects: number\n tasks: number\n comments: number\n```\n\n## Operations\n\nDiscovery operations — read-only, no local writes.\n\n```mdl\nop GetGitHubRepositories\n key: org.dxos.operation.github.getRepositories\n desc: |\n List GitHub repositories reachable from an integration token.\n Read-only: no local objects are created. Orgs are NOT listed here;\n they are auto-pulled during SyncGitHubRepositories.\n input:\n connection: Ref<Connection> # renamed from `integration`; see plugin-connector's ConnectorSpec\n output: GetSyncTargetsOutput\n effects: [http]\n errors:\n Unauthorized: token missing or revoked\n NetworkError: transient HTTP failure after retries\n```\n\n```mdl\nop MaterializeGitHubTarget\n key: org.dxos.operation.github.materializeTarget\n desc: |\n Find-or-create the empty local root Project bound to a selected GitHub repo, keyed by the\n repo's foreign id, so a Cursor can reference it as its `spec.target`.\n input:\n connection: Ref<Connection>\n remoteTarget?: RemoteTarget\n output: { target: Ref<Obj> }\n effects: [echo:write]\n```\n\nEffectful sync operations — pull from GitHub, push diverged fields back.\n\n```mdl\nop SyncGitHubRepositories\n key: org.dxos.operation.github.syncRepositories\n desc: |\n Reconcile selected GitHub repositories plus their owning organizations,\n members, issues, PRs, and (future) comments with ECHO.\n Pull direction: upserts Organization, Person, Project, Task via foreign-key.\n Push direction: snapshot-diffs Project.description and Task title /\n description / status and PATCHes diverged fields back to GitHub.\n PR status is pull-only (push is intentionally disabled).\n Updates Integration.targets[i].lastSyncAt / lastError per target.\n input:\n connection: Ref<Connection> # renamed from `integration`; every binding of the connection is synced\n priority?: string # cursor id to sync first\n output: SyncResult\n effects: [echo:read, echo:write, http]\n errors:\n Unauthorized: token missing or revoked\n NetworkError: transient HTTP failure after retries\n RepositoryNotAccessible: token cannot see one or more selected repos\n note: |\n Parallelism: up to 4 repos concurrently (REPO_CONCURRENCY); up to 4\n issues per repo (ISSUE_CONCURRENCY). Person upserts are serialized via\n a semaphore + login-keyed cache to prevent duplicates across fibers.\n Pagination: up to 10 pages per paginated endpoint (1 000 items max).\n```\n\n```mdl\nop ImportPullRequest\n key: org.dxos.operation.github.importPullRequest\n desc: |\n Add one pull request to the space, named by a github.com URL or `owner/repo#number`,\n so a reviewer with a link in hand need not sync the whole repository first.\n Idempotent by owner/repo/number: a pull request the space already holds is returned\n as it stands. The object is filed via SpaceOperation.AddObject, not merely added.\n input:\n reference: string # https://github.com/owner/repo/pull/123, or owner/repo#123\n output: { pullRequest: Ref<PullRequest>, imported: boolean }\n effects: [echo:read, echo:write, http]\n errors:\n GitHubPullRequestReferenceError: the text names no pull request\n NetworkError: transient HTTP failure after retries\n\n```\n\n```mdl\nop ImportPullRequestFromSnapshot\n key: org.dxos.operation.github.importPullRequestFromSnapshot\n desc: |\n The browser extension's page action: import the pull request the open page shows.\n Nothing is extracted from the DOM — the snapshot's `source.url` names the pull request\n and ImportPullRequest does the rest, so the anonymous-read fallback and the\n already-held check are shared. Answers with the object's id, which is the shape the\n extension bridge acks and the Composer side opens.\n input:\n snapshot: PageAction.Snapshot # the extension's generic page snapshot; only source.url is read\n target: Database # the active space's database\n output: { id: string }\n effects: [echo:read, echo:write, http]\n errors:\n GitHubPullRequestReferenceError: the page's URL names no pull request\n```\n\n```mdl\nop SubmitPullRequestApproval\n key: org.dxos.operation.github.submitPullRequestApproval\n desc: |\n Approve a pull request as the space's GitHub connection. Where GitHub refuses the\n review -- 422 on the author's own pull request, 403 on a token without review\n permission -- the approval is posted as a conversation comment carrying the\n `<!-- dxos:approval state=approved -->` marker instead, so the verdict is recorded\n and an agent polling the conversation can still read \"good to land\". Any other\n failure (401, network) surfaces rather than becoming a comment.\n input:\n pullRequest: Ref<PullRequest>\n body?: string # review summary, kept above the marker in the comment\n output: { reviewId?: number, commentId?: number, url?: string, commented: boolean }\n effects: [echo:read, http]\n errors:\n Unauthorized: token missing or revoked\n```\n\n## Features\n\n```mdl\nfeat F-1: OAuth Integration\n\n req F-1.1:\n when: user connects a GitHub integration\n then: plugin-connector OAuth flow redirects to GitHub for authorization\n\n req F-1.2:\n when: OAuth callback completes\n then: accessToken stored in ECHO; fetchUser called to set accessToken.account to user login\n\n req F-1.3: Integration source is \"github.com\"; provider id is \"github\".\n```\n\n```mdl\nfeat F-2: Repository Discovery\n\n req F-2.1:\n when: user opens the integration target picker\n then: GetGitHubRepositories returns all repos visible to the token sorted by full_name (case-insensitive)\n\n req F-2.2: No local ECHO objects are created during discovery.\n\n req F-2.3: Owner, collaborator, and org-member repo affiliations are included.\n```\n\n```mdl\nfeat F-3: Pull — Organizations and People\n\n req F-3.1:\n when: a selected repo is owned by a GitHub organization\n then: that org is upserted as an Organization in ECHO (name, description, website, image)\n\n req F-3.2:\n when: org is synced\n then: org members are upserted as Person objects linked to the Organization\n\n req F-3.3: Personal-account repos (owner is not an org) skip org/member pull without error.\n\n req F-3.4: A single org is pulled at most once per sync pass regardless of how many repos it owns.\n```\n\n```mdl\nfeat F-4: Pull — Repositories as Projects\n\n req F-4.1:\n when: a selected repo does not yet have a local mirror\n then: Project created in ECHO with foreign key [source: \"github.com\", id: String(repo.id)]\n\n req F-4.2:\n when: a selected repo already has a local mirror\n then: Project fields updated via three-way merge against the stored snapshot\n\n req F-4.3:\n when: Integration.targets[i].object is missing or points at a different Project\n then: target.object is rewired to the upserted Project\n```\n\n```mdl\nfeat F-5: Pull — Issues and PRs as Tasks\n\n req F-5.1:\n when: issue/PR does not yet have a local mirror\n then: Task created with fields title, description, status (open→todo, closed→done), assignee, project ref\n\n req F-5.2:\n when: issue/PR already has a local mirror\n then: Task fields updated via three-way merge against stored snapshot\n\n req F-5.3: PRs are treated identically to issues on pull; pull_request field marks them as PRs.\n\n req F-5.4:\n when: maxDaysBack is set on a target\n then: only issues/PRs updated within that window are fetched from GitHub\n```\n\n```mdl\nfeat F-6: Push — Local Edits Back to GitHub\n\n req F-6.1:\n when: Project.description diverges from the last pulled snapshot\n then: PATCH /repos/{owner}/{repo} sends the new description\n\n req F-6.2:\n when: Task.title or Task.description diverges from snapshot\n then: PATCH /repos/{owner}/{repo}/issues/{number} sends the updated fields\n\n req F-6.3:\n when: Task.status diverges from snapshot and the issue is not a PR\n then: PATCH sends state: open or closed accordingly\n\n req F-6.4:\n when: PR status diverges locally\n then: divergence is logged; push is skipped (PRs are pull-only for status)\n\n req F-6.5: Project.name (repo rename) divergence is logged but never pushed.\n```\n\n```mdl\nfeat F-7: Error Handling and Resilience\n\n req F-7.1:\n when: a per-target sync fails\n then: lastError is set on that target; other targets continue\n\n req F-7.2:\n when: a repo is inaccessible to the integration token\n then: lastError is set to \"Repository not accessible to integration token\"\n\n req F-7.3:\n when: an HTTP request returns 429 or 5xx\n then: request is retried with exponential backoff + jitter (max 3 retries, 500 ms base)\n\n req F-7.4:\n when: sync succeeds\n then: LayoutOperation.AddToast fires a success notification\n\n req F-7.5:\n when: sync fails\n then: LayoutOperation.AddToast fires an error notification with a human-readable message\n```\n\n```mdl\nfeat F-8: Link Previews\n\n req F-8.1:\n when: a document contains a repository, pull-request or issue URL\n then: githubLinks (contributed via MarkdownCapabilities.ExtensionProvider) renders it as an anchor chip\n\n req F-8.2:\n when: the chip is activated\n then: the plugin's PreviewCapabilities.LinkResolver answers with an in-memory Repo, PullRequest or Issue (@dxos/types), never stored\n\n req F-8.3: The object comes from a contributed GitHubCapabilities.LinkSource when a host provides one; otherwise it is fetched from the GitHub API with the space's connection token, or anonymously when the space has none.\n\n req F-8.4: GitHubCard is the CardContent surface for Repo, Issue and PullRequest, so the popover shows reference, state, author, diff size (or default branch) and a link out.\n```\n\n```mdl\nfeat F-9: Pull Request Review\n\n req F-9.1:\n when: the user runs the \"Import pull request\" command and names a pull request\n then: ImportPullRequest files it in the active space and the deck opens it\n\n req F-9.2: The article's subject is the PullRequest, not its walkthrough — so a pull request with no narration yet opens, showing its state, CI outcome and a \"Generate walkthrough\" action.\n\n req F-9.3:\n when: the space holds a walkthrough of the open pull request\n then: the article's Walkthrough tab renders its prose and diff chunks, and the toolbar action regenerates rather than generates\n\n req F-9.4: A Walkthrough opened by id resolves to the same article, through the pull request it narrates.\n\n req F-9.5:\n when: the user clicks \"Open PR in Composer\" in the browser extension on a github.com pull\n request page\n then: ImportPullRequestFromSnapshot files that pull request in the active space, and the\n extension's auto-open setting opens it in the deck\n\n req F-9.6: The article opens on an Overview tab showing the pull request's live description as markdown, with the harness's Claude Code footer and CI's Composer preview block taken out of the prose.\n\n req F-9.7: A link into the agent-artifacts R2 bucket renders as a pill that previews its image or video in place, and each such artifact, the Composer preview and the Claude Code session are listed as related cards in a masonry grid.\n\n req F-9.8: The Overview lists every check run on the head commit, failures first, with its outcome, duration and a link to the provider's logs.\n\n req F-9.9: The Overview shows the pull request's reference, state, CI outcome and branches as a read-only form in a details card.\n\n req F-9.10: A Files tab shows one changed file at a time as the walkthrough's own diff chunk, beside a tree of every changed file with its change counts; the toolbar steps to the previous or next file.\n\n req F-9.11:\n when: the reader checks a file off, in the tree or with the toolbar's Reviewed action\n then: the file counts as reviewed in that browser until a push changes it, and the toolbar action moves on to the next file\n```\n\n## Acceptance\n\n```mdl\nscenario T-1: Token account populated on connect\n given: user completes GitHub OAuth\n when: onTokenCreated fires\n then:\n - GET /user is called with the new token\n - accessToken.account === user.login\n```\n\n```mdl\nscenario T-2: Repository discovery is read-only\n given: valid GitHub integration\n when: GetGitHubRepositories is invoked\n then:\n - list of SyncTargetDescriptor returned sorted by full_name\n - no Organization, Person, Project, or Task objects are created in ECHO\n```\n\n```mdl\nscenario T-3: First sync — create Project and Tasks\n given: integration with one selected repo (no prior local mirror)\n when: SyncGitHubRepositories runs\n then:\n - Project created with foreign key for the repo\n - one Task created per issue/PR\n - open issues map to status todo; closed issues map to status done\n - ProjectSnapshot and TaskSnapshot written for each object\n```\n\n```mdl\nscenario T-4: Incremental pull — remote-wins merge\n given: integration with a previously synced repo; remote title changed\n when: SyncGitHubRepositories runs\n then:\n - Task.title updated to remote value\n - TaskSnapshot.title updated to match\n```\n\n```mdl\nscenario T-5: Push issue edit\n given: Task.description differs from TaskSnapshot.description; issue is not a PR\n when: SyncGitHubRepositories runs\n then:\n - PATCH /repos/{owner}/{repo}/issues/{number} called with new body\n - TaskSnapshot.description updated to sent value\n```\n\n```mdl\nscenario T-6: PR status not pushed\n given: Task (backed by a PR) status differs from snapshot\n when: SyncGitHubRepositories runs\n then:\n - no PATCH issued for that task's status\n - divergence logged at warn level\n```\n\n```mdl\nscenario T-7: Inaccessible repo error surfaced\n given: integration target whose repo id is not in fetchUserRepos response\n when: SyncGitHubRepositories runs\n then:\n - target.lastError === \"Repository not accessible to integration token\"\n - other targets continue and complete normally\n```\n\n```mdl\nscenario T-8: Org deduplication\n given: two selected repos with the same owner org\n when: SyncGitHubRepositories runs\n then:\n - fetchOrg called once for that owner\n - exactly one Organization upserted\n```\n\n```mdl\nscenario T-9: Personal-account owner skips org pull\n given: selected repo owned by a GitHub user (not an org)\n when: SyncGitHubRepositories runs\n then:\n - org lookup returns 404\n - no Organization created; sync continues without error\n```\n\n```mdl\nscenario T-10: maxDaysBack filters issue window\n given: target with maxDaysBack = 7\n when: SyncGitHubRepositories runs\n then:\n - fetchRepoIssues called with since = (now − 7 days).toISOString()\n - issues older than the window are not fetched\n```\n\n---\n\n## QA\n\nExecutable tests. Each step carries a human instruction (`do`) and, where the step maps to an\ninvocable operation, an agent binding (`invoke`). Report failures by test and step number.\n\n```mdl\ntest QA-1: Connect, select a repository, and sync\n desc: The core round-trip — authorize a GitHub connection, discover repos, materialize and sync one as a Project with its issues as Tasks.\n actors: both\n covers: [F-1.1, F-1.2, F-2.1, F-2.2, F-4.1, F-5.1, T-2, T-3]\n status: unverified\n given:\n - an identity exists\n - space: a space is open\n - a GitHub account reachable for OAuth, owning at least one repo with at least one open issue\n - no Project with foreign key [source: \"github.com\", id: <that repo's numeric id>] exists —\n ABORT rather than reusing a Project this test did not create\n steps:\n - name: Connect a GitHub account\n id: connect\n do: Open the GitHub connector panel (Settings -> Connectors -> GitHub) and complete the OAuth authorization test.\n capture: connection\n expect: a Connection object exists with accessToken.account set to the authorized user's GitHub login\n note: |\n NO `invoke` — the OAuth redirect and callback are real browser navigation through GitHub's\n consent screen; the debug port cannot drive it. This step is human-only for any account\n that has not already authorized the app.\n - name: Discover repositories\n do: Open the target picker for the new connection.\n invoke: [op:GetGitHubRepositories] { connection: $connection.connection }\n capture: targets\n expect: the picker lists repos visible to the token, sorted by full_name, and no Organization/Person/Project/Task objects are created yet\n assert: return $result.targets.length > 0 && !$result.targets.some((t) => /^\\d+$/.test(t.id) === false)\n - name: Select the repository as a sync target\n do: Pick the target repo from the list and confirm.\n invoke: [op:MaterializeGitHubTarget] { connection: $connection.connection, remoteTarget: $targets.targets[0] }\n capture: materialized\n expect: an empty local root Project now exists, bound to the selected repo\n assert: return !!$materialized.target\n - name: Sync the connection\n do: Click \"Sync now\" on the connection (or wait for the scheduled sync).\n invoke: [op:SyncGitHubRepositories] { connection: $connection.connection }\n capture: synced\n expect: the Project's fields are populated from the repo, and one Task exists per open/closed issue and PR in that repo\n assert: return $synced.pulled.projects >= 1 && $synced.pulled.tasks >= 1\n after:\n - name: Remove the synced Project and its Tasks\n do: Right-click the Project in the navtree and choose Delete, then repeat for each Task it produced (or delete the containing collection).\n invoke: org.dxos.operation.space.removeObjects { objects: [$materialized.target] }\n expect: the Project and its Tasks leave the navtree; the underlying GitHub repo and issues are untouched\n - name: Disconnect the GitHub account\n do: In Settings -> Connectors -> GitHub, remove the connection.\n expect: the Connection object and its stored access token are removed\n```\n\n```mdl\ntest QA-2: Local edit pushes back to GitHub\n desc: A push-direction check — editing a synced Task's title round-trips to the GitHub issue via PATCH.\n actors: human\n covers: [F-6.2, T-5]\n status: unverified\n given:\n - an identity exists\n - space: a space is open\n - a GitHub account reachable for OAuth, with write access to a repo owning at least one open\n (non-PR) issue\n - no Project with foreign key [source: \"github.com\", id: <that repo's numeric id>] exists —\n ABORT rather than reusing a Project this test did not create\n - connection: a fresh GitHub Connection, authorized against that account (same human-only\n OAuth step as QA-1's \"Connect a GitHub account\")\n - materialized: the target repo materialized and synced as a Project via\n op:MaterializeGitHubTarget then op:SyncGitHubRepositories (same steps as QA-1), leaving at\n least one open (non-PR) Task\n steps:\n - name: Edit the task title\n do: Open the synced Task and change its title.\n expect: the edit is saved locally\n note: NO `invoke` — this is an ordinary field edit through the Task surface, not a github operation.\n - name: Re-sync\n do: Click \"Sync now\" on the connection again.\n invoke: [op:SyncGitHubRepositories] { connection: $given.connection }\n expect: GitHub shows the issue's title updated to match, and the local TaskSnapshot.title now matches the new value\n note: |\n Verify by opening the issue on github.com — SyncGitHubRepositories's snapshot-diff push has\n no separate read-back operation in this document, so the effect is checked against GitHub\n itself (Execution Rule 3).\n after:\n - name: Revert the title on GitHub\n do: Edit the issue's title back to its original value directly on github.com, then re-sync.\n invoke: [op:SyncGitHubRepositories] { connection: $given.connection }\n expect: the local Task.title reflects the reverted value\n - name: Remove the synced Project and its Tasks\n do: Right-click the Project in the navtree and choose Delete, then repeat for each Task it\n produced (or delete the containing collection).\n invoke: |\n org.dxos.operation.space.removeObjects {\n refs: [$given.materialized.target,\n ...(await space.db.query(dxos.Filter.type(dxos.DXN.make('org.dxos.type.task'))).run()).objects\n .filter((task) => task.project?.target?.id === $given.materialized.target.target?.id)\n .map((task) => window.__echo.Ref.make(task))]\n }\n note: |\n `materialized.target` is a Ref, so it travels in `refs`, not `objects`; the synced Tasks\n are resolved separately because removing the Project does not cascade to them.\n expect: the Project and its Tasks leave the navtree; the underlying GitHub repo and issues are untouched\n - name: Disconnect the GitHub account\n do: In Settings -> Connectors -> GitHub, remove the connection.\n expect: the Connection object and its stored access token are removed\n```\n\n```mdl\ntest QA-3: Open a pull request from the browser extension\n desc: |\n The plugin-crx page action, end to end through the operation it names. Uses a public pull\n request so no GitHub connection is needed — the import falls back to an anonymous read.\n actors: both\n covers: [F-9.5, F-9.3]\n status: unverified\n automated:\n - composer-e2e:crx.spec.ts#Extension page actions › contributes the pull request action to the extension registry\n - composer-e2e:crx.spec.ts#Extension page actions › imports the pull request the page names\n - composer-e2e:crx-extension.spec.ts#Extension › opens the pull request the toolbar action is clicked on\n given:\n - an identity exists\n - space: a space is open\n - no PullRequest with owner \"dxos\", repo \"dxos\", number 1 exists — ABORT rather than\n deleting one this test did not create\n steps:\n - name: Open the pull request from the extension\n do: |\n On https://github.com/dxos/dxos/pull/1, open the Composer extension side panel and click\n \"Open PR in Composer\". The extension captures the page snapshot and invokes the operation\n against the active space.\n invoke: |\n org.dxos.operation.github.importPullRequestFromSnapshot {\n snapshot: { source: { url: \"https://github.com/dxos/dxos/pull/1\", title: \"chore: release 1.0.0 by github-actions[bot] - Pull Request #1 - dxos/dxos\", clippedAt: \"2026-09-22T00:00:00Z\" } },\n target: $given.space.db\n }\n capture: imported\n expect: a PullRequest titled \"chore: release 1.0.0\" now exists in the space\n assert: return !!$imported.id\n note: |\n Only `source.url` is read — the page title above is ignored, which is the point of the\n operation taking a snapshot rather than an extraction.\n - name: Re-invoke on the same pull request\n do: Click \"Open PR in Composer\" again on the same page.\n invoke: |\n org.dxos.operation.github.importPullRequestFromSnapshot {\n snapshot: { source: { url: \"https://github.com/dxos/dxos/pull/1\", title: \"chore: release 1.0.0\", clippedAt: \"2026-09-22T00:00:00Z\" } },\n target: $given.space.db\n }\n expect: the same object is returned and the space still holds exactly one copy\n assert: return $result.id === $imported.id\n - name: Generate its walkthrough\n do: Open the imported pull request and click \"Generate walkthrough\" in the article toolbar.\n invoke: |\n org.dxos.operation.github.generateWalkthrough { pullRequest: { \"/\": \"echo://$given.space.id/$imported.id\" } }\n expect: the article renders narrated prose with the change's diff chunks spliced in\n assert: return !!$result.walkthrough\n note: |\n Needs an AI provider configured — the only step here that does. GitHub itself is still read\n anonymously, so no GitHub connection is required.\n after:\n - name: Delete the imported pull request\n do: Right-click the pull request in the navtree and choose Delete.\n invoke: |\n org.dxos.operation.space.removeObjects { objects: [{ \"/\": \"echo://$given.space.id/$imported.id\" }], target: $given.space.db }\n expect: the pull request no longer appears in the space\n```\n\n---\n\n## Appendix: Extension Definitions\n\nExtension block types used in this document are defined below using\nthe core `ext` primitive — the only construct the base language provides.\n\n```mdl\next type\n uri: org.dxos.mdl.type@1.0\n desc: A named data structure with typed fields and optional literals.\n fields:\n desc?: Prose\n fields?: FieldMap # name[?]: TypeExpr (# inline comment)\n literals?: UnionList # a | b | c\n extends?: TypeRef[]\n```\n\n```mdl\next feat\n uri: org.dxos.mdl.feat@1.0\n desc: A named feature grouping one or more requirements.\n fields:\n desc?: Prose\n req: RequirementList\n nesting: self # feat blocks may contain feat blocks\n```\n\n```mdl\next scenario\n uri: org.dxos.mdl.scenario@1.0\n desc: An acceptance scenario expressed as given / when / then steps.\n fields:\n given?: Step | Step[]\n when?: Step | Step[]\n then: Step | Step[]\n tags?: TagList\n```\n\n```mdl\next component\n uri: org.dxos.mdl.component@1.0\n desc: A UI component with props, internal state, slots, actions, and events.\n fields:\n desc?: Prose\n props?: FieldMap # external inputs (immutable inside component)\n state?: FieldMap # internal reactive state\n slots?: FieldMap # named ReactNode injection points\n actions?: ActionMap # methods the component exposes or handles\n emits?: EventMap # events the component raises to its parent\n layout?: CodeBlock # ASCII sketch of visual structure (non-normative)\n```\n\n```mdl\next op\n uri: org.dxos.mdl.op@1.1\n desc: |\n A named operation with typed inputs, outputs, and declared errors.\n Pure ops have no effects or requires. Effectful ops declare both.\n fields:\n key?: NSID # runtime operation key — what the invoker receives\n desc?: Prose\n input?: FieldMap # named input parameters\n output?: TypeExpr # return type\n errors?: ErrorMap # name: Prose (when this error occurs)\n effects?: EffectList # echo:read | echo:write | http | fs | ...\n requires?: ServiceList # injected service dependencies\n note?: Prose # implementation guidance (non-normative)\n```\n";
3
3
  //#endregion
4
- export { PLUGIN_default as t };
4
+ export { PLUGIN_default as default };
5
5
 
6
6
  //# sourceMappingURL=chunk-PLUGIN.mjs.map