/** * 能力目录(架构设计 2 / 4:registry 模块)。 * * 保存已注册 Provider 与它们声明的能力;上层按身份取「能力清单」(A4 起按策略过滤, * 当前只做注册与查找)。能力目录是唯一来源——引擎的工具列表是它的投影。 */ import type { Capability, Provider, ProviderManifest } from '@aps/provider-sdk'; export interface RegisteredProvider { manifest: ProviderManifest; provider: Provider; } export interface ResolvedCapability { capability: Capability; provider: Provider; providerId: string; /** 该系统是否需要平台用户绑定账号(A4.1);缺省 true */ requiresIdentity: boolean; /** 登录方式声明(ADR-0012);没声明表示该系统没有账号概念 */ authKind?: 'oauth' | 'password-exchange' | 'apikey'; } export class CapabilityRegistry { private readonly providers = new Map(); async register(provider: Provider): Promise { const manifest = await provider.describe(); if (manifest.platformVersion !== 1) { throw new Error(`Provider ${manifest.id} 声明兼容平台版本 ${manifest.platformVersion},当前平台只支持 1`); } this.providers.set(manifest.id, { manifest, provider }); return manifest; } list(): Capability[] { return [...this.providers.values()].flatMap((entry) => entry.manifest.capabilities); } resolve(capabilityId: string): ResolvedCapability | undefined { for (const entry of this.providers.values()) { const capability = entry.manifest.capabilities.find((item) => item.id === capabilityId); if (capability) { return { capability, provider: entry.provider, providerId: entry.manifest.id, requiresIdentity: entry.manifest.requiresIdentity !== false, ...(entry.manifest.auth === undefined ? {} : { authKind: entry.manifest.auth.kind }), }; } } return undefined; } /** 某个 Provider 的 manifest(绑定流程要读它的 auth 声明) */ manifest(providerId: string): ProviderManifest | undefined { return this.providers.get(providerId)?.manifest; } /** 某个 Provider 实例(绑定流程要用它的 exchange / checkCredential) */ provider(providerId: string): Provider | undefined { return this.providers.get(providerId)?.provider; } providerIds(): string[] { return [...this.providers.keys()]; } async health(): Promise> { const results: Array<{ providerId: string; status: string; detail?: string }> = []; for (const [providerId, entry] of this.providers) { try { const health = await entry.provider.health(); results.push(health.detail === undefined ? { providerId, status: health.status } : { providerId, status: health.status, detail: health.detail }); } catch (error) { results.push({ providerId, status: 'down', detail: error instanceof Error ? error.message : '健康探测失败' }); } } return results; } }