Skip to content

copilot: support Copilot authentication and service - #10

Closed
mathstuf wants to merge 1 commit into
jamespember:mainfrom
mathstuf:copilot-support
Closed

mathstuf wants to merge 1 commit into
jamespember:mainfrom
mathstuf:copilot-support

Conversation

@mathstuf

Copy link
Copy Markdown
Contributor

Co-authored-by: GitHub Copilot(claude-opus-4.6)
Fixes: #2


Based on #9 and #5.

@mathstuf
mathstuf force-pushed the copilot-support branch 2 times, most recently from 162c63c to 4279ff1 Compare March 18, 2026 04:55
@mathstuf
mathstuf force-pushed the copilot-support branch from 4279ff1 to 887741a Compare May 4, 2026 13:17
@mathstuf
mathstuf marked this pull request as ready for review May 4, 2026 13:18
@mathstuf
mathstuf requested a review from jamespember as a code owner May 4, 2026 13:18

@fredheir fredheir left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking correctness issue: CopilotSummarizer defines CopilotTokenManager, but the client path sends the long-lived GitHub OAuth token directly to https://api.githubcopilot.com. That bypasses the /copilot_internal/v2/token exchange and will fail for the intended Copilot API flow.

I prepared and tested a local patch that changes _get_client() to call CopilotTokenManager.get_token(), invalidates that session token on retry, removes the setup_cloud.sh TODO cost text, and adds focused tests proving the OpenAI-compatible client receives the Copilot session token rather than the GitHub OAuth token. Proof run locally: uv run --extra dev --extra copilot -m pytest -q tests/test_summarizers.py -> 10 passed; uv run --extra dev --extra copilot ruff check meeting_notes/copilot_auth.py meeting_notes/ai_summarizer.py tests/conftest.py tests/test_summarizers.py -> passed.

I cannot push to mathstuf/meeting-notes-tui from this token despite maintainerCanModify, so the branch cannot be updated in place from here.

@fredheir

Copy link
Copy Markdown

Reference branch with the tested fix, since I cannot push to the contributor fork directly: https://github.com/Markolo-Research/meeting-notes-streaming/tree/codex/pr10-copilot-session-token-fix

Incremental commit range in my worktree: 887741a..fe6ce29.

@mathstuf

Copy link
Copy Markdown
Contributor Author

Your fork is private and I cannot access it.

@mathstuf

Copy link
Copy Markdown
Contributor Author

I have a diff assisted by DeepSeek applied now. @fredheir is this similar to what you have?

@fredheir

Copy link
Copy Markdown

@mathstuf my apologies, my agent went rogue.
I've set my fork to public, perhaps this can still be useful for you.

@mathstuf

Copy link
Copy Markdown
Contributor Author

Thanks; I've integrated the changes in (except the spurious whitespace diffs).

@mathstuf

Copy link
Copy Markdown
Contributor Author

Rebased on main.

Fixes-by: Rolf Fredheim <[email protected]> (agent-assisted)
Co-authored-by: GitHub Copilot (claude-opus-4.6)
Fixes: jamespember#2
bryangruneberg added a commit to bryangruneberg/omascribe that referenced this pull request Sep 16, 2026
…way and DeepInfra

OpenAICompatibleSummarizer runs the shared prompt and parser against any
OpenAI chat-completions endpoint: a subclass sets BASE_URL, ENV_VAR, LABEL
and a tier -> model-id table. Two providers use it, both serving Claude with
ai_model haiku | sonnet | opus:

- assemblyai: AssemblyAI's LLM Gateway, authenticated with the same key as
  AssemblyAI transcription, so one key covers the whole pipeline.
- deepinfra: DeepInfra's OpenAI-compatible API.

Choices that matter for current models:
- no temperature: Claude 5 models on the gateway reject it;
- MAX_TOKENS = 16000: reasoning models spend output tokens before writing
  text (a 34-minute meeting needed ~5,400 for ~1,100 visible);
- finish_reason "length" raises SummaryTruncated rather than parsing a
  partial response.

