The interactive GitHub Copilot device-code provider auth ("github-copilot".auth.run)
short-circuited with { profiles: [] } whenever process.stdin.isTTY was false and
otherwise delegated to githubCopilotLoginCommand, which drives readline against
stdin/stdout. That made the device flow unusable from the gateway RPC bridge
and any GUI wizard frontend (including the WinUI tray app), where there is no
controlling TTY and no shared stdin with the gateway process.
This change adds a high-level runGitHubCopilotDeviceFlow() helper in
extensions/github-copilot/login.ts that:
- validates the GitHub verification URL (must be https://github.com/login/device)
and trims/length-checks user_code before exposing them to the host UI;
- exposes a small io interface (showCode + openUrl) so callers render the
code through their own surface (ctx.prompter.note + ctx.openUrl);
- returns a typed result of { authorized | access_denied | expired }
instead of throwing for normal terminal states.
runGitHubCopilotAuth() in extensions/github-copilot/index.ts is rewritten to
use that helper: it drops the isTTY gate, emits the URL/code/expiry through
ctx.prompter.note, best-effort calls ctx.openUrl, and returns the credential
inline via the returned profiles. The framework then persists it under the
correct agentDir, identical to the existing non-interactive path that Val
introduced in 461c10bb51.
requestDeviceCode and pollForAccessToken stay private to login.ts (no api.ts
export). The CLI entry githubCopilotLoginCommand is unchanged.
The provider auth contract tests in
src/plugin-sdk/test-helpers/provider-auth-contract.ts are updated to reflect
the new contract: the suite stubs fetch for the github.com device-code and
access-token endpoints and asserts that
- the credential is sourced from the device flow response (not a post-hoc
auth-store readback);
- the provider drives the host UI through ctx.prompter.note + ctx.openUrl
(no stdin/stdout dependency);
- auth completes when process.stdin.isTTY is false (GUI/RPC clients).
Validation
- pnpm tsgo:extensions
- pnpm test:extension github-copilot (all github-copilot tests pass; the
3 failures in models.test.ts are pre-existing on main, unrelated to this
change: vitest mock for openclaw/plugin-sdk/provider-model-shared is missing
the resolveProviderEndpoint export)
- End-to-end manual: ran a Windows tray-app onboarding wizard against a local
gateway, picked GitHub Copilot, browser opened to the verification URL,
authorization succeeded, token persisted under the correct agentDir as
github-copilot:github, chat through the new credential worked.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(pi-embedded): strip [tool calls omitted] from user-facing text
The internal replay placeholder '[tool calls omitted]' was leaking
into channel output (e.g. Telegram) after aborted tool calls.
Fix: strip the placeholder early in sanitizeUserFacingText so all
channels are protected by default. The replay transcript path in
turns.ts is unaffected — it uses the placeholder internally.
Fixes#74573.
Signed-off-by: Blasius Patrick <blasius.patrick@gmail.com>
* fix(pi-embedded): preserve whitespace when stripping placeholder
* test(pi-embedded): document replay placeholder sanitization
* fix(pi-embedded): strip consecutive replay placeholders
---------
Signed-off-by: Blasius Patrick <blasius.patrick@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>