Files
openclaw/src/plugins/provider-plugin.types.ts
Peter Steinberger d37e873420 refactor(plugins): split plugin type contracts (#108416)
* refactor(plugins): split plugin type contracts

* refactor(plugins): split provider type contracts

* refactor(plugins): extract plugin definition contract
2026-07-15 12:51:39 -07:00

694 lines
27 KiB
TypeScript

import type { AuthProfileCredential, OAuthCredential } from "../agents/auth-profiles/types.js";
import type { FailoverReason } from "../agents/embedded-agent-helpers/types.js";
import type { ModelCatalogEntry } from "../agents/model-catalog.types.js";
import type { AgentMessage, StreamFn } from "../agents/runtime/index.js";
import type { ProviderSystemPromptContribution } from "../agents/system-prompt-contribution.js";
import type { AnyAgentTool } from "../agents/tools/common.js";
import type { ModelProviderConfig } from "../config/types.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { ProviderUsageSnapshot } from "../infra/provider-usage.types.js";
import type { PluginTextTransforms } from "./cli-backend.types.js";
import type {
ProviderAuthMethod,
ProviderDeferSyntheticProfileAuthContext,
ProviderModelSelectedContext,
ProviderOAuthProfileIdRepair,
ProviderPluginWizard,
ProviderSystemPromptContributionContext,
ProviderTransformSystemPromptContext,
} from "./provider-authentication.types.js";
import type {
ProviderPluginCatalog,
ProviderBuiltInModelSuppressionContext,
ProviderBuiltInModelSuppressionResult,
ProviderModernModelPolicyContext,
ProviderAugmentModelCatalogContext,
ProviderPluginDiscovery,
} from "./provider-catalog.types.js";
import type {
ProviderApplyConfigDefaultsContext,
ProviderNormalizeConfigContext,
ProviderResolveConfigApiKeyContext,
} from "./provider-config-context.types.js";
import type {
ProviderExternalAuthProfile,
ProviderExternalOAuthProfile,
ProviderResolveExternalAuthProfilesContext,
ProviderResolveExternalOAuthProfilesContext,
ProviderResolveSyntheticAuthContext,
ProviderSyntheticAuthResult,
} from "./provider-external-auth.types.js";
import type {
ProviderReasoningOutputMode,
ProviderCapabilities,
ProviderReplayPolicy,
ProviderReplayPolicyContext,
ProviderSanitizeReplayHistoryContext,
ProviderValidateReplayTurnsContext,
ProviderNormalizeToolSchemasContext,
ProviderToolSchemaDiagnostic,
ProviderReasoningOutputModeContext,
} from "./provider-replay.types.js";
import type { ProviderRuntimeModel } from "./provider-runtime-model.types.js";
import type {
ProviderResolveDynamicModelContext,
ProviderPrepareDynamicModelContext,
ProviderPreferRuntimeResolvedModelContext,
ProviderNormalizeResolvedModelContext,
ProviderNormalizeModelIdContext,
ProviderNormalizeTransportContext,
ProviderPrepareRuntimeAuthContext,
ProviderPreparedRuntimeAuth,
ProviderResolveUsageAuthContext,
ProviderResolvedUsageAuth,
ProviderFetchUsageSnapshotContext,
ProviderAuthDoctorHintContext,
ProviderPrepareExtraParamsContext,
ProviderExtraParamsForTransportContext,
ProviderExtraParamsForTransportResult,
ProviderResolvePromptOverlayContext,
ProviderFollowupFallbackRouteContext,
ProviderFollowupFallbackRouteResult,
ProviderResolveAuthProfileIdContext,
} from "./provider-runtime.types.js";
import type {
ProviderDefaultThinkingPolicyContext,
ProviderThinkingProfile,
ProviderThinkingPolicyContext,
} from "./provider-thinking.types.js";
import type {
ProviderCreateStreamFnContext,
ProviderWrapStreamFnContext,
ProviderTransportTurnState,
ProviderResolveTransportTurnStateContext,
ProviderWebSocketSessionPolicy,
ProviderResolveWebSocketSessionPolicyContext,
ProviderFailoverErrorContext,
PluginEmbeddingProvider,
ProviderCreateEmbeddingProviderContext,
ProviderCacheTtlEligibilityContext,
ProviderBuildMissingAuthMessageContext,
ProviderBuildUnknownModelHintContext,
} from "./provider-transport.types.js";
export type ProviderPlugin = {
id: string;
pluginId?: string;
label: string;
docsPath?: string;
aliases?: string[];
/**
* Internal-only aliases used for runtime/config hook lookup.
*
* Unlike `aliases`, these values are not treated as user-facing provider ids
* for auth/setup surfaces. Use them for legacy config keys or compat-only
* hook routing.
*/
hookAliases?: string[];
/**
* Provider-related env vars shown in setup/search/help surfaces.
*
* Keep entries in preferred display order. This can include direct auth env
* vars or setup inputs such as OAuth client id/secret vars.
*/
envVars?: string[];
auth: ProviderAuthMethod[];
/**
* Legacy text-provider catalog hook.
*
* @deprecated New catalog/control-plane surfaces should use
* `api.registerModelCatalogProvider`. This hook remains the text runtime
* source until the unified loader fully replaces it.
* Returns provider config/model definitions that merge into models.providers.
*/
catalog?: ProviderPluginCatalog;
/**
* Legacy offline text-provider catalog hook for display-only surfaces.
*
* @deprecated New static rows should be registered with
* `api.registerModelCatalogProvider`.
*
* Unlike `catalog`, this hook must not perform network I/O or require real
* credentials. Use it for bundled/static rows that can be shown before auth is
* configured.
*/
staticCatalog?: ProviderPluginCatalog;
/**
* Show catalog row labels as the literal `<provider>/<entry.id>`
* composition instead of the canonical (deduped) key.
*
* `modelKey` strips a duplicate `<provider>/` prefix so storage and
* lookups stay stable. This flag only changes the picker label — the
* option value and persisted config remain canonical.
*
* Set when the leading `<provider>/` segment in the native model id is
* a meaningful vendor namespace (e.g. NVIDIA's `nvidia/nemotron-...`
* alongside `moonshotai/kimi-k2.5`).
*/
preserveLiteralProviderPrefix?: boolean;
/**
* @deprecated Use catalog.
*
* Legacy alias for catalog.
* Kept for compatibility with existing provider plugins.
*/
discovery?: ProviderPluginDiscovery;
/**
* Sync runtime fallback for model ids not present in the local catalog.
*
* Hook order:
* 1. discovered/static model lookup
* 2. plugin `resolveDynamicModel`
* 3. core fallback heuristics
* 4. generic provider-config fallback
*
* Keep this hook cheap and deterministic. If you need network I/O first, use
* `prepareDynamicModel` to prime state for the async retry path.
*/
resolveDynamicModel?: (
ctx: ProviderResolveDynamicModelContext,
) => ProviderRuntimeModel | null | undefined;
/**
* Optional async prefetch for dynamic model resolution.
*
* OpenClaw calls this only from async model resolution paths. After it
* completes, `resolveDynamicModel` is called again.
*/
prepareDynamicModel?: (ctx: ProviderPrepareDynamicModelContext) => Promise<void>;
/**
* Lets a provider plugin opt exact configured models into a runtime
* metadata comparison pass before the embedded runner returns the explicit
* entry unchanged.
*/
preferRuntimeResolvedModel?: (ctx: ProviderPreferRuntimeResolvedModelContext) => boolean;
/**
* Provider-owned transport normalization.
*
* Use this to rewrite a resolved model without forking the generic runner:
* swap API ids, update base URLs, or adjust compat flags for a provider's
* transport quirks.
*/
normalizeResolvedModel?: (
ctx: ProviderNormalizeResolvedModelContext,
) => ProviderRuntimeModel | null | undefined;
/**
* Provider-owned model-id normalization.
*
* Runs before model lookup/canonicalization. Use this for alias cleanup such
* as provider-owned preview/legacy model ids.
*/
normalizeModelId?: (ctx: ProviderNormalizeModelIdContext) => string | null | undefined;
/**
* Provider-owned transport-family normalization before generic model
* assembly.
*
* Use this for API/baseUrl cleanup that may apply to custom provider ids
* which still target the provider's transport family.
*/
normalizeTransport?: (
ctx: ProviderNormalizeTransportContext,
) => { api?: string | null; baseUrl?: string } | null | undefined;
/**
* Provider-owned config normalization for `models.providers.<id>`.
*
* Use this for provider-specific baseUrl/model-id cleanup that should stay
* with the plugin rather than in core config-policy tables.
*/
normalizeConfig?: (ctx: ProviderNormalizeConfigContext) => ModelProviderConfig | null | undefined;
/**
* Provider-owned final native-streaming compat pass for config providers.
*
* Use this when a provider opts specific native base URLs into
* `supportsUsageInStreaming` or similar transport compatibility flags.
*/
applyNativeStreamingUsageCompat?: (
ctx: ProviderNormalizeConfigContext,
) => ModelProviderConfig | null | undefined;
/**
* Provider-owned config apiKey/env marker resolution.
*
* Use this when a provider resolves auth from env vars such as AWS/GCP
* markers rather than a normal API-key env var.
*/
resolveConfigApiKey?: (ctx: ProviderResolveConfigApiKeyContext) => string | null | undefined;
/**
* @deprecated Legacy static capability bag kept only for compatibility.
*
* New provider behavior should use explicit hooks instead. Core replay and
* stream/runtime logic no longer consumes this field.
*/
capabilities?: ProviderCapabilities;
/**
* Provider-owned replay/compaction policy override.
*
* Use this when transcript replay or compaction should follow provider-owned
* rules that are more expressive than the static `capabilities` bag.
*/
buildReplayPolicy?: (ctx: ProviderReplayPolicyContext) => ProviderReplayPolicy | null | undefined;
/**
* Provider-owned replay-history sanitization.
*
* Runs after OpenClaw performs generic transcript cleanup. Use this for
* provider-specific replay rewrites that should stay with the provider
* plugin rather than in shared core compaction helpers.
*/
sanitizeReplayHistory?: (
ctx: ProviderSanitizeReplayHistoryContext,
) => Promise<AgentMessage[] | null | undefined> | AgentMessage[] | null | undefined;
/**
* Provider-owned final replay-turn validation.
*
* Use this when provider transports need stricter replay-time validation or
* turn reshaping after generic sanitation. Returning a non-null value
* replaces the built-in replay validators rather than composing with them.
*/
validateReplayTurns?: (
ctx: ProviderValidateReplayTurnsContext,
) => Promise<AgentMessage[] | null | undefined> | AgentMessage[] | null | undefined;
/**
* Provider-owned tool-schema normalization.
*
* Use this for transport-family schema cleanup before OpenClaw registers
* tools with the embedded runner.
*/
normalizeToolSchemas?: (
ctx: ProviderNormalizeToolSchemasContext,
) => AnyAgentTool[] | null | undefined;
/**
* Provider-owned tool-schema diagnostics after normalization.
*
* Use this when a provider wants to surface transport-specific schema
* warnings without teaching core about provider-specific keyword rules.
*/
inspectToolSchemas?: (
ctx: ProviderNormalizeToolSchemasContext,
) => ProviderToolSchemaDiagnostic[] | null | undefined;
/**
* Provider-owned reasoning output mode.
*
* Use this when a provider requires tagged reasoning/final output instead of
* native structured reasoning fields.
*/
resolveReasoningOutputMode?: (
ctx: ProviderReasoningOutputModeContext,
) => ProviderReasoningOutputMode | null | undefined;
/**
* Provider-owned extra-param normalization before generic stream option
* wrapping.
*
* Typical uses: set provider-default `transport`, map provider-specific
* config aliases, or inject extra request metadata sourced from
* `agents.defaults.models.<provider>/<model>.params`.
*/
prepareExtraParams?: (
ctx: ProviderPrepareExtraParamsContext,
) => Record<string, unknown> | null | undefined;
/**
* Provider-owned request params after transport/model resolution.
*
* Use this for transport-family request knobs that should be keyed by the
* resolved model API/transport rather than a hardcoded core allowlist.
*/
extraParamsForTransport?: (
ctx: ProviderExtraParamsForTransportContext,
) => ProviderExtraParamsForTransportResult | null | undefined;
/**
* Provider-owned transport factory.
*
* Use this when the provider needs a fully custom StreamFn instead of a
* wrapper around the normal `streamSimple` path.
*/
createStreamFn?: (ctx: ProviderCreateStreamFnContext) => StreamFn | null | undefined;
/**
* Provider-owned stream wrapper applied after generic OpenClaw wrappers.
*
* Typical uses: provider attribution headers, request-body rewrites, or
* provider-specific compat payload patches that do not justify a separate
* transport implementation.
*/
wrapStreamFn?: (ctx: ProviderWrapStreamFnContext) => StreamFn | null | undefined;
/**
* Provider-owned wrapper for direct `completeSimple` callers.
*
* Opt in only when the provider must enforce the same wire contract outside
* the embedded agent runtime.
*/
wrapSimpleCompletionStreamFn?: (ctx: ProviderWrapStreamFnContext) => StreamFn | null | undefined;
/**
* Provider-owned native transport turn identity.
*
* Use this when a provider wants generic transports to attach provider-native
* request headers or metadata on each turn without hardcoding vendor logic in
* core.
*/
resolveTransportTurnState?: (
ctx: ProviderResolveTransportTurnStateContext,
) => ProviderTransportTurnState | null | undefined;
/**
* Provider-owned WebSocket session policy.
*
* Use this when a provider wants generic WebSocket transports to attach
* native session headers or tune the session-scoped cool-down before HTTP
* fallback.
*/
resolveWebSocketSessionPolicy?: (
ctx: ProviderResolveWebSocketSessionPolicyContext,
) => ProviderWebSocketSessionPolicy | null | undefined;
/**
* Provider-owned embedding provider factory.
*
* Use this when memory embedding behavior belongs with the provider plugin
* rather than the core embedding switchboard.
*/
createEmbeddingProvider?: (
ctx: ProviderCreateEmbeddingProviderContext,
) =>
| Promise<PluginEmbeddingProvider | null | undefined>
| PluginEmbeddingProvider
| null
| undefined;
/**
* Runtime auth exchange hook.
*
* Called after OpenClaw resolves the raw configured credential but before the
* runner stores it in runtime auth storage. This lets plugins exchange a
* source credential (for example a GitHub token) into a short-lived runtime
* token plus optional base URL override.
*/
prepareRuntimeAuth?: (
ctx: ProviderPrepareRuntimeAuthContext,
) => Promise<ProviderPreparedRuntimeAuth | null | undefined>;
/**
* Usage/billing auth resolution hook.
*
* Called by provider-usage surfaces (`/usage`, status snapshots, reporting).
* Use this when a provider's usage endpoint needs provider-owned token
* extraction, blob parsing, or alias handling.
*/
resolveUsageAuth?: (
ctx: ProviderResolveUsageAuthContext,
) =>
| Promise<ProviderResolvedUsageAuth | null | undefined>
| ProviderResolvedUsageAuth
| null
| undefined;
/**
* Usage/quota snapshot fetch hook.
*
* Called after `resolveUsageAuth` by `/usage` and related reporting surfaces.
* Use this when the provider's usage endpoint or payload shape is
* provider-specific and you want that logic to live with the provider plugin
* instead of the core switchboard.
*/
fetchUsageSnapshot?: (
ctx: ProviderFetchUsageSnapshotContext,
) => Promise<ProviderUsageSnapshot | null | undefined> | ProviderUsageSnapshot | null | undefined;
/**
* Provider-owned failover context-overflow matcher.
*
* Return true when the provider recognizes the raw error as a context-window
* overflow shape that generic heuristics would miss.
*/
matchesContextOverflowError?: (ctx: ProviderFailoverErrorContext) => boolean | undefined;
/**
* Provider-owned failover error classification.
*
* Return a failover reason when the provider recognizes a provider-specific
* raw error shape. Return undefined to fall back to generic classification.
*/
classifyFailoverReason?: (ctx: ProviderFailoverErrorContext) => FailoverReason | null | undefined;
/**
* Provider-owned cache TTL eligibility.
*
* Use this when a proxy provider supports Anthropic-style prompt caching for
* only a subset of upstream models.
*/
isCacheTtlEligible?: (ctx: ProviderCacheTtlEligibilityContext) => boolean | undefined;
/**
* Provider-owned missing-auth message override.
*
* Return a custom message when the provider wants a more specific recovery
* hint than OpenClaw's generic auth-store guidance.
*/
buildMissingAuthMessage?: (
ctx: ProviderBuildMissingAuthMessageContext,
) => string | null | undefined;
/**
* Provider-owned unknown-model hint override.
*
* Return a suffix when the provider wants a more specific recovery hint than
* OpenClaw's generic `Unknown model` error after catalog/runtime lookup
* fails.
*/
buildUnknownModelHint?: (ctx: ProviderBuildUnknownModelHintContext) => string | null | undefined;
/**
* Provider-owned built-in model suppression.
*
* Return `{ suppress: true }` to hide a stale upstream row. Include
* `errorMessage` when OpenClaw should surface a provider-specific hint for
* direct model resolution failures.
*
* @deprecated Use manifest `modelCatalog.suppressions`. Runtime suppression
* hooks are no longer called by model resolution.
*/
suppressBuiltInModel?: (
ctx: ProviderBuiltInModelSuppressionContext,
) => ProviderBuiltInModelSuppressionResult | null | undefined;
/**
* Provider-owned final catalog augmentation.
*
* @deprecated Use `api.registerModelCatalogProvider` for supplemental catalog
* rows. This hook is kept only for existing text-provider runtime
* compatibility during the migration window.
*
* Return extra rows to append to the final catalog after discovery/config
* merging. OpenClaw deduplicates by `provider/id`, so plugins only need to
* describe the desired supplemental rows.
*/
augmentModelCatalog?: (
ctx: ProviderAugmentModelCatalogContext,
) =>
| Array<ModelCatalogEntry>
| ReadonlyArray<ModelCatalogEntry>
| Promise<Array<ModelCatalogEntry> | ReadonlyArray<ModelCatalogEntry> | null | undefined>
| null
| undefined;
/**
* Provider-owned binary thinking toggle.
*
* Return true when the provider exposes a coarse on/off reasoning control
* instead of the normal multi-level ladder shown by `/think`.
*
* @deprecated Prefer `resolveThinkingProfile`.
*/
isBinaryThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
/**
* Provider-owned xhigh reasoning support.
*
* Return true only for models that should expose the `xhigh` thinking level.
*
* @deprecated Prefer `resolveThinkingProfile`.
*/
supportsXHighThinking?: (ctx: ProviderThinkingPolicyContext) => boolean | undefined;
/**
* Provider-owned thinking level profile.
*
* Prefer this over the individual thinking capability hooks when a provider
* or model exposes a custom set of thinking levels. OpenClaw stores the
* canonical `id`, shows `label` when provided, and downgrades stale stored
* values by profile rank.
*/
resolveThinkingProfile?: (
ctx: ProviderDefaultThinkingPolicyContext,
) => ProviderThinkingProfile | null | undefined;
/**
* Provider-owned default thinking level.
*
* Use this to keep model-family defaults (for example Claude 4.6 =>
* adaptive) out of core command logic.
*
* @deprecated Prefer `resolveThinkingProfile`.
*/
resolveDefaultThinkingLevel?: (
ctx: ProviderDefaultThinkingPolicyContext,
) => "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive" | null | undefined;
/**
* Provider-owned system-prompt contribution.
*
* Use this when a provider/model family needs cache-aware prompt tuning
* without replacing the full OpenClaw-owned system prompt.
*/
resolveSystemPromptContribution?: (
ctx: ProviderSystemPromptContributionContext,
) => ProviderSystemPromptContribution | null | undefined;
/**
* Provider-owned GPT/model prompt overlay seam.
*
* Runs after OpenClaw's built-in overlay is resolved and before the
* provider's regular system-prompt contribution is merged.
*/
resolvePromptOverlay?: (
ctx: ProviderResolvePromptOverlayContext,
) => ProviderSystemPromptContribution | null | undefined;
/**
* Provider-owned fallback route override for model/profile failure handling.
*
* Return undefined/null to keep OpenClaw's default fallback policy.
*/
followupFallbackRoute?: (
ctx: ProviderFollowupFallbackRouteContext,
) => ProviderFollowupFallbackRouteResult | null | undefined;
/**
* Provider-owned auth profile resolver.
*
* Return a profile id from the supplied order to prefer it for this attempt;
* invalid or missing ids are ignored by core.
*/
resolveAuthProfileId?: (ctx: ProviderResolveAuthProfileIdContext) => string | null | undefined;
/**
* Provider-owned final system-prompt transform.
*
* Use this sparingly when a provider transport needs small compatibility
* rewrites after OpenClaw has assembled the complete prompt. Return
* `undefined`/`null` to leave the prompt unchanged.
*/
transformSystemPrompt?: (ctx: ProviderTransformSystemPromptContext) => string | null | undefined;
/**
* Provider-owned bidirectional text replacements.
*
* `input` applies to system prompts and text message content before transport.
* `output` applies to assistant text deltas/final text before OpenClaw handles
* its own control markers or channel delivery.
*/
textTransforms?: PluginTextTransforms;
/**
* Provider-owned global config defaults.
*
* Use this when config materialization needs provider-specific defaults that
* depend on auth mode, env, or provider model-family semantics.
*/
applyConfigDefaults?: (
ctx: ProviderApplyConfigDefaultsContext,
) => OpenClawConfig | null | undefined;
/**
* Provider-owned "modern model" matcher used by live profile/smoke filters.
*
* Return true when the given provider/model ref should be treated as a
* preferred modern model candidate.
*/
isModernModelRef?: (ctx: ProviderModernModelPolicyContext) => boolean | undefined;
wizard?: ProviderPluginWizard;
/**
* Provider-owned auth-profile API-key formatter.
*
* OpenClaw uses this when a stored auth profile is already valid and needs to
* be converted into the runtime `apiKey` string expected by the provider. Use
* this for providers whose auth profile stores extra metadata alongside the
* bearer token (for example Gemini CLI's `{ token, projectId }` payload).
*/
formatApiKey?: (cred: AuthProfileCredential) => string;
/**
* Legacy auth-profile ids that should be retired by `openclaw doctor`.
*
* Use this when a provider plugin replaces an older core-managed profile id
* and wants cleanup/migration messaging to live with the provider instead of
* in hardcoded doctor tables.
*/
deprecatedProfileIds?: string[];
/**
* Legacy OAuth profile-id migrations that `openclaw doctor` should offer.
*
* Use this when a provider moved from a legacy default OAuth profile id to a
* newer identity-based id and wants doctor to own the config rewrite without
* another core-specific migration branch.
*/
oauthProfileIdRepairs?: ProviderOAuthProfileIdRepair[];
/**
* Provider-owned OAuth refresh.
*
* OpenClaw calls this before falling back to the shared `shared model runtime` OAuth
* refreshers. Use it when the provider has a custom refresh endpoint, or when
* the provider needs custom refresh-failure behavior that should stay out of
* core auth-profile code.
*/
refreshOAuth?: (cred: OAuthCredential) => Promise<OAuthCredential>;
/**
* Provider-owned auth-doctor hint.
*
* Return a multiline repair hint when OAuth refresh fails and the provider
* wants to steer users toward a specific auth-profile migration or recovery
* path. Return nothing to keep OpenClaw's generic error text.
*/
buildAuthDoctorHint?: (
ctx: ProviderAuthDoctorHintContext,
) => string | Promise<string | null | undefined> | null | undefined;
/**
* Provider-owned config-backed auth resolution.
*
* Providers own any provider-specific fallback secret rules here so core
* auth/discovery code can stay generic and avoid parsing provider-private
* config layouts.
*
* The returned `apiKey` may be:
* - a real credential from the active runtime snapshot, suitable for runtime use
* - a non-secret marker (for example a managed SecretRef marker), suitable only
* for discovery/bootstrap callers
*
* Runtime callers must not treat non-secret markers as runnable credentials;
* they should retry against the active runtime snapshot when available.
*
* This hook is the canonical seam for provider-specific fallback auth
* derived from plugin/private config. It may return:
* - a runnable literal credential for runtime callers
* - a non-secret marker for managed-secret source config, which is still useful
* for discovery/bootstrap callers
*
* Runtime callers must not treat non-secret markers as runnable credentials;
* they should retry against the active runtime snapshot when available.
*
* Use this when the provider can operate without a real secret for certain
* configured local/self-hosted cases and wants auth resolution to treat that
* config as available.
*/
resolveSyntheticAuth?: (
ctx: ProviderResolveSyntheticAuthContext,
) => ProviderSyntheticAuthResult | null | undefined;
/**
* Provider-owned external auth profile discovery.
*
* Use this when credentials are managed by an external tool and should be visible
* to runtime auth resolution without being written back into `auth-profiles.json`
* by core.
*/
resolveExternalAuthProfiles?: (
ctx: ProviderResolveExternalAuthProfilesContext,
) =>
| Array<ProviderExternalAuthProfile>
| ReadonlyArray<ProviderExternalAuthProfile>
| null
| undefined;
/**
* @deprecated Declare `contracts.externalAuthProviders` in the plugin manifest
* and implement `resolveExternalAuthProfiles` instead. Kept at the public
* plugin boundary until the SDK removal window closes.
*/
resolveExternalOAuthProfiles?: (
ctx: ProviderResolveExternalOAuthProfilesContext,
) =>
| Array<ProviderExternalOAuthProfile>
| ReadonlyArray<ProviderExternalOAuthProfile>
| null
| undefined;
/**
* Provider-owned precedence rule for stored synthetic auth profiles.
*
* Return true when a stored profile API key is only a provider-owned
* synthetic placeholder and should yield to env/config-backed auth before
* OpenClaw falls back to that stored profile.
*/
shouldDeferSyntheticProfileAuth?: (
ctx: ProviderDeferSyntheticProfileAuthContext,
) => boolean | undefined;
onModelSelected?: (ctx: ProviderModelSelectedContext) => Promise<void>;
};