文档内容加载与读写

了解 Agent 的最小内容操作流程,并装配 Collaboration Runtime、Inspection、API Reference 与 Content Execution。

Agent 的最小内容操作流程

业务 CLI 会在每次内容命令中加载目标 Unit 并同步最新内容。从 Agent 的视角,一次典型的内容操作流程如下:

100%

图中的 api find / api show、read 模式和最终审查都是按需步骤。Agent 根据下面的边界选择能力:

Agent 的目标优先能力
了解文档结构和主体内容分布inspect overview
读取 Range、Paragraph、Slide 等标准内容inspect selector
读取 Inspection 未覆盖的条件格式、图表配置等细节execute --mode read
查找或确认不熟悉的 Facade APIapi find / api show
修改并提交文档execute --mode write
审查结果inspect / execute --mode read

示例:更新一个 Sheet Range

例如,任务是“把 book-1Data!A2:B2 更新为 [["华东", 128000]]”。假设业务 CLI 已按本章后续内容 完成组装,Agent 可以执行以下流程。

  1. 先用 Inspection 了解 Workbook 和目标 Range:
Bash
UNIT_ID="book-1"my-cli inspect workbook --unit "$UNIT_ID" --jsonmy-cli inspect range A1:B2 --worksheet name:Data --unit "$UNIT_ID" --json
  1. 为演示 API Reference,这里假设 Agent 不熟悉 setValues,先查找并确认签名:
Bash
my-cli api find setValues --unit sheetmy-cli api show FWorkbook.getSheetByName FWorksheet.getRange FRange.setValues
  1. 以 write 模式执行 Facade code;业务 execute 命令负责 commit:
Bash
my-cli execute --unit "$UNIT_ID" --mode write \  --code 'const sheet = workbook.getSheetByName("Data");if (!sheet) throw new Error("Worksheet Data not found");sheet.getRange("A2:B2").setValues([["华东", 128000]]);'
  1. 按任务风险决定是否审查。Inspection 已覆盖 Range 值,因此直接重新读取:
Bash
my-cli inspect range A2:B2 --worksheet name:Data --unit "$UNIT_ID" --json

这个任务不需要 read 模式,因为 Inspection 已经可以读取写入前后的 Range。只有当所需内容没有被 Inspection 覆盖时,才使用 read 模式;后文会给出条件格式和图表配置的例子。

在业务 CLI 中装配这些能力

本章从 @univer-cli/univer-collaboration-runtime 开始,逐步加入 Inspection、API Reference 和 Content Execution。代码片段只突出每一步的核心接口,Server 配置、身份、错误展示和命令参数仍由业务应用补充。

本章把每一步加入同一个 Commander 根程序:

TypeScript
import { Command } from "commander";const program = new Command("my-cli");// 在这里注册后续章节介绍的 inspect、execute 和 api 命令。// 所有命令注册完成后,再解析 CLI 参数。await program.parseAsync();

1. 加载一个协同 Unit

Collaboration Runtime 是 Node.js 中面向 Agent 的 Unit 执行环境和协同客户端。一个 Runtime 在整个生命周期 中只绑定一个 Unit。

TypeScript
import {  createCollaborationServerAdapter,  createUniverCollaborationRuntimeFactory,} from "@univer-cli/univer-collaboration-runtime";import { UniverInstanceType } from "@univerjs/core";const factory = createUniverCollaborationRuntimeFactory({  backend: createCollaborationServerAdapter({    snapshotServerUrl,    collabSubmitChangesetUrl,    collabWebSocketUrl,    wsSessionTicketUrl,  }),  createUniver: headlessUniverFactory,});const unitId = "book-1";const runtime = await factory.load(unitId, UniverInstanceType.UNIVER_SHEET);

headlessUniverFactory 由应用注入,可以使用 @univer-cli/headless-univer 的标准实现,也可以使用自定义 composition;这里不展开初始化配置。业务应用还负责把 Server 配置、身份和 Unit target 转换成 adapter 所需的 协议地址。Runtime 负责加载 Snapshot、维护 revision 和 changeset,并提供 Facade 执行环境。

Runtime 的核心 API:

