Skip to content

[feature] Coding agents cannot show a pull request — add a Pulls panel, and make "don't fetch if nothing changed" true with GitHub conditional requests #401

Description

@serge-ivo

The Coder can open a PR and then cannot show you one

Four GitHub tools exist (connectors/github.ts): github_workflow_runs, github_list_issues,
github_read_issue, github_create_issue. There is no pull-request support anywheregrep
for /pulls across workers/api/src returns nothing.

Worse than absent: the one place GitHub hands them over, we discard them. lib/github-issues.ts:107

return data.filter((i) => !i.pull_request).map(toSummary);

with the comment "GitHub returns PRs from the issues endpoint too". Correct for an issues list,
and it means the data arrives and is dropped.

This matters because the Coder's safest mode produces exactly this artefact. The per-repo merge
policy (#314) has a pr setting: the agent does the work, opens a pull request and stops. That is
the mode a careful owner picks — and having picked it, the console can show them the issue that
started the work and the build that ran, but not the PR that is the actual output. They have to
leave for GitHub to see what their agent just produced.

The Coding tab already has the shape: Terminal · Issues · Builds. This is the missing fourth.

What to show

Per repo, the open PRs, and for each: number, title, author, draft flag, mergeable/conflicted,
review state (approved / changes requested / none), check status (which is already fetched for
Builds — fetchWorkflowRuns — so the two panels are reading the same runs from different angles),
branch, updated-at. Plus, and this is the one that closes the loop: which PR came from which
agent run
, when a Pilot opened it.

Caching — and specifically "don't fetch if nothing changed"

There are TWO layers here and the repo has exactly one of them. Naming both, because the cheap one
is not the one that protects the rate limit.

Layer 1 — console → platform. Built, for builds only. routes/coding-repos.ts:293-300 merges a
durable KV history, computes a weak ETag over the result, and answers If-None-Match with a 304.
That is the pattern to copy verbatim; it saves bytes and re-renders.

Layer 2 — platform → GitHub. Not built, anywhere. Even the builds path fetches GitHub on every
poll and only then decides whether to send the client a 304. GitHub's own conditional requests are
the mechanism the request is asking for:

  • store the ETag GitHub returned, send it back as If-None-Match;
  • a 304 does not count against the rate limit — that is the entire point of it;
  • on 304, serve the cached copy and touch nothing else.

That is what makes "don't fetch if there were no changes" true rather than approximately true. It
matters here more than usual: /deployments documents an unauthenticated fallback on a shared
~60/hr IP budget, and issues-mode calls listIssues on every Loop iteration via nextIssue()
— today that is an unconditional GitHub round-trip per iteration, per repo.

Complementary, not a substitute: ?since= on issues and sort=updated&direction=desc on pulls
bound the payload; the ETag bounds the request.

Suggested shape

  1. lib/github-prs.ts beside github-issues.ts — same auth path (App installation token, with
    the same unauth fallback for public repos), same summary/detail split.
  2. A conditional-fetch helper, shared by issues, PRs and builds: store {etag, payload, fetchedAt} in KV per (repo, resource), send If-None-Match, return the cached payload on 304.
    One place, three consumers — and it retro-fixes the builds path's Layer-2 gap.
  3. GET /:instanceId/coding/repos/:repoId/pulls mirroring /deployments, including the weak
    ETag and 304 for Layer 1.
  4. A Pulls panel in the Coding tab beside Issues and Builds.
  5. github_list_pulls / github_read_pull tools (read scope) so the agent can answer "is my PR
    green? did anyone review it?" without a browser. github_merge_pull is deliberately NOT proposed
    here — merging is what the merge policy ([safety] Nothing decides whether an agent may merge to main — three unattended merges already happened #314) governs, and a tool that bypasses it would hand
    the agent the authority that ticket exists to withhold.

Worth deciding

  • Does the PR panel show only PRs the agent opened, or all of them? All of them is more useful
    and makes the panel a real view of the repo; agent-opened ones should be badged, since "did my
    agent actually open it" is the question the board cannot answer today.
  • How stale may a cached list be when GitHub is unreachable? The builds path already answers
    this well (durable KV history that survives retention and transient failure) and the same answer
    probably applies.

Files: workers/api/src/lib/github-issues.ts:103-122, workers/api/src/lib/connectors/github.ts:134-165,
workers/api/src/routes/coding-repos.ts:264-305, workers/api/src/lib/build-history.ts.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions