Skip to content

Move provider authentication for API-key and Posit AI Pass providers to Posit Assistant - #16102

Draft
melissa-barca wants to merge 29 commits into
mainfrom
migrate-auth
Draft

melissa-barca wants to merge 29 commits into
mainfrom
migrate-auth

Conversation

@melissa-barca

@melissa-barca melissa-barca commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Moves authentication for Anthropic, OpenAI, OpenAI-compatible, Gemini, DeepSeek, custom providers and Posit AI Pass from Positron's authentication extension to Posit Assistant, and renames every auth provider to its catalog id. Second of three coordinated PRs with posit-dev/ai-lib#114 and posit-dev/assistant#2450; none merges until all three are approved. Builds on George's prototype/local-assistant-auth branch. Part of #14190.

  • The authentication extension now registers only Bedrock, Google Vertex, Foundry, Snowflake Cortex and Databricks, with Bedrock and Vertex renamed to bedrock and google-vertex.
  • Removes the core provider configuration modal and the positron.ai API behind it. The configure-providers entry points open Assistant's provider manager instead.
  • Lets extensions open webview panels in the modal editor part, which Assistant uses for its provider manager.
  • Extensions granted auth access in product.json skip the create-session consent prompt.
  • Positron copies every credential the authentication extension stored for a moved provider into Assistant's secret store once per profile at startup: API keys, custom provider entries and the Posit AI Pass token set. The originals stay in place and a key Assistant already holds is not overwritten. If no secret is readable yet, the copy runs again on the next launch.
  • Grants Assistant access to the moved providers under their catalog ids in product.json.
  • Next Edit Suggestions reads the Posit AI Pass session as positai and depends on Posit Assistant instead of the authentication extension.
  • Pins ai-lib to Use catalog ids as auth provider ids ai-lib#114 so the headless language model service resolves each provider's auth id as its catalog id.
  • Renames the provider ids in the e2e page objects and skips the suites that drove the removed modal until the provider manager has a page object.

Phase 2

  • Decides per-provider ownership from the auth ids Positron's manifest still declares, replacing the hardcoded host-owned list, so a newer Assistant defers automatically once an older Positron drops a provider's registration.
  • Deletes Positron's Microsoft Foundry auth provider; Assistant now serves it, including the Workbench-delegated bearer and Entra mode.
  • Core's headless service (Git Suggestions, notebook AI) synthesizes the same Entra credential from the catalog that Assistant's own requests use, so Foundry works in both without a stored session.
  • Copies a stored Foundry API key into Assistant's credential store alongside the Phase 1 providers, so a user signed in before this change stays signed in.

Smoke-tested by hand: credentials saved on main appear in Assistant after one launch of this branch with the matching Assistant build, and the Assistant branch still signs in against a main Positron.

🤖 Generated with Claude Code

georgestagg and others added 29 commits September 7, 2026 09:08
Positron's LLM provider authentication is moving into the Posit Assistant
extension, which will own the providers that hold a language-model API key and
publish them through `vscode.authentication`. The providers that authenticate
against a general-purpose cloud credential system, or against Posit Workbench
managed credentials, stay here: Bedrock (AWS credential chain), Microsoft
Foundry (Workbench delegation), Snowflake Cortex, Databricks, and GEAP.

Remove the moved providers (Anthropic, Posit AI Pass, OpenAI, OpenAI
Compatible, Gemini, DeepSeek, and the custom-provider registry) along with
their validators and tests, and drop the whole config-dialog layer: with the
core modal gone there is nothing to describe provider sources to, so
`providerSources.ts` reduces to the metadata the surviving registrations and
diagnostics need.

The AWS SSO recovery previously only ran through the modal's connect path, so
it moves into `AuthProvider.createSession`, where `getSession` with
`createIfNone` reaches it.

Add a one-shot credential handoff so moving ownership does not sign users out.
It pushes to a command the Assistant registers rather than exposing an export
the Assistant calls: `executeCommand` carries no caller identity, so a pull API
would hand these secrets to any extension that guessed its name.

The extension no longer uses the `positron` API at all, so drop positron.d.ts
from its tsconfig.
The provider-configuration modal and the `positron.ai` surface that fed it
existed so an extension could describe language-model providers to the IDE and
open a dialog over them. With authentication moving into the Posit Assistant
extension, which presents its own provider manager and publishes credentials
through `vscode.authentication`, nothing populates that registry and nothing
opens that modal.

