完整指南:虚拟文件系统实现文件的增删查与沙箱协同)
Composio Tool Router 会话文件挂载Session Files Mount完整指南虚拟文件系统实现文件的增删查与沙箱协同【免费下载链接】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/composioTool Router 会话自带一个虚拟文件系统virtual filesystem mount使 Agent 工作流、文档处理及需要读写文件的工具可以在会话内安全地存储与取回文件。本文基于 Composio TypeScript SDKcomposio/core源码与官方文档系统讲解session.experimental.files的 list / upload / download / delete 四大能力、RemoteFile对象模型、上传输入归一化与 SSRF 防护等底层原理并给出可直接运行的完整示例。背景Tool Router 会话与文件挂载Tool Router 是 Composio 提供的隔离式 MCPModel Context Protocol会话机制可为每个用户创建独立会话并以作用域限定方式暴露 toolkit 与工具参见 Tool Router 会话文档。在每个 Tool Router 会话之上SDK 额外挂载了一个虚拟文件系统工具在执行时可以在沙箱内访问这些文件例如/mnt/files/而宿主应用可以通过session.experimental.files从外部向该挂载点上传、浏览、下载与删除文件。文件挂载的核心能力包括List带游标cursor分页浏览挂载点上的文件与目录Upload支持本地路径、HTTP(S) URL、原生File对象、原始缓冲区ArrayBuffer/Uint8Array四种输入Download获取预签名presigned下载 URL 与RemoteFile实例Delete删除挂载点上的文件或目录。挂载 ID 默认为files常量DEFAULT_TOOL_ROUTER_SESSION_FILES_MOUNT_ID定义于 ts/packages/core/src/utils/constants.ts使用自定义挂载时可显式覆盖。底层实现类为 ToolRouterSessionFilesMount通过composio.create(...)/composio.use(...)创建的任意 Tool Router 会话均可在session.experimental.files上访问该 API。注意此功能与工具执行过程中的文件自动上传/下载Auto Upload and Download是两个不同特性后者面向单次工具调用的文件处理见 Auto Upload and Download。快速开始安装 SDK 后npm install composio/core0.4.0或pnpm add composio/core0.4.0即可在一个会话上完成文件的上传、列出、下载全流程import { Composio } from composio/core; const composio new Composio({ apiKey: process.env.COMPOSIO_API_KEY }); const session await composio.create(default); // 上传一个文件 const file await session.experimental.files.upload(/path/to/report.pdf); console.log(Uploaded:, file.mountRelativePath); // 列出文件 const { items, nextCursor } await session.experimental.files.list({ path: / }); // 下载文件 const remoteFile await session.experimental.files.download(report.pdf); const buffer await remoteFile.buffer(); await remoteFile.save(/tmp/report.pdf);upload返回RemoteFilelist返回带nextCursor的分页结果download同样返回RemoteFile可直接用其方法取回内容或落盘。列出文件List使用list浏览挂载点某个路径下的文件与目录支持基于游标的分页。方法签名session.experimental.files.list(options?: ToolRouterSessionFilesMountListOptions): PromiseFileListResponse选项说明选项类型默认值说明pathstring-要列出的目录路径根目录使用/mountIdstringfiles文件挂载 IDcursorstring-上一次响应nextCursor返回的分页游标limitnumber-每页最大文件数1–500limit的取值范围1–500由 Zod schema 在运行时强制校验见 ToolRouterSessionFilesMount.types.ts超出范围的取值会抛出ValidationError。响应结构interface FileListResponse { items: Array{ lastModified: string; // ISO 8601 时间戳 mountRelativePath: string; // 如 report.pdf sandboxMountPrefix: string; // 如 /mnt/files size: number; // 文件大小字节 }; nextCursor?: string; // 存在更多页时返回 }需要说明的是API 原始响应为 snake_caselast_modified、mount_relative_path、sandbox_mount_prefix、next_cursorSDK 通过FileListResponseSchema在返回前完成 camelCase 转换见 ToolRouterSessionFilesMount.types.ts因此应用层拿到的一律是 camelCase 字段。内部实现细节从 ToolRouterSessionFileMount.ts 的实现可以看出两点行为根目录归一化当path为undefined、空串或/时mount_relative_prefix会被置为undefined直接省略非根路径则会去掉开头的/API 不接受前导斜杠。参数校验选项先经ToolRouterSessionFilesMountListOptionsSchema.safeParse校验失败时抛出带 cause 的ValidationError响应同样经FileListResponseSchema.safeParse校验。示例// 列出根目录 const { items } await session.experimental.files.list({ path: / }); // 列出子目录 const { items } await session.experimental.files.list({ path: /documents }); // 分页遍历 let result await session.experimental.files.list({ path: /, limit: 10 }); while (result.nextCursor) { result await session.experimental.files.list({ path: /, cursor: result.nextCursor, limit: 10, }); }游标分页的行为在 ToolRouterSessionFilesMount.test.ts 中有对应测试path: /会以mount_relative_prefix: undefined传给后端同时cursor与limit原样透传。上传文件Uploadupload向会话挂载点写入文件接受四种输入类型文件路径本地或 URL、原生File对象、原始缓冲区。方法签名session.experimental.files.upload( input: string | File | ArrayBuffer | Uint8Array, options?: ToolRouterSessionFilesMountUploadOptions ): PromiseRemoteFile输入类型输入类型说明示例string本地路径或 HTTP(S) URL/path/to/file.pdf、https://example.com/file.pdfFile原生浏览器 / NodeFileinputElement.files[0]ArrayBuffer原始二进制缓冲区await file.arrayBuffer()Uint8Array类型化数组缓冲区new TextEncoder().encode(hello)上传选项选项类型默认值说明remotePathstring-挂载点上的远程路径/文件名。传入缓冲区时必填提供文件名mimetype 默认application/octet-streammountIdstringfiles文件挂载 IDmimetypestring-MIME 类型。传入缓冲区时除非已提供remotePath否则必填传入File时忽略使用file.type输入归一化逻辑How It Worksupload的内部流程由normalizeUploadInput实现见 ToolRouterSessionFileMount.ts路径string以http://或https://开头时视为 URL先经ssrfSafeFetch防护后抓取内容否则视为本地文件路径用platform.readFileSync读取。文件名从路径或 URL 的最后一段推导若 URL 末段没有扩展名则根据响应Content-Type通过getExtensionFromMimeType推导扩展名并生成upload-{id}.{ext}形式的文件名。File直接使用文件名取file.nameMIME 类型取file.type除非显式传remotePath。缓冲区ArrayBuffer/Uint8Array包装为File对象。mimetype与remotePath至少提供其一否则抛出明确错误只给remotePath时 mimetype 默认application/octet-stream只给mimetype时按扩展名生成文件名upload-{id}.{ext}。其中 MIME 类型到扩展名的映射由 utils/mime.ts 提供内置覆盖常见文档、图片、音视频类型如application/pdf → pdf、image/png → png、application/vnd.openxmlformats-officedocument.spreadsheetml.sheet → xlsx等对type/subtypexxx形式的复合类型会优先识别svg/atom/rss前缀或json/xml/yaml/zip/gzip结构化后缀兜底返回bin。上传三步流程与安全机制upload的底层实现并不是一次性 POST 文件内容而是三段式流程见 ToolRouterSessionFileMount.ts申请上传地址调用toolRouter.session.files.createUploadURL(mountId, { session_id, mount_relative_path, mimetype })获取预签名upload_urlPUT 文件内容以PUT方法携带文件字节与Content-Type请求头写入该预签名地址。关键安全点upload_url来自 API 响应属于不可信输入因此同样经过ssrfSafeFetchWhereSupported校验后才发送数据防止响应被篡改后诱导客户端向内网/云元数据地址发起 PUT获取下载信息调用createDownloadURL拿到下载元数据解析为RemoteFile返回。此外URL 输入与远程响应读取还受到以下约束均有对应测试SSRF 防护用户提供的 URL 在抓取前会被校验阻断解析到内网地址的请求即使是看似公共的 URL若重定向指向云元数据地址也会被拦截见 ToolRouterSessionFilesMount.test.ts。响应体大小上限从用户 URL 抓取的内容受MAX_URL_UPLOAD_SIZE_BYTES 100 MiB限制见 utils/readResponseBody.ts超过 100 MiB 会被拒绝对应测试见 ToolRouterSessionFilesMount.test.ts。请求失败时的资源释放URL 抓取失败或响应不 OK 时响应体会被显式cancel()释放避免依赖垃圾回收。示例// 从本地路径上传 const file await session.experimental.files.upload(/path/to/report.pdf); // 从 URL 上传 const file await session.experimental.files.upload(https://example.com/document.pdf); // 从原生 File如文件输入框上传 const file await session.experimental.files.upload(fileInput.files[0]); // 从缓冲区上传显式指定路径与 mimetype const buffer new TextEncoder().encode({key: value}); const file await session.experimental.files.upload(buffer, { remotePath: data.json, mimetype: application/json, }); // 从缓冲区上传——mimetype 或 remotePath 至少提供其一 const pngBytes new Uint8Array([0x89, 0x50, 0x4e, 0x47, ...]); const file await session.experimental.files.upload(pngBytes, { remotePath: screenshot.png, mimetype: image/png, });下载文件Downloaddownload获取挂载点上某个文件的RemoteFile实例通过该实例可拿到预签名下载 URL并以多种方式取回内容。方法签名session.experimental.files.download( filePath: string, options?: ToolRouterSessionFilesMountDownloadOptions ): PromiseRemoteFile参数filePath挂载点上的文件路径如report.pdf、output/data.csvoptions.mountId挂载 ID默认files。RemoteFile 对象模型返回的RemoteFile具有以下只读属性属性类型说明expiresAtstring下载 URL 过期时间ISO 8601mountRelativePathstring挂载点内路径sandboxMountPrefixstring挂载绝对路径如/mnt/filesdownloadUrlstring预签名下载 URLfilenamestring路径的 basename其中filename是一个 getter基于mountRelativePath用platform.basename计算得出如output/report.pdf→report.pdf见 RemoteFile.ts。RemoteFile提供四个内容取回方法buffer()以Uint8Array返回内容text()以 UTF-8 字符串返回内容blob()以Blob返回内容save(path?)下载并保存到磁盘仅 Node.js不传路径时默认保存到~/.composio/files/。内部实现细节从源码看RemoteFile.tsbuffer()/text()/blob()共享downloadBytes私有方法统一经ssrfSafeFetchWhereSupported请求downloadUrl失败时抛出携带statusCode、statusText、downloadUrl、mountRelativePath等上下文的RemoteFileDownloadError。非 OK 响应同样会先释放响应体再抛错。save()首先检查platform.supportsFileSystem在不支持文件系统的运行时如 Cloudflare Workers / Edge直接抛错并提示改用buffer()/text()/blob()。默认保存路径为{homeDir}/.composio/files/{filename}拼接COMPOSIO_DIR与TEMP_FILES_DIRECTORY_NAME常量目录不存在时会自动创建返回最终写入的绝对路径。示例const remoteFile await session.experimental.files.download(/output/report.pdf); // 取回内容 const buffer await remoteFile.buffer(); const text await remoteFile.text(); // 保存到磁盘Node.js await remoteFile.save(/tmp/report.pdf); await remoteFile.save(); // 使用 ~/.composio/files/{filename}删除文件Deletedelete从挂载点删除文件或目录。方法签名session.experimental.files.delete( remotePath: string, options?: ToolRouterSessionFilesMountDeleteOptions ): PromiseFileDeleteResponse删除操作是破坏性的、通常不可逆源码注释明确提示“Deleted files cannot be recovered”请确保路径存在且确为待删除对象后再调用。底层调用toolRouter.session.files.delete(mountId, { session_id, mount_relative_path })响应经FileDeleteResponseSchema校验并转换为 camelCase 的{ mountRelativePath, sandboxMountPrefix }。示例await session.experimental.files.delete(/temp/cache.json); await session.experimental.files.delete(/old-backup, { mountId: custom-mount });类型参考Type ReferenceToolRouterSessionFilesMountListOptionsinterface ToolRouterSessionFilesMountListOptions { path?: string; mountId?: string; // 默认: files cursor?: string; limit?: number; // 1-500 }ToolRouterSessionFilesMountUploadOptionsinterface ToolRouterSessionFilesMountUploadOptions { remotePath?: string; mountId?: string; // 默认: files mimetype?: string; }FileListResponseinterface FileListResponse { items: Array{ lastModified: string; mountRelativePath: string; sandboxMountPrefix: string; size: number; }; nextCursor?: string; }RemoteFiledownload / upload 返回值interface RemoteFile { readonly expiresAt: string; readonly mountRelativePath: string; readonly sandboxMountPrefix: string; readonly downloadUrl: string; readonly filename: string; buffer(): PromiseUint8Array; text(): Promisestring; blob(): PromiseBlob; save(path?: string): Promisestring; // 仅 Node.js }导出与平台支持composio/core从入口 index.ts 导出以下与文件挂载相关的内容FileListResponse– 列表响应类型ToolRouterSessionFilesMountListOptions– 列表选项类型RemoteFile– 提供buffer/text/blob/save的文件类getExtensionFromMimeType– 将 MIME 类型映射为文件扩展名。平台支持情况Node.js完整支持路径读取、save()落盘Bun完整支持浏览器Browser路径读取与save()受限请使用File或缓冲区Cloudflare Workers / Edge无文件系统仅支持File或缓冲区输入内容只能通过buffer()/text()/blob()在内存中处理。典型应用场景与最佳实践结合源码与 Tool Router 文档 中的会话能力文件挂载适合以下几类场景Agent 文档处理上传 PDF、DOCX 等文档到挂载点让沙箱内工具可访问/mnt/files/执行解析、抽取、格式转换再把产物下载回宿主。工具间数据交接前一个工具产出的文件写入挂载点后一个工具直接按mountRelativePath读取避免大对象在对话上下文里来回传输。结果持久化与回传使用RemoteFile.save()把运行产物落盘到~/.composio/files/供后续审计或离线分析。实践建议缓冲区上传务必携带remotePath或mimetype否则直接抛错——这是最容易踩的坑分页遍历用while (result.nextCursor)循环limit保持在 1–500 区间下载 URL 会过期RemoteFile.expiresAt表明预签名 URL 有时效需要持久化时应尽快调用buffer()/save()取回内容而不是长期保存 URL沙箱路径与挂载路径分离sandboxMountPrefix如/mnt/files是沙箱内的绝对路径mountRelativePath如output/data.csv是 API 层使用的相对路径二者通过前缀拼接即可得到沙箱内完整路径Edge / Workers 环境不要依赖本地文件系统能力统一使用File或缓冲区输入并用buffer()/text()/blob()消费内容。本文所涉能力均有源码与测试支撑核心实现见 ToolRouterSessionFileMount.ts 与 RemoteFile.ts类型与校验见 ToolRouterSessionFilesMount.types.ts行为验证见 ToolRouterSessionFilesMount.test.ts读者可按图索骥深入研读。【免费下载链接】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),仅供参考