news 2026/9/10 8:48:35

Composio 文档构建期 TypeScript 代码块类型检查(Twoslash)机制全解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Composio 文档构建期 TypeScript 代码块类型检查(Twoslash)机制全解

Composio 文档构建期 TypeScript 代码块类型检查(Twoslash)机制全解

【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio

Composio 官方文档(位于docs/目录的 Next.js + Fumadocs 站点)将Twoslash 构建时类型检查作为保障文档与 SDK 同步的核心手段:所有 TypeScript 代码块在bun run build时都会经过真实的 TypeScript 编译器校验,任何类型错误都会直接导致构建失败。本文以 docs/agent-guidance/context/twoslash.md 为骨架,结合 docs/source.config.ts 的实际配置与 .github/workflows/docs-typescript-check.yml 的 CI 流水线,完整讲解该机制的配置、常用写法、注解语法与排错指南,帮助你在撰写 Composio 文档或搭建同类文档工程时,让每一段 TypeScript 示例都保持"可编译、可运行、与 SDK 零漂移"。

核心机制:所有 TS 代码块在构建期被真实编译

Twoslash 原本是 TypeScript 官方用于交互式展示类型推断的工具("在代码上悬停即可看到类型")。Composio 文档工程对它做了一次"去交互化"改造——只保留类型检查能力,关闭悬停 UI,并让它默认作用于全部 TypeScript 代码块:

  • 默认开启,无需任何注解tstypescripttsx语言标记的代码块全部被校验;Python 代码块参与类型检查(对应原文档中的 Note 说明)。
  • 构建期失败即终止:类型错误会直接让next build失败,从源头阻止"示例代码已经过时"的文档合入主分支。
  • 开发环境关闭bun dev时 Twoslash 被禁用,以避免堆内存问题;它只运行在bun run build与 CI 中。这一点在 docs/agent-guidance/context/fumadocs.md 的 "Common Gotchas" 中亦有印证:"Twoslash is disabled inbun devdue to heap memory issues"。

这一设计回答了文档维护中最棘手的问题:如何让示例代码跟上 SDK 演进。当@composio/core升级改变了 API 签名时,文档里旧的调用写法会在下次构建时立刻暴露为 TS 错误,而不是等读者复制粘贴后才发现跑不通。

配置实现:source.config.ts 中的 transformerTwoslash

Twoslash 的实际接线发生在文档工程的构建配置 docs/source.config.ts 中,它在全局mdxOptions.rehypeCodeOptions.transformers里注册了transformerTwoslash,且只在生产构建(NODE_ENV === 'production')下生效:

// docs/source.config.ts(节选) transformers: process.env.NODE_ENV === 'production' ? [ transformerTwoslash({ explicitTrigger: false, twoslashOptions: { compilerOptions: { jsx: 4, // JsxEmit.ReactJSX jsxImportSource: 'react', ignoreDeprecations: '6.0', types: ['node'], }, }, typesCache: createFileSystemTypesCache({ dir: '.next/cache/twoslash', }), renderer: { // Empty renderer - type checks but renders nothing nodeStaticInfo: () => ({}), nodeError: () => ({}), nodeQuery: () => ({}), nodeCompletion: () => ({}), }, }), ] : [],

几个值得展开的配置点:

  • explicitTrigger: false:关闭显式触发开关。默认情况下 Shiki 的 twoslash transformer 只处理包含@twoslash注释的代码块;设为false后,所有TypeScript 代码块都会被纳入检查,这正是原文档 "Default on: All TypeScript blocks are validated. No annotation needed" 的底层来源。
  • 空 renderernodeStaticInfonodeErrornodeQuerynodeCompletion四个渲染回调全部返回空对象,即只做编译校验、不向页面注入悬停 UI 与错误气泡,保持文档代码块外观与普通高亮一致。
  • 文件系统类型缓存:通过createFileSystemTypesCache将类型解析结果缓存到.next/cache/twoslash,避免每次构建对相同导入重复解析,缩短构建时间。
  • compilerOptions 细节jsx: 4对应JsxEmit.ReactJSX(配合jsxImportSource: 'react',使tsx代码块能正确编译 JSX);ignoreDeprecations: '6.0'用于屏蔽 TS 6 对虚拟环境中默认baseUrl的弃用警告(TS5101);types: ['node']则显式引入 Node 类型,弥补 TS 6 不再自动包含@types/node的行为变化(否则cryptoprocessBuffer等全局会报 TS2591)。这些细节充分说明:文档代码块是在 Twoslash 自己的虚拟 TS 环境中编译的,需要单独配置才能获得与根tsconfig.json一致的类型解析能力。