API用途
pull()拉取远端 changeset,通过 OT 协调并更新当前 Unit
execute({ mode, code })执行 Facade 代码;read 用于读取,write 用于产生 mutation
commit()手动提交当前 pending mutations
exportUnitData()导出当前 Runtime 中完整的 UnitData
getState()查看 revision、连接、pending state 与冲突状态
close()释放 backend handle 和 Headless Univer

2. 使用 Inspection 理解内容

Agent 不需要为常见读取任务重复编写 Facade code。@univer-cli/content-inspection 提供稳定、结构化、只读的 查询结果:

UnitInspection 概览Agent 快速获得的全局认知
SheetWorkbook 概览Worksheet 身份、有效区域以及 Table、Rule、Drawing 摘要
DocDocument 概览文档模式、段落索引、正文预览和 Feature 数量
SlidePresentation 概览页面索引、文字预览、元素数量以及 Presentation 尺寸和 Layout 数

Collaboration Runtime 可以直接适配 Inspection 所需的只读执行接口:

TypeScript
import { inspectContent } from "@univer-cli/content-inspection";const workbook = await inspectContent(  {    unitId: runtime.unitId,    unitType: "sheet",    execute: async (input) => {      const result = await runtime.execute(input);      return { value: result.value };    },  },  { kind: "workbook" },);

inspectContent() 使用 unitId 生成只读 Facade 程序,并通过 univerAPI.getWorkbook(unitId) 定位目标 Workbook;unitType 用于检查查询类型与 Unit 类型是否匹配。

先使用 overview 查询快速了解 Unit 结构和主体内容,再使用 worksheet、range、paragraph 和 slide selector 读取 Inspection 已覆盖的标准化内容。只有当所需配置或细节没有出现在 Inspection 结果中时,例如完整的条件格式 规则或图表配置,才使用 execute({ mode: "read" }) 编写最小的定向查询。

需要默认 Commander 交互时,直接添加 inspect 预设命令。业务应用只负责提供 Runtime lease:

TypeScript
import type { ContentInspectionLease } from "@univer-cli/content-inspection-command";import { createContentInspectionCommand } from "@univer-cli/content-inspection-command";program.addCommand(  createContentInspectionCommand({    async acquireRuntime({ unitId }) {      const runtime = await factory.load(unitId, UniverInstanceType.UNIVER_SHEET);      await runtime.pull();      const lease: ContentInspectionLease = {        unitId,        unitType: "sheet",        execute: async (input) => {          const result = await runtime.execute(input);          return { value: result.value };        },        invalidate: () => runtime.close(),        release: () => runtime.close(),      };      return lease;    },  }),);

acquireRuntime 是预设命令公开的依赖字段,返回值遵循 ContentInspectionLease;这里没有 pool,所以 invalidate()release() 都直接关闭独占 Runtime。预设命令负责 selector 解析、文本或 JSON 输出以及 lease 释放。业务应用仍负责 target 映射、Runtime 初始化、认证和远端内容加载。自定义 Agent 协议时,直接调用 inspectContent()

3. 查找和理解 Facade API

当 Agent 知道目标但不确定使用哪个 Facade API 时,使用 @univer-cli/api-reference。它随当前 SDK 发布, 不需要加载 Unit,也不访问在线文档服务。

TypeScript
import { createStandardApiReference } from "@univer-cli/api-reference";const reference = createStandardApiReference();const matches = reference.find({  terms: ["setValues", "conditional formatting"],  unit: "sheet",  limit: 20,});const details = reference.show(["FRange", "FRange.setValues", "ICellData.v"]);
  • find() 根据任务关键词寻找候选 symbol;
  • show() 返回 class、member、type 或 enum 的精确详情;
  • @univer-cli/api-reference-command 提供可选的 api findapi show 预设命令。

把同一个 reference 直接接入 Commander:

TypeScript
import { createApiCommand } from "@univer-cli/api-reference-command";program.addCommand(createApiCommand({ reference }));

API Reference 是执行前的辅助能力:Agent 可以先 Inspect 了解当前内容,再 Find/Show 选择 API,最后生成并 执行 Facade code。

4. 执行 Facade 读写

自由读取和修改使用 Collaboration Runtime 的 execute()@univer-cli/content-execution 可以先把 Facade JavaScript 绑定到明确的 Unit,并注入对应的稳定 binding:

TypeScript
import { prepareContentExecutionProgram } from "@univer-cli/content-execution";const executionProgram = prepareContentExecutionProgram({  unitId,  unitType: "sheet",  code: 'workbook.getActiveSheet().getRange("A1").setValue("done");',});const execution = await runtime.execute({  mode: "write",  code: executionProgram,});
  • mode: "read" 用于自由只读查询,不允许产生 mutation;
  • mode: "write" 捕获 Facade 产生的 mutation,并加入 Runtime 的本地 pending state;
  • 执行成功只表示代码已经运行,不表示 changeset 已经提交到 Server。

content-execution 只生成 execution program,不获取 Runtime、不提交 changeset,也不提供公开的 execute 预设命令包。因此业务 CLI 使用 Commander 封装自己的应用级命令:

TypeScript
const executeCommand = new Command("execute")  .requiredOption("--unit <id>")  .requiredOption("--code <javascript>")  .option("--mode <read|write>", "execute without or with mutations", "write")  .action(async ({ unit, code, mode }) => {    if (mode !== "read" && mode !== "write") {      throw new Error("--mode must be read or write");    }    const runtime = await factory.load(unit, UniverInstanceType.UNIVER_SHEET);    try {      await runtime.pull();      const executionProgram = prepareContentExecutionProgram({        unitId: unit,        unitType: "sheet",        code,      });      const execution = await runtime.execute({ mode, code: executionProgram });      if (mode === "read") {        process.stdout.write(`${JSON.stringify(execution.value, null, 2)}\n`);        return;      }      let committed = await runtime.commit();      if (committed.status === "pull-required") {        await runtime.pull();        committed = await runtime.commit();      }      if (committed.status !== "confirmed") {        throw new Error(`Commit failed: ${committed.status}`);      }      process.stdout.write(        `${JSON.stringify(          {            commit: committed.status,            mutations: execution.mutations.length,            revision: committed.state.baseRevision,            value: execution.value,          },          null,          2,        )}\n`,      );    } finally {      await runtime.close();    }  });program.addCommand(executeCommand);

这个应用级命令默认使用 write 模式;read 模式只输出 Facade code 的返回值,不产生 mutation,也不调用 commit()。write 模式只有在 commit confirmed 后才输出 mutation 数量、revision 和返回值,Agent 因此可以明确 判断提交结果。Commander 负责参数和命令生命周期;Application 负责 Runtime 获取、提交重试、错误输出和权限 策略。这里固定使用 Sheet 以保持片段最小;支持 Doc、Slide、Base 或 Board 时,再增加 CLI Unit 类型到 UniverInstanceType 的显式映射。

只用 read 模式补充 Inspection 未覆盖的内容

例如,Inspection 可以返回 Worksheet 的条件格式数量,但不包含每条规则的完整配置。Agent 需要这些配置时, 先确认 API,再以 read 模式执行最小的 Facade code:

Bash
my-cli api find getConditionalFormattingRules --unit sheetmy-cli api show FWorksheet.getConditionalFormattingRulesmy-cli execute --unit "$UNIT_ID" --mode read \  --code 'const sheet = workbook.getSheetByName("Data");if (!sheet) throw new Error("Worksheet Data not found");return sheet.getConditionalFormattingRules();'

Inspection 也可以告诉 Agent Worksheet 中有多少个 Chart;如果任务需要完整图表配置,可以定向返回 sheet.getCharts().map((chart) => chart.getInfo())。read 模式不允许产生 mutation,它只补充 Inspection 没有覆盖的 内容,不是 Inspection 的默认替代品。

总结

到这里,同一个 Commander 程序已经组合了 Collaboration Runtime、Inspection、API Reference 和 Content Execution。Runtime 负责加载、同步、执行与手动提交;Inspection 负责结构化读取;API Reference 帮助 Agent 查找 Facade API;Commander 将这些能力组织成一致的 CLI 入口。

一次典型操作先用 inspect 了解结构、主体内容和已覆盖的标准化细节;API 不明确时使用 api find / api show。 只有 Inspection 没有覆盖所需配置或细节时,才以 read 模式执行 Facade code,然后以 write 模式编辑并提交。 审查阶段继续遵循同一条 Inspection 覆盖边界。

下一步

下一步增加Office 文件导入导出,将 Office 文件转换成同一条内容操作链使用的 UnitData,或把最新 UnitData 导出为 Office 文件。

你觉得这篇文档如何?

© 2026 DreamNum Co., Ltd.