Code Mode 来宾 API
来宾运行时 API¶
以下 TypeScript 声明文档化了来宾 API。可执行单元格使用不带类型注释的纯 JavaScript。
declare const catalog: ToolCatalog;
declare const MCP: Record<string, unknown>;
declare const namespaces: Record<string, unknown>;
declare function setTimeout(
callback: (...args: unknown[]) => void,
delay?: number,
...args: unknown[]
): number;
declare function clearTimeout(id: number): void;
declare function text(value: unknown): void;
declare function json(value: unknown): void;
declare function yield_control(reason?: string): Promise<void>;
TextEncoder 和 TextDecoder 可用于本地文本和字节转换。在任一执行器下,编码器和解码器实例都能存活于 wait。这些 API 提供本地字节转换,不提供文件系统、模块或网络访问。返回值仍使用仅限 JSON 的桥接;应输出解码后的文本或字节值数组,而不是二进制附件。
console.log、console.info、console.warn、console.error 和 console.debug 通过与 text 和 json 相同的有序输出通道输出诊断文本,而不是通过宿主日志。它们返回 undefined;console.error 不会抛出异常。非日志方法会在其消息前加上级别前缀,例如 [warn]。参数之间以空格分隔;类似 %s 的 printf 风格标记保持字面量。未提供其他 Console API 方法。
控制台检查是有意受限的,而不是 Node/浏览器控制台的模拟。字符串不加引号;对象和数组使用紧凑的 JSON 风格检查可枚举自有属性,并包含 Error 的自有 message。它不会调用 getter 或自定义 toJSON 方法。循环、访问器、未 await 的 Promise 以及检查失败会获得诊断占位符。每次调用最多访问 100 个值、每个对象 50 个属性,以及四个对象层级。字符串值和键最多保留 512 个 UTF-16 码元;消息最多保留 4096 个,外加截断后缀,且不会拆分代理对。
在所有恢复过程中,控制台条目还有一个额外的保守限制:16,384 个序列化 JSON UTF-16 码元(少于 49,152 个 UTF-8 字节)。一旦达到上限,单个 [console output truncated] 条目会替换下一条消息,后续控制台调用将被忽略。现有的累计 maxOutputBytes 和模型结果上限仍然适用于控制台输出,并与 text、json 以及最终值或错误一起生效。当诊断检查不足时,请使用更窄输入的显式 text/json。
来宾定时器通过宿主桥接,因此在任一执行器下都能存活于 wait,并仍受 Code Mode 执行和继续限制约束。clearTimeout 还会取消在更早挂起之前创建的定时器;这适用于交互式 Code Mode 和无头自动化脚本。
每个有效的非 MCP 工具也会作为异步全局函数安装。模型可见的 exec 描述包含最终可调用名称的有界、确定性子集、紧凑输入提示以及受信任的声明输出提示。描述保持延迟,以防止对抗性目录文本引导模型。当该索引遗漏某个工具时,调用 catalog.search(...);其结果是可调用函数。
每个快速索引行中的箭头描述可调用函数的值。-> Array<{ id: string }> 是声明的输出提示;-> ? 表示输出未知。对于未知输出,请原样返回值,或返回 await results.save(value) 以获取有界预览。在后续 exec 中过滤或映射之前,先观察原始值或预览;不要在同一程序中将猜测的字段输入到依赖逻辑中。当声明输出的读取馈送到最终的 -> ? 调用时,也适用此规则:返回或保存该最终原始值,不要将其包装在猜测的答案形状中。
results.load(id) 返回同一 agent 运行中后续单元格使用的分离 JSON 副本,results.delete(id) 释放容量。通过 API.read 读取 results.d.ts 以获取类型、限制和生命周期,或参见 跨单元格重用数据。过大的最终对象和数组可能返回自动 value.reference,而不是不可恢复的显示前缀;使用其 id 与 results.load。更大的预览会显示明确采样的路径、计数和观察到的形状。这些样本不是模式;在处理完整数据之前,请加载原始值。
type ToolCatalogMetadata = {
callableName: string;
toolName: string;
label?: string;
description: string;
source: "openclaw" | "client" | "mcp";
apiPath?: string;
input?: string;
output?: string;
};
type ToolCatalogHandle = ((input?: unknown) => Promise<unknown>) &
ToolCatalogMetadata & {
describe(): Promise<ToolCatalogDescription | McpCatalogDescription>;
toJSON(): ToolCatalogMetadata;
};
返回 await catalog.search(...) 或 catalog.all() 会将每个可调用句柄序列化为此有界元数据。序列化不会调用 describe() 或启动另一个桥接请求;在同一程序内部,句柄仍保持可调用。
input 是常见情况的有界 TypeScript 风格签名。当仍需要精确完整模式时,使用句柄的 describe()。客户端条目使用 input: "unknown",使其不受信任的模式保持延迟,直到 describe()。output 仅当存在从受信任的 OpenClaw 核心或插件 outputSchema 派生的完整紧凑提示时才存在。MCP 和客户端输出模式声明不会被提升到此受信任目录提示中。
插件工具使用 source: "openclaw";没有单独的 "plugin" 源值。搜索包括可见的 MCP 工具,使用与原生工具相同的排名和总结果限制。MCP 句柄具有 source: "mcp"、完全限定的 callableName(例如 MCP.accounting.listInvoices)、原始 MCP toolName,以及 apiPath(例如 mcp/accounting.d.ts)。其远程描述限制为 512 个 UTF-16 码元,且不会拆分代理对;输入和输出提示仍缺失。返回或输出 MCP 发现元数据会使用常规的不受信任内容包装器,即使没有调用任何 MCP 工具。
MCP 句柄通过一个对象参数调用现有的命名空间路径,包括其输入默认值、策略检查、审批以及原生 MCP 结果投影。它们的 describe() 返回对应工具的 $api(method, { schema: true }) 头部和模式。在选择 $api 声明时,规范化方法名优先于冲突的原始工具名。使用 API.read(handle.apiPath) 获取整个服务器的 TypeScript 声明。搜索也接受完全限定的 callableName。catalog.all() 仍然只列出原生和客户端句柄;搜索不会将远程工具添加到该列表或受信任快速索引中。
完整模式仅在需要时加载:
type ToolCatalogDescription = Omit<ToolCatalogMetadata, "toolName"> & {
name: string;
parameters: unknown;
outputSchema?: unknown;
};
MCP 描述形状:
type McpCatalogDescription = {
kind: "mcp_api";
scope: "tool";
server: { identifier: string; serverName: string };
header: string;
tools: unknown[];
schemas: Record<string, unknown>;
note: string;
};
目录辅助函数:
type ToolCatalog = {
search(query: string, options?: { limit?: number }): Promise<ToolCatalogHandle[]>;
all(): readonly ToolCatalogHandle[];
};
catalog.search(...) 返回可调用句柄的冻结数组;如果没有工具匹配,则返回空数组。如果匹配的可调用名称超出可用的程序数据收件箱容量,搜索会拒绝并给出缩小请求范围的指导。它绝不会静默地替换为空或部分匹配列表。错误之后,更窄的搜索仍然可用。
精确的可调用拼写优先于不区分大小写的匹配。当已启用名称仅在大小写上不同时,使用句柄的 callableName 来查找同一工具。
配对的 Gateway 节点可通过 nodes 全局变量访问:
const available = await nodes.list();
const node = await nodes.get(available[0].id);
const status = await node.invoke("device.status");
nodes.list() 返回配对节点的 id、名称、平台、连接状态以及已通告的命令。API 声明描述了这些字段和节点句柄方法。由于每个节点命令都定义自己的负载,命令参数和结果仍保持为 unknown;在组合结果之前请检查结果。nodes.get(idOrName) 先解析精确 id,再解析显示名称,并返回包含 id、name 和 invoke(command, params?) 的句柄。调用使用正常的 nodes 工具路径,因此配对、命令策略、作用域、审批、超时、钩子和遥测均保持不变。仅当节点通告 fs.listDir 时,句柄才包含 listDir(path)。它不包含 exec:通用节点界面将 system.run 保留给带有节点主机的常规 shell exec 工具。
直接调用快速索引全局变量,或在需要查找时使用可调用目录句柄:
const content = await read({ path: "README.md" });
const [tool] = await catalog.search("...");
const result = await tool({ query: "OpenClaw" });
const [search] = await catalog.search("search the web", { limit: 1 });
const schema = await search.describe();
const hits = await search({ query: "OpenClaw code mode" });
调用原生全局变量或原生目录句柄会直接返回常规工具的 JSON details 值。当工具将其结果标记为 isError: true,且其 details 中没有非空的 message 或 error 字符串时,该值会将工具的文本内容作为 message 包含在内,以便来宾代码和模型能够看到调用失败的原因。MCP 句柄保留原生 MCP 结果(content、可选的 structuredContent 以及可选的 isError)。精确目录 id 和原始 { tool, result } 信封对来宾不可见。
ls、find 和 grep 工具会将有界的列表或搜索文本包含在 content 中,包括空结果消息和截断通知。目录页保留 nextAfter;搜索结果保留其现有的 limit 和截断元数据。
读取分页文件数据¶
对于文本文件页,read(...) 会在 content 中返回文件文本;文件名解析和分页通知保留在人类可读的工具显示中,而不是结构化文件数据中。现有的文件脱敏仍然适用。解析前请检查 kind:"truncated" 表示在 continuation 处还有更多数据可用。使用相同的路径以及返回的 offset、可选的 cursor 和可选的 limit 读取下一页。用 "\n" 连接行续传;直接追加游标续传。不要从文件数据中删除显示通知模式:这些字符串可能是实际文件内容。每次调用仍会遵守其显式的 limit;如果仍有更多文件数据,结果将是 "truncated",其 continuation 描述下一页。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw