// 对外 API 的数据结构(docs/design/04-api.md) import type { InteractionRequest, ProviderId, UsagePayload } from './events' export type PermissionMode = 'ask' | 'auto' | 'readonly' export type SessionStatus = 'idle' | 'running' | 'waiting_input' export type RunStatus = 'queued' | 'running' | 'waiting_input' | 'completed' | 'failed' | 'interrupted' export interface SessionDto { id: string title: string provider: ProviderId model: string profileId: string | null status: SessionStatus archived: boolean source: string lastSeq: number createdAt: string updatedAt: string } export interface SessionDetailDto extends SessionDto { activeRunId: string | null pendingInteractions: InteractionRequest[] /** 实际生效的权限模式:会话覆盖值(仅后台可设)或 Profile 的设置 */ permissionMode: PermissionMode permissionModeOverridden: boolean systemPromptAppend: string } export interface CreateSessionBody { profileId?: string model?: string title?: string permissionMode?: PermissionMode systemPromptAppend?: string } export interface SendMessageBody { text: string attachments?: string[] } export interface RunDto { id: string sessionId: string status: RunStatus startedAt: string | null endedAt: string | null usage: UsagePayload | null error: string | null } export interface FileDto { id: string sessionId: string path: string origin: 'upload' | 'agent' mime: string size: number createdAt: string updatedAt: string } export interface FileAccessPolicy { mode: 'restricted' | 'broad' read: PathRule[] write: PathRule[] deny: string[] } export type PathRule = { knowledgeRootId: string } | { path: string } export interface ProfileDto { id: string name: string description: string provider: ProviderId model: string systemPrompt: string permissionMode: PermissionMode allowedTools: string[] disallowedTools: string[] skills: string[] | 'all' fileAccess: FileAccessPolicy knowledgeRootIds: string[] isDefault: boolean /** 内置 Profile(通用助手)不可删除 */ builtin: boolean version: number updatedAt: string } export type ProfileInput = Omit export interface KnowledgeRootDto { id: string name: string path: string description: string access: 'read' | 'write' enabled: boolean check: PathCheck } export interface PathCheck { exists: boolean readable: boolean isDirectory: boolean /** 命中的全局禁止项 */ denied: string | null /** 位于 home 下,systemd ProtectHome 部署时需要额外绑定 */ underHome: boolean message: string | null } export interface ProviderStatusDto { id: ProviderId enabled: boolean available: boolean loggedIn: boolean | null account: string | null cliPath: string version: string | null models: string[] defaultModel: string message: string | null } export interface ResolvedAccessDto { readable: string[] writable: string[] denied: string[] mode: FileAccessPolicy['mode'] } export interface ApiKeyDto { id: string name: string prefix: string enabled: boolean allowedProfileIds: string[] defaultProfileId: string | null createdAt: string lastUsedAt: string | null } export interface ApiErrorBody { error: { code: string; message: string; details?: unknown } } export interface Page { items: T[] nextCursor: string | null } // ---- 技能与插件(通过 Claude Code 官方插件机制安装,ADR-0013)---- export type LicenseKind = 'open' | 'restricted' | 'unknown' export interface SkillInfo { /** 带插件前缀的技能 ID,例如 agent-skills:report-conventions、document-skills:xlsx */ id: string name: string description: string plugin: string /** local 本地技能目录;plugin Claude 插件;official 从官方仓库安装(Codex);system 引擎自带;community 第三方技能(两个引擎共用,需在 Profile 中单独启用) */ source: 'local' | 'plugin' | 'official' | 'system' | 'community' license: LicenseKind } export interface InstalledPluginDto { id: string name: string marketplace: string version: string | null enabled: boolean installPath: string installedAt: string | null lastUpdated: string | null skills: SkillInfo[] license: { kind: LicenseKind; summary: string | null } } export interface AvailablePluginDto { pluginId: string name: string description: string marketplaceName: string version: string | null installed: boolean } export interface MarketplaceDto { name: string source: string location: string | null } export interface PluginStateDto { cliPath: string installed: InstalledPluginDto[] available: AvailablePluginDto[] marketplaces: MarketplaceDto[] localSkills: SkillInfo[] error: string | null } export type PluginAction = | { action: 'marketplace-add'; source: string } | { action: 'marketplace-remove' | 'marketplace-update'; name: string } | { action: 'install' | 'uninstall' | 'update' | 'enable' | 'disable'; plugin: string } export interface ApiKeyProfiles { allowedProfileIds: string[] defaultProfileId: string } export interface CodexCatalogSkillDto { name: string description: string license: LicenseKind licenseName: string | null installed: boolean installedSha: string | null updatable: boolean } export interface CodexSkillCatalogDto { repo: string sha: string | null fetchedAt: string | null skills: CodexCatalogSkillDto[] unmanaged: string[] } // ---- 第三方技能(skills.sh 目录,从 GitHub 按提交安装,两个引擎共用,ADR-0017)---- /** 第三方技能的插件名,技能 ID 形如 community-skills: */ export const COMMUNITY_SKILL_PLUGIN = 'community-skills' export interface CommunitySearchResultDto { /** GitHub 仓库 owner/repo */ source: string skillId: string name: string installs: number installed: boolean /** 不能从这里安装的原因(如官方技能仓库应在对应引擎的页面安装) */ blocked: string | null } export interface CommunitySkillPreviewDto { source: string skillId: string /** 安装后的技能名(取自 SKILL.md 的 name) */ name: string description: string sha: string /** 技能在仓库中的路径 */ path: string skillMd: string files: { path: string; size: number }[] /** 技能包含可执行脚本(.py / .sh / .js 等) */ hasScripts: boolean license: LicenseKind licenseName: string | null /** 许可证来自哪里:技能目录、SKILL.md 声明或仓库根目录 */ licenseFrom: 'skill' | 'frontmatter' | 'repo' | null installed: { sha: string } | null /** 同名技能已从其他来源安装 */ conflict: string | null } export interface CommunitySkillDto { id: string name: string description: string source: string skillId: string path: string sha: string license: string | null installedAt: string } // ---- Codex 插件(OpenAI 官方 openai-curated 目录,只在 Playground 中使用,ADR-0018)---- export interface CodexPluginDto { /** 插件 ID(plugin/uninstall 使用),形如 gmail@openai-curated-remote */ id: string name: string displayName: string description: string category: string | null developer: string | null marketplace: string installed: boolean enabled: boolean /** NOT_AVAILABLE / AVAILABLE / INSTALLED_BY_DEFAULT */ installPolicy: string /** AVAILABLE / DISABLED_BY_ADMIN */ availability: string logoUrl: string | null } export interface CodexPluginCatalogDto { items: CodexPluginDto[] /** 符合筛选条件的总数 */ total: number categories: string[] fetchedAt: string | null error: string | null } export interface CodexPluginDetailDto extends CodexPluginDto { longDescription: string | null skills: { name: string; description: string }[] apps: { id: string; name: string; description: string | null; installUrl: string | null }[] mcpServers: string[] websiteUrl: string | null privacyPolicyUrl: string | null termsOfServiceUrl: string | null } export interface CodexPluginInstallResultDto { /** 需要在 ChatGPT 中授权的应用(打开 installUrl 完成连接) */ appsNeedingAuth: { id: string; name: string; installUrl: string | null }[] } // ---- 用量统计 ---- export interface UsageTotals { runs: number failed: number interrupted: number inputTokens: number outputTokens: number cacheReadTokens: number cacheWriteTokens: number /** 订阅登录下为引擎给出的估算值 */ costUsd: number durationMs: number } export interface UsageSummaryDto { /** 统计区间(含首尾,服务器本地日期) */ from: string to: string total: UsageTotals today: UsageTotals /** 每天一项,没有用量的日期也会列出 */ daily: ({ date: string } & UsageTotals)[] /** 按来源:API Key(平台)或后台 Playground(source = admin) */ bySource: ({ source: string; name: string } & UsageTotals)[] byModel: ({ provider: string; model: string } & UsageTotals)[] } export interface RecentErrorDto { runId: string sessionId: string sessionTitle: string source: string provider: string error: string endedAt: string | null } // ---- 浏览器令牌(业务平台后端用 API Key 换取,交给浏览器使用,ADR-0019)---- export interface CreateBrowserTokenBody { /** 有效期(秒),默认 3600,最长 43200 */ ttlSeconds?: number } export interface BrowserTokenDto { token: string expiresAt: string }