Craft Agents Monorepo 核心类型层解析:深入理解 `@craft-agent/core` 的类型设计、工具导出与演进约束
发布时间:2026/9/17 20:44:15 作者:尧图编辑部 阅读量:1,286

Craft Agents Monorepo 核心类型层解析深入理解craft-agent/core的类型设计、工具导出与演进约束【免费下载链接】craft-agents-oss项目地址: https://gitcode.com/GitHub_Trending/cr/craft-agents-oss导读craft-agent/core是 Craft Agents 单体仓库monorepo中面向全仓库共享的类型层type layer承载 workspace工作区、session会话、message消息与 agent event代理事件等核心领域模型的类型定义并附带少量轻量工具函数用于跨包一致性。本文以 packages/core/CLAUDE.md 为主线结合 packages/core/src 下的真实源码系统讲解该包的定位、类型导出全景、工具函数实现、类型检查命令以及保持稳定、依赖轻量、类型优先的演进硬性规则。读完本文你将掌握该类型层的完整结构知道如何在packages/shared与apps/*等下游消费方中正确引用、验证与演进这些类型。一、包的定位Monorepo 的共享类型契约CLAUDE.md开篇即明确了该包的根本职责craft-agent/coreis the sharedtype layerused across the monorepo.也就是说它不是一个包含业务逻辑的运行时模块而是整个仓库的公共类型契约。这一点在 packages/core/src/index.ts 的包级注释中体现得尤为直白/** * craft-agent/core * * Core types and utilities for Craft Agent. * * NOTE: This package currently only exports types and utilities. * Storage, credentials, agent, auth, mcp, and prompts are still * imported directly from src/ in the consuming apps. */该注释明确划定了边界当前版本只导出类型与工具函数存储、凭据、Agent 逻辑、认证、MCP 与提示词prompts等运行时能力仍由消费方应用直接从各自src/导入。这也解释了为什么本包能保持稳定且依赖轻量——它不需要依赖大量运行时模块。从包清单 packages/core/package.json 可以看到craft-agent/core的运行时依赖几乎为空仅声明了两位 peer dependencyanthropic-ai/claude-agent-sdk版本以当前锁定的0.3.197为准README 示例中曾为0.3.154请以 package.json 实际版本为准modelcontextprotocol/sdk1.29.0同时通过exports字段暴露三个入口.根入口、./types类型子路径与./utils工具子路径便于按需引用。二、当前范围两种导出一清二楚CLAUDE.md将包的当前范围概括为两点类型导出覆盖 workspaces、sessions、messages 与 agent events。轻量共享工具导出服务于跨包一致性。对应到源码packages/core/src/index.ts 只是两行转发// Re-export all types export * from ./types/index.ts; // Re-export utilities export * from ./utils/index.ts;类型统一由 packages/core/src/types/index.ts 聚合转发工具统一由 packages/core/src/utils/index.ts 聚合转发。任何新类型或新工具都应先落位于对应目录的源文件再在此处登记导出形成单一事实来源source of truth。三、源码结构CLAUDE.md 声明的唯一事实来源CLAUDE.md明确给出了三条事实来源路径与仓库实际布局完全一致公共导出packages/core/src/index.ts类型定义packages/core/src/types/工具导出packages/core/src/utils/实际目录结构如下packages/core/ ├── CLAUDE.md # 包开发约束与命令 ├── README.md # 面向使用方的说明文档 ├── package.json ├── tsconfig.json └── src/ ├── index.ts # 主入口转发 types 与 utils ├── types/ │ ├── index.ts # 类型聚合转发 │ ├── workspace.ts # Workspace、认证类型 │ ├── session.ts # 会话类型 │ ├── message.ts # 消息、事件、工具状态等 │ ├── message-mapper.ts # 消息持久化映射messageToStored / storedToMessage │ └── server.ts # 无头服务器操作类型 └── utils/ ├── index.ts # 工具聚合转发 ├── debug.ts # 调试工具默认 no-op └── paths.ts # 跨平台路径工具其中 packages/core/src/types/index.ts 按领域分组workspace 与 config、session、message、server并以export type { ... }的形式精确转发每个类型同时额外转出两个运行时函数generateMessageId与messageToStored/storedToMessage来自 message.ts 与 message-mapper.ts。四、类型导出全景四大领域逐一拆解4.1 Workspace 与配置workspace.tspackages/core/src/types/workspace.ts 定义了工作区与认证相关契约核心类型包括类型说明McpAuthTypeMCP 服务器认证方式workspace_oauth|workspace_bearer|public注意与单源场景的oauth/bearer/none区分RemoteServerConfig远程 Craft Agent Server 配置urlws://或wss://、token、remoteWorkspaceId设置后 handler 调用将通过 WebSocket 代理WorkspaceInfo面向客户端的 workspace DTO可安全经 RPC 发给远程客户端不暴露服务端内部文件系统路径Workspace继承WorkspaceInfo并追加服务端内部字段rootPath本地绝对路径远程 workspace 会自动创建与createdAtAuthTypeAI 提供商认证类型api_keyAnthropic API Key、oauth_tokenClaude Max OAuth、codex_oauthChatGPT Plus OAuth、codex_api_keyOpenAI API Key via CodexOAuthCredentials一次全新 OAuth 流程得到的凭据accessToken、可选refreshToken、expiresAt、clientId、tokenType用于 UI 临时状态最终应写入凭据存储StoredConfig存储在 JSON 文件中的应用配置凭据不在此而是存于加密文件authType、workspaces、activeWorkspaceId、activeSessionId、model值得注意的设计细节WorkspaceInfo刻意不含rootPath因为该字段包含服务端内部文件系统路径绝不能通过 RPC 暴露给远程客户端而Workspace只供服务端代码与本地 Electron 渲染器的LOCAL_ONLY通道使用。4.2 会话session.tspackages/core/src/types/session.ts 将Session 定义为对话的隔离边界——每个 Session 与一个 CraftAgent 实例及一个 SDK conversation 一一对应。核心类型SessionStatus工作流状态枚举todo|in_progress|needs_review|done|cancelledAgent 可主动更新以反映会话当前状态。Sessionid稳定且立即可知的唯一标识、sdkSessionId首次消息后捕获、workspaceId、可选name、createdAt、lastUsedAt以及收件箱/归档能力isArchived、isFlagged、status与已读追踪lastReadMessageId。StoredSession继承Session并追加持久化所需数据——messages: StoredMessage[]与tokenUsage: TokenUsage。SessionMetadata用于列表展示的轻量元数据不加载完整消息除基础字段外还包含messageCount、首条用户消息preview以及收件箱/归档相关的isArchived、isFlagged、status、hidden。4.3 消息与事件message.tspackages/core/src/types/message.ts 是体量最大、字段最丰富的文件定义了从运行时消息到持久化格式、从工具执行状态到类型化错误的完整契约MessageRoleuser|assistant|tool|error|status|info|warning|plan|auth-request。ToolStatuspending|executing|completed|error|backgrounded。TokenUsage与AgentEventUsage输入/输出/总 token 数、上下文 token、成本costUsd、缓存读写 tokencacheReadTokens、cacheCreationTokens等AgentEventUsage是complete事件中 SDK 上报的子集。Message运行时消息与StoredMessage持久化消息的职责划分非常关键StoredMessage明确剔除仅运行时存在的瞬态字段如isStreaming、isPending同时保留turnId、isIntermediate、statusType、infoLevel等重载后渲染所需的字段例如 TurnCard 组件在 reload 后依赖turnId分组。丰富的业务字段工具展示元数据ToolDisplayMeta含 base64 图标的iconDataUrl保证 Electron 与 Web viewer 均可用、附件MessageAttachment/StoredAttachment图片自动缩放wasResized、Office 转 Markdown 的markdownPath等、行内徽章ContentBadgelinear、commit等模式高亮、注释体系AnnotationV1含 text-quote / text-position / block / xywh / table-cell 五种选择器、后台任务字段taskId、shellId、elapsedSeconds、isBackground、计划字段planPath、以及整套认证请求字段authRequestType、authCredentialMode、authHeaderNames等。TypedError与ErrorCode类型化错误体系ErrorCode枚举涵盖invalid_api_key、expired_oauth_token、rate_limited、proxy_error、mcp_auth_required、model_no_tool_support、image_too_large、queued_message_replay_failed、sdk_binary_missing等 20 错误码源码注释指出必须与packages/shared/src/agent/errors.ts中AgentError.code保持一致。PermissionRequest权限请求契约支持bash|file_write|mcp_mutation|api_mutation|admin_approval五类附带appName、reason、impact、commandHash、approvalTtlSeconds等用于管理员审批体验的字段。AgentEventCraftAgent 在聊天过程中发出的事件联合类型discriminated union覆盖status/info/text_delta/text_complete、tool_start/tool_result、permission_request、error/typed_error、complete带 usage、working_directory_changed、task_backgrounded/task_progress/task_completed、shell_backgrounded/shell_killed、workflow_agent_completed、source_activated、usage_update、steer_undelivered等 20 余种事件类型turnId作为 APImessage.id的相关性 ID 贯穿一整个 assistant turn 的所有事件。4.4 服务器操作server.tspackages/core/src/types/server.ts 面向无头headless服务器操作供server:RPC 命名空间使用ServerStatusserverId、version、自启动以来的uptime秒、connectedClients、各 workspace 的activeSessions/automationCount/schedulerRunning以及内存统计heapUsed、heapTotal、rss单位字节。ServerHealthok|degraded|unhealthy三态 一组pass/fail检查项。SessionProcessingStatus会话处理状态联合类型非字符串化idle|processing|waiting_input|error|completed。ActiveSessionInfo跨 workspace 的客户端安全活动会话信息含触发来源triggeredBy自动化名称与时间戳。五、工具函数导出为跨包一致性而生的轻量实现packages/core/src/utils/index.ts 目前导出四个工具5.1debug()—— 默认空操作的调试桩import { debug } from craft-agent/core; debug(Processing message:, message.id);packages/core/src/utils/debug.ts 中的实现是一个no-op 桩默认不输出任何内容源码注释明确建议如需完整日志请使用craft-agent/shared的 debug 工具。也就是说这个函数存在的意义是为调用方预留一致的调用接口后续可通过process.env.DEBUG之类的方式增强而不破坏已有调用点。5.2 跨平台路径工具paths.tspackages/core/src/utils/paths.ts 提供三个用于 Windows/macOS/Linux 三端一致的路径处理函数import { normalizePath, pathStartsWith, stripPathPrefix } from craft-agent/core; // 统一为正斜杠便于跨平台比较与正则匹配 normalizePath(C:\\Users\\foo\\bar); // C:/Users/foo/bar // 判断文件是否位于某目录之下避免 /home/user2 误判为 /home/user 之下 pathStartsWith(C:\\Users\\foo\\file.txt, C:\\Users\\foo); // true pathStartsWith(/home/user2/file.txt, /home/user); // false // 剥离目录前缀得到相对路径 stripPathPrefix(/home/user/docs/file.txt, /home/user); // docs/file.txt设计要点所有比较前一律先normalizePath转正斜杠且pathStartsWith通过normalizedDir /前缀判断从根本上规避了/home/user2这类目录前缀误判问题。5.3generateMessageId()与消息映射器generateMessageId()定义于 message.tsexport function generateMessageId(): string { return msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}; } // 示例输出msg-1702736400000-a1b2c3采用时间戳 随机后缀的格式无需外部依赖即可生成全局唯一消息 ID。此外 types/index.ts 还转出了messageToStored/storedToMessage两个持久化映射函数实现于 message-mapper.ts用于运行时消息与存储格式之间的双向转换。六、如何安装与使用6.1 安装在 monorepo 的 workspace 包中bun add craft-agent/core或直接在package.json中声明 workspace 依赖{ dependencies: { craft-agent/core: workspace:* } }由于仓库使用 bun.lock 与 bunfig.toml 管理依赖建议统一使用bun add以保证锁文件一致。6.2 导入类型与工具// 导入类型type-only import符合类型优先原则 import type { Workspace, Session, Message, TokenUsage, AgentEvent, } from craft-agent/core; // 导入工具函数 import { generateMessageId, debug } from craft-agent/core; // 也可按子路径按需引入 import type { Workspace } from craft-agent/core/types; import { normalizePath } from craft-agent/core/utils;更完整的导出清单可查阅 packages/core/README.md 与 packages/core/src/types/index.ts。七、类型检查命令与开发工作流CLAUDE.md给出的唯一命令是类型检查需在仓库根目录执行cd packages/core bun run tsc --noEmit该命令基于 packages/core/tsconfig.json 对src/做仅类型检查不产出文件。开发者在修改本包后的标准工作流是修改src/types/*.ts或src/utils/*.ts中的定义在 types/index.ts 或 utils/index.ts 中登记导出运行上述bun run tsc --noEmit通过类型检查验证下游packages/shared与apps/*的编译见下一节。八、演进硬性规则Hard rules为何本包必须稳字当头CLAUDE.md明确列出三条硬性规则它们共同决定了这个类型层的演进方式保持本包稳定且依赖轻量Keep this package stable and dependency-light。这意味着新增依赖、引入运行时逻辑都应当极其谨慎——本包当前零运行时依赖的状态正是这条规则的直接结果。除非存在明确的跨包运行时需求否则优先做纯类型变更Prefer type-only changes unless there is a clear cross-package runtime need。纯类型变更不会改变运行时行为风险最低即便未来需要运行时能力也应先在packages/shared等更偏运行的包中实现再考虑是否上提。变更导出类型时必须验证packages/shared与apps/*的下游使用When changing exported types, validate downstream usage inpackages/sharedandapps/*。第三点尤其重要本仓库中packages/shared含agent/、sessions/、sources/、automations/等大量实现、apps/electron、apps/cli、apps/webui、apps/viewer以及packages/server-core都直接或间接消费本包类型。改动一个字段例如Message的某个可选字段就可能波及会话持久化、RPC 传输、渲染层展示等多个环节。因此任何破坏性变更都应先在仓库中全局搜索引用点例如搜索import type ... from craft-agent/core逐一确认影响面后再落地。九、总结类型层的价值与使用建议craft-agent/core的价值不在于代码量而在于它作为全仓库共享的类型契约所起到的稳定锚点作用统一领域模型Workspace、Session、Message、AgentEvent 等核心概念在类型层一次性定义避免各应用各自建模导致漂移明确安全边界WorkspaceInfo与Workspace的拆分、StoredConfig与加密凭据的分离都把哪些数据可以过 RPC、哪些只能留本地固化进了类型系统持久化与运行时解耦Message与StoredMessage的字段差异精准刻画了瞬态字段与重载必需字段的边界轻量可演进零运行时依赖 纯类型优先的规则使该包可以作为全仓库类型重构的低风险地基。在 Craft Agents 的后续开发中任何涉及跨包共享数据结构的改动都应先回到packages/core/src/types/审视类型契约再通过bun run tsc --noEmit与下游编译验证从而让这个最稳的包持续发挥其类型地基的作用。【免费下载链接】craft-agents-oss项目地址: https://gitcode.com/GitHub_Trending/cr/craft-agents-oss创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考