feat: add provider auth plugins
This commit is contained in:
@@ -190,6 +190,7 @@ function createPluginRecord(params: {
|
||||
status: params.enabled ? "loaded" : "disabled",
|
||||
toolNames: [],
|
||||
channelIds: [],
|
||||
providerIds: [],
|
||||
gatewayMethods: [],
|
||||
cliCommands: [],
|
||||
services: [],
|
||||
|
||||
23
src/plugins/providers.ts
Normal file
23
src/plugins/providers.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { createSubsystemLogger } from "../logging.js";
|
||||
import { loadClawdbotPlugins } from "./loader.js";
|
||||
import type { ProviderPlugin } from "./types.js";
|
||||
|
||||
const log = createSubsystemLogger("plugins");
|
||||
|
||||
export function resolvePluginProviders(params: {
|
||||
config?: Parameters<typeof loadClawdbotPlugins>[0]["config"];
|
||||
workspaceDir?: string;
|
||||
}): ProviderPlugin[] {
|
||||
const registry = loadClawdbotPlugins({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
logger: {
|
||||
info: (msg) => log.info(msg),
|
||||
warn: (msg) => log.warn(msg),
|
||||
error: (msg) => log.error(msg),
|
||||
debug: (msg) => log.debug(msg),
|
||||
},
|
||||
});
|
||||
|
||||
return registry.providers.map((entry) => entry.provider);
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
ClawdbotPluginChannelRegistration,
|
||||
ClawdbotPluginCliRegistrar,
|
||||
ClawdbotPluginHttpHandler,
|
||||
ProviderPlugin,
|
||||
ClawdbotPluginService,
|
||||
ClawdbotPluginToolContext,
|
||||
ClawdbotPluginToolFactory,
|
||||
@@ -47,6 +48,12 @@ export type PluginChannelRegistration = {
|
||||
source: string;
|
||||
};
|
||||
|
||||
export type PluginProviderRegistration = {
|
||||
pluginId: string;
|
||||
provider: ProviderPlugin;
|
||||
source: string;
|
||||
};
|
||||
|
||||
export type PluginServiceRegistration = {
|
||||
pluginId: string;
|
||||
service: ClawdbotPluginService;
|
||||
@@ -66,6 +73,7 @@ export type PluginRecord = {
|
||||
error?: string;
|
||||
toolNames: string[];
|
||||
channelIds: string[];
|
||||
providerIds: string[];
|
||||
gatewayMethods: string[];
|
||||
cliCommands: string[];
|
||||
services: string[];
|
||||
@@ -78,6 +86,7 @@ export type PluginRegistry = {
|
||||
plugins: PluginRecord[];
|
||||
tools: PluginToolRegistration[];
|
||||
channels: PluginChannelRegistration[];
|
||||
providers: PluginProviderRegistration[];
|
||||
gatewayHandlers: GatewayRequestHandlers;
|
||||
httpHandlers: PluginHttpRegistration[];
|
||||
cliRegistrars: PluginCliRegistration[];
|
||||
@@ -95,6 +104,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
plugins: [],
|
||||
tools: [],
|
||||
channels: [],
|
||||
providers: [],
|
||||
gatewayHandlers: {},
|
||||
httpHandlers: [],
|
||||
cliRegistrars: [],
|
||||
@@ -189,6 +199,35 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
});
|
||||
};
|
||||
|
||||
const registerProvider = (record: PluginRecord, provider: ProviderPlugin) => {
|
||||
const id = typeof provider?.id === "string" ? provider.id.trim() : "";
|
||||
if (!id) {
|
||||
pushDiagnostic({
|
||||
level: "error",
|
||||
pluginId: record.id,
|
||||
source: record.source,
|
||||
message: "provider registration missing id",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const existing = registry.providers.find((entry) => entry.provider.id === id);
|
||||
if (existing) {
|
||||
pushDiagnostic({
|
||||
level: "error",
|
||||
pluginId: record.id,
|
||||
source: record.source,
|
||||
message: `provider already registered: ${id} (${existing.pluginId})`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
record.providerIds.push(id);
|
||||
registry.providers.push({
|
||||
pluginId: record.id,
|
||||
provider,
|
||||
source: record.source,
|
||||
});
|
||||
};
|
||||
|
||||
const registerCli = (
|
||||
record: PluginRecord,
|
||||
registrar: ClawdbotPluginCliRegistrar,
|
||||
@@ -241,6 +280,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
registerTool: (tool, opts) => registerTool(record, tool, opts),
|
||||
registerHttpHandler: (handler) => registerHttpHandler(record, handler),
|
||||
registerChannel: (registration) => registerChannel(record, registration),
|
||||
registerProvider: (provider) => registerProvider(record, provider),
|
||||
registerGatewayMethod: (method, handler) => registerGatewayMethod(record, method, handler),
|
||||
registerCli: (registrar, opts) => registerCli(record, registrar, opts),
|
||||
registerService: (service) => registerService(record, service),
|
||||
@@ -254,6 +294,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
pushDiagnostic,
|
||||
registerTool,
|
||||
registerChannel,
|
||||
registerProvider,
|
||||
registerGatewayMethod,
|
||||
registerCli,
|
||||
registerService,
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import type { Command } from "commander";
|
||||
|
||||
import type { AuthProfileCredential, OAuthCredential } from "../agents/auth-profiles/types.js";
|
||||
import type { AnyAgentTool } from "../agents/tools/common.js";
|
||||
import type { ChannelDock } from "../channels/dock.js";
|
||||
import type { ChannelPlugin } from "../channels/plugins/types.js";
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import type { ModelProviderConfig } from "../config/types.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import type { WizardPrompter } from "../wizard/prompts.js";
|
||||
import type { createVpsAwareOAuthHandlers } from "../commands/oauth-flow.js";
|
||||
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
|
||||
|
||||
export type PluginLogger = {
|
||||
@@ -54,6 +59,48 @@ export type ClawdbotPluginToolFactory = (
|
||||
ctx: ClawdbotPluginToolContext,
|
||||
) => AnyAgentTool | AnyAgentTool[] | null | undefined;
|
||||
|
||||
export type ProviderAuthKind = "oauth" | "api_key" | "token" | "device_code" | "custom";
|
||||
|
||||
export type ProviderAuthResult = {
|
||||
profiles: Array<{ profileId: string; credential: AuthProfileCredential }>;
|
||||
configPatch?: Partial<ClawdbotConfig>;
|
||||
defaultModel?: string;
|
||||
notes?: string[];
|
||||
};
|
||||
|
||||
export type ProviderAuthContext = {
|
||||
config: ClawdbotConfig;
|
||||
agentDir?: string;
|
||||
workspaceDir?: string;
|
||||
prompter: WizardPrompter;
|
||||
runtime: RuntimeEnv;
|
||||
isRemote: boolean;
|
||||
openUrl: (url: string) => Promise<void>;
|
||||
oauth: {
|
||||
createVpsAwareHandlers: typeof createVpsAwareOAuthHandlers;
|
||||
};
|
||||
};
|
||||
|
||||
export type ProviderAuthMethod = {
|
||||
id: string;
|
||||
label: string;
|
||||
hint?: string;
|
||||
kind: ProviderAuthKind;
|
||||
run: (ctx: ProviderAuthContext) => Promise<ProviderAuthResult>;
|
||||
};
|
||||
|
||||
export type ProviderPlugin = {
|
||||
id: string;
|
||||
label: string;
|
||||
docsPath?: string;
|
||||
aliases?: string[];
|
||||
envVars?: string[];
|
||||
models?: ModelProviderConfig;
|
||||
auth: ProviderAuthMethod[];
|
||||
formatApiKey?: (cred: AuthProfileCredential) => string;
|
||||
refreshOAuth?: (cred: OAuthCredential) => Promise<OAuthCredential>;
|
||||
};
|
||||
|
||||
export type ClawdbotPluginGatewayMethod = {
|
||||
method: string;
|
||||
handler: GatewayRequestHandler;
|
||||
@@ -123,6 +170,7 @@ export type ClawdbotPluginApi = {
|
||||
registerGatewayMethod: (method: string, handler: GatewayRequestHandler) => void;
|
||||
registerCli: (registrar: ClawdbotPluginCliRegistrar, opts?: { commands?: string[] }) => void;
|
||||
registerService: (service: ClawdbotPluginService) => void;
|
||||
registerProvider: (provider: ProviderPlugin) => void;
|
||||
resolvePath: (input: string) => string;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user