@milespossing/pi-copilot-discovery

Dynamic GitHub Copilot model discovery for pi — replaces pi-ai's static catalog with the live /models list from your Copilot tenant.

Packages

Package details

extension

Install @milespossing/pi-copilot-discovery from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@milespossing/pi-copilot-discovery
Package
@milespossing/pi-copilot-discovery
Version
0.4.1
Published
Aug 1, 2026
Downloads
460/mo · 77/wk
Author
milespossing
License
MIT
Types
extension
Size
23.6 KB
Dependencies
0 dependencies · 0 peers
Pi manifest JSON
{
  "extensions": [
    "./src/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-copilot-discovery

A pi extension that augments the built-in github-copilot provider with the full live model catalog returned by your Copilot tenant.

Why

Pi 0.83 performs dynamic availability filtering, but its model definitions remain static:

  1. Pi calls Copilot's /models endpoint and records the available model IDs.
  2. Pi filters its bundled GITHUB_COPILOT_MODELS catalog to those IDs.
  3. IDs absent from the bundled catalog are still invisible because Pi has no model configuration for them.

This extension uses the full /models response to create model definitions at runtime. That surfaces new public, preview, and tenant-private models without waiting for another Pi release.

What it does

  • Preserves Pi's built-in provider. Authentication, credential persistence, token refresh, enterprise endpoint selection, request headers, and streaming remain owned by Pi 0.83's native github-copilot provider.
  • Discovers models on session start and after login. The extension wraps the effective provider with a native refreshModels implementation.
  • Refreshes on demand. /copilot-refresh re-fetches the tenant catalog.
  • Enables tenant policies after login. The wrapped built-in OAuth login runs POST /models/<id>/policy {"state":"enabled"} for every discovered model.
  • Classifies unknown models conservatively. Claude uses Anthropic Messages, GPT-5/o1/o3 use OpenAI Responses, responses-only models (for example Grok 4.5) use OpenAI Responses from supported_endpoints, and remaining chat models use OpenAI Chat Completions.

Install

As a Pi package

pi install npm:@milespossing/pi-copilot-discovery

Or try it for one session:

pi -e npm:@milespossing/pi-copilot-discovery

Directly from git

pi install git:github.com/milespossing/pi-copilot-discovery
pi -e git:github.com/milespossing/pi-copilot-discovery

From a local checkout

git clone https://github.com/milespossing/pi-copilot-discovery ~/src/pi-copilot-discovery
ln -s ~/src/pi-copilot-discovery ~/.pi/agent/extensions/copilot-discovery

Restart Pi or run /reload. Existing github-copilot credentials continue to work. If needed, run /login github-copilot.

Commands

Command What it does
/login github-copilot Built-in device-code login plus policy enablement for live models
/copilot-refresh Re-fetch the live /models catalog
/logout github-copilot Built-in credential removal

How it works

Pi initializes its built-in github-copilot provider
  └─ session_start
       ├─ extension obtains the effective provider from ctx.modelRegistry
       ├─ wraps it without replacing auth or streaming
       ├─ registers a native provider with refreshModels
       └─ refreshModels receives Pi's already-refreshed credential
            ├─ GET <credential-specific proxy>/models
            ├─ build Model[] from the live response
            └─ publish the live catalog synchronously through getModels()

The wrapper keeps the literal provider ID github-copilot, so Pi's built-in Copilot header injection and provider-specific request behavior still apply. Each discovered model also receives the static Copilot client headers required by the proxy.

Family → API routing

Model family / endpoint signal Pi API Reasoning
claude-* (3.5+, 4.x, 5.x) anthropic-messages yes
claude-2.x, claude-3 (3.0–3.4) anthropic-messages no
gpt-5*, o1, o3 openai-responses yes
responses-only (supported_endpoints: ["/responses"]) openai-responses if advertised
gpt-4*, gemini-*, other chat-completions openai-completions no

supported_endpoints wins for responses-only models such as grok-4.5 and mai-code-1-flash-picker. Routing those to /chat/completions yields unsupported_api_for_model. Name heuristics still classify Claude and GPT-5 families when endpoints are absent or include multiple paths.

The heuristics in src/families.ts intentionally choose the safest known API for an unfamiliar family.

Troubleshooting

Symptom Likely cause Fix
/model has no Copilot entries No configured Copilot credential Run /login github-copilot
Only Pi's bundled models appear Live refresh failed or the extension did not load Run /copilot-refresh and inspect the notification
A preview model returns 403 Its tenant policy was not enabled Re-run /login github-copilot
Proxy rejects Editor-Version or User-Agent Pi changed its Copilot client headers Update COPILOT_HEADERS in src/models.ts
unsupported_api_for_model on /chat/completions Model is responses-only (supported_endpoints: ["/responses"]) Ensure discovery reads supported_endpoints; update if needed
A new family is misrouted Conservative fallback selected openai-completions Refine src/families.ts using the returned family/id/endpoints

Requirements

  • @earendil-works/pi-coding-agent >= 0.83.0
  • @earendil-works/pi-ai >= 0.83.0
  • Node.js >= 22.19.0

Version 0.4.0 uses Pi's native Provider and OAuth APIs.

Development

npm install
npx --yes --package typescript@5.9.3 tsc \
  --noEmit --strict --target ES2023 \
  --module NodeNext --moduleResolution NodeNext \
  --allowImportingTsExtensions --skipLibCheck \
  src/index.ts src/models.ts src/oauth.ts src/families.ts

For an end-to-end test, force-load the checkout with Pi 0.83, select a model that is absent from Pi's bundled catalog, and send a short prompt.

Publishing

Pushing a v*.*.* tag triggers the npm trusted-publishing workflow, which checks that the tag matches package.json before publishing.

Layout

.
├── package.json
├── src/
│   ├── index.ts     wrap the native provider and register refresh commands
│   ├── oauth.ts     wrap native login only to enable discovered policies
│   ├── models.ts    fetch /models and build native Model[] entries
│   └── families.ts  map family/id to API and compatibility metadata
├── AGENTS.md
├── README.md
└── LICENSE

License

MIT