@dxos/plugin-github 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/lib/GitHubOperation.mjs +27 -1
  2. package/dist/lib/GitHubOperation.mjs.map +1 -1
  3. package/dist/lib/chunk-PullRequestArticle.mjs +31 -11
  4. package/dist/lib/chunk-PullRequestArticle.mjs.map +1 -1
  5. package/dist/lib/chunk-import-pull-request.mjs +78 -3
  6. package/dist/lib/chunk-import-pull-request.mjs.map +1 -1
  7. package/dist/lib/chunk-refresh-pull-requests.mjs +49 -0
  8. package/dist/lib/chunk-refresh-pull-requests.mjs.map +1 -0
  9. package/dist/lib/chunk-sync-pull-request.mjs +11 -9
  10. package/dist/lib/chunk-sync-pull-request.mjs.map +1 -1
  11. package/dist/lib/operations.mjs +2 -1
  12. package/dist/lib/operations.mjs.map +1 -1
  13. package/dist/types/src/components/PullRequestOverview/CheckRunList.d.ts +5 -2
  14. package/dist/types/src/components/PullRequestOverview/CheckRunList.d.ts.map +1 -1
  15. package/dist/types/src/components/PullRequestOverview/CheckRunList.test.d.ts +2 -0
  16. package/dist/types/src/components/PullRequestOverview/CheckRunList.test.d.ts.map +1 -0
  17. package/dist/types/src/components/PullRequestStatus/PullRequestStatus.d.ts.map +1 -1
  18. package/dist/types/src/operations/import-pull-request.d.ts.map +1 -1
  19. package/dist/types/src/operations/index.d.ts.map +1 -1
  20. package/dist/types/src/operations/refresh-pull-requests.d.ts +5 -0
  21. package/dist/types/src/operations/refresh-pull-requests.d.ts.map +1 -0
  22. package/dist/types/src/operations/refresh.d.ts +37 -0
  23. package/dist/types/src/operations/refresh.d.ts.map +1 -0
  24. package/dist/types/src/operations/refresh.test.d.ts +2 -0
  25. package/dist/types/src/operations/refresh.test.d.ts.map +1 -0
  26. package/dist/types/src/operations/sync-pull-request.d.ts.map +1 -1
  27. package/dist/types/src/stories/PullRequestOverview.stories.d.ts.map +1 -1
  28. package/dist/types/src/types/GitHubOperation.d.ts +11 -0
  29. package/dist/types/src/types/GitHubOperation.d.ts.map +1 -1
  30. package/dist/types/tsconfig.tsbuildinfo +1 -1
  31. package/package.json +42 -42
  32. package/src/components/PullRequestOverview/ArtifactPill.tsx +1 -1
  33. package/src/components/PullRequestOverview/CheckRunList.test.ts +29 -0
  34. package/src/components/PullRequestOverview/CheckRunList.tsx +28 -7
  35. package/src/components/PullRequestStatus/PullRequestStatus.tsx +8 -5
  36. package/src/operations/import-pull-request.ts +8 -0
  37. package/src/operations/index.ts +1 -0
  38. package/src/operations/refresh-pull-requests.ts +69 -0
  39. package/src/operations/refresh.test.ts +112 -0
  40. package/src/operations/refresh.ts +111 -0
  41. package/src/operations/sync-pull-request.ts +10 -13
  42. package/src/stories/PullRequestOverview.stories.tsx +2 -1
  43. package/src/types/GitHubOperation.ts +26 -0