CI 强制:任何 docs/ 改动都必须通过类型检查

Twoslash 的约束力来自 CI。工作流 .github/workflows/docs-typescript-check.yml(名称为 "Docs - Lint and TypeScript Validation")在所有触及docs/**的 PR上运行,步骤依次为:

  1. bun install --frozen-lockfile安装依赖;
  2. bun run lint(oxlint);
  3. bun run types:check
  4. bun run build—— 注释明确写着 "Build (validates Twoslash TypeScript code blocks)"。

也就是说,一个 PR 只要修改了文档目录,就必须保证其中每个 TS 代码块能通过真实编译,否则无法合并。工作流还缓存了~/.bun/install/cache以加速依赖安装;docs/内的 pipeline 总览见 docs/agent-guidance/context/pipelines.md 中的 "Lint + TypeScript" 一行。

排除项:content/reference 目录不参与检查

并非所有 TS 代码块都需要类型检查。自动生成的 SDK/API 参考文档位于docs/content/reference/,它们由 OpenAPI 与 SDK 构建产物自动生成,内容不依赖手工维护,因此通过集合级mdxOptions被整体排除在 Twoslash 之外:

// docs/source.config.ts(节选) export const reference = defineDocs({ dir: 'content/reference', docs: { schema: docsSchema, postprocess: { includeProcessedMarkdown: true }, mdxOptions: applyMdxPreset({ remarkPlugins: [remarkMdxMermaid], rehypeCodeOptions: { themes: { light: 'github-light', dark: 'github-dark' }, // No twoslash transformer - SDK reference docs skip type checking }, }), }, ... });

注意两点工程细节:其一,这里使用applyMdxPreset重新声明rehypeCodeOptions,只配置了themes而未挂载 twoslash transformer,从而覆盖全局配置;其二,代码注释提示applyMdxPreset是"替换而非合并"("replaces, not merges"),所以必须同时带上remarkPlugins: [remarkMdxMermaid],否则合并进参考文档的 Mermaid 图表会失去渲染插件。同理,content/docscontent/examplescontent/toolkitscontent/kb等集合都走全局配置,TS 代码块照常被检查。

常用模式一:用---cut---隐藏 setup 代码

文档示例往往需要导入与初始化代码,但它们不该占据读者视线。// ---cut---注释把代码块切成两段:上方的代码参与编译、不参与渲染下方的代码同时参与编译与渲染。原文档给出的标准模板:

```typescript import { Composio } from '@composio/core'; const composio = new Composio({ apiKey: 'key' }); const userId = 'user_123'; // ---cut--- // Only code below this line is shown in docs const tools = await composio.tools.get(userId, { toolkits: ['GITHUB'] }); ```

这种写法在真实文档中大量落地。例如 docs/content/docs/auth-configuration/connected-accounts.mdx 中,每个 TypeScript Tab 都在new Composio({ apiKey: 'your_api_key' })之后插入// ---cut---,再展示composio.connectedAccounts.list(...)等真正的教学代码。读者看到的是干净的业务逻辑,而编译器看到的是一段完整可编译的程序。

常用模式二:优先使用 SDK 导出的回调类型

在编写modifySchemabeforeExecuteafterExecute这类修饰器回调时,与其手写内联类型标注(容易与 SDK 实际签名漂移),不如直接导入@composio/core导出的类型:

```typescript import { Composio, TransformToolSchemaModifier } from '@composio/core'; const modifySchema: TransformToolSchemaModifier = ({ toolSlug, toolkitSlug, schema }) => { // TypeScript infers all parameter types! return schema; }; ```

@composio/core提供的修饰器回调类型包括:

类型适用回调
beforeExecuteModifierbeforeExecute回调
afterExecuteModifierafterExecute回调
TransformToolSchemaModifiermodifySchema回调

这样参数对象(toolSlugtoolkitSlugschema)的类型全部由 SDK 推断,回调签名一旦变化,构建期即可发现。从 docs/package.json 可见@composio/core(当前版本^0.18.1)连同@composio/openai@composio/langchain等各框架适配包都被安装在devDependencies中——这正是 Twoslash 能在虚拟环境里解析这些导入的前提。

常用模式三:跳过检查与声明外部变量

跳过类型检查:当示例依赖未安装的第三方包(如尚未发布的模块)时,可在代码块开头加// @noErrors,该块将不做任何类型校验:

```typescript // @noErrors import { SomeExternalThing } from 'not-installed-package'; ```

声明外部变量:当代码使用了片段内未定义的变量时,应在---cut---上方用declare声明,让它既参与编译又不出现在输出中:

```typescript import { Composio } from '@composio/core'; declare const composio: Composio; declare const userId: string; // ---cut--- const tools = await composio.tools.get(userId, { toolkits: ['GITHUB'] }); ```

这一模式解决的是 TS 错误 2304("Cannot find name"):在隐藏段声明变量,相当于为片段补齐了运行环境,编译通过的同时保持输出整洁。类似地,需要展示特定错误时可用// @errors: 2322声明期望的错误码(构建不会因此失败);需要展示某位置的类型时用// ^?注释。

注解速查表

注解作用
// ---cut---隐藏上方代码(参与编译但不输出)
// @noErrors跳过该代码块的全部类型检查
// @errors: 2322声明该块期望出现指定错误码,构建不失败
// ^?在该位置展示悬停类型(本仓库 renderer 为空,主要用于校验场景)

配置要点与依赖清单

要让 Twoslash 正常工作,工程层面有三件事必须做对:

  1. 注册 transformer:在 docs/source.config.ts 的全局rehypeCodeOptions.transformers中启用transformerTwoslash(生产环境生效),并为参考文档集合单独覆盖rehypeCodeOptions以排除检查;
  2. 安装 SDK 包为 devDependencies:Twoslash 在虚拟 TS 环境里解析代码块中的导入,因此文档中引用的@composio/*包必须出现在 docs/package.json 的devDependencies(同时也用到@shikijs/twoslash@shikijs/vitepress-twoslashcreateFileSystemTypesCache);
  3. 本地构建验证:开发阶段 Twoslash 被禁用,推送前必须本地执行bun run build验证全部代码块,再由 CI 中的docs-typescript-check.yml兜底。

Troubleshooting 速查

问题解决方案
导入失败确认对应包已加入devDependencies
依赖外部包对未在 package.json 中的示例使用// @noErrors
需要 setup 代码// ---cut---加入可编译但不展示的导入/声明
错误码 2304(Cannot find name)在隐藏段用declare声明变量
错误码 2322(类型不匹配)修正类型,或改用 SDK 导出的类型(如TransformToolSchemaModifier
回调参数类型优先导入 SDK 类型,避免手写{ foo: string }内联标注

最后再次强调原文档的收尾建议:推送前始终在本地运行bun run build——这是你在进入 CI 前验证所有代码块的唯一可靠手段,也是让 Composio 文档保持"示例即真相"的最后一公里。

【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 8:46:00

AutoHedge:期权Delta和Gamma动态对冲引擎的设计与实战

1. 项目背景:为什么我会动手做 AutoHedge 做衍生品交易的人,尤其是天天和期权打交道的老手,应该都有过这种体验:持仓里十几个不同的期权合约,下方还拖着一堆现货或期货头寸,明明整体风险敞口算过没问题&…

作者头像 李华