The same base would also cover other OpenAI-compatible services, e.g. the
Copilot request in jamespember#2 / jamespember#10.

Config validation, provider_api_key(), Settings (shared Claude tier buttons,
key inputs) and NoteMaker are wired for both; tests use fake clients only.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@jamespember

Copy link
Copy Markdown
Owner

Great contribution @mathstuf — a well-scoped implementation of the GitHub Device Flow with token caching, and it fits cleanly alongside the other providers.

What I like:

  • omascribe/copilot_auth.py is nicely self-contained. start_device_flow / poll_for_token handle every documented device-flow error state (authorization_pending, slow_down, expired_token, access_denied), the timeout defaults are sensible, and the polling loop honours GitHub's requested slow_down interval bumps.
  • CopilotTokenManager split from the OAuth token exchange. GitHub OAuth tokens are long-lived, Copilot session tokens are ~30 min — the two-tier caching (with a 60 s expiry buffer) matches how VS Code Copilot itself does it, and invalidate() gives the summarizer a clean way to force a refresh on 401.
  • _refresh_token distinguishes 401 vs 403 vs 404 and gives each a specific, actionable message. The 404 case in particular ("the OAuth token may have been issued with an unrecognised client_id") is the sort of hint that saves someone half a day.
  • CopilotAuthScreen (device-flow modal in the TUI). Runs the flow in a background worker so the UI stays responsive, shows the user_code + verification_uri, spins while polling, and dismisses back to Settings with the token on success. Cancellable throughout. Nice UX.
  • Token redaction in to_safe_dict. Same pattern as the other keys.
  • CI already passing on both Python 3.10 and 3.14.

Rebase notes (merged locally on top of #16–#20):

The PR conflicted with the AssemblyAI/DeepInfra provider additions from #19/#20 because both series added new elements to the same enumerations. I resolved them by keeping both:

  • ai_provider union in config.py includes both sets
  • CLOUD_PROVIDERS in note_maker.py includes copilot too
  • ai_summarizer.py has OpenAICompatibleSummarizer, AssemblyAISummarizer, DeepInfraSummarizer, and CopilotSummarizer all coexisting
  • settings.py renders all three provider-specific sections

Two small fixes I made on top during the rebase:

  1. setup_cloud.sh's Python heredoc used setattr(config, f"{provider}_api_key", …), which would have written to a nonexistent copilot_api_key field rather than github_copilot_token. Added an override so the shell can pass the correct field name.
  2. Same script's menu still said [1-3] — updated to [1-6] and added the two missing entries (AssemblyAI, DeepInfra) alongside Copilot.
  3. In CopilotSummarizer.summarize I wired in the shared _raise_if_truncated helper from fix(summaries): treat a truncated AI summary as an error #18 so a length-truncated Copilot response fails the same way as every other provider — otherwise Copilot would have been the one outlier that silently saved half a summary.
  4. Added test_copilot_wired_into_provider_infrastructure to lock in that Copilot is in CLOUD_PROVIDERS, that AppConfig.provider_api_key() resolves github_copilot_token, and that validate_config rejects a non-Copilot model tier. This catches exactly the class of bug the future "add another provider" PR is likely to introduce.

One thing worth flagging (not blocking):

The default COPILOT_CLIENT_ID = "Iv1.b507a08c87ecfe98" is the public VS Code Copilot client ID. That works today but ties omascribe's Copilot support to Microsoft honouring that ID for third-party device flows. Longer-term omascribe probably wants its own registered GitHub OAuth App; the GITHUB_COPILOT_CLIENT_ID env-var / settings-input override you already added means users can point at a different one if the VS Code default ever stops working.

Local: 162 tests pass, ruff clean. Merging via local squash (workflow scope again — same reason as #19/#20).

@jamespember

Copy link
Copy Markdown
Owner

Landed as commit dd398e0 on main. Thanks again @mathstuf — Copilot summarisation is live.

@mathstuf
mathstuf deleted the copilot-support branch September 17, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RFE: Support Copilot as a cloud provider

3 participants