@@ -23,6 +23,7 @@ var GitHubOperation_exports = /* @__PURE__ */ __exportAll({
23
23
  ImportPullRequest: () => ImportPullRequest,
24
24
  ImportPullRequestFromSnapshot: () => ImportPullRequestFromSnapshot,
25
25
  MaterializeGitHubTarget: () => MaterializeGitHubTarget,
26
+ RefreshPullRequests: () => RefreshPullRequests,
26
27
  ReviewState: () => ReviewState,
27
28
  SubmitPullRequestApproval: () => SubmitPullRequestApproval,
28
29
  SyncGitHubRepositories: () => SyncGitHubRepositories,
@@ -263,6 +264,31 @@ var SyncPullRequest = Operation.make({
263
264
  updated: Schema.Array(Schema.String) }),
264
265
  types: [PullRequest.PullRequest]
265
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"));
266
292
  /** Aggregate outcome of a commit's check runs; `none` when the commit has no checks at all. */
267
293
  var CiState = Schema.Literals([
268
294
  "success",
@@ -353,6 +379,6 @@ var GetPullRequestDiff = Operation.make({
353
379
  */
354
380
  var createWalkthroughProgressKey = (pullRequest) => Obj.getURI(pullRequest, { prefer: "absolute" }).toString() + "#walkthrough";
355
381
  //#endregion
356
- export { AddPullRequestComment, AddPullRequestReviewComment, CheckCounts, CheckOutcome, CheckRun, CiState, GenerateWalkthrough, GetGitHubRepositories, GetPullRequestDiff, GetPullRequestStatus, ImportPullRequest, ImportPullRequestFromSnapshot, MaterializeGitHubTarget, ReviewState, SubmitPullRequestApproval, SyncGitHubRepositories, SyncOptions, SyncPullRequest, createWalkthroughProgressKey, GitHubOperation_exports as t };
382
+ export { AddPullRequestComment, AddPullRequestReviewComment, CheckCounts, CheckOutcome, CheckRun, CiState, GenerateWalkthrough, GetGitHubRepositories, GetPullRequestDiff, GetPullRequestStatus, ImportPullRequest, ImportPullRequestFromSnapshot, MaterializeGitHubTarget, RefreshPullRequests, ReviewState, SubmitPullRequestApproval, SyncGitHubRepositories, SyncOptions, SyncPullRequest, createWalkthroughProgressKey, GitHubOperation_exports as t };
357
383
 
358
384
  //# sourceMappingURL=GitHubOperation.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"GitHubOperation.mjs","names":[],"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/** 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 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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"}
1
+ {"version":3,"file":"GitHubOperation.mjs","names":[],"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 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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"}
@@ -575,7 +575,7 @@ var ArtifactPill = ({ artifact, children }) => {
575
575
  size: "sm",
576
576
  classNames: "bg-input-surface text-fg font-normal ring-inset ring ring-neutral-border hover:bg-hover-surface hover:ring-info-border align-baseline",
577
577
  icon: artifactIcon[artifact.kind],
578
- iconClassNames: artifact.kind === "video" ? "text-violet-500" : "text-sky-500",
578
+ iconClassNames: artifact.kind === "video" ? "text-violet-text" : "text-sky-text",
579
579
  label,
580
580
  "data-testid": "pull-request.artifact.pill"
581
581
  })
@@ -619,14 +619,29 @@ var outcomeOrder = [
619
619
  "neutral",
620
620
  "skipped"
621
621
  ];
622
- /** `4m 12s`, or undefined for a run that has not both started and finished. */
623
- var formatDuration = (startedAt, completedAt) => {
624
- if (!startedAt || !completedAt) return;
625
- const seconds = Math.max(0, Math.round((Date.parse(completedAt) - Date.parse(startedAt)) / 1e3));
622
+ /**
623
+ * `4m 12s` from start to finish, or to `now` for a run still in progress;
624
+ * undefined for a run that has not started, or has not finished when no `now` is given.
625
+ */
626
+ var formatDuration = (startedAt, completedAt, now) => {
627
+ const end = completedAt ? Date.parse(completedAt) : now;
628
+ if (!startedAt || end === void 0) return;
629
+ const seconds = Math.max(0, Math.round((end - Date.parse(startedAt)) / 1e3));
626
630
  if (Number.isNaN(seconds)) return;
627
631
  const minutes = Math.floor(seconds / 60);
628
632
  return minutes > 0 ? `${minutes}m ${seconds % 60}s` : `${seconds}s`;
629
633
  };
634
+ /** The current time, re-rendering once a second while `active` so elapsed times stay current. */
635
+ var useNow = (active) => {
636
+ const [now, setNow] = useState(() => Date.now());
637
+ useEffect(() => {
638
+ if (!active) return;
639
+ setNow(Date.now());
640
+ const interval = setInterval(() => setNow(Date.now()), 1e3);
641
+ return () => clearInterval(interval);
642
+ }, [active]);
643
+ return now;
644
+ };
630
645
  /** Sorts runs by what needs attention, then by name so shards read in order. */
631
646
  var sortCheckRuns = (runs) => [...runs].sort((a, b) => outcomeOrder.indexOf(a.outcome) - outcomeOrder.indexOf(b.outcome) || a.name.localeCompare(b.name, void 0, { numeric: true }));
632
647
  /** Every check on the head commit: its outcome, how long it took, and its logs a click away. */
@@ -634,6 +649,7 @@ var CheckRunList = ({ runs }) => {
634
649
  const { t } = Hooks.useTranslation(meta.profile.key);
635
650
  const sorted = useMemo(() => runs ? sortCheckRuns(runs) : void 0, [runs]);
636
651
  const summary = useCheckSummary(runs);
652
+ const now = useNow(runs?.some((run) => run.outcome === "pending" && run.startedAt) ?? false);
637
653
  if (!sorted || sorted.length === 0) return /* @__PURE__ */ jsx(Status.Empty, { children: t(sorted ? "no-checks.message" : "checks-loading.message") });
638
654
  return /* @__PURE__ */ jsx(Listbox.Root, {
639
655
  items: sorted.map((run) => ({
@@ -645,9 +661,9 @@ var CheckRunList = ({ runs }) => {
645
661
  "data-testid": "pull-request.checks",
646
662
  children: sorted.map((run) => {
647
663
  const { icon, classNames } = outcomeIcon[run.outcome];
648
- const duration = formatDuration(run.startedAt, run.completedAt);
664
+ const duration = formatDuration(run.startedAt, run.completedAt, run.outcome === "pending" ? now : void 0);
649
665
  const detail = run.conclusion && run.conclusion !== run.outcome && run.conclusion !== "failure" ? run.conclusion.replace(/_/g, " ") : void 0;
650
- const outcome = run.outcome === "skipped" ? t("check-outcome.skipped.label") : duration ?? t(`check-outcome.${run.outcome}.label`);
666
+ const outcome = run.outcome === "skipped" ? t("check-outcome.skipped.label") : run.outcome === "pending" ? [t("check-outcome.pending.label"), duration].filter(Boolean).join(" · ") : duration ?? t(`check-outcome.${run.outcome}.label`);
651
667
  const url = run.url;
652
668
  return /* @__PURE__ */ jsxs(Listbox.Item, {
653
669
  id: `${run.name}-${url ?? ""}`,
@@ -1004,9 +1020,11 @@ var ciHue = {
1004
1020
  /** One line answering where the pull request stands: open or merged, approved or not, CI green or red. */
1005
1021
  var PullRequestStatus = ({ reference, title, state, review, ci }) => {
1006
1022
  const { t } = Hooks.useTranslation(meta.profile.key);
1007
- return /* @__PURE__ */ jsxs("div", {
1023
+ return /* @__PURE__ */ jsxs(Layout.Flex, {
1024
+ align: "center",
1025
+ gap: "sm",
1008
1026
  role: "status",
1009
- className: "flex items-center gap-2 px-3 py-1.5 border-b border-separator-subtle text-sm min-w-0",
1027
+ classNames: "px-3 py-1.5 border-b border-separator-subtle text-sm min-w-0",
1010
1028
  "data-testid": "pull-request.status",
1011
1029
  children: [
1012
1030
  /* @__PURE__ */ jsx("span", {
@@ -1018,8 +1036,10 @@ var PullRequestStatus = ({ reference, title, state, review, ci }) => {
1018
1036
  className: "truncate grow",
1019
1037
  children: title
1020
1038
  }),
1021
- /* @__PURE__ */ jsxs("div", {
1022
- className: "flex items-center gap-2 shrink-0 ml-auto",
1039
+ /* @__PURE__ */ jsxs(Layout.Flex, {
1040
+ align: "center",
1041
+ gap: "sm",
1042
+ classNames: "shrink-0 ml-auto",
1023
1043
  children: [
1024
1044
  state && /* @__PURE__ */ jsx("span", {
1025
1045
  className: "dx-tag dx-tag-inline",