Repository navigation
feat(cli-registry): GitHub Copilot CLI as a run mode - #592
opticon454 wants to merge 9 commits into
Conversation
|
Switched to draft as I'll implement the missing features so GH copilot goes in complete |
232994c to
ccead2e
Compare
Copilot (`copilot`, npm @github/copilot) as a stock CLI entry with the same launch options as the other agent CLIs: model (--model), resume (--resume), continue (--continue) and allow-all (--yolo, clamped off for non-granted multi-user owners). Adds a resolver and GET /api/copilot/status probe, the agent-image package, Run-menu/mobile/logo entries, skill docs and tests.
ccead2e to
7407bbc
Compare
|
I've been using this manually from my desktop and mobile and I can't find any faults with it |
|
Thanks @opticon454, this is a thorough piece of work: GitHub Copilot CLI becomes a full run mode through a registry entry, with launch options, the multi-user clamp, BYOK custom endpoints, footer-based working/idle and model detection, a status probe and tests to match. The measurements in the entry comments are exactly what makes a new CLI reviewable. Typecheck, lint, format and the full test gate all pass here. A few things to change before merge:
Smaller things I can pick up at merge time if you prefer: the Prettier re-padding of the unrelated tables in Once 1 to 4 are in, this is ready to merge. Thanks again for driving it all the way to a complete mode. |
7407bbc to
1d107ec
Compare
- Drop GH_TOKEN / GITHUB_TOKEN from env.allowedKeys. The allowlist is one global list with no mode context, so they were settable on every session. COPILOT_GITHUB_TOKEN is already admitted by the COPILOT_ prefix. - Declare capabilities.mcpConfig (copilot-json, COPILOT_HOME relocation) so Settings does not list Copilot as unsupported while the sync-only target also lists it. The sync-only row is skipped while the run mode is enabled. - Require a leading alphanumeric on the resume id (path-segment in the registry, matching regex in the schema): --resume's value is optional, so `--resume --yolo` made --yolo its own flag and bypassed the allowAll clamp. Golden cases added; "ids only" wording corrected. - Remove the unread overlays.credStore line and document signing in inside a Docker container. - Add the zh-CN "Run GitHub Copilot" string, pin the new declarations in tests and update the MCP registry expectations.
Copilot's TUI turns mouse tracking on itself. Under `strip-mux-only` those DECSETs reached xterm, which then reported a plain drag to the TUI instead of selecting (only Shift+drag selected), so Auto Copy and copy-on-select did nothing. This is the failure opencode had and `strip-mux-and-mouse` was added for: the DECSETs are stripped, a drag is a local selection and clicks still reach the CLI through the browser's hand-encoded tap (`cliMouseTracking`). Stripping them also stops xterm from encoding the wheel for the CLI, so `_shouldForwardWheelToApp` now forwards it as SGR reports while Copilot is tracking the mouse (the same bytes xterm sent natively, which is what scrolling was verified against). Shift+wheel stays on local scrollback and a stale flag falls back to PageUp/PageDown. Tests: the strip flavor for copilot (stripped DECSETs, 3J kept, cliMouseTracking, direct-PTY untouched) and the wheel gate (forwards while tracking, no other non-claude mode changes).
…its for it Copilot had no composerReadyMark, so `codeman agent spawn --mode copilot` returned as soon as the session existed, before the composer could take a prompt (and before folder trust was answered). The mark is the composer's footer hint, not the glyph: the trust dialog draws `❯ 1. Yes`, so `❯` would call a worker ready while it still asks for trust. Measured on 1.0.95: the dialog footer reads `↑/↓ to navigate`, the composer's reads `/ commands · ? help`.
`/api/sessions/:id/last-response` fell through to the Claude transcript scan for copilot (not in the external-CLI list), so `codeman agent read` answered empty even with an answer on screen. Copilot is a repainting full-screen TUI whose stream is absolute cursor moves, so the buffer cannot be cut into lines either; the route now reads the pane's visible screen (tmux capture-pane) for such modes and falls back to the buffer where there is no pane. The segmenter gets a small per-CLI "pane dialect" row instead of another branch in the Codex-oriented loop: `❯ <prompt> HH:MM`, `● <answer>` with indented continuation, the cwd / `Session: N AIC used` row, composer, footer and the `┃` scrollbar gutter are chrome, and everything before the first prompt (banner, trust dialog) is dropped so a session that has not been asked anything answers nothing rather than serving its logo. Fixture is a real Copilot 1.0.95 pane. Tool-call rows are not modelled and read as answer text.
1d107ec to
25ee641
Compare
|
Thanks for the careful review. All four are in as new commits on top of the original, so the delta is easy to see (
From the smaller list I did the zh-CN One more fix, found while testing: copy on selection. Copilot's TUI turns mouse tracking on itself. Under Two more, from the
How I checked it: a throwaway Codeman instance (own data dir and tmux socket) against a local OpenAI-compatible endpoint, with a real Chromium. A plain drag in a Copilot pane gave a selection that Auto Copy put on the clipboard and the wheel left as Full suite ( |
The Copilot CLI has no scriptable usage command (`copilot billing` exists only inside the TUI), but the quota the editors show is `GET https://api.github.com/copilot_internal/user`, readable with the CLI's own sign-in token. The header chip gets a `Copilot` row with one `mo` window (the calendar-month premium-request quota) beside Claude's and Codex's, with request counts and the reset in the tooltip. The host polls it every 10 minutes, read-only like the Codex poll, and only when the CLI is installed, a token resolves (COPILOT_GITHUB_TOKEN, GH_TOKEN, GITHUB_TOKEN, then authTokens in <COPILOT_HOME or ~/.copilot>/config.json) and plan-usage display is on, so turning the chip off also stops the request. The endpoint is undocumented, so every failure (offline, 401, a changed shape, an unlimited quota) yields no row. The token is never logged and is sent only to api.github.com with redirects refused.
|
One more addition since the review fixes: the header plan-usage chip now has a Copilot row ( What it shows. One Where it comes from. The Copilot CLI has no scriptable usage command (
Tests. The parser (including overage clamping and the unlimited case), the token lookup (env precedence, the commented Also confirmed since the last comment: touch swipes on a phone reach Copilot as wheel reports in both directions (the same wheel forwarding that fixed drag selection), checked with real touch events in an emulated phone. If you'd rather not ship the network read in this PR, it is one self-contained commit and easy to drop; say so and I'll split it out. |
- New docs/copilot-integration.md in the shape of the other CLI guides: install and identity probe, authentication (keychain vs plain-text config.json, COPILOT_GITHUB_TOKEN), what Codeman wires up (Run button --yolo and its clamp, model, resume, continue, --name rule), BYOK custom endpoints, terminal behaviour (drag selection, wheel and touch), the codeman agent verbs (ready mark, read), plan usage, Docker, Remote SSH, what is deliberately not wired, known gaps. - Agent-CLIs wiki: the eleven-modes table, a GitHub Copilot CLI section, the env prefix row, the feature-comparison rows and the status endpoint list. - README, Home, FAQ, Core Concepts, Docker Cases, Remote SSH, Contributing, The Dashboard and Custom Model Endpoints: mode lists and counts; CLAUDE.md: stack line, SessionMode, prefixes, resolver list, external-CLI notes and the plan-usage source; api-reference MCP target wording; the env allowlist error message names COPILOT_*.
FAQ, Installation and Security said the only network traffic is browser to server. The plan-usage Copilot row asks api.github.com for the user's own quota, so each now states that one optional exception, when it happens (CLI installed and signed in, chip on) and how to stop it.
|
Thanks @opticon454, this round closes all four points from the first review exactly as asked: Two of the newer pieces need a fix before merge:
Smaller things I will pick up at merge time unless you get to them first:
Once 1 to 3 are in, this is ready to merge. Thanks again for taking Copilot all the way to a complete mode, with measurements to back every choice. |
…allback, review nits Review of 8659ba2..be987fb: - Usage: a Free account answers premium_interactions {entitlement: 0, remaining: 0, percent_remaining: 0, unlimited: false, has_quota: false}, which read as 100% used. The parser now returns null when has_quota is false or the entitlement is not positive, with that payload as a fixture. Free meters chat (200) and completions (2000) too, so the comment no longer says they are unlimited on every plan. - agent read: rows were skipped until a `❯ <prompt>` row, so an answer taller than the pane (prompt scrolled off the top) read as "". With no prompt row AND no banner / trust dialog on screen, the rows above the composer are now the tail of the last answer. Text typed in the composer (a prompt-shaped row between the two rules) is not a prompt row. - Page keys: measured on 1.0.95 in tmux that Copilot pages on PageUp/PageDown (three PageUp moved lines 109-140 to 010-042, PageDown returned) as well as on SGR wheel reports, so copilot joins claude and opencode in _localScrollbackIsHollow(); the stale-tracking-flag fallback the comment and docs describe is now true, for the main pane and a TerminalTile (same function), with tests. - X-GitHub-Api-Version is 2022-11-28, a version GitHub supports (verified against the live endpoint); readPlanUsageTelemetryEnabled() is checked before isCopilotAvailable() so a switched-off chip skips the resolver probe too. - Palette label for Copilot in panels-ui.js; stale comments in types/session.ts and stock.ts. - Docs: Past Sessions continues with --continue (resumeSessionId is for API callers), nothing sets continueSession on a respawn, and only a tab name the user set is passed as --name; the usage wording for Free; the wheel and mouse-strip paragraphs in CLAUDE.md and architecture-invariants; the changeset describes the whole feature.
|
Thanks, all three are fixed in 1. Free shows 100% used. 2. 3. PageUp/PageDown fallback. I measured it rather than drop the claim: on 1.0.95 in tmux, three PageUp moved a 140-line answer from lines 109-140 to 010-042 and three PageDown returned, so Copilot does page on those keys (SGR wheel reports also scroll it, 3 lines per report). Smaller things, done so you do not have to:
|
Summary
GitHub Copilot CLI (
copilot, npm@github/copilot) as a stock run mode, with the same launch options as the other agent CLIs. Covers #198.It shows up in the Run menu, welcome screen, phone picker and cron agent list once installed, runs in tmux like the other agent CLIs, and CLI management can install it (
npm install -g @github/copilot).copilotConfigon the session create and quick-start bodies, the same shape asgrokConfig/ompConfig:model(--model),resumeSessionId(--resume <value>for API callers: one plain word starting with a letter or digit, so a flag-shaped value such as--yolois dropped),continueSession(--continue, which Past Sessions sends: the most recent conversation in that directory) andallowAll(--yolo).allowAll: true, like grok'salwaysApproveand antigravity'sdangerouslySkipPermissions.allowAllis aprivilegedParam, so a non-granted multi-user owner has it forced back tofalse; an absent config is not materialized, because a barecopilotis already in Manual Approval.COPILOT_HOMEandCOPILOT_ALLOW_ALLare privileged env keys.◉ Working esc edit prompt(the dot alternates◉/◎); the composer is the❯between two rules. A tool waiting for approval replaces the composer and the tab reads idle.COPILOT_PROVIDER_BASE_URL,_API_KEY,COPILOT_MODEL) are injected for a Custom Model Endpoint, with the/v1suffix, so the Run menu's custom endpoint rows work for it; the three are privileged env keys.--name(an automaticw1-…name is not pinned), except next to--resume/--continue, which Copilot refuses to combine with it (a continued session keeps its name).altScreen: 'strip-mux-and-mouse'like opencode: a plain drag is a local selection (Auto Copy and copy-on-select work, not just Shift+drag), clicks still reach the CLI through the hand-encoded tap, and the wheel is forwarded as SGR reports while the CLI is tracking the mouse.codeman agentverbs: the session exportsCODEMAN_MUX,CODEMAN_SESSION_IDandCODEMAN_API_URL, sols,spawn,send,wait,read,interruptandrmwork.composerReadyMarkis the composer's footer hint (/ commands · ? help), not❯, which the folder-trust dialog also draws.agent readreturns the last answer: the route reads the pane's visible screen for this repainting TUI and segments it with a per-CLI pane dialect (prompt, answer bullet, chrome, scrollbar gutter). Tool-call rows are not modelled and read as answer text. A prompt row scrolled off by a tall answer reads as the answer's tail (unless the banner or trust dialog is on screen).--until stopis refused for Copilot like other hook-less modes;idle,exitor--matchmarkers work.Copilotrow with the calendar-month premium-request quota (mo, with request counts and the reset in the tooltip), read fromGET api.github.com/copilot_internal/userwith the CLI's own sign-in token. The endpoint is not part of GitHub's documented API (the editors use it), so the read is best-effort and silent: 10-minute host poll, only when the CLI is installed, a token resolves and plan-usage display is on; any failure, an unlimited quota or no premium quota at all (a Free account answersentitlement: 0, has_quota: false) just shows no row.GET /api/copilot/status(available,path,version), backed bycopilot-cli-resolver.ts, which only accepts a binary whose--versionsaysGitHub Copilot CLI.COPILOT_prefix only (a headless host setsCOPILOT_GITHUB_TOKEN);GH_TOKEN/GITHUB_TOKENstay out of the global allowlist.capabilities.mcpConfig(~/.copilot/mcp-config.json,COPILOT_HOMErelocation), so Settings no longer lists Copilot as unsupported. The sync-only row inmcp-sync-targets.tsis skipped while the run mode is enabled.credStore; Copilot's token is plain text inconfig.jsonon a host without a keyring, so it is not seeded. Sign in inside the container (documented inDocker-Cases.md).Measured on 1.0.94 inside tmux
Alternate-screen TUI with mouse tracking on. Keystrokes sent with
tmux send-keysand throughPOST /api/sessions/:id/inputreach the composer, Shift+Enter inserts a newline, mouse-wheel scrolling works, and shell tool calls complete (an approval prompt, a 6 s command, 3000 lines of output). github/copilot-cli#4180 (a driven PTY ignores input) and #4223 (a shell command never completes under tmux) were filed against 1.0.70 to 1.0.74; neither reproduces on 1.0.94, so older installs may still hit them.Also checked against a mock OpenAI endpoint (1.0.95)
With
COPILOT_PROVIDER_BASE_URL=http://127.0.0.1:<port>/v1,COPILOT_PROVIDER_API_KEYandCOPILOT_MODELset,copilot -pposts to/v1/chat/completionswith the key and the model name, no GitHub sign-in.--resume <id> --model <m>and--continue --model <m>resume the earlier session;--namewith either is rejected, hence the rule above.Checked end to end
A throwaway Codeman instance (own data dir and tmux socket) against a local OpenAI-compatible endpoint, with a real Chromium: a plain drag in a Copilot pane produced a 38-character selection that Auto Copy put on the clipboard, and the wheel went out as
ESC[<64;…Mreports. A shell pane that turns mouse tracking on itself (the pre-fix situation) produced no selection and left the clipboard alone, so the check does detect the failure. Thecodeman agentlifecycle ran against two Copilot panes:spawnwarns instead of claiming ready while the trust dialog is up,--waitresolves onidle,readreturns the answer, theWORKDONE_4711marker wait matches,interruptandrmwork, andrmof self is refused.Tests
Spawn golden and
copilot-cli-resolvertests, the multi-user clamp, history-resume fidelity, the capability-predicate row, remote/docker overlay commands, install.sh detection parity, docker-agent-image coverage, the id-branching guard (legacy<Mode>Configplumbing allowlisted as for grok), and the registry load/schema tests.tsc --noEmitand lint clean.