Skip to content

feat: open PR links in panels, drop files on sidebar threads, and measure turn tokens - #458

Merged
rynfar merged 12 commits into
pylonfrom
upstream/2026-09-10-web-panels
Sep 11, 2026
Merged

feat: open PR links in panels, drop files on sidebar threads, and measure turn tokens#458
rynfar merged 12 commits into
pylonfrom
upstream/2026-09-10-web-panels

Conversation

@rynfar

@rynfar rynfar commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Ten upstream T3 Code sources in the web-panels lane (frozen head 6c583620ff7ad3235b135af7107c0543467eecfa, tracking #414) were missing from Pylon: PR links and markdown images in the panels, a text generation model that only saved to one connection, usage columns that moved between limit rows, no file drops on sidebar rows, terminal links that needed a modifier to open, Codex usage-limit stops relayed as "out of credits", and no normalized per-turn token telemetry.

How it was ported

Each source was cherry-picked in upstream order with -x. Conflicts were resolved by splicing only that source's hunks into Pylon's files; no file was taken from upstream wholesale. ProviderService.ts was rebuilt from Pylon's version with the telemetry hunks applied one by one. Each commit names its source.

Sources

Source Upstream PR Outcome
1587f248dd81ed45e214d476451ebf16dbfadb1a #9132 measure provider turn token usage Adopted (adapted)
d64335bb5913c21869633a4236d9409911e3da52 #10473 name the Codex usage limit and its reset Adopted (adapted)
ea2983afbbcd5ad6ee2e7db80c2a9270ff4964a9 #10615 copy selected PR link from PR page Adopted
d081ab7abc16a21570d3d96948acb6c1f8d847a4 #10623 open PR markdown links in the panel Adopted
6df0add6e65b7c0040b5774635f794e4ff802ddd #10625 navigate markdown images as galleries Adopted
bc4b00666272188027d086361fa5ae01cda53bd2 #10526 generate thread titles with the selected model across connections Adopted
1f14d6d10afbcc99ec255b23544ee25c08dea321 #10690 keep account columns aligned across limit rows Adopted (adapted)
bde39d4d7977ce85d6ea396a983d6b6a25bf7e07 #7892 accept file drops into sidebar threads Adopted
b5d89038ae72142038dfa8cf69d49b7a607fe98e #7892 (duplicate commit) Already covered: empty commit with no file changes
772ea1473a4a8f8fb0e0a5c9ba6d7a2ef14eac6e #10060 honor terminal link browser overrides Adopted (adapted)

Pylon adaptations

  • Turn telemetry (#9132). AnalyticsService still sends nothing unless a Pylon T3CODE_POSTHOG_KEY is set. ProviderService watches turn analytics only after an event passes the runtime generation and session incarnation checks. It flushes held completions on session start, stop, session.exited, a thread moving to another instance, a fenced adapter rebuild, and shutdown. Shutdown flushes at the start of runShutdown, because Pylon's finalizer skips runStopAll when an adapter owns shutdown (the Prime daemon adapter does). The pending admission, rollback and compaction paths are untouched.
    • Codex: token accounting is added inside Pylon's mapper, the step that stamps the incarnation and matches admissions.
    • OpenCode: Pylon already keeps only text parts, so this uses upstream's final #10116 design (unresolvedStepsByMessageId). perf(server): reduce OpenCode streaming memory #307 had dropped the token-usage check from that test, and it is back.
    • Prime: reported as unavailable, like Cursor, Grok and Antigravity. Prime does send raw per-message usage, but its input/cache meaning and child-agent scope are not verified.
    • Tests: upstream's ProviderService analytics tests now start sessions first, because Pylon drops events from threads with no current session. They switch instances between events, since a thread routes one instance at a time. The mismatched-model case now expects the rejection Pylon already applies. The shutdown test also provides NodeServices, and it now runs twice: once as upstream wrote it, once with an adapter that owns shutdown. Two more tests cover the Pylon paths that fence out a session: switching the thread to another instance, and rebuilding a fenced adapter.
    • Docs: Pylon had no telemetry doc for this. I added docs/internals/product-analytics.md (maintainer-facing, trimmed like upstream's final version) and docs/user/telemetry.md in Pylon voice: off by default, key-gated, and how to opt out.
  • Codex limit naming (#10473). The new runtime.error carries the session incarnation. Pylon keeps relaying every account/rateLimits/updated notification for its pushed usage windows, and the snapshot merge is extra state on the side. One upstream test now counts the sparse update Pylon relays.
  • PR link copy (#10615). The command palette keeps Pylon's detected branch-PR fallback, and the panel URL hook keeps Pylon's environment-scoped cached detail lookup.
  • Image galleries (#10625). Pylon's preview caption has no snapshot-contents control, so only the caption color change applies there.
  • Shared title model (#10526). The source/target settings arguments are added to Pylon's settings writer, which also handles provider instances. Mobile's thread-settings writer never sends the text generation model, so it keeps its call. Background text generation and Prime selection are unchanged.
  • Usage columns (#10690). Pools are ordered by normalized window names, because older servers leave out window ids and kinds; a new test covers this. columns uses Pylon's NamedUsageWindow. Pylon's hub account keys stay, and the shorter usage guide now describes the column order.
  • Sidebar file drops (#7892). The row prop sits next to Pylon's change-request snapshot props; the other Sidebar.tsx edits match upstream line for line. The guide text is placed in Pylon's sidebar doc.
  • Terminal links (#10060). Only the forceBrowser hunks were spliced in. Pylon's helper still falls back to the system browser when an in-app open fails. Upstream's reject-on-settings-failure test and the drawer's error toast predate #10060 and were never in Pylon; this is an existing Pylon difference, not something cut from this source. docs/user/opening-links.md now describes the plain click and the Cmd/Ctrl override.

Exclusions and deferrals

Nothing deferred and nothing cut from these sources. Two pre-existing differences stay: the terminal link settings-failure behavior (see above) and the snapshot-contents caption UI Pylon does not have. OpenCode turn.started no longer sends a variant-derived effort; nothing in Pylon read it. Upstream's Sidebar.tsx also imports isSameSidebarThreadRef without using it; I kept that line as is.

Verification

  • Tests: 1,687 passed.
    • Server: 501 (Claude/Codex/OpenCode adapters, ProviderService, AnalyticsService, codexUsageLimits, ClaudeTextGeneration, providerRateLimitEvents, providerUsageLimits).
    • Contracts: 19.
    • Client-runtime shared settings: 26.
    • Shared usage limits: 54.
    • Web: 1,087 (rightPanelStore, openPullRequestLink, ChatMarkdown, chat components, PR markdown, useSettings, sidebar drop store, Sidebar logic, terminal link preview, terminal-links, Ghostty surface, markdown-links).
  • Typecheck passes for @t3tools/web, t3, @t3tools/shared, @t3tools/client-runtime, @t3tools/contracts and @t3tools/mobile.
  • vp lint and vp fmt --check on all 55 changed files: no errors. The only warnings are an unused useNavigate that is already in SettingsPanels.tsx on pylon, and upstream's unused sidebar import.
  • git grep PRIME_AGENT_DRIVER_KIND usages are unchanged from origin/pylon.

UI evidence: no local client pass was run; the orchestrator runs one integrated pass later. Upstream evidence: #10615 screenshot, #10625 gallery screenshots, #10690 before/after, #7892 video, #10060 video, #10473 before/after.

Ported by Claude Opus 5 in Claude Code.

t3dotgg and others added 10 commits September 10, 2026 18:17
Adapters now attach normalized main-agent token usage to terminal turn
events, and ProviderService records one provider.turn.completed analytics
event per provider instance, thread, and turn. AnalyticsService stays inert
unless a Pylon PostHog key is configured.

Pylon adaptations:
- Codex splices usage tracking into the incarnation stamping and pending
  admission correlation mapper.
- OpenCode uses the finished upstream design from #10116
  (unresolvedStepsByMessageId) because Pylon already retains only text parts.
- ProviderService observes analytics after the runtime generation and
  session incarnation fences, flushes held completions on start, stop,
  session exit, and shutdown.
- Prime, Cursor, Grok, and Antigravity report usage as unavailable.
- Upstream tests adapted to Pylon session fencing and its rejection of model
  selections for another provider instance.
- Documented in new docs/internals/product-analytics.md and
  docs/user/telemetry.md in Pylon voice.

Adopted from 1587f248dd81ed45e214d476451ebf16dbfadb1a (#9132)
…ut of credits"

When Codex stops a turn on a usage limit, the failed turn and its runtime
error now name the exhausted window, its reset, and the next step, composed
from the session's merged rate-limit snapshot.

Pylon adaptations:
- The composed runtime.error carries the session incarnation like every
  other event the adapter emits.
- Pylon keeps relaying every account/rateLimits/updated notification for its
  pushed usage windows; the snapshot merge is side state only. The earlier
  snapshot test counts the sparse update Pylon relays.

(cherry picked from commit d64335bb5913c21869633a4236d9409911e3da52)
Adopted from d64335bb5913c21869633a4236d9409911e3da52 (#10473)
The copy-reference shortcut and command palette action now copy the pull
request open on the pull requests page, including a provider URL carried by
the surface.

Pylon adaptation: the command palette keeps Pylon's detected branch pull
request fallback for thread references, and the panel URL hook keeps
Pylon's environment-scoped cached detail lookup.

(cherry picked from commit ea2983afbbcd5ad6ee2e7db80c2a9270ff4964a9)
Adopted from ea2983afbbcd5ad6ee2e7db80c2a9270ff4964a9 (#10615)
Pull request links in PR descriptions, comments, and previews now open in
the panel that shows them, including the standalone pull requests page,
instead of leaving it.

(cherry picked from commit d081ab7abc16a21570d3d96948acb6c1f8d847a4)
Adopted from d081ab7abc16a21570d3d96948acb6c1f8d847a4 (#10623)
Opening an image from chat or pull request markdown now lets arrow buttons
move through every image in that message or PR section, wrapping at either
end, with larger overlay navigation buttons.

Pylon adaptation: Pylon's preview caption has no snapshot contents control,
so only the caption color change applies.

(cherry picked from commit 6df0add6e65b7c0040b5774635f794e4ff802ddd)
Adopted from 6df0add6e65b7c0040b5774635f794e4ff802ddd (#10625)
The text generation model is now a shared server setting: choosing it in
General writes the model and its options to every connected environment
whose matching provider instance is enabled, and "Apply to all" reconciles
drift. Claude text generation runs in non-interactive dontAsk mode so
titles work on servers running as root.

Pylon adaptation: splice the source settings and target settings arguments
into Pylon's provider-instance-aware settings writer. Mobile's thread
settings writer never sends the text generation model, so it keeps its
existing call.

(cherry picked from commit bc4b00666272188027d086361fa5ae01cda53bd2)
Adopted from bc4b00666272188027d086361fa5ae01cda53bd2 (#10526)
Pooled limit rows now keep each account in one column across windows,
ordered by the session reset (or the first available window), with a gap
where an account does not report a window. Each row's reset list stays
chronological. Web, desktop, and mobile share the order.

Pylon adaptations: ordering reads the same normalized window names the
pools use, because older servers omit window ids and kinds; a focused test
covers that. The Pylon hub account keys and the condensed usage guide are
kept, with the column order described.

(cherry picked from commit 1f14d6d10afbcc99ec255b23544ee25c08dea321)
Adopted from 1f14d6d10afbcc99ec255b23544ee25c08dea321 (#10690)
Dropping files from the computer onto a sidebar thread row or search result
opens that thread and attaches the files in its composer through the same
path as a workspace drop. Nothing is sent. The flat and project sidebars
both accept drops.

Pylon adaptation: splice the row prop and handler beside Pylon's change
request snapshot props, and describe the drop in Pylon's sidebar guide.
b5d89038ae72142038dfa8cf69d49b7a607fe98e is an empty duplicate of this
source and changes nothing.

(cherry picked from commit bde39d4d7977ce85d6ea396a983d6b6a25bf7e07)
Adopted from bde39d4d7977ce85d6ea396a983d6b6a25bf7e07 (#7892)
Already covered: b5d89038ae72142038dfa8cf69d49b7a607fe98e (#7892, empty duplicate)
Terminal links now open with a primary click, dragging from a link starts a
text selection, and Cmd/Ctrl-click sends the link to the system browser
regardless of the Open links in setting.

Pylon adaptation: Pylon's terminal link helper keeps falling back to the
system browser when a settings read or in-app open fails, so upstream's
reject-on-settings-failure test and the drawer's error toast are not
ported. The link guide now describes the plain click and the override.

(cherry picked from commit 772ea1473a4a8f8fb0e0a5c9ba6d7a2ef14eac6e)
Adopted from 772ea1473a4a8f8fb0e0a5c9ba6d7a2ef14eac6e (#10060)
@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pylon-marketing Ready Ready Preview Sep 11, 2026 1:15am UTC

@github-actions github-actions Bot added size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Sep 11, 2026
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.9 KiB 13.9 KiB −7 B (−0.0%) 15.1 KiB
Codex Thread snapshot wire 7.2 KiB 7.2 KiB +1 B (+0.0%) 7.3 KiB
Codex Live turn WebSocket wire 6.7 KiB 6.7 KiB −8 B (−0.1%) 7.8 KiB
Codex Live turn WebSocket decoded 58.0 KiB 58.0 KiB 0 B (0.0%) 66.4 KiB
Codex Live turn messages 8 8 0 (0.0%) 21
Claude Total thread wire 13.9 KiB 14.1 KiB +156 B (+1.1%) 15.1 KiB
Claude Thread snapshot wire 7.2 KiB 7.2 KiB 0 B (0.0%) 7.3 KiB
Claude Live turn WebSocket wire 6.7 KiB 6.9 KiB +156 B (+2.3%) 7.8 KiB
Claude Live turn WebSocket decoded 58.8 KiB 59.7 KiB +928 B (+1.5%) 66.4 KiB
Claude Live turn messages 8 10 +2 (+25.0%) 21

Baseline: 1e1a43d · PR result: 74868a2 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 115.6 KiB
  • Claude decoded thread snapshot: 116.3 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

…ions

Pylon's finalizer runs runShutdown, which reaches runStopAll only when no
adapter owns shutdown, so held turn completions were never recorded when the
Prime daemon adapter was registered. Flush them at the start of runShutdown
as well.

When a thread starts on another provider instance, or a fenced adapter is
rebuilt, Pylon drops the old session's later turn events before analytics
sees them. Clear that instance's analytics for the thread in both paths so
its held completions are recorded instead of lingering until reuse.

Focused tests cover the adapter-owned shutdown path, an instance switch,
and a fenced adapter rebuild.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants