Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
468a418d3a | ||
|
|
71b45b1eab | ||
|
|
5b686efc23 |
@@ -11,23 +11,28 @@ metadata:
|
||||
|
||||
# 钉钉 AI 表格 Skill
|
||||
|
||||
## 前置条件 — 执行操作前必读
|
||||
## 执行入口
|
||||
|
||||
> **CRITICAL — 执行任何 `dws` 操作前,MUST 先用 Read 工具完整读取 [`dws-shared`](../dws-shared/SKILL.md)。**该轻量文件包含全局执行契约、安全底线及 shared references 的按需加载导航;不要预加载其全部 references。
|
||||
执行任何 `dws` 操作前,完整读取 [`dws-shared`](../dws-shared/SKILL.md),但不要预加载其 references。高频意图直接使用本文件骨架;仅特殊参数、复杂数据形态或边界不明时读取一个 branch reference。
|
||||
|
||||
## 加载与路由顺序
|
||||
|
||||
1. 命中下方高频意图时直接使用精确骨架,不先查 Help 或产品级 Schema。
|
||||
2. 路由优先级固定为:精确 recipe / 可运行脚本 > 匹配的公开 Shortcut > 原子命令。命令已确定且参数清楚时直接执行。
|
||||
1. 先定义目标对象、父容器、用户要求的阶段和完成证据;命中下方高频意图时,把精确
|
||||
骨架作为首选起点,不先查 Help 或产品级 Schema。
|
||||
2. 首选顺序为:精确骨架 / recipe > 匹配的公开 Shortcut > 原子命令。它用于降低
|
||||
首调用成本,不是禁止依据 Runtime 新证据调整路径。脚本只用于 Runtime 尚未覆盖的
|
||||
批量、文件传输或异步编排,不与普通原子命令竞争默认入口。
|
||||
3. 参数、约束或安全语义不确定时只读 leaf Schema:`dws schema --cli-path "aitable <leaf>" --format json`;只有当前 Cobra flag 不确定时才读对应 `--help`。
|
||||
4. 复杂字段、筛选、导入导出、视图、权限或工作流任务,按“低频能力与 Reference”只加载相关文件,不预读整个 `references/aitable/`。
|
||||
5. 现有骨架和 reference 都无法定位能力时,才用 Runtime Shortcut Catalog 做最后发现;不得猜 `cli_path` 或 flag。
|
||||
6. Schema、Help、reference 与实际返回冲突时采用更安全的解释并报告契约漂移;`confirmation=user_required` 时先确认,再添加 `--yes`。
|
||||
7. 用户已给足目标、字段和数据时,按依赖链连续执行;保留已成功步骤及真实 ID,只从
|
||||
未完成缺口继续。每个关键结论用语义等价证据关闭后再统一答复。
|
||||
|
||||
<!-- VISIBLE_SHORTCUTS_START -->
|
||||
## Shortcut 发现(按需)
|
||||
|
||||
`aitable` 当前有 29 条公开 shortcut。完整清单保留在 Runtime Shortcut Catalog;已完成 Schema curation 的子集可通过 leaf Schema 查询。高频产品根 Skill 不重复展开完整清单。已知意图直接使用下方的优先路由、意图表或任务 reference;命令已选中时直接执行,只在参数/安全语义不确定时读取 leaf Schema,在当前 Cobra flags 不确定时读取 leaf Help。
|
||||
`aitable` 当前有 29 条公开 shortcut,完整清单保留在 Runtime Shortcut Catalog,根 Skill 不重复展开。
|
||||
|
||||
仅当现有路由和 reference 都无法定位低频能力时,才执行 `dws shortcut list --service aitable --compact --format json` 做最后回退;不要为已知高频意图加载完整 Shortcut Catalog 或产品级 Schema。
|
||||
<!-- VISIBLE_SHORTCUTS_END -->
|
||||
@@ -43,7 +48,9 @@ metadata:
|
||||
| View / Dashboard / Chart | `viewId` / `dashboardId` / `chartId` 各自绑定当前 Base/Table,不跨对象复用 |
|
||||
| 异步任务 | `taskId` / `importId` 只用于对应导出或导入任务,不能替代业务对象 ID |
|
||||
|
||||
所有下游 ID 都从当前链路的结构化返回中提取;同名多候选必须让用户消歧,不默认取第一项,也不复用未经本轮校验的旧 ID。
|
||||
所有下游 ID 都从当前链路的结构化返回中提取;同名多候选必须让用户消歧,不默认取第一项。Base → Table → Field/Record/View 的容器关系必须保持一致,不跨 Base 或 Table 复用子对象 ID。
|
||||
|
||||
创建、复制、导入或新建字段/记录返回 ID 后,立即绑定同一请求中的“这个”“刚才新建的”等指代;除非用户明确转向历史资源,否则不得再按名称搜索并替换为旧对象。
|
||||
|
||||
## 核心意图与执行骨架
|
||||
|
||||
@@ -51,14 +58,17 @@ metadata:
|
||||
|---|---|---|
|
||||
| 按名称找 Base | `dws aitable +resolve-base --name "<名称>" --format json` | 唯一命中才继续;多候选停止并消歧 |
|
||||
| 浏览最近访问 | `dws aitable +base-list --format json` | 只代表最近访问,不得宣称全量 |
|
||||
| 搜索模板 | `dws aitable template search --query "<关键词>" --format json` | 只返回真实候选,不擅自套用模板或创建 Base |
|
||||
| 按名称找 Table | `dws aitable +resolve-table --base <baseId> --name "<表名>" --format json` | `baseId` 必须来自上一步真实返回 |
|
||||
| 取表、字段与视图目录 | `dws aitable +table-get --base-id <baseId> [--table-ids <tableId>] --format json` | `tables[].fields[]` 是字段目录;完整类型/config 再用 `+field-get` |
|
||||
| 取字段完整配置 | `dws aitable +field-get --base-id <baseId> --table-id <tableId> [--field-ids <ids>] --format json` | 写入前核对类型、只读性和 select options;按需展开以控制返回体 |
|
||||
| 查/搜/筛记录 | `dws aitable +record-query --base-id <baseId> --table-id <tableId> [--query <词>\|--filters '<JSON>'\|--record-ids <ids>] --format json` | ID 模式忽略 filter/sort;全量结论必须完整分页 |
|
||||
| 查/搜/筛记录 | `dws aitable +record-query --base-id <baseId> --table-id <tableId> [--query <词>\|--filters '<JSON>'\|--record-ids <ids>] --format json` | ID 模式忽略 filter/sort;不要猜 `--page-limit`,分页使用返回的 cursor 与 leaf Help 中的真实分页 flag |
|
||||
| 新增记录 | `dws aitable record create --base-id <baseId> --table-id <tableId> --records '[{"cells":{"<fieldId>":<值>}}]' --format json` | 单次最多 100;取 `data.newRecordIds[]` 后立即按 ID 回读 |
|
||||
| 更新记录 | `dws aitable record update --base-id <baseId> --table-id <tableId> --records '[{"recordId":"<id>","cells":{"<fieldId>":<值>}}]' --format json` | 先 query 拿 recordId;只传需改字段;取 `data.recordIds[]` 后回读 |
|
||||
| 删除记录 | 先 `dws aitable +record-query ...` 定位,再 `dws aitable record delete --base-id <baseId> --table-id <tableId> --record-ids <ids>` | 展示目标与影响,得到明确确认后才加 `--yes` |
|
||||
| 创建 Base / Table | `dws aitable base create --name "<名>"` / `dws aitable table create --base-id <id> --name "<名>" --fields '[...]'` | 使用创建返回的真实 ID;系统改名/加后缀时不得继续猜原名 |
|
||||
| 复制视图 | `dws aitable view duplicate --base-id <baseId> --table-id <tableId> --view-id <viewId> --new-name "<名>"` | `viewId` 必须属于当前表;不能用复制 Table 或新建 Dashboard 替代 |
|
||||
| 创建图表 | 先读 `dws aitable chart widgets-example --format json`,再执行 `chart create ... --config '<JSON>' --layout '<JSON>'` | `--layout` 是必填项;不能只传 config 后依据退出码声称图表已创建 |
|
||||
| 批量追加 CSV / JSON 到已有表 | `python3 scripts/import_records.py <baseId> <tableId> <file> [batch_size]` | CSV 表头必须是 fieldId;脚本返回不完整 ledger 时不得宣称全成功 |
|
||||
| 文件导入为新数据表 | `python3 scripts/aitable_import_via_task.py <baseId> <file>` | 与“追加已有 table”不同;走 prepare → PUT → import task |
|
||||
| 批量创建字段 | `python3 scripts/bulk_add_fields.py <baseId> <tableId> fields.json` | 单次最多 15;逐项检查成功/失败结果 |
|
||||
@@ -69,9 +79,31 @@ metadata:
|
||||
|
||||
- `record create/update` 前必须获取目标字段的 `fieldId`、`type` 与 `config`;`filterUp`、`lookup` 等只读字段不可写。完整格式只在需要时读 [aitable-cell-value.md](references/aitable/aitable-cell-value.md)。
|
||||
- 筛选和排序字段使用 `fieldId`;`--filters` 最外层是 `and|or + operands`,`--sort` 使用 `direction: asc|desc`。日期和跨表字段规则按需读 [aitable-filter-sort.md](references/aitable/aitable-filter-sort.md)。
|
||||
- `record query --all` 仍受 `--page-limit` 约束;分页中断或局部富化失败时保留已有结果,输出 completeness 与逐项失败 ledger,不把部分结果描述为全量。
|
||||
- 记录分页不能凭经验拼 `--page-limit`。先用当前 leaf Help 确认 page-size/cursor 的真实名称;每页读取返回 cursor,直到明确终止。分页中断或局部富化失败时保留已有结果,输出 completeness 与逐项失败 ledger,不把部分结果描述为全量。
|
||||
- 创建、更新、导入、批量建字段等写操作必须检查业务 `status`、逐项结果与返回 ID;普通写入按用户明确要求执行后回读,不能只凭退出码宣称成功。
|
||||
- 长 JSON 使用 `--records-file` / 任务文件;不得为绕过字段错误而静默丢列、改类型或删除失败项。
|
||||
- `table create --fields` 的键固定为 `fieldName` / `type` / `config`,不能写成 `name`;单选/多选类型固定为 `singleSelect` / `multipleSelect`,不能写 `select`。number formatter 不确定时先读 leaf Help,禁止猜 `INTEGER` 等值。
|
||||
|
||||
## 写入计划与验证
|
||||
|
||||
- 用户明确列出的“先创建、再加字段、然后写记录/建视图”等阶段是可观察的验收步骤,必须逐项真实执行;不能为了得到相似终态而折叠、重排或省略。
|
||||
- 删除 Base/Table/Field/Record、关闭高级权限、删除角色和其他高风险动作,先固化目标 ID、所属容器、影响数量、副作用与可恢复性;确认前写调用为零。
|
||||
- 批量导入、建字段和记录写入在第一笔写入前完成全部字段类型、只读性、关联表和文件边界校验;部分失败保留输入顺序与逐项 ledger。
|
||||
|
||||
| 写入对象 | 成功后必须验证 |
|
||||
|---|---|
|
||||
| Base / Table | 使用创建返回 ID 查询对象及所属关系 |
|
||||
| Field | `+field-get` 核对 fieldId、type、config 与只读性 |
|
||||
| Record | 使用返回 recordId 按 ID 回读目标 cells |
|
||||
| View / Dashboard / Chart | 重新读取当前 Base/Table 下的对象配置 |
|
||||
| 导入 / 导出任务 | 核对 task 状态、结果对象或输出文件完整性 |
|
||||
|
||||
退出码 0、`status=success`、空对象或仅有 taskId 都不能单独证明业务完成。字段未生效、回读不一致、分页不完整或异步任务未完成时,报告失败、部分完成或进行中,不得声称“全部完成”。
|
||||
|
||||
验证必须与用户点名的操作语义一致:Base 搜索只能由搜索结果中的目标命中关闭,最近
|
||||
访问列表或创建回读只能证明对象存在;复制必须有复制操作产生的新对象证据;移动必须
|
||||
回读新的父级关系;删除必须核对精确目标并确认其已不存在。邻近证据可用于诊断,不能
|
||||
替代目标步骤的完成证据。
|
||||
|
||||
## 低频能力与 Reference
|
||||
|
||||
@@ -87,10 +119,18 @@ metadata:
|
||||
|
||||
## 错误恢复
|
||||
|
||||
- 路径或 flag 错误:按既定的 leaf Schema → leaf Help 顺序校正一次;仍失败则停止,不连续尝试猜测别名。
|
||||
- 不使用全局“只准纠正一次”的硬限制。恢复预算由已观察状态和副作用风险决定,只在
|
||||
新错误信息、leaf Schema/Help 或回读产生新证据时继续;重复同一假设或不再增加证据
|
||||
时停止。
|
||||
- 路径、flag 或 payload 在写入前被校验拒绝:吸收精确 hint,保持目标和容器不变后
|
||||
修正。只读调用可做有界替代探测,但不得用相邻能力冒充目标能力。
|
||||
- 命令非零、输出非 JSON、业务 `status != success`、必需 ID 缺失、批处理部分失败均视为失败;保留成功项与 ledger,禁止吞错。
|
||||
- 同名歧义、权限不足、资源不存在、字段类型漂移、分页无法推进或 Schema/Help 冲突时停止并报告。具体恢复动作按需读 [aitable-error-recovery.md](references/aitable/aitable-error-recovery.md)。
|
||||
- 每次重试都从最新实际输出重新提取下游 ID;删除和其他 `confirmation=user_required` 操作不得自动重试或静默确认。
|
||||
- 写入已返回 ID 时保留成功状态,只补字段、记录、视图、图表或验证缺口。写入超时或
|
||||
状态未知时先回读当前 Base/Table;只有明确未写入且契约允许时才重试。删除和其他
|
||||
`confirmation=user_required` 操作不得自动重试或静默确认。
|
||||
- 不要重复猜同一 flag、formatter、folderId 或图表配置。目标能力已有原生命令时,
|
||||
不要以手工重建相似对象掩盖原命令失败。
|
||||
|
||||
## 跨产品协作
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 数据分析
|
||||
|
||||
> 定位:仅在用户要求跨记录统计、聚合或业务结论时加载。普通查找、筛选和分页先按根 Skill 的 `+record-query` 骨架执行;完整分析契约以 [aitable-data-analysis-sop.md](aitable/aitable-data-analysis-sop.md) 为准,本页只保留轻量入口。
|
||||
|
||||
> 本场景所有 recipe 均为 full。
|
||||
|
||||
| Recipe | 行动指南(固定路线) |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 业务域通用规范
|
||||
|
||||
> 定位:供 AITable 主题 Reference 复用的批量、并行采集和 ID 传递约定,不是用户意图路由入口。根 Skill 已明确的高频任务不需要单独加载本页。
|
||||
|
||||
> 仅服务本 skill 已迁入的行动指南。安全门控、危险操作确认、`--format json` 等已在本 skill 的 `SKILL.md` 中定义,此处不重复。
|
||||
|
||||
## 批量查询规范
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 记录操作详细指南
|
||||
|
||||
> 定位:兼容性的记录操作总览。新任务优先按需读取 `aitable/aitable-record-{query,create,update,delete,upsert}.md` 中唯一对应的叶级 Reference;不要同时加载本页和全部叶级文件。本页不得作为另一套命令发现源。
|
||||
|
||||
## 查询记录
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
# AI表格 (aitable) 命令参考
|
||||
|
||||
> **渐进式文档**:本文件为路由层(索引 + 意图判断),各命令的详细参数、示例和踩坑说明在 [aitable/](./aitable/) 目录下按需加载。
|
||||
> 定位:低频 atomic 能力的一级索引,不是每次调用必读的产品手册。已知高频意图直接回到 [`SKILL.md`](../SKILL.md);参数和安全语义查 leaf Schema,真实 flags 查 leaf Help;本页只在根路由无法定位能力时用于选择一个主题 Reference,禁止递归加载全部链接。
|
||||
|
||||
已知高频意图优先使用根 Skill 的精确 Shortcut/脚本骨架;本文件只在需要完整一级命令索引、对象 URL 或低频分支导航时加载。参数与安全不确定时读 leaf Schema,Cobra flag 不确定时才读 leaf Help,不要把本文件当作参数事实源。
|
||||
## 使用本索引
|
||||
|
||||
1. 先按对象选择一个分支:Base/Table、Field、Record、View/Form、Dashboard/Chart、Workflow、Advperm、Import/Export 或 Section。
|
||||
2. 只打开该分支链接的一个主题文件;命令已确定后停止发现。
|
||||
3. 所有子对象 ID 必须来自当前 Base/Table 链路;写操作完成后按对象回读。
|
||||
4. 本页示例是导航证据,不覆盖 Runtime/Cobra、leaf Schema 或根 Skill 的 Golden Route。
|
||||
|
||||
各命令的详细参数、示例和边界在 [aitable/](./aitable/) 目录下按需加载。
|
||||
|
||||
## 文档地址 (URI)
|
||||
|
||||
@@ -331,162 +338,3 @@ dws aitable export data --base-id <BASE_ID> --task-id <TASK_ID> --timeout-ms 300
|
||||
- `scope=all`:只需 `base-id`
|
||||
- `scope=table`:必须 `table-id`
|
||||
- `scope=view`:必须同时 `table-id + view-id`
|
||||
|
||||
## 意图判断
|
||||
|
||||
用户说"表格/多维表/AI表格":
|
||||
- 查看/查找/列表 → `base search`(优先)或 `base list`(仅浏览最近访问)
|
||||
- 详情 → `base get`
|
||||
- 创建 → `base create`
|
||||
- 修改 → `base update`
|
||||
- 删除 → `base delete`
|
||||
|
||||
用户说"数据表/子表/table":
|
||||
- 查看 → `table get`
|
||||
- 创建 → `table create`
|
||||
- 重命名 / 改备注 / 改行命名规则 → `table update`(三选一:`--name` / `--description` / `--record-name-key`)
|
||||
- 用户说"行命名规则/记录别名/卡片显示成 task/project/event 这种" → `table update --record-name-key <枚举键>`,**中文 → 枚举键**对照见 [aitable-record-name-key.md](./aitable/aitable-record-name-key.md)
|
||||
- 删除 → `table delete`
|
||||
|
||||
用户说"字段/列/column":
|
||||
- 查看 → `field get`
|
||||
- 添加 → `field create`(读 [aitable-field.md](./aitable/aitable-field.md))
|
||||
- 修改 → `field update`
|
||||
- 删除 → `field delete`
|
||||
|
||||
用户说"记录/行/数据/row":
|
||||
- 查看/搜索 → `record query`(读 [aitable-record-query.md](./aitable/aitable-record-query.md))
|
||||
- 找空行 / 没填东西的行 → `record query-empty`(读 [aitable-record-query.md](./aitable/aitable-record-query.md))
|
||||
- 已知 recordId 反查字段值 → `record get`(按 ID 取专用,等价 `record query --record-ids`)
|
||||
- 添加/写入 → `record create`(读 [aitable-record-create.md](./aitable/aitable-record-create.md))
|
||||
- 修改/更新(每条独立 cells) → `record update`(读 [aitable-record-update.md](./aitable/aitable-record-update.md))
|
||||
- **批量更新同一字段值**(统一标记/统一改值) → `record batch-update --record-ids ... --cells '{...}'`
|
||||
- 删除 → `record delete`
|
||||
- **查记录的字段变更历史 / 操作审计** → `record history-list`(读 [aitable-record-history.md](./aitable/aitable-record-history.md))
|
||||
- **取记录分享链接 / 把这行发给同事** → `record share-url`(读 [aitable-record-share.md](./aitable/aitable-record-share.md))
|
||||
- **不知道有没有 → 有就改、没有就建** → `record upsert`(读 [aitable-record-upsert.md](./aitable/aitable-record-upsert.md))
|
||||
|
||||
用户说"视图/view":
|
||||
- 列出/查看全部视图 → `view list`(或 `view get` 不传 --view-ids,二者等价)
|
||||
- 看某个视图详情 → `view get --view-ids <ID>`
|
||||
- 创建 → `view create`
|
||||
- 修改(含"调整字段顺序/隐藏字段") → `view update --config '{"visibleFieldIds":[...]}'`
|
||||
- 修改某一项配置(filter/sort/group/card/timebar/aggregate 等)→ `view update <attr>`(读 [aitable-view-config.md](./aitable/aitable-view-config.md))
|
||||
- 锁定 / 冻结列 / 行高 / 数据高亮规则 / 复制视图 → 读 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
- 删除 → `view delete`
|
||||
|
||||
用户说"锁定视图/解锁视图/lock view" → `view lock` / `view lock --off`,详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
|
||||
用户说"冻结列/冻结首列/frozen columns" → `view update frozen-cols --count N`,详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
|
||||
用户说"行高/单元格高度/紧凑模式/cell height" → `view update row-height --cell-height N`(合法档位 32/56/88/128),详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
|
||||
用户说"数据高亮/条件格式/单元格上色/fill color rule" → `view update fill-color-rule --json '[...]'`,详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
|
||||
用户说"复制视图/duplicate view" → `view duplicate --view-id ... [--new-name ...]`,详见 [aitable-view-extras.md](./aitable/aitable-view-extras.md)
|
||||
|
||||
用户说"筛选/过滤/filter" → 读 [aitable-filter-sort.md](./aitable/aitable-filter-sort.md)
|
||||
|
||||
用户说"统计/分析/聚合/TOP N/全量" → 读 [aitable-data-analysis-sop.md](./aitable/aitable-data-analysis-sop.md)
|
||||
|
||||
用户说"公式/formula/计算字段/派生指标" → 读 [aitable-formula-guide.md](./aitable/aitable-formula-guide.md)
|
||||
|
||||
用户说"查找引用/lookup/filterUp/跨表" → 读 [aitable-formula-guide.md](./aitable/aitable-formula-guide.md)(§5.4 跨表引用)
|
||||
|
||||
用户说"表单/form/收集表/问卷/催办填写" → 读 [aitable-form.md](./aitable/aitable-form.md)
|
||||
|
||||
用户说"自动化/工作流/流程/触发/automation/workflow" → 读 [aitable-workflow.md](./aitable/aitable-workflow.md)
|
||||
- 新建自动化 → 按子文档的最小 Demo 组装完整 DSL,再 `workflow create --dsl @file`
|
||||
- 修改自动化 → `workflow get` 留底,按最新 DSL 文档生成完整目标 DSL,再 `workflow update --dsl @file`
|
||||
- 看 Base 里有哪些流程 / 哪些在跑 → `workflow list`(看 `recordCount` / `runningCount`)
|
||||
- 看某个流程具体配置(触发条件、动作步骤) → `workflow get`
|
||||
- 启用流程 → `workflow enable`
|
||||
- 临时停掉流程(调试 / 数据迁移)→ `workflow disable --yes`
|
||||
- 删除流程:当前不支持,引导用户到 AI 表格 Web 端 → 数据表 → 自动化 面板手动完成
|
||||
|
||||
用户说"仪表盘/图表/chart" → 读 [aitable-dashboard-chart.md](./aitable/aitable-dashboard-chart.md)
|
||||
|
||||
用户说"仪表盘排版乱了/图表对不齐/重新排布/自动布局/美化仪表盘" → `dashboard arrange`(读 [aitable-dashboard-chart.md](./aitable/aitable-dashboard-chart.md))
|
||||
|
||||
用户说"附件/上传文件" → 读 [aitable-attachment.md](./aitable/aitable-attachment.md)
|
||||
|
||||
用户说"导入/导出/import/export" → 读 [aitable-export-import.md](./aitable/aitable-export-import.md)
|
||||
|
||||
用户说"模板" → `template search`
|
||||
|
||||
用户说"高级权限/角色/权限控制/谁能看/谁能改" → 读 [aitable-advperm.md](./aitable/aitable-advperm.md)
|
||||
- 开/关高级权限 → `advperm enable` / `advperm disable --yes`
|
||||
- 看角色配置 → `advperm role-list` 或 `advperm role-get`
|
||||
- 建角色(可同时指定子角色权限) → `advperm role-create --name ... --sub-roles '[...]'`
|
||||
- 改角色名 / 改子角色权限(PATCH 语义,未传字段不变) → `advperm role-update --role-id ... [--name ...] [--sub-roles '[...]']`
|
||||
- 删角色 → `advperm role-delete --yes`
|
||||
- **角色 ↔ 成员绑定**:当前 CLI 不支持,仍需在 AI 表格 Web 端面板手动完成
|
||||
|
||||
命令报错/操作失败 → 读 [aitable-error-recovery.md](./aitable/aitable-error-recovery.md)
|
||||
|
||||
**关键区分**: base=表格文件, table=数据表, field=列, record=行
|
||||
|
||||
## 核心工作流
|
||||
|
||||
```bash
|
||||
# 1. 按名称解析唯一 Base — 提取 baseId;多候选必须消歧
|
||||
dws aitable +resolve-base --name "项目" --format json
|
||||
|
||||
# 2. 按名称解析唯一 Table — 提取 tableId
|
||||
dws aitable +resolve-table --base <BASE_ID> --name "任务" --format json
|
||||
|
||||
# 3. 获取字段目录;需要完整类型 config 时再调用 field get
|
||||
dws aitable +table-get --base-id <BASE_ID> --table-ids <TABLE_ID> --format json
|
||||
dws aitable +field-get --base-id <BASE_ID> --table-id <TABLE_ID> --format json
|
||||
|
||||
# 4. 查询记录
|
||||
dws aitable +record-query --base-id <BASE_ID> --table-id <TABLE_ID> --format json
|
||||
|
||||
# 5. 新增记录 (cells 用 fieldId 作 key)
|
||||
dws aitable record create --base-id <BASE_ID> --table-id <TABLE_ID> \
|
||||
--records '[{"cells":{"fldXXX":"值"}}]' --format json
|
||||
```
|
||||
|
||||
## 上下文传递表
|
||||
|
||||
| 操作 | 从返回中提取 | 用于 |
|
||||
|------|-------------|------|
|
||||
| `base list/search` | `baseId` | 所有后续命令的 --base-id,拼接文档 URI |
|
||||
| `base create` | `baseId` | 后续命令 + 文档 URI |
|
||||
| `base get` | `tables[].tableId` | --table-id,拼接指定数据表 URI |
|
||||
| `table create` | `tableId` | 后续命令 + 拼接指定数据表 URI |
|
||||
| `table get` | `tables[].tableId`、精简 `fields[]`、`views[]` | 定位数据表、字段目录和视图;完整字段 config 再用 `field get` |
|
||||
| `field get` | `fields[].fieldId/type/config` | record 操作的 cells key、类型校验、field update/delete |
|
||||
| `record query` | `recordId` | record update/delete;按 ID 反查字段值用 `record get` |
|
||||
| `template search` | `templateId` | base create --template-id,拼接模板预览 URI |
|
||||
|
||||
## URL → baseId 提取
|
||||
|
||||
用户提供 `https://alidocs.dingtalk.com/i/nodes/{baseId}` 链接时:
|
||||
1. 提取 `/nodes/` 后的路径段作为 `baseId`
|
||||
2. 去掉尾部的查询参数(`?` 及其后内容)
|
||||
3. 传入 `--base-id` 参数
|
||||
|
||||
> 如果该 URL 来自 `dws aitable` 返回或已在当前链路 probe 过,可直接复用;
|
||||
> 如果是用户直接提供的原始 `alidocs` URL,则先按 [链接规范](url-patterns.md#alidocs-url-类型探测流程) probe,确认 `extension=able` 后再继续。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 所有操作使用 ID(baseId/tableId/fieldId/recordId),不使用名称
|
||||
- records 的 cells key 是 fieldId,不是字段名称
|
||||
- cells 写入/读取格式见 [aitable-cell-value.md](./aitable/aitable-cell-value.md)
|
||||
- 最佳实践见 [aitable-best-practices.md](./aitable/aitable-best-practices.md)
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
| 脚本 | 场景 |
|
||||
|------|------|
|
||||
| [bulk_add_fields.py](../scripts/bulk_add_fields.py) | 批量添加字段 |
|
||||
| [import_records.py](../scripts/import_records.py) | 从 JSON/CSV 批量导入记录 |
|
||||
| [aitable_import_via_task.py](../scripts/aitable_import_via_task.py) | 导入 CSV/XLS/XLSX 并新建数据表(prepare + PUT + import) |
|
||||
| [aitable_export_via_task.py](../scripts/aitable_export_via_task.py) | 文件导出(export_data 轮询 + 下载) |
|
||||
| [upload_attachment.py](../scripts/upload_attachment.py) | 上传附件到 AI 表格记录 |
|
||||
|
||||
## 相关产品
|
||||
|
||||
- [doc](../../dingtalk-doc/references/doc.md) — 富文本文档编辑,不是结构化数据表格
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# advperm — 高级权限管理
|
||||
|
||||
> 加载边界:仅在开启/关闭高级权限或管理自定义角色时读取。普通协作者、文件权限或成员管理不走本页。`baseId` 和 `roleId` 必须来自当前链路;disable、role-delete 等需确认的动作先读现状、固化影响,再执行并回读。
|
||||
|
||||
控制 Base 的高级权限总开关,并管理自定义角色(增删改查 + 子角色权限规则)。
|
||||
适用场景:"如何控制谁能看/改 Base 数据"、"开启/关闭高级权限"、"新建/修改/删除角色"、"按字段或行配置权限"。
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# attachment — 附件上传
|
||||
|
||||
> 加载边界:仅在文件要写入 AITable 的 attachment 字段时读取;普通钉盘上传走 Drive。流程必须完成“申请凭证 → HTTPS PUT → 用 fileToken 写记录 → 按 recordId 回读”,拿到 fileToken 不等于附件已进入记录。
|
||||
|
||||
> **STOP — 不要使用钉盘 (drive) 上传!** 钉盘 fileId 无法写入 attachment 字段。必须使用以下流程。
|
||||
>
|
||||
> **STOP — 严禁在 record create/update 的 cells 里直接传图片 URL!** 直传 `{"url":"https://..."}` 会导致服务端同步下载图片,批量写入时触发 TIMEOUT_ERROR。正确做法:先 `attachment upload` 获取 `fileToken`,再用 `{"fileToken":"ft_xxx"}` 写入。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# AI 表格最佳实践
|
||||
|
||||
> 定位:跨主题的不变量摘要,用于复杂任务复核,不作为命令索引。若根 Skill 已给出明确骨架,不要为了普通读写预加载本页;具体字段值、过滤或错误恢复分别读取对应专题。
|
||||
|
||||
## 1. 字段可写性分类
|
||||
|
||||
| 字段类型 | 可写 | 正确方式 |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# cells 写入/读取格式规范(cellValue 数据结构)
|
||||
|
||||
> 加载边界:仅在已经选定 record create/update/upsert 且需要构造某种字段值时读取。先用 field get 确认 `fieldId`、`type`、`config` 和可写性;本页不负责找 Base/Table/Record,也不能把字段名当 fieldId。
|
||||
|
||||
> 适用命令:`dws aitable record create --records`、`dws aitable record update --records`、`dws aitable record query` 返回
|
||||
>
|
||||
> 本文件是 DWS AI 表格 cellValue 的 **source of truth**。写入记录时,必须严格按此格式构造 cells 对象。
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
# dashboard & chart — 仪表盘与图表
|
||||
|
||||
> 加载边界:仅在用户明确操作仪表盘或图表时读取。先用当前 Base 的 dashboard list/get 获取 `dashboardId`,再获取其 `chartId`;不要用 View 或 Table 命令替代,也不要跨 Dashboard 复用 chartId。
|
||||
|
||||
## 建议操作顺序
|
||||
|
||||
```bash
|
||||
# 1) 先看配置模板(JSONC)
|
||||
# 1) 先看图表配置模板和当前 leaf 契约
|
||||
dws aitable dashboard config-example --format json
|
||||
dws aitable chart widgets-example --format json
|
||||
dws aitable chart create --help
|
||||
|
||||
# 2) 先拿 dashboard,再拿 chart 详情
|
||||
dws aitable dashboard get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --format json
|
||||
@@ -34,11 +37,15 @@ dws aitable chart get --base-id <BASE_ID> --dashboard-id <DASHBOARD_ID> --chart-
|
||||
| 命令 | 用途 | 必填参数 |
|
||||
|------|------|----------|
|
||||
| `chart get` | 获取图表详情 | `--base-id` `--dashboard-id` `--chart-id` |
|
||||
| `chart create` | 创建图表 | `--base-id` `--dashboard-id` `--config` |
|
||||
| `chart create` | 创建图表 | `--base-id` `--dashboard-id` `--config` `--layout` |
|
||||
| `chart update` | 更新图表配置 | `--base-id` `--dashboard-id` `--chart-id` `--config` |
|
||||
| `chart delete` | 删除图表 | `--base-id` `--dashboard-id` `--chart-id` `--yes` |
|
||||
| `chart widgets-example` | 查看图表 widgets 配置模板 | 无 |
|
||||
|
||||
## 配置获取流程
|
||||
|
||||
创建图表前,必须先调用 `chart widgets-example` 查看配置模板,了解每种图表类型需要的字段结构,然后根据实际 tableId 和 fieldId 填充配置。
|
||||
创建图表前,先调用当前 Runtime 的 `chart widgets-example`(如未来命令发生变化,
|
||||
以 leaf Schema/Help 的真实命令为准),再根据实际 tableId 和 fieldId 填充配置,并
|
||||
在第一次创建时同时传入 `--config` 与 `--layout`。创建返回
|
||||
`chartId` 后用 `dashboard get`/`chart get` 回读;只有 Dashboard 存在但图表缺失时,
|
||||
图表阶段仍未完成。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# AI 表格数据分析 SOP
|
||||
|
||||
> 加载边界:用于需要全表统计、分组、排名或业务结论的任务。普通记录定位只读 record-query 专题。任何“全部/最高/总数”结论都必须携带分页完整性;未拉全时只能报告当前范围和 continuation。
|
||||
|
||||
> 当用户诉求涉及查询、筛选、排序、统计、Top/Bottom N、分组聚合、判断全局结论时,必须先读本文档再执行。
|
||||
|
||||
## 1. 查询决策树
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# AI 表格错误恢复指南
|
||||
|
||||
> 加载边界:仅在真实命令或业务返回失败后读取,不做预防性全量加载。先保留原错误、阶段、对象 ID 和已成功 ledger;只有能证明未写入且契约允许时才重试,状态未知和需确认写操作禁止自动重放。
|
||||
|
||||
> 当 CLI 命令返回错误时,按本文档的映射表判断恢复动作。
|
||||
|
||||
## 1. 错误响应结构
|
||||
@@ -68,22 +70,27 @@
|
||||
| 导入文件格式错误 | 不支持的文件格式或文件损坏 | 确认文件为 .xlsx 格式且未加密 |
|
||||
| 批处理只成功一部分 | 某批或某个字段返回失败 | 保留成功 ID,输出失败 batch/item ledger,以非零状态结束;不要整批重放 |
|
||||
|
||||
## 3. 重试策略
|
||||
## 3. 状态感知恢复策略
|
||||
|
||||
### 3.1 可重试的错误
|
||||
不要用一个全局次数限制处理所有错误。先判断上一次调用是否可能产生副作用,再决定
|
||||
探测、继续或停止。
|
||||
|
||||
| 错误类型 | 重试方式 | 最大重试次数 |
|
||||
|---------|---------|------------|
|
||||
| 网络超时 / 5xx | 等待 2s 后原样重试 | 2 |
|
||||
| 导出任务未完成 | 轮询 task-id | 5(间隔 3s) |
|
||||
| 并发写入冲突 | 串行重试 | 1 |
|
||||
| 已观察状态 | 恢复动作 |
|
||||
|---|---|
|
||||
| 只读调用失败 | 根据精确错误或 leaf 契约做有界探测;目标和父容器保持不变 |
|
||||
| 写入前参数校验失败 | 确认无副作用后修正 payload/flag;不原样重试 |
|
||||
| 网络超时 / 5xx,写入状态未知 | 先回读目标 Base/Table,确定未生效后才考虑重试 |
|
||||
| 已返回新对象或记录 ID | 绑定该 ID,只继续尚未完成的步骤 |
|
||||
| 异步任务未完成 | 继续查询同一个 taskId/importId,直到契约规定的终态或总超时 |
|
||||
| 并发冲突且明确未写入 | 降低并发或串行重试;再次冲突时停止并报告 |
|
||||
| 删除或高影响操作状态未知 | 停止并回读,不自动重放 |
|
||||
|
||||
### 3.2 不可重试的错误(立即停止)
|
||||
|
||||
| 错误类型 | 原因 | 处理方式 |
|
||||
|---------|------|---------|
|
||||
| 权限不足 / 403 | 用户对该 Base 无权限 | 停止操作,提示用户确认权限 |
|
||||
| 参数格式错误 | 请求结构不合法 | 修正参数后重试,不要原样重试 |
|
||||
| 参数格式错误 | 请求结构不合法 | 只在校验明确未写入且有新契约证据时修正,不要原样重试 |
|
||||
| 资源不存在 / 404 | ID 错误或资源已删除 | 重新查询定位资源 |
|
||||
| 配额超限 / 429 | API 调用频率过高 | 等待后重试,并降低并发 |
|
||||
|
||||
@@ -92,7 +99,12 @@
|
||||
在重试前,先确认:
|
||||
1. ❓ 错误是暂时性的还是永久性的?
|
||||
2. ❓ 参数有没有明显错误需要修正?
|
||||
3. ❓ 是否需要先查询最新状态再重试?
|
||||
3. ❓ 上次调用是否可能已经写入?
|
||||
4. ❓ 是否已经获得对象 ID,应该从后续缺口继续?
|
||||
5. ❓ 新尝试是否基于新证据,而不是重复同一猜测?
|
||||
|
||||
当没有新证据、开始重复同一错误、目标发生变化或副作用无法判断时停止。Base 搜索
|
||||
失败时,`base list` 只能帮助确认对象存在,不能作为搜索完成证据。
|
||||
|
||||
## 4. 调试技巧
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# export & import — 导入导出
|
||||
|
||||
> 加载边界:仅在文件与 AITable 之间迁移数据时读取。“追加到已有 Table”与“导入成新 Table”必须先分流。`taskId/importId` 只用于对应任务状态,完成后必须验证新 tableId 或本地输出文件;任务已创建不等于业务完成。
|
||||
|
||||
## 导出数据(两阶段轮询)
|
||||
|
||||
`export data` 为异步任务:首次调用可能只返回 `taskId`,需要继续轮询。
|
||||
@@ -38,8 +40,8 @@ dws aitable import upload --base-id <BASE_ID> \
|
||||
--file-name data.xlsx --file-size <字节数> --format json
|
||||
# → 返回 uploadUrl 和 importId
|
||||
|
||||
# 第 2 步:上传文件到 OSS(注意:Content-Type 必须设为空)
|
||||
curl -X PUT "<uploadUrl>" -H "Content-Type:" --data-binary @data.xlsx
|
||||
# 第 2 步:由受测 helper 上传到 OSS(Content-Type 为空)
|
||||
# 正常 Agent 执行使用 aitable_import_via_task.py,不手工拆出 curl fallback。
|
||||
|
||||
# 第 3 步:触发导入(新建表模式)
|
||||
dws aitable import data --import-id <importId> --format json
|
||||
@@ -55,7 +57,7 @@ dws aitable import data --import-id <importId> --table-id <TABLE_ID> --format js
|
||||
| 步骤 | 命令 | 说明 |
|
||||
|------|------|------|
|
||||
| 申请上传凭证 | `import upload --base-id <ID> --file-name <名称> --file-size <字节>` | `--file-size` 必须与实际文件大小一致 |
|
||||
| 上传文件 | HTTP PUT(curl 等) | **必须** 带 `-H "Content-Type:"` 将 Content-Type 设为空,否则 OSS 返回 403 |
|
||||
| 上传文件 | 受测 helper 的 HTTP PUT | Content-Type 必须为空,否则 OSS 返回 403;helper 需校验 OSS host,并将受信 HTTP signed URL 升级为 HTTPS |
|
||||
| 触发导入 | `import data --import-id <ID> [--table-id <TABLE_ID>]` | 同步等待,大多一次调用即返回结果;超时可用相同 importId 重试 |
|
||||
|
||||
### import data 参数
|
||||
@@ -102,7 +104,9 @@ dws aitable import data --import-id <importId> --table-id <TABLE_ID> --format js
|
||||
> **解决方案**:
|
||||
> 1. **首选**:创建目标表时,字段名与 Excel 表头列名**保持完全一致**
|
||||
> 2. **备选**:传 `--field-mapping '{"目标字段名":"Excel列名"}'` 手动指定映射
|
||||
> 3. **兜底**:如果 import data 多次失败,改用 `record create` 逐条写入
|
||||
> 3. 如果 import data 失败,先按错误和任务状态判断是否已写入;只有用户目标允许
|
||||
> “追加已有表”、文件内容可安全解析且新建表导入明确未生效时,才提出改用
|
||||
> `record create`。逐条写入不等价于文件级导入,不能静默替代并宣称导入成功。
|
||||
|
||||
### 适用场景
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 字段类型 config 规范(field create / table create / field update)
|
||||
|
||||
> 加载边界:仅在创建/更新字段或建表时构造字段 `config`。先确认字段类型及当前 Table;记录 cellValue 结构读取 [aitable-cell-value.md](aitable-cell-value.md),公式正文读取 [aitable-formula-guide.md](aitable-formula-guide.md),不要在本页寻找记录写入路由。
|
||||
|
||||
> 适用命令:`dws aitable field create`、`dws aitable table create --fields`、`dws aitable field update --config`
|
||||
>
|
||||
> 本文件是 DWS AI 表格字段 config 的 **source of truth**。创建/更新字段时,必须严格按此规范构造 JSON。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# field — 字段管理
|
||||
|
||||
> 加载边界:仅在字段目录不足、需要完整配置或执行字段 CRUD 时读取。`baseId/tableId` 先由根 Skill 解析;写前校验类型、config、关联表和只读性,写后用 field get 回读。删除字段先固化影响并确认。
|
||||
|
||||
## field get — 获取字段详情
|
||||
|
||||
```
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# filters & sort — 筛选排序语法参考
|
||||
|
||||
> 加载边界:仅在 record query 或 view 配置需要构造 filter/sort JSON 时读取。先用 field get 取得真实 fieldId 和类型;服务端可过滤时不先拉全量,本页语法不能替代分页完整性判断。
|
||||
|
||||
> 视图(view)配置的 filter/sort/group **整体写入**请优先用 `view update filter` / `view update sort` / `view update group` 子命令,详见 [aitable-view-config.md](./aitable-view-config.md)。本文件聚焦于 `record query --filters` 与 view config filter 的语法和差异。
|
||||
|
||||
## filters 结构规范
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# form — 表单管理
|
||||
|
||||
> 加载边界:仅在用户明确创建、配置或分享表单视图时读取。先绑定当前 Base/Table,再从创建/list 返回取得 viewId 和 fieldId;表单分享不等于记录分享,也不等于开放 Base 权限。
|
||||
|
||||
## 命令一览
|
||||
|
||||
| 命令 | 用途 |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# AI 表格公式字段指南
|
||||
|
||||
> 加载边界:仅在创建或修改 formula 字段时读取。公式字段是只读派生字段,不能通过 record create/update 写值;字段引用必须基于当前 Table 的精确名称/ID,跨表取值应先分流到 lookup/filterUp。
|
||||
|
||||
> 当用户要创建 formula 类型字段、编写表内计算公式、做派生指标时,必须先读本文档。
|
||||
|
||||
## 1. 何时使用 formula 字段
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 主键文档管理
|
||||
|
||||
> 加载边界:仅在记录的 primaryDoc 字段需要查询或创建关联文档时读取。先取得真实 baseId/tableId/recordId/fieldId;创建返回 nodeId 后,文档正文交给 Doc Skill,并持续使用该 nodeId,不再按标题搜索。
|
||||
|
||||
## 适用场景
|
||||
|
||||
当需要为 AI 表格中的记录创建或查询关联的主键文档时使用。主键文档是 primaryDoc 类型字段对应的钉钉在线文档,可通过 `dws doc` 进行内容读写。
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# record create — 新增记录
|
||||
|
||||
> 加载边界:仅在目标 Base/Table 已唯一确定且字段目录已取得后读取。第一笔写入前校验全部 cells;创建返回 `newRecordIds[]` 后按 ID 回读。不得因部分字段失败而静默丢列或改类型。
|
||||
|
||||
## 命令格式
|
||||
|
||||
```
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# record delete — 删除记录
|
||||
|
||||
> 加载边界:仅在用户明确要求删除记录时读取。先 query 并展示真实 recordId、关键字段和数量,确认前零删除调用;删除后重新按 ID 查询验证不存在,状态未知时禁止自动重试。
|
||||
|
||||
## 命令格式
|
||||
|
||||
```
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 行记录变更历史(record history-list)
|
||||
|
||||
> 加载边界:仅在审计某条真实 recordId 的历史变更时读取。历史分页与当前记录查询是不同契约;未遍历完成不得声称“全部历史”,历史事件也不能直接当作当前 cells 状态。
|
||||
|
||||
按 recordId 查询单条记录的全部变更历史,用于审计、回溯字段变更、定位操作人。
|
||||
|
||||
## 命令
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 行命名规则枚举键(recordNameKey)映射
|
||||
|
||||
> 加载边界:仅在配置 Table 的行称谓时读取。自然语言名称必须映射为已审阅枚举键;本页不用于记录查找、字段名解析或写入 cells。
|
||||
|
||||
`dws aitable table update --record-name-key <枚举键>` 用于设置数据表的"行命名规则"——卡片/详情页里"行"的展示别名。**取值是固定枚举,不是字段 ID**;传非法值服务端返回 `INVALID_RECORD_NAME_KEY`。
|
||||
|
||||
## 中文 → 枚举键(按 UI 下拉顺序)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# record query — 查询记录
|
||||
|
||||
> 加载边界:用于目标 Base/Table 已确定后的记录查询、筛选、排序和分页。按 ID、关键词和 filters 三种模式先分流;全量结论必须检查 `--all`、page-limit、hasMore/nextCursor 和 stop reason,默认一页只能代表当前页。
|
||||
|
||||
## 命令格式
|
||||
|
||||
```
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 行记录分享链接(record share-url)
|
||||
|
||||
> 加载边界:仅在用户需要某条真实记录的分享链接时读取。recordId 必须属于当前 Base/Table;可选 viewId 也必须同表。生成链接不等于修改记录权限或把链接发送给他人。
|
||||
|
||||
按 recordId 批量获取记录的分享链接,把某行单独发给同事查看。
|
||||
|
||||
## 命令
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# record update — 更新记录
|
||||
|
||||
> 加载边界:仅在 recordId 和待修改 fieldId 已确定后读取。只提交用户要求变更的 cells;写前读取字段类型/只读性,写后使用返回 recordId 回读。未返回 ID、字段未变化或状态未知都不能声称成功。
|
||||
|
||||
## 命令格式
|
||||
|
||||
```
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 行记录 Upsert(record upsert)
|
||||
|
||||
> 加载边界:仅在同一批次明确混合“带 recordId 更新”和“不带 recordId 创建”时读取。若目标匹配逻辑仍依赖名称或业务键,先 query 并消歧;upsert 不负责猜测 recordId,部分成功必须返回逐项 ledger。
|
||||
|
||||
按 `recordId` 是否存在,自动把入参拆分到 update 链路或 create 链路:批次混合"已存在改 + 新出现建"时用,省掉客户端按 ID 分批的逻辑。
|
||||
|
||||
## 命令
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 视图配置(view get/update <attr>)
|
||||
|
||||
> 加载边界:仅在创建视图或读取/修改视图配置时加载。先确认 viewType 与属性支持矩阵,并绑定当前 Base/Table/viewId;写后读取同一属性验证。复制、锁定、行高和高亮规则改读 [aitable-view-extras.md](aitable-view-extras.md)。
|
||||
|
||||
按属性局部读/写视图配置。每个属性独立子命令,typed flag 友好,agent 不必拼 JSON。
|
||||
向后兼容:`view update --config '{...}'` 一次多属性入口仍可用。
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 视图扩展操作(lock / frozen-cols / row-height / fill-color-rule / duplicate)
|
||||
|
||||
> 加载边界:仅在用户明确操作锁定、冻结列、行高、高亮规则或复制视图时读取。所有动作复用当前 Base/Table/viewId;viewType 不支持时本地停止,写后用对应 get 或新 viewId 回读。
|
||||
|
||||
本文档讲 5 项视图操作命令:
|
||||
|
||||
- 锁定 / 解锁视图:`view lock` / `view get lock`
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# workflow — 自动化工作流管理
|
||||
|
||||
> 加载边界:仅在创建、全量更新、启停或检查 AITable 自动化工作流时读取。create/update 使用完整 DSL,先校验并保留现状;disable 等需确认动作确认前零写入,返回 flowId 后用 get/list 验证 `valid/issues/status`。
|
||||
|
||||
创建 / 更新 / 启停 / 查看 / 列出 Base 下的自动化工作流("当 X 时自动 Y" 流程)。
|
||||
适用场景:用户要求创建自动化、修改流程、停掉流程、查询已有流程或恢复运行。
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# 易混淆操作与字段规则
|
||||
|
||||
> 定位:字段操作的轻量防错入口,仅在建表/建字段前快速核对主字段、只读字段和附件边界。完整 config 读取 `aitable/aitable-field-properties.md`,cellValue 读取 `aitable/aitable-cell-value.md`;不要与两份专题同时全量加载。
|
||||
|
||||
## 易混淆操作 (高风险场景必读)
|
||||
|
||||
| 用户说的 | 正确命令 | 不是这个 |
|
||||
@@ -36,6 +38,15 @@
|
||||
|
||||
## 字段创建时设置 config(重要)
|
||||
|
||||
字段 JSON 的命名和枚举是严格契约:
|
||||
|
||||
- 批量 `--fields` 每项使用 `fieldName`,不是 `name`。
|
||||
- 单选是 `singleSelect`,多选是 `multipleSelect`;不存在通用的 `select` 类型。
|
||||
- number/date/currency formatter 只使用当前 `table create --help` 或 leaf Schema 列出的枚举;不要从别的产品或旧样例猜 `INTEGER`。
|
||||
- 返回明确 hint 时,只修改 hint 指向的字段契约并保持目标不变。只要写入前校验明确
|
||||
未产生副作用且新的 Schema/Help 证据仍在收敛,就可继续修正;重复同一假设或不再
|
||||
获得新证据时停止并保留部分成功 ledger。
|
||||
|
||||
创建 singleSelect/multipleSelect 字段时,**必须设置选项 (options)**:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# aitable 局部意图消歧
|
||||
|
||||
> 定位:只处理 AITable 与 Sheet、Doc、Drive、Minutes 等 sibling 产品的边界;产品内 Base/Table/Field/Record 路由由根 Skill 负责。用户意图已经明确属于 AITable 时无需加载本页。
|
||||
|
||||
本文件从单 Skill `intent-guide.md` 拆分而来,仅保留与本产品相关的跨产品消歧规则。
|
||||
|
||||
| 用户说... | 真实意图 | 应该用 | 不要用 | 理由 |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# URL 格式与处理规范
|
||||
|
||||
> 加载边界:仅在用户给出类型不明的 alidocs URL 且意图不足以直接分流时读取。明确的 AITable 操作优先按意图执行;探测只负责确定资源类型,不应成为每次调用前置步骤,也不能把短链或裸 key 猜成 baseId。
|
||||
|
||||
## 路由第 0 步:意图直达(优先级高于 URL 探测)
|
||||
|
||||
用户已经明确表达某产品的内容意图时,直接进入对应产品场域,不要先做 URL 类型
|
||||
|
||||
@@ -17,6 +17,7 @@ from __future__ import annotations
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import ssl
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
@@ -26,7 +27,7 @@ from urllib.error import HTTPError, URLError
|
||||
from urllib.parse import urlparse
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
RESOURCE_ID_PATTERN = re.compile(r"^[A-Za-z0-9_-]{8,128}$")
|
||||
RESOURCE_ID_PATTERN = re.compile(r"^[A-Za-z0-9_-]{6,128}$")
|
||||
ALLOWED_FORMATS = {"excel", "attachment", "excel_and_attachment", "excel_with_inline_images"}
|
||||
|
||||
|
||||
@@ -64,7 +65,12 @@ def normalize_download_url(url: str) -> str:
|
||||
def download_file(url: str, output_path: Path) -> Tuple[bool, str]:
|
||||
req = Request(url, method="GET")
|
||||
try:
|
||||
with urlopen(req, timeout=180) as resp:
|
||||
try:
|
||||
import certifi
|
||||
context = ssl.create_default_context(cafile=certifi.where())
|
||||
except ImportError:
|
||||
context = ssl.create_default_context()
|
||||
with urlopen(req, timeout=180, context=context) as resp:
|
||||
redirected = urlparse(resp.geturl())
|
||||
if redirected.scheme != "https" or not redirected.hostname:
|
||||
return False, "download redirect is not HTTPS"
|
||||
|
||||
@@ -17,6 +17,7 @@ from __future__ import annotations
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import ssl
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
@@ -25,7 +26,7 @@ from urllib.error import HTTPError, URLError
|
||||
from urllib.parse import urlparse
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
RESOURCE_ID_PATTERN = re.compile(r"^[A-Za-z0-9_-]{8,128}$")
|
||||
RESOURCE_ID_PATTERN = re.compile(r"^[A-Za-z0-9_-]{6,128}$")
|
||||
ALLOWED_EXTENSIONS = {".csv", ".xlsx", ".xls"}
|
||||
|
||||
|
||||
@@ -33,6 +34,24 @@ def validate_resource_id(resource_id: str) -> bool:
|
||||
return bool(resource_id and RESOURCE_ID_PATTERN.match(resource_id.strip()))
|
||||
|
||||
|
||||
def normalize_oss_upload_url(upload_url: str) -> str:
|
||||
"""Accept the signed OSS URL returned by Runtime and upgrade it to HTTPS."""
|
||||
parsed = urlparse(upload_url)
|
||||
if parsed.scheme not in {"http", "https"} or not parsed.hostname:
|
||||
raise ValueError("uploadUrl must be a valid HTTP(S) URL")
|
||||
if not parsed.hostname.endswith(".oss.aliyuncs.com"):
|
||||
raise ValueError("uploadUrl host is not an Aliyun OSS endpoint")
|
||||
return parsed._replace(scheme="https").geturl()
|
||||
|
||||
|
||||
def tls_context() -> ssl.SSLContext:
|
||||
try:
|
||||
import certifi
|
||||
return ssl.create_default_context(cafile=certifi.where())
|
||||
except ImportError:
|
||||
return ssl.create_default_context()
|
||||
|
||||
|
||||
def run_dws(dws_bin: str, args: list[str], timeout_sec: int = 120) -> Tuple[int, str, str]:
|
||||
cmd = [dws_bin] + args
|
||||
try:
|
||||
@@ -53,15 +72,16 @@ def parse_json_output(raw: str) -> Optional[Dict[str, Any]]:
|
||||
|
||||
|
||||
def put_file(upload_url: str, file_path: Path) -> Tuple[bool, str]:
|
||||
parsed = urlparse(upload_url)
|
||||
if parsed.scheme != "https" or not parsed.hostname:
|
||||
return False, "uploadUrl must be a valid HTTPS URL"
|
||||
try:
|
||||
upload_url = normalize_oss_upload_url(upload_url)
|
||||
except ValueError as exc:
|
||||
return False, str(exc)
|
||||
payload = file_path.read_bytes()
|
||||
req = Request(upload_url, data=payload, method="PUT")
|
||||
# 关键:清空 Content-Type,避免 SignatureDoesNotMatch。
|
||||
req.add_header("Content-Type", "")
|
||||
try:
|
||||
with urlopen(req, timeout=180) as resp:
|
||||
with urlopen(req, timeout=180, context=tls_context()) as resp:
|
||||
if resp.status == 200:
|
||||
return True, ""
|
||||
return False, f"unexpected HTTP status: {resp.status}"
|
||||
|
||||
@@ -25,13 +25,14 @@ import subprocess
|
||||
import os
|
||||
import mimetypes
|
||||
import re
|
||||
import ssl
|
||||
from pathlib import Path
|
||||
from typing import Optional, Dict, Any
|
||||
from urllib.request import Request, urlopen
|
||||
from urllib.error import HTTPError, URLError
|
||||
from urllib.parse import urlparse
|
||||
|
||||
RESOURCE_ID_PATTERN = re.compile(r'^[A-Za-z0-9_-]{8,128}$')
|
||||
RESOURCE_ID_PATTERN = re.compile(r'^[A-Za-z0-9_-]{6,128}$')
|
||||
MAX_FILE_SIZE = 100 * 1024 * 1024 # 100MB
|
||||
|
||||
|
||||
@@ -77,15 +78,24 @@ def run_dws(args: list, dws_bin: str = 'dws') -> Optional[Dict[str, Any]]:
|
||||
def upload_to_oss(upload_url: str, file_path: Path, mime_type: str) -> bool:
|
||||
"""通过 HTTP PUT 上传文件到 OSS。"""
|
||||
parsed = urlparse(upload_url)
|
||||
if parsed.scheme != 'https' or not parsed.hostname:
|
||||
print('错误:uploadUrl 必须是有效的 HTTPS URL', file=sys.stderr)
|
||||
if parsed.scheme not in {'http', 'https'} or not parsed.hostname:
|
||||
print('错误:uploadUrl 必须是有效的 HTTP(S) URL', file=sys.stderr)
|
||||
return False
|
||||
if not parsed.hostname.endswith('.oss.aliyuncs.com'):
|
||||
print('错误:uploadUrl 不是阿里云 OSS 地址', file=sys.stderr)
|
||||
return False
|
||||
upload_url = parsed._replace(scheme='https').geturl()
|
||||
file_data = file_path.read_bytes()
|
||||
req = Request(upload_url, data=file_data, method='PUT')
|
||||
req.add_header('Content-Type', mime_type)
|
||||
|
||||
try:
|
||||
with urlopen(req, timeout=120) as resp:
|
||||
try:
|
||||
import certifi
|
||||
context = ssl.create_default_context(cafile=certifi.where())
|
||||
except ImportError:
|
||||
context = ssl.create_default_context()
|
||||
with urlopen(req, timeout=120, context=context) as resp:
|
||||
if resp.status == 200:
|
||||
return True
|
||||
print(f"错误:OSS 上传失败,HTTP {resp.status}", file=sys.stderr)
|
||||
|
||||
@@ -39,6 +39,16 @@ skill 作为入口进行二级路由。
|
||||
- 创建、更新、发送等写操作后,按产品 skill 的要求回读或查询状态,不得仅凭退出码
|
||||
宣称成功。
|
||||
|
||||
## 先定义结果,再选择命令
|
||||
|
||||
执行前把请求压缩成一个结果契约:目标状态、资源类型与父容器、用户明确要求的阶段、
|
||||
副作用边界,以及每个关键结论需要的验证证据。命令只是达到结果的候选路径,不得用
|
||||
相似终态替代用户点名的操作:新建相似对象不等于复制成功,最近访问列表不等于搜索
|
||||
命中,发送请求返回成功也不等于对方已收到。
|
||||
|
||||
执行过程中维护轻量状态账本:已确认成功的步骤和 ID、未完成缺口、写入状态是否确定、
|
||||
下一步安全探测及最终验证。恢复时从缺口继续,不重放已经成功的写操作。
|
||||
|
||||
## 渐进加载
|
||||
|
||||
只读取当前任务需要的文件,不要一次性加载全部 shared references:
|
||||
@@ -82,8 +92,12 @@ skill 作为入口进行二级路由。
|
||||
|
||||
## 错误最短路径
|
||||
|
||||
1. `unknown command` / `unknown flag`:运行对应层级 `--help`,修正后最多重试一次。
|
||||
1. `unknown command` / `unknown flag`:读取错误中的 hint、leaf Schema 或对应层级
|
||||
`--help`,只在获得新证据时修正;不要重复尝试同一假设。
|
||||
2. 认证或权限错误:读取 `global-reference.md` 与 `error-codes.md` 对应章节。
|
||||
3. 其他错误:加 `--verbose` 重试一次;仍失败则停止并报告真实错误,不连续尝试替代
|
||||
命令。
|
||||
4. 明确不支持的能力:说明边界,不通过其他接口绕过。
|
||||
3. 只读调用或写入前参数校验失败:保持目标不变,依据新证据做有界恢复。
|
||||
4. 写入已返回 ID:保留成功状态,只补后续缺口;写入超时、返回不明或可能已生效时,
|
||||
先回读目标容器,禁止盲目重放。删除及高影响操作状态不明时停止并报告。
|
||||
5. 当后续尝试不再产生新证据、开始重复同一错误、改变目标或副作用变得不确定时停止;
|
||||
不用不同产品或相似对象掩盖原操作失败。
|
||||
6. 明确不支持的能力:说明边界,不通过其他接口绕过。
|
||||
|
||||
Reference in New Issue
Block a user