Skip to content

[FEATURE]: v2 plugin API: expose credential list/activate on ctx.integration #51410

Closed

Description

@remorses

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

v2 only. I'm writing a v2 plugin that falls back when a subscription is rate limited or out of quota. The retry hook plus ctx.session.switchModel already handles switching models.

The missing piece is rotating accounts of the same provider. v2 already stores many credentials per integration (every login adds one and activates it), but plugins can only read them, not switch between them:

  • ctx.integration.get() returns connections[]
  • ctx.integration.connection.active() / resolve() exist
  • there's no activate. It only exists on the HTTP client (client.credential.activate)

Proposed API

Core Credential.Service already implements this, so the change is only wiring in packages/plugin/src/promise/integration.ts + packages/core/src/plugin/host.ts:

export interface IntegrationDomain {
  // ...existing
  readonly credential: {
    readonly list: (integrationID: string) => Promise<Array<{ id: string; label: string }>>
    readonly activate: (credentialID: string) => Promise<void>
  }
}

Usage

await ctx.session.hook('retry', async (event) => {
  if (event.error.type !== 'provider.rate-limit' && event.error.type !== 'provider.quota') return
  const integrationID = event.model.providerID
  const active = await ctx.integration.connection.active(integrationID)
  const next = (await ctx.integration.credential.list(integrationID))
    .find((c) => c.id !== (active?.type === 'credential' ? active.id : undefined) && !isCoolingDown(c.id))
  if (!next) return
  await ctx.integration.credential.activate(next.id) // publishes credential.switched
  event.decision = { retry: true, delay: 0 }
})

Related: #38203 (recovering credentials after 401/403 would use the same primitive).

Activity

  1. github-actions commented on Sep 25, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

  2. remorses commented on Sep 29, 2026

    @remorses
    ContributorAuthor

    I can list credential connections with (await ctx.integration.get({ integrationID })).data.connections.filter((connection) => connection.type === "credential"). The proposed list method is redundant. The only missing server-plugin API is activate(credentialID) so the retry hook can switch the active account before retrying. A TUI plugin can already call ctx.client.credential.activate, but the server-plugin context has no client.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions