import type { LLMProvider } from '@/shared/types.js'; /** * Static, backend-owned description of what one provider integration supports. * * The frontend renders its composer UI (permission mode picker, image upload, * abort button, ...) purely from this shape, which is what keeps the frontend * free of per-provider conditionals. New provider features should be exposed * here instead of branching on the provider id in React components. */ type ProviderCapabilities = { provider: LLMProvider; /** Permission modes the provider runtime understands, in cycle order. */ permissionModes: string[]; defaultPermissionMode: string; /** Whether image attachments can be included in a chat.send. */ supportsImages: boolean; /** Whether an in-flight run can be cancelled via chat.abort. */ supportsAbort: boolean; /** Whether interactive tool permission prompts can reach the UI. */ supportsPermissionRequests: boolean; /** Whether the token-usage endpoint has data for this provider. */ supportsTokenUsage: boolean; }; /** * The capability matrix mirrors what each runtime actually implements today: * - permission modes match the option sets accepted by each CLI/SDK. * - only the Claude SDK integration surfaces interactive permission requests. * - Cursor has no token usage endpoint support (its store.db has no usage rows). */ const PROVIDER_CAPABILITIES: Record = { claude: { provider: 'claude', permissionModes: ['default', 'auto', 'acceptEdits', 'bypassPermissions', 'plan'], defaultPermissionMode: 'default', supportsImages: true, supportsAbort: true, supportsPermissionRequests: true, supportsTokenUsage: true, }, cursor: { provider: 'cursor', permissionModes: ['default', 'acceptEdits', 'bypassPermissions', 'plan'], defaultPermissionMode: 'default', supportsImages: false, supportsAbort: true, supportsPermissionRequests: false, supportsTokenUsage: false, }, codex: { provider: 'codex', permissionModes: ['default', 'acceptEdits', 'bypassPermissions'], defaultPermissionMode: 'default', supportsImages: false, supportsAbort: true, supportsPermissionRequests: false, supportsTokenUsage: true, }, gemini: { provider: 'gemini', permissionModes: ['default', 'acceptEdits', 'bypassPermissions', 'plan'], defaultPermissionMode: 'default', supportsImages: false, supportsAbort: true, supportsPermissionRequests: false, supportsTokenUsage: true, }, opencode: { provider: 'opencode', permissionModes: ['default'], defaultPermissionMode: 'default', supportsImages: false, supportsAbort: true, supportsPermissionRequests: false, supportsTokenUsage: true, }, }; /** * Application service exposing the provider capability matrix. */ export const providerCapabilitiesService = { getProviderCapabilities(provider: LLMProvider): ProviderCapabilities { return PROVIDER_CAPABILITIES[provider]; }, listAllProviderCapabilities(): ProviderCapabilities[] { return Object.values(PROVIDER_CAPABILITIES); }, };