Delete both modals, their view components and icons, and the RPC that drove
them: `$languageModelConfig`, `$registerProvider`, `$unregisterProvider`,
`$updateProvider`, `$getRegisteredProviders`, and the ext-host callbacks
`$responseProviderAction`, `$onCompleteLanguageModelConfig` and
`$onDidChangeProviderConfig`. `$onDidChangeProviderEnablement` and
`isProviderEnabled` stay: `extensions/copilot` uses them, and they are backed
by the provider catalog rather than the registry.

`IPositronAssistantConfigurationService` kept a registry of provider sources
that only the modal rendered. Nothing fills it now, so `isProviderEnabled`
reads the resolved catalog directly. That changes one verdict: a provider the
catalog has never heard of is now enabled rather than disabled, matching the
rule the old source-level fallback already documented. Without it every chat
vendor would be filtered out of the model picker. It also removes the reason
the API tests registered provider metadata by hand.

`getProviderStatus` loses its sign-in and health fields for the same reason,
and says so in its agent-facing contract: credentials belong to the extensions
that register the authentication providers, so enabled no longer implies
signed in.

Quarantine the seven e2e suites that drove the modal. Provider sign-in has no
automated coverage until the Assistant's provider-manager webview has a page
object; `modelProviderModal.ts` is retained, unused, as the specification of
what that page object must cover.
With the provider-configuration surface gone, most of what was left in
`positron.ai` had no consumer in either this repo or the Posit Assistant
extension. Verified against both before removing: the Assistant uses only
`getCurrentPlotUri`, `validateAndExecuteCommand`, `getAgentSkillRoots` and the
provider-config members that went with the modal.

Remove `registerChatAgent`, `ChatAgentData`, `ChatParticipant`,
`getPositronChatContext`, `responseProgress`, `getChatExport`, `ChatContext`,
`ChatProvider`, `getCurrentProvider`, `getCurrentChatMode`, `getProviders`,
`setCurrentProvider` and `areCompletionsEnabled`, together with their RPC and
the service methods that only the RPC reached. The namespace goes from around
forty members to fifteen, each with a named consumer.

`getPositronChatContext` stays on the service: `$generateAssistantPrompt`
assembles the prompt from it. `$getCurrentChatMode` becomes a private helper
for the same reason.

`areCompletionsEnabled` and its five tests go with it. The gate was already
unreachable -- nothing called the API -- and the enforcement it composed lives
in `isCompletionsEnabled` and `isFileExcludedFromAI`, which keep their own
tests.
`posit-assistant.manageProviders` opens the provider-manager panel directly and
is gated on the native dialog being in effect, which it no longer is.
`posit-assistant.configureProviders` is the entry point the Assistant intends
callers to use: it owns the native-vs-panel routing itself and already falls
through to the panel when no native dialog is available.
Both extensions activate on `onStartupFinished`, so checking `getCommands` for
the import command could run before the Assistant registered it. The handoff
then deferred to the next activation, which meant users needed one extra
restart before their keys moved -- signed out in the meantime for no reason.

Activate the Assistant explicitly first. The dependency direction is already
established: next-edit-suggestions declares `posit.assistant` in
`extensionDependencies`.
Deleting this extension's secrets after the handoff made the branch one-way: a
user who tried it and went back to a build where this extension still owns the
language-model providers would find themselves signed out of all of them.

Keep the secrets and the account index. The two stores can drift if someone
re-keys a provider on the older build -- the handoff runs once and does not
reconcile afterwards -- which is worth it for being able to switch back.
Adds a `modal` flag to the show options of `window.createWebviewPanel`,
behind the `positronModalWebview` API proposal. When set, the panel is
routed to `MODAL_GROUP` so it renders in the centered modal overlay that
Settings, Extensions and MCP servers use, unless the user has set
`workbench.editor.useModal` to `off`.

The flag is remembered on the panel so that revealing it again keeps it
in the modal.
…rompt

Extensions listed in trustedExtensionAuthAccess only ever bypassed the
prompt when reusing an existing session; creating a brand new one via
createIfNone always showed "wants to sign in", regardless of trust.
That gap surfaced once provider configuration moved into the Assistant
extension: a genuinely cross-extension request to create a Bedrock
session (previously a same-extension internal call from within
extensions/authentication) now always prompts, even though both
extensions are already product.json-trusted for that provider.

Extract isProviderTrusted from isAccessAllowed's product.json check
and consult it before showing the login prompt on the create path too.
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.

3 participants