语义 SDK
把企业数据变成「有意思的对象」:工单、线体、订单、客户……每个对象类型有属性(显示名、单位、同义词)、有链接(工单 → 线体)、有 Action(「登记异常」「指定负责人」这类受控的写操作)。应用和智能体读的是语义层,改的也是语义层——ERP / MES 这些数据源永远只读,永远不会被改。
参照的是 Palantir 的 Ontology:
ERP / MES / OA ──(连接 SDK:发布端,只读)──▶ 数据层(AIDC 中枢,数据 SDK)──(语义 SDK:类型 / 链接 / Action)──▶ 应用 · 智能体
import { semantic } from "/developer/sdk/v1/aidc.js";
三个概念
| 概念 | 是什么 | 例子(吉兴天津 8100) |
|---|---|---|
| 对象类型 | 一类业务对象:主键 + 属性。属性要么来自数据源(同步进来,只读),要么只在语义层维护(writeback:备注、负责人、异常状态…) |
production.order_line(工单线体进度):工单、线体、计划、累计合格 ← SAP;异常状态、异常说明、登记人 ← 语义层 |
| 链接 | 对象之间的关系。最常见的是一个属性引用另一个类型的主键(references) |
工单线体 → 线体(line_code) |
| Action | 受控的写操作:参数(类型 / 必填 / 长度 / 枚举)+ 改哪些属性 + 谁能做 + 日志里的一句话 | production.flag_issue 登记异常:参数「异常说明」「级别」;写 issue、status、owner = 执行人 |
改数据只有两条路:成员用 Action(校验、权限、留痕);开发者用数据 SDK 直接改(管理用)。两条路的改动都落在语义层(对象的 edits),数据源下一次同步只更新它自己那一层,不会冲掉人改过的值。
读:说明书与对象
const space = await semantic.describe();
// space.types:看得见的对象类型(属性、单位、同义词、链接、对象数)
// space.actions:Action 与「我能不能执行」(allowed)
// space.markdown:给大模型读的整份说明书——智能体先读它再干活
// space.release:当前语义版本(v3…)
const hit = semantic.search(space, "合格数"); // 按业务说法定位:[{ kind: "property", type: "production.order_line", name: "ok" }]
const issues = await semantic.objects("production.order_line")
.where({ status: { in: ["关注", "异常"] }, day: "2026-09-26" })
.sort("-gap")
.list(); // { objects, total, seq }
const order = await semantic.objects("production.order_line").get("100001955718|TJ01-05");
const line = await semantic.objects("production.order_line").linked(order.pk, "production.order_line.line_code");
const byLine = await semantic.objects("production.order_line").aggregate({ groupBy: ["line_code"], metrics: { ok: ["ok", "sum"] } });
每个对象:props(当前值 = 数据源的值被语义层改动覆盖后)、rev(每改一次 +1)、edited(语义层改过的属性)、overridden(被改动盖住、数据源现在是另一个值的属性 → 数据源的值)、sourceGone(数据源里已经没有这一行)。
条件写法:{ 属性: 值 } 相等;{ 属性: { gt, gte, lt, lte, ne, in, nin, contains, startsWith, null } };多个属性之间是「且」;$or: [{…}, {…}] 任意一组成立。
实时
const view = semantic.objects("production.order_line").where({ day: today }).sort("-ok").live({
onUpdate(objects, change) { render(objects); }, // 先全量,之后数据一变就回调(同步、Action、别人的修改都算)
onStatus({ connection }) { badge(connection); },
});
// view.close()
底层是数据 SDK 的 watch(SSE,断线按序号续传,不丢不重)。
写:执行 Action
const r = await semantic.action("production.flag_issue").apply(
{ issue: "缺料:顶蓬面料未到", severity: "异常" },
{ object: "100001955718|TJ01-05", ifRev: order.rev },
);
// r.object:改后的对象;r.event.summary:「TJ01-05 登记异常:缺料…」(进日志 SDK 的操作记录)
- 参数按定义校验(不合法 422,信息里写明哪一项);
semantic.checkParams(actionInfo, params)可以在表单提交前本地预检。 - 谁能执行:应用清单
semantic.actions登记了它,且访客角色在 Action 的roles里(缺省 developer / member / editor)。只读访客(公开链接、只读分享)与匿名访客永远不能写。 ifRev:对象当前 rev 不等于它就 409rev_mismatch(别人刚改过,刷新再改)。dryRun: true:只校验、返回计划,不落库。
定义与发布(开发者:CLI / 智能体)
定义就是 JSON。四种词条:enum、object、link、action。
{
"kind": "object",
"apiName": "production.order_line",
"title": "工单线体进度",
"description": "每个工单在每条线体上的当日进度(SAP ZPP015)",
"schema": {
"titleColumn": "line_code",
"synonyms": ["工单行", "生产任务"],
"columns": [
{ "name": "order_no", "type": "text", "primaryKey": true, "title": "工单" },
{ "name": "line_code", "type": "text", "primaryKey": true, "title": "线体", "references": { "entity": "production.line", "column": "line_code" } },
{ "name": "ok", "type": "integer", "title": "累计合格", "unit": "件", "synonyms": ["合格数", "良品数"] },
{ "name": "status", "type": "text", "enumRef": "production.issue_status", "writeback": true, "title": "异常状态" },
{ "name": "issue", "type": "text", "writeback": true, "title": "异常说明" }
]
}
}
{
"kind": "action",
"apiName": "production.flag_issue",
"title": "登记异常",
"schema": {
"objectType": "production.order_line",
"operation": "modify",
"parameters": [
{ "name": "issue", "type": "text", "title": "异常说明", "required": true, "maxLength": 200 },
{ "name": "severity", "type": "text", "title": "级别", "enumRef": "production.issue_status" }
],
"edits": { "issue": "$issue", "status": "$severity", "owner": "$userName", "flagged_at": "$now" },
"roles": ["developer", "member", "editor"],
"summary": "{line_code} 登记异常:{issue}"
}
}
取值表达式:$参数名、$now(当前时间)、$user(执行人账号)、$userName(执行人名字)、$uuid(新主键,create 用);其他是字面量(以 $ 开头的字面量写成 $$…)。operation:modify 改一个对象、create 新建(edits 要给出主键)、delete 删除(语义层墓碑)。
aidc semantic define ontology/ # 目录里的 *.json 整批提交:一起校验、按 枚举 → 对象 → 链接 → Action 落(有则改)
aidc semantic define ontology/ --dry-run # 只检查:整批引用是否闭合(批内互相引用算数)、相对上一个语义版本有哪些破坏性变更
aidc semantic publish --notes "加了异常登记" # 发一个语义版本 vN(只增;定义没变不占号)
aidc semantic describe --markdown # 给智能体读的说明书
aidc semantic act production.flag_issue --object "100001955718|TJ01-05" --param issue=缺料 --param severity=异常
- 引用闭合:Action 改的属性、引用的参数、外键目标、枚举都必须存在,否则定义直接 422。一个目录是一批(
semantic.defineAll(定义数组)/POST …/semantic/{命名空间}/types):在「整批改完之后」的全体定义上校验,批内互相引用算数,不闭合一条都不写。 - 破坏性变更(删类型 / 删属性 / 改类型 / 改主键 / Action 删参数或新增必填参数…)会在定义时返回、在发布时记档(
changeKind: breaking)。发布前先确认调用它的应用都改好了。 - 语义版本就是这家公司 Ontology 的版本号,与应用版本号一起出现在日志 SDK 里;自提升 SDK 采纳的语义改进会自动发新版本。
权限一览
| 谁 | 读 | 执行 Action | 直接写(数据 SDK) | 定义 / 发布 |
|---|---|---|---|---|
| 开发者 Key(CLI / 智能体) | 本公司全部 | 全部 | 全部 | ✓ |
| 应用里的 developer 访客 | 清单 semantic.types 登记的(含部门级) |
清单登记 + roles 允许 | 清单 semantic.write 登记的 |
— |
| 应用里的 member / editor | 清单登记、且对公司全员可见的 | 清单登记 + roles 允许 | — | — |
| viewer(只读分享 / 公开链接)、匿名 | 同上 | — | — | — |
应用清单里这样登记:
{
"sdk": ["semantic", "data", "auth", "log"],
"semantic": {
"types": ["production.order_line", "production.line"],
"actions": ["production.flag_issue", "production.resolve_issue"],
"write": []
}
}
"*" 表示看得见的全部(数据浏览器这类通用应用)。
API
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/v1/developer/semantic/{命名空间} |
说明书(按凭证裁剪) |
| GET / POST | /api/v1/developer/semantic/{命名空间}/types |
全部定义(开发者)/ 一次定义一批({definitions: […]},整批校验) |
| GET / PUT / DELETE | /api/v1/developer/semantic/{命名空间}/types/{apiName} |
读 / 定义 / 归档 |
| POST | /api/v1/developer/semantic/{命名空间}/actions/{apiName} |
执行 Action |
| GET / POST | /api/v1/developer/semantic/{命名空间}/releases |
语义版本列表 / 发布 |
对象的查询、聚合、订阅在数据 SDK(/api/v1/developer/data/…)。命名空间 = 公司 cellId(cell-…);应用里自动取应用所在公司。
本页由 developer/docs/semantic.md 生成 · Markdown 原文 · llms.txt