@agentic/platform-core:Agentic 平台核心工具库的安装、导出清单与源码级实现解析
【免费下载链接】agenticYour API ⇒ Paid MCP. Instantly.项目地址: https://gitcode.com/GitHub_Trending/ag/agentic
本文围绕 Agentic 仓库中的 packages/platform-core/readme.md 展开,系统介绍@agentic/platform-core这个“跨平台共享的核心工具包”:包括安装与引入方式、完整导出清单,以及对象操作、Zod 校验、SHA-256 哈希、限流响应头、错误体系等每个模块的源码实现细节。读完本文,你可以直接在自研服务端复用这些工具函数,并理解 Agentic 的 API 与网关如何依赖该包维持行为一致性。
包定位与安装
@agentic/platform-core的定位在 readme 中一句话概括:“Core utilities shared across the Agentic platform”(Agentic 平台各部分共享的核心工具)。它本身不是面向最终用户的入口包——readme 明确提示,大多数场景应优先使用面向公众的 @agentic/cli、@agentic/platform 与工具客户端等包,本包是它们的公共底座。
安装方式:
npm i @agentic/platform-core从 packages/platform-core/package.json 可以确认该包的关键工程属性:
- 包名与版本:
@agentic/platform-core,当前仓库内版本为8.4.4; - 运行环境:
engines.node >= 18,即需要 Node.js 18 及以上; - 模块形态:
"type": "module"纯 ESM,且声明了"sideEffects": false,便于打包器做 Tree-shaking; - 依赖:
zod、parse-json、sort-keys、decircular、is-obj、@sindresorhus/slugify、type-fest、zod-validation-error、ohash等,版本大多通过 pnpm catalog("catalog:")统一管理; - 许可:AGPL-3.0(GNU AGPL 3.0)。
发布产物由tsup构建("build": "tsup"),发布时只包含dist目录,并输出index.js与index.d.ts;仓库内开发时则直接以 TypeScript 源码为入口("exports": { ".": "./src/index.ts" })。
完整导出清单
入口文件 packages/platform-core/src/index.ts 只有 5 行,清晰地界定了包的五个组成部分:
export * from './errors' export * from './hash-object' export * from './rate-limit-headers' export type * from './types' export * from './utils'其中types仅导出类型(Logger、RateLimitResult),其余四个模块导出运行时值。此外utils模块还会再导出第三方库parse-json的默认函数,因此parseJson也是本包的公开 API。readme 的 Usage 示例即展示了典型引入方式:
import { assert, omit, pick, parseJson, parseZodSchema, sha256, getEnv, sanitizeSearchParams, pruneUndefined, slugify // etc... } from '@agentic/platform-core'在仓库内,该包被大量服务端代码直接依赖,例如 apps/api 中 auth、consumers、deployments、projects 等目录下的众多接口处理函数都从@agentic/platform-core引入工具,说明它是平台 API 层事实上的公共依赖。
对象操作工具:omit、pick 与 assert
packages/platform-core/src/utils.ts 是工具最密集的文件。omit与pick用于按键裁剪对象,二者都返回新对象、不修改入参:
omit({ a: 1, b: 2, c: 3 }, 'a', 'c') // { b: 2 } pick({ a: 1, b: 2, c: 3 }, 'a', 'c') // { a: 1, c: 3 }实现上两者都先把 key 列表放入Set再过滤Object.entries,因此对大对象而言过滤是近似 O(n) 而非 O(n·m)。返回类型分别用Omit<T, K>与Pick<T, K>标注,能在 TypeScript 层面得到裁剪后的精确类型。packages/platform-core/src/utils.test.ts 中还覆盖了嵌套对象与不存在的 key(如pick一个不存在的'b'会直接不产生该键),可以确认这两个函数只做浅层键过滤,不做深层处理。
assert是带类型收窄的重载断言,提供两种用法:
// 用法一:普通断言,失败抛出 Error export function assert(expr: unknown, message?: string): asserts expr // 用法二:传入数字视为 HTTP 状态码,失败抛出 HttpError export function assert(expr: unknown, statusCode?: number, message?: string): asserts expr源码中的关键分支是:第二个参数为number时构造HttpError({ statusCode, message }),否则视为错误消息字符串。默认消息为'Internal assertion failed',且两种分支都会调用Error.captureStackTrace(error, assert)把堆栈截断到调用方,便于线上定位。这个设计让服务端代码可以写assert(result, 404, 'Not found')这类简洁的防御性检查。
校验与解析:parseZodSchema 与 parseJson
parseZodSchema是 Zod 校验的服务端统一封装:
export function parseZodSchema<TSchema extends ZodType<any, any, any>>( schema: TSchema, input: unknown, { error, statusCode = 500 }: { error?: string; statusCode?: number } = {} ): z.infer<TSchema>它的行为是:schema.parse(input)成功则返回推断类型z.infer<TSchema>的解析结果;失败则抛出ZodValidationError,默认statusCode = 500,并可通过prefix(参数名error)为错误消息加前缀。这使 API 层可以对外暴露“哪个字段、什么约束失败”的结构化错误,而不必各自处理 Zod 的ZodError。
parseJson直接 re-export 自第三方包parse-json(见 utils.ts 第 6 行export { default as parseJson } from 'parse-json'),用于容错解析 JSON 字符串(相比原生JSON.parse提供更友好的错误信息)。
哈希工具:sha256 与 hashObject
sha256基于 Web Crypto API(crypto.subtle.digest('SHA-256', ...))实现,支持字符串与ArrayBuffer/ArrayBufferView输入:字符串会先经TextEncoder编码,输出统一为小写十六进制(每个字节格式化为两位 hex)。值得注意的是其默认参数——不传输入时会用crypto.randomUUID()作为哈希源,utils.test.ts 验证了两个特性:无参调用两次得到两个不同的 64 位 hex 串,同参调用则幂等。
hashObject(packages/platform-core/src/hash-object.ts)解决“对象的稳定哈希”问题,这是部署内容指纹、配置变更检测这类场景的基础。其处理链为:
- 入参检查:非对象直接抛
TypeError('Expected an object'); - 去环:
decircular(object)处理循环引用(hash-object.test.ts 专门构造了object.a.b = object的循环结构并断言能得到确定性哈希); - Unicode 归一化:递归对字符串与对象 key 做 NFD 归一化,避免同形不同码的点字产生不同哈希;
- 深排序:
sortKeys(normalizedObject, { deep: true })让 key 顺序不影响结果; - 序列化后 SHA-256:
sha256(JSON.stringify(...))。
测试给出的事实基准:hashObject({ unicorn: 'rainbow' })恒等于0bdeed89f3fbb21d7c4fa488992470030e98387c4ad3f4e18cebb70d7dac59dd;且{ a: 0, b: { a: 0, b: 0 } }与{ b: { b: 0, a: 0 }, a: 0 }的哈希相同,直接印证了“key 顺序无关”的稳定性承诺。
环境变量与查询参数:getEnv 与 sanitizeSearchParams
getEnv(name)是一个跨环境安全的环境变量读取器:先判断typeof process !== 'undefined'再读process.env?.[name],任何异常都兜底返回undefined而非抛出。这使得同一份代码在 Node、Worker 与无process的运行时中都能安全调用。
sanitizeSearchParams把任意Record<string, string | number | boolean | 数组 | undefined>清洗为URLSearchParams,规则如下:
undefined的 key 或 value 直接丢弃;- 数组值默认展开为重复键(
a=1&a=2形式); - 传
{ csv: true }时改为逗号分隔(a=1,2形式),源码中用flatMap+ 手动拼接实现; - 所有值统一
String(v)强制转字符串。
从源码结构看,这类工具通常服务于把业务参数安全地拼进上游请求 URL 的场景(例如转发到 origin 的请求),避免数组与空值破坏查询串。
prune 系列:清理空值
utils.ts提供了一组“修剪”函数,按严格程度递增:
| 函数 | 行为 |
|---|---|
pruneUndefined | 仅移除值为undefined的键 |
pruneNullOrUndefined | 移除undefined与null |
pruneNullOrUndefinedDeep | 上述行为递归到嵌套对象与数组 |
pruneEmpty | 浅层移除“空值”:undefined、null、空字符串、空数组、空对象 |
pruneEmptyDeep | 深度递归移除空值,若结果整体为空则返回undefined |
utils.test.ts 中的边界用例值得注意:pruneEmpty({ a: 0, b: {}, c: [], d: '' })结果为{ a: 0 }——数字0被保留,说明“空”的判定不包含零值;而pruneEmptyDeep对{ a: null, b: {...全空}, c: ['','',''], d: '', e: undefined }返回undefined而非{},意味着深度修剪后空对象会整体坍缩。这些语义对“序列化前把无意义字段从请求体/响应体中去掉”的场景非常关键。
slugify
slugify是对@sindresorhus/slugify的薄封装,行为在 JSDoc 中逐条列出:转小写、驼峰拆词(fooBar -> foo-bar)、非拉丁字符转写、空格转连字符、去除首尾与重复连字符。utils.test.ts 展示了代表性用例:
expect(slugify('FooBarBaz')).toBe('foo-bar-baz') expect(slugify('я люблю единорогов')).toBe('ya-lyublyu-edinorogov') expect(slugify(' Déjà Vu! ')).toBe('deja-vu') expect(slugify('I ♥ Dogs')).toBe('i-love-dogs')结合仓库根目录下 packages/validators 中对项目 slug 的解析逻辑来看,可以推断平台在创建项目/部署时会依赖该函数做名称的规范化处理。
错误体系:BaseError 到 JsonRpcError
packages/platform-core/src/errors.ts 定义了一条完整的错误继承链,是平台统一错误响应的骨架:
BaseError:所有平台错误的根类,name自动取构造器名,并支持cause;HttpError:附加statusCode(默认 500)与可选headers,供 HTTP 层直接映射为响应;RateLimitError:继承自HttpError,固定statusCode: 429,构造时自动把RateLimitResult通过getRateLimitHeaders展开进响应头,并保留rateLimitResult字段供上层读取;JsonRpcError:附加jsonRpcErrorCode与jsonRpcId,用于 JSON-RPC(MCP 协议)通道的错误编码;ZodValidationError:把 Zod 的校验错误经zod-validation-error的fromError转成人类可读消息(支持prefix),再包成带状态码的HttpError,与前述parseZodSchema配套。
值得说明的是JsonRpcError的存在印证了本仓库的协议面:Agentic 网关同时暴露 HTTP 与 MCP(JSON-RPC)两种接口,错误类型需要在两者间保持同构。
限流响应头与 RateLimitResult 类型
packages/platform-core/src/types.ts 定义了限流结果的数据契约:
export type RateLimitResult = { id: string // 限流主体标识,通常是客户 ID 或 IP passed: boolean // 本次请求是否通过限流 intervalMs: number // 限流窗口(毫秒) limit: number // 窗口内最大请求数 current: number // 当前已用请求数 remaining: number // 剩余可用次数,超限时为 0 resetTimeMs: number // 窗口重置时间(Unix epoch 毫秒) }packages/platform-core/src/rate-limit-headers.ts 的getRateLimitHeaders把这些字段映射为标准限流响应头,注释中明确参考了 IETF 草案draft-ietf-httpapi-ratelimit-headers-06:
ratelimit-policy:{limit};w={intervalSeconds}格式;ratelimit-limit/ratelimit-remaining/ratelimit-reset:窗口、余量与重置秒数(均由毫秒向上取整为秒);x-ratelimit-id:限流主体 ID;- 仅当
passed === false时追加retry-after(距resetTimeMs的秒数,且不小于 0)。
源码注释还记录了一个工程细节:Cloudflare 与 origin 服务器可能各自设置x-前缀的限流头,因此这里刻意只写标准头、保留 origin 自带的头作为“额外元数据出口”。RateLimitError在抛出时自动带上这些头,意味着 429 响应无需调用方再手动组装。
另外,types.ts中的Logger接口定义了trace/debug/info/warn/error五级日志签名,types.test.ts 用expectTypeOf<Console>().toExtend<Logger>()断言console天然满足该接口——即平台内任何接受Logger的组件都可以直接注入 Node 的console。
在仓库中的实际用法与适用边界
该包在整个仓库中的角色可以从两点确认:其一,apps/api 的 auth、consumers、deployments、projects 等接口文件普遍import { ... } from '@agentic/platform-core',说明它是 API 层共享依赖;其二,readme 的 TIP 指出它不是面向终端开发者的首选包,公开能力应通过 packages/cli(命令行)、packages/platform(项目配置加载与校验)等封装包消费。
使用时需要注意的适用前提:
- Node >= 18:
sha256依赖crypto.subtle,低版本 Node 需自行 polyfill; - 纯 ESM:包为
"type": "module",CommonJS 项目需await import(...)或转 ESM; - 行为确定性:
hashObject、sha256的结果在仓库测试中被固定为具体 hex 值,若上游修改了归一化或排序逻辑,哈希基准会变化,引用其输出的下游逻辑需同步评估; - 许可:AGPL-3.0,二次分发与网络服务场景需遵守该协议条款。
小结
@agentic/platform-core是 Agentic 平台的公共工具层:readme 给出安装与引入方式,package.json 固定了版本与依赖边界,而 src/index.ts 之下的五个模块——对象工具(utils.ts)、稳定哈希(hash-object.ts)、限流头(rate-limit-headers.ts)、错误链(errors.ts)与类型契约(types.ts)——共同支撑了 API、网关等上层包的一致行为。对需要自建“API 转 MCP 网关”类系统的开发者而言,直接npm i @agentic/platform-core后复用其parseZodSchema+ZodValidationError、RateLimitError+getRateLimitHeaders、hashObject这三组组合,即可快速获得与 Agentic 同构的校验、限流与内容指纹能力。
【免费下载链接】agenticYour API ⇒ Paid MCP. Instantly.项目地址: https://gitcode.com/GitHub_Trending/ag/agentic
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考