From e25f634d50c0f30bcd8f394997acdc0e794ca455 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 27 Mar 2026 17:13:53 +0000 Subject: [PATCH] refactor: move oauth profile repair metadata into providers --- docs/.generated/plugin-sdk-api-baseline.json | 44 ++++----- docs/.generated/plugin-sdk-api-baseline.jsonl | 44 ++++----- extensions/anthropic/index.ts | 6 ++ ...octor-auth.deprecated-cli-profiles.test.ts | 93 ++++++++++++++++++- src/commands/doctor-auth.ts | 46 +++++---- src/flows/doctor-health-contributions.ts | 4 +- src/plugins/provider-validation.ts | 26 ++++++ src/plugins/types.ts | 23 +++++ 8 files changed, 222 insertions(+), 64 deletions(-) diff --git a/docs/.generated/plugin-sdk-api-baseline.json b/docs/.generated/plugin-sdk-api-baseline.json index 7b5819120d8..6f64e958b50 100644 --- a/docs/.generated/plugin-sdk-api-baseline.json +++ b/docs/.generated/plugin-sdk-api-baseline.json @@ -253,7 +253,7 @@ "exportName": "CliBackendPlugin", "kind": "type", "source": { - "line": 1461, + "line": 1484, "path": "src/plugins/types.ts" } }, @@ -397,7 +397,7 @@ "exportName": "MediaUnderstandingProviderPlugin", "kind": "type", "source": { - "line": 1114, + "line": 1137, "path": "src/plugins/types.ts" } }, @@ -415,7 +415,7 @@ "exportName": "OpenClawPluginApi", "kind": "type", "source": { - "line": 1505, + "line": 1528, "path": "src/plugins/types.ts" } }, @@ -523,7 +523,7 @@ "exportName": "SpeechProviderPlugin", "kind": "type", "source": { - "line": 1089, + "line": 1112, "path": "src/plugins/types.ts" } }, @@ -3549,7 +3549,7 @@ "exportName": "MediaUnderstandingProviderPlugin", "kind": "type", "source": { - "line": 1114, + "line": 1137, "path": "src/plugins/types.ts" } }, @@ -3567,7 +3567,7 @@ "exportName": "OpenClawPluginApi", "kind": "type", "source": { - "line": 1505, + "line": 1528, "path": "src/plugins/types.ts" } }, @@ -3576,7 +3576,7 @@ "exportName": "OpenClawPluginCommandDefinition", "kind": "type", "source": { - "line": 1231, + "line": 1254, "path": "src/plugins/types.ts" } }, @@ -3594,7 +3594,7 @@ "exportName": "OpenClawPluginDefinition", "kind": "type", "source": { - "line": 1487, + "line": 1510, "path": "src/plugins/types.ts" } }, @@ -3603,7 +3603,7 @@ "exportName": "OpenClawPluginService", "kind": "type", "source": { - "line": 1454, + "line": 1477, "path": "src/plugins/types.ts" } }, @@ -3612,7 +3612,7 @@ "exportName": "OpenClawPluginServiceContext", "kind": "type", "source": { - "line": 1446, + "line": 1469, "path": "src/plugins/types.ts" } }, @@ -3639,7 +3639,7 @@ "exportName": "PluginCommandContext", "kind": "type", "source": { - "line": 1129, + "line": 1152, "path": "src/plugins/types.ts" } }, @@ -3648,7 +3648,7 @@ "exportName": "PluginInteractiveTelegramHandlerContext", "kind": "type", "source": { - "line": 1260, + "line": 1283, "path": "src/plugins/types.ts" } }, @@ -3972,7 +3972,7 @@ "exportName": "SpeechProviderPlugin", "kind": "type", "source": { - "line": 1089, + "line": 1112, "path": "src/plugins/types.ts" } }, @@ -4064,7 +4064,7 @@ "exportName": "MediaUnderstandingProviderPlugin", "kind": "type", "source": { - "line": 1114, + "line": 1137, "path": "src/plugins/types.ts" } }, @@ -4082,7 +4082,7 @@ "exportName": "OpenClawPluginApi", "kind": "type", "source": { - "line": 1505, + "line": 1528, "path": "src/plugins/types.ts" } }, @@ -4091,7 +4091,7 @@ "exportName": "OpenClawPluginCommandDefinition", "kind": "type", "source": { - "line": 1231, + "line": 1254, "path": "src/plugins/types.ts" } }, @@ -4109,7 +4109,7 @@ "exportName": "OpenClawPluginDefinition", "kind": "type", "source": { - "line": 1487, + "line": 1510, "path": "src/plugins/types.ts" } }, @@ -4118,7 +4118,7 @@ "exportName": "OpenClawPluginService", "kind": "type", "source": { - "line": 1454, + "line": 1477, "path": "src/plugins/types.ts" } }, @@ -4127,7 +4127,7 @@ "exportName": "OpenClawPluginServiceContext", "kind": "type", "source": { - "line": 1446, + "line": 1469, "path": "src/plugins/types.ts" } }, @@ -4154,7 +4154,7 @@ "exportName": "PluginCommandContext", "kind": "type", "source": { - "line": 1129, + "line": 1152, "path": "src/plugins/types.ts" } }, @@ -4163,7 +4163,7 @@ "exportName": "PluginInteractiveTelegramHandlerContext", "kind": "type", "source": { - "line": 1260, + "line": 1283, "path": "src/plugins/types.ts" } }, @@ -4433,7 +4433,7 @@ "exportName": "SpeechProviderPlugin", "kind": "type", "source": { - "line": 1089, + "line": 1112, "path": "src/plugins/types.ts" } } diff --git a/docs/.generated/plugin-sdk-api-baseline.jsonl b/docs/.generated/plugin-sdk-api-baseline.jsonl index f4fafdb3e07..7b7c8635b5c 100644 --- a/docs/.generated/plugin-sdk-api-baseline.jsonl +++ b/docs/.generated/plugin-sdk-api-baseline.jsonl @@ -26,7 +26,7 @@ {"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"index","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":100,"sourcePath":"src/channels/plugins/types.core.ts"} {"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"index","exportName":"ClawdbotConfig","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"} {"declaration":"export type CliBackendConfig = CliBackendConfig;","entrypoint":"index","exportName":"CliBackendConfig","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/config/types.agent-defaults.ts"} -{"declaration":"export type CliBackendPlugin = CliBackendPlugin;","entrypoint":"index","exportName":"CliBackendPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1461,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type CliBackendPlugin = CliBackendPlugin;","entrypoint":"index","exportName":"CliBackendPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1484,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type CompiledConfiguredBinding = CompiledConfiguredBinding;","entrypoint":"index","exportName":"CompiledConfiguredBinding","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":38,"sourcePath":"src/channels/plugins/binding-types.ts"} {"declaration":"export type ConfiguredBindingConversation = ConversationRef;","entrypoint":"index","exportName":"ConfiguredBindingConversation","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/channels/plugins/binding-types.ts"} {"declaration":"export type ConfiguredBindingResolution = ConfiguredBindingResolution;","entrypoint":"index","exportName":"ConfiguredBindingResolution","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":49,"sourcePath":"src/channels/plugins/binding-types.ts"} @@ -42,9 +42,9 @@ {"declaration":"export type ImageGenerationResolution = ImageGenerationResolution;","entrypoint":"index","exportName":"ImageGenerationResolution","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/image-generation/types.ts"} {"declaration":"export type ImageGenerationResult = ImageGenerationResult;","entrypoint":"index","exportName":"ImageGenerationResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":36,"sourcePath":"src/image-generation/types.ts"} {"declaration":"export type ImageGenerationSourceImage = ImageGenerationSourceImage;","entrypoint":"index","exportName":"ImageGenerationSourceImage","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":14,"sourcePath":"src/image-generation/types.ts"} -{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"index","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1114,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"index","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1137,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"index","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"} -{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"index","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1505,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"index","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1528,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"index","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":99,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"index","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":70,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"index","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"} @@ -56,7 +56,7 @@ {"declaration":"export type RuntimeLogger = RuntimeLogger;","entrypoint":"index","exportName":"RuntimeLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/plugins/runtime/types-core.ts"} {"declaration":"export type SecretInput = SecretInput;","entrypoint":"index","exportName":"SecretInput","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":16,"sourcePath":"src/config/types.secrets.ts"} {"declaration":"export type SecretRef = SecretRef;","entrypoint":"index","exportName":"SecretRef","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":10,"sourcePath":"src/config/types.secrets.ts"} -{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"index","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1089,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"index","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1112,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type StatefulBindingTargetDescriptor = StatefulBindingTargetDescriptor;","entrypoint":"index","exportName":"StatefulBindingTargetDescriptor","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/binding-types.ts"} {"declaration":"export type StatefulBindingTargetDriver = StatefulBindingTargetDriver;","entrypoint":"index","exportName":"StatefulBindingTargetDriver","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":15,"sourcePath":"src/channels/plugins/stateful-target-drivers.ts"} {"declaration":"export type StatefulBindingTargetReadyResult = StatefulBindingTargetReadyResult;","entrypoint":"index","exportName":"StatefulBindingTargetReadyResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/channels/plugins/stateful-target-drivers.ts"} @@ -390,18 +390,18 @@ {"declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":76,"sourcePath":"src/channels/plugins/types.plugin.ts"} {"declaration":"export type GatewayBindUrlResult = GatewayBindUrlResult;","entrypoint":"core","exportName":"GatewayBindUrlResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/shared/gateway-bind-url.ts"} {"declaration":"export type GatewayRequestHandlerOptions = GatewayRequestHandlerOptions;","entrypoint":"core","exportName":"GatewayRequestHandlerOptions","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":114,"sourcePath":"src/gateway/server-methods/types.ts"} -{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"core","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1114,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"core","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1137,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"core","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"} -{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1505,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1231,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1528,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1254,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":99,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1487,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1454,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1446,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1510,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1477,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1469,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"core","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":114,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"core","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":135,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1129,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"core","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1260,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1152,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"core","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1283,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"core","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":70,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"} {"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"core","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":657,"sourcePath":"src/plugins/types.ts"} @@ -437,7 +437,7 @@ {"declaration":"export type RoutePeerKind = ChatType;","entrypoint":"core","exportName":"RoutePeerKind","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":19,"sourcePath":"src/routing/resolve-route.ts"} {"declaration":"export type SecretFileReadOptions = SecretFileReadOptions;","entrypoint":"core","exportName":"SecretFileReadOptions","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/infra/secret-file.ts"} {"declaration":"export type SecretFileReadResult = SecretFileReadResult;","entrypoint":"core","exportName":"SecretFileReadResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/infra/secret-file.ts"} -{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"core","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1089,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"core","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1112,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type TailscaleStatusCommandResult = TailscaleStatusCommandResult;","entrypoint":"core","exportName":"TailscaleStatusCommandResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/shared/tailscale-status.ts"} {"declaration":"export type TailscaleStatusCommandRunner = TailscaleStatusCommandRunner;","entrypoint":"core","exportName":"TailscaleStatusCommandRunner","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/shared/tailscale-status.ts"} {"declaration":"export type UsageProviderId = UsageProviderId;","entrypoint":"core","exportName":"UsageProviderId","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":20,"sourcePath":"src/infra/provider-usage.types.ts"} @@ -447,18 +447,18 @@ {"declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"plugin-entry","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export","sourceLine":129,"sourcePath":"src/plugin-sdk/plugin-entry.ts"} {"declaration":"export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"emptyPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export","sourceLine":108,"sourcePath":"src/plugins/config-schema.ts"} {"declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"plugin-entry","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/agents/tools/common.ts"} -{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"plugin-entry","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1114,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"plugin-entry","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1137,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"plugin-entry","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"} -{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1505,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1231,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1528,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1254,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":99,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1487,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"plugin-entry","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1454,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1446,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1510,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"plugin-entry","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1477,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1469,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":114,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"plugin-entry","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":135,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"plugin-entry","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1129,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"plugin-entry","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1260,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"plugin-entry","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1152,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"plugin-entry","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1283,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"plugin-entry","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":70,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":657,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":170,"sourcePath":"src/plugins/types.ts"} @@ -488,7 +488,7 @@ {"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"plugin-entry","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":310,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":622,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"plugin-entry","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":508,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"plugin-entry","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1089,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"plugin-entry","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1112,"sourcePath":"src/plugins/types.ts"} {"category":"provider","entrypoint":"provider-onboard","importSpecifier":"openclaw/plugin-sdk/provider-onboard","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/provider-onboard.ts"} {"declaration":"export function applyAgentDefaultModelPrimary(cfg: OpenClawConfig, primary: string): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyAgentDefaultModelPrimary","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":76,"sourcePath":"src/plugins/provider-onboarding-config.ts"} {"declaration":"export function applyOnboardAuthAgentModelsAndProviders(cfg: OpenClawConfig, params: { agentModels: Record; providers: Record; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyOnboardAuthAgentModelsAndProviders","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/provider-onboarding-config.ts"} diff --git a/extensions/anthropic/index.ts b/extensions/anthropic/index.ts index c36bf9b8e08..6fa44c30cd3 100644 --- a/extensions/anthropic/index.ts +++ b/extensions/anthropic/index.ts @@ -378,6 +378,12 @@ export default definePluginEntry({ docsPath: "/providers/models", envVars: ["ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY"], deprecatedProfileIds: [CLAUDE_CLI_PROFILE_ID], + oauthProfileIdRepairs: [ + { + legacyProfileId: "anthropic:default", + promptLabel: "Anthropic", + }, + ], auth: [ { id: "cli", diff --git a/src/commands/doctor-auth.deprecated-cli-profiles.test.ts b/src/commands/doctor-auth.deprecated-cli-profiles.test.ts index 88b63c17018..d8bd596583b 100644 --- a/src/commands/doctor-auth.deprecated-cli-profiles.test.ts +++ b/src/commands/doctor-auth.deprecated-cli-profiles.test.ts @@ -3,11 +3,21 @@ import os from "node:os"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig } from "../config/config.js"; +import type { ProviderPlugin } from "../plugins/types.js"; import { captureEnv } from "../test-utils/env.js"; -import { maybeRemoveDeprecatedCliAuthProfiles } from "./doctor-auth.js"; +import { + maybeRemoveDeprecatedCliAuthProfiles, + maybeRepairLegacyOAuthProfileIds, +} from "./doctor-auth.js"; import type { DoctorPrompter } from "./doctor-prompter.js"; import type { DoctorRepairMode } from "./doctor-repair-mode.js"; +const resolvePluginProvidersMock = vi.fn<() => ProviderPlugin[]>(() => []); + +vi.mock("../plugins/providers.runtime.js", () => ({ + resolvePluginProviders: () => resolvePluginProvidersMock(), +})); + let envSnapshot: ReturnType; let tempAgentDir: string | undefined; @@ -36,6 +46,8 @@ beforeEach(() => { tempAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-auth-")); process.env.OPENCLAW_AGENT_DIR = tempAgentDir; process.env.PI_CODING_AGENT_DIR = tempAgentDir; + resolvePluginProvidersMock.mockReset(); + resolvePluginProvidersMock.mockReturnValue([]); }); afterEach(() => { @@ -87,6 +99,21 @@ describe("maybeRemoveDeprecatedCliAuthProfiles", () => { "utf8", ); + resolvePluginProvidersMock.mockReturnValue([ + { + id: "anthropic", + label: "Anthropic", + auth: [], + deprecatedProfileIds: ["anthropic:claude-cli"], + }, + { + id: "openai-codex", + label: "OpenAI Codex", + auth: [], + deprecatedProfileIds: ["openai-codex:codex-cli"], + }, + ]); + const cfg = { auth: { profiles: { @@ -120,3 +147,67 @@ describe("maybeRemoveDeprecatedCliAuthProfiles", () => { expect(next.auth?.order?.["openai-codex"]).toEqual(["openai-codex:default"]); }); }); + +describe("maybeRepairLegacyOAuthProfileIds", () => { + it("repairs provider-owned legacy OAuth profile ids", async () => { + if (!tempAgentDir) { + throw new Error("Missing temp agent dir"); + } + const authPath = path.join(tempAgentDir, "auth-profiles.json"); + fs.writeFileSync( + authPath, + `${JSON.stringify( + { + version: 1, + profiles: { + "anthropic:user@example.com": { + type: "oauth", + provider: "anthropic", + access: "token-a", + refresh: "token-r", + expires: Date.now() + 60_000, + email: "user@example.com", + }, + }, + lastGood: { + anthropic: "anthropic:user@example.com", + }, + }, + null, + 2, + )}\n`, + "utf8", + ); + + resolvePluginProvidersMock.mockReturnValue([ + { + id: "anthropic", + label: "Anthropic", + auth: [], + oauthProfileIdRepairs: [{ legacyProfileId: "anthropic:default" }], + }, + ]); + + const next = await maybeRepairLegacyOAuthProfileIds( + { + auth: { + profiles: { + "anthropic:default": { provider: "anthropic", mode: "oauth" }, + }, + order: { + anthropic: ["anthropic:default"], + }, + }, + } as OpenClawConfig, + makePrompter(true), + ); + + expect(next.auth?.profiles?.["anthropic:default"]).toBeUndefined(); + expect(next.auth?.profiles?.["anthropic:user@example.com"]).toMatchObject({ + provider: "anthropic", + mode: "oauth", + email: "user@example.com", + }); + expect(next.auth?.order?.anthropic).toEqual(["anthropic:user@example.com"]); + }); +}); diff --git a/src/commands/doctor-auth.ts b/src/commands/doctor-auth.ts index fc2ad6f840a..3df000fc138 100644 --- a/src/commands/doctor-auth.ts +++ b/src/commands/doctor-auth.ts @@ -22,30 +22,42 @@ import { resolveProviderAuthLoginCommand, } from "./provider-auth-guidance.js"; -export async function maybeRepairAnthropicOAuthProfileId( +export async function maybeRepairLegacyOAuthProfileIds( cfg: OpenClawConfig, prompter: DoctorPrompter, ): Promise { const store = ensureAuthProfileStore(); - const repair = repairOAuthProfileIdMismatch({ - cfg, - store, - provider: "anthropic", - legacyProfileId: "anthropic:default", + let nextCfg = cfg; + const providers = resolvePluginProviders({ + config: cfg, + env: process.env, + bundledProviderAllowlistCompat: true, + bundledProviderVitestCompat: true, }); - if (!repair.migrated || repair.changes.length === 0) { - return cfg; - } + for (const provider of providers) { + for (const repairSpec of provider.oauthProfileIdRepairs ?? []) { + const repair = repairOAuthProfileIdMismatch({ + cfg: nextCfg, + store, + provider: provider.id, + legacyProfileId: repairSpec.legacyProfileId, + }); + if (!repair.migrated || repair.changes.length === 0) { + continue; + } - note(repair.changes.map((c) => `- ${c}`).join("\n"), "Auth profiles"); - const apply = await prompter.confirm({ - message: "Update Anthropic OAuth profile id in config now?", - initialValue: true, - }); - if (!apply) { - return cfg; + note(repair.changes.map((c) => `- ${c}`).join("\n"), "Auth profiles"); + const apply = await prompter.confirm({ + message: `Update ${repairSpec.promptLabel ?? provider.label} OAuth profile id in config now?`, + initialValue: true, + }); + if (!apply) { + continue; + } + nextCfg = repair.config; + } } - return repair.config; + return nextCfg; } function pruneAuthOrder( diff --git a/src/flows/doctor-health-contributions.ts b/src/flows/doctor-health-contributions.ts index 38206295f5f..ec16caf03dc 100644 --- a/src/flows/doctor-health-contributions.ts +++ b/src/flows/doctor-health-contributions.ts @@ -10,7 +10,7 @@ import { import { formatCliCommand } from "../cli/command-format.js"; import { maybeRemoveDeprecatedCliAuthProfiles, - maybeRepairAnthropicOAuthProfileId, + maybeRepairLegacyOAuthProfileIds, noteAuthProfileHealth, } from "../commands/doctor-auth.js"; import { noteBootstrapFileSize } from "../commands/doctor-bootstrap-size.js"; @@ -136,7 +136,7 @@ async function runGatewayConfigHealth(ctx: DoctorHealthFlowContext): Promise { - ctx.cfg = await maybeRepairAnthropicOAuthProfileId(ctx.cfg, ctx.prompter); + ctx.cfg = await maybeRepairLegacyOAuthProfileIds(ctx.cfg, ctx.prompter); ctx.cfg = await maybeRemoveDeprecatedCliAuthProfiles(ctx.cfg, ctx.prompter); await noteAuthProfileHealth({ cfg: ctx.cfg, diff --git a/src/plugins/provider-validation.ts b/src/plugins/provider-validation.ts index 836b8782eff..28f4e1671be 100644 --- a/src/plugins/provider-validation.ts +++ b/src/plugins/provider-validation.ts @@ -41,6 +41,28 @@ function normalizeOnboardingScopes( return normalized.length > 0 ? normalized : undefined; } +function normalizeProviderOAuthProfileIdRepairs( + values: ProviderPlugin["oauthProfileIdRepairs"], +): ProviderPlugin["oauthProfileIdRepairs"] { + if (!Array.isArray(values)) { + return undefined; + } + const normalized = values + .map((value) => { + const legacyProfileId = normalizeText(value?.legacyProfileId); + const promptLabel = normalizeText(value?.promptLabel); + if (!legacyProfileId && !promptLabel) { + return null; + } + return { + ...(legacyProfileId ? { legacyProfileId } : {}), + ...(promptLabel ? { promptLabel } : {}), + }; + }) + .filter((value): value is NonNullable => value !== null); + return normalized.length > 0 ? normalized : undefined; +} + function normalizeProviderWizardSetup(params: { providerId: string; pluginId: string; @@ -273,6 +295,9 @@ export function normalizeRegisteredProvider(params: { const docsPath = normalizeText(params.provider.docsPath); const aliases = normalizeTextList(params.provider.aliases); const deprecatedProfileIds = normalizeTextList(params.provider.deprecatedProfileIds); + const oauthProfileIdRepairs = normalizeProviderOAuthProfileIdRepairs( + params.provider.oauthProfileIdRepairs, + ); const envVars = normalizeTextList(params.provider.envVars); const wizard = normalizeProviderWizard({ providerId: id, @@ -309,6 +334,7 @@ export function normalizeRegisteredProvider(params: { ...(docsPath ? { docsPath } : {}), ...(aliases ? { aliases } : {}), ...(deprecatedProfileIds ? { deprecatedProfileIds } : {}), + ...(oauthProfileIdRepairs ? { oauthProfileIdRepairs } : {}), ...(envVars ? { envVars } : {}), auth, ...(catalog ? { catalog } : {}), diff --git a/src/plugins/types.ts b/src/plugins/types.ts index fa0509b2db1..00f19dbce2d 100644 --- a/src/plugins/types.ts +++ b/src/plugins/types.ts @@ -733,6 +733,21 @@ export type ProviderPluginWizard = { modelPicker?: ProviderPluginWizardModelPicker; }; +export type ProviderOAuthProfileIdRepair = { + /** + * Legacy OAuth profile id to migrate away from. + * + * When omitted, OpenClaw falls back to `:default`. + */ + legacyProfileId?: string; + /** + * Optional custom doctor prompt label. + * + * Defaults to the provider label when omitted. + */ + promptLabel?: string; +}; + export type ProviderModelSelectedContext = { config: OpenClawConfig; model: string; @@ -989,6 +1004,14 @@ export type ProviderPlugin = { * 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. *