@tier0/sdk-v2 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -15
- package/dist/cjs/capabilities.js +2 -2
- package/dist/cjs/capabilities.js.map +1 -1
- package/dist/cjs/client.d.ts +283 -375
- package/dist/cjs/cloud-transport.js +7 -3
- package/dist/cjs/cloud-transport.js.map +1 -1
- package/dist/cjs/controls.d.ts +19 -7
- package/dist/cjs/controls.js +37 -34
- package/dist/cjs/controls.js.map +1 -1
- package/dist/cjs/data/bootstrap.js +3 -2
- package/dist/cjs/data/bootstrap.js.map +1 -1
- package/dist/cjs/data/collection.d.ts +22 -0
- package/dist/cjs/data/collection.js +10 -9
- package/dist/cjs/data/collection.js.map +1 -1
- package/dist/cjs/data/schema.js +5 -1
- package/dist/cjs/data/schema.js.map +1 -1
- package/dist/cjs/files.d.ts +9 -9
- package/dist/cjs/mq/broker.d.ts +1 -1
- package/dist/cjs/mq/broker.js +1 -1
- package/dist/cjs/mq/broker.js.map +1 -1
- package/dist/cjs/mq/types.d.ts +1 -1
- package/dist/cjs/mq/types.js.map +1 -1
- package/dist/cjs/openapi/api.generated.d.ts +417 -541
- package/dist/cjs/openapi/api.generated.js +292 -377
- package/dist/cjs/openapi/api.generated.js.map +1 -1
- package/dist/cjs/openapi/client.js +1 -1
- package/dist/cjs/openapi/client.js.map +1 -1
- package/dist/cjs/openapi/codecs.generated.d.ts +394 -652
- package/dist/cjs/openapi/codecs.generated.js +2 -2
- package/dist/cjs/openapi/codecs.generated.js.map +1 -1
- package/dist/cjs/openapi/types.generated.d.ts +696 -905
- package/dist/cjs/openapi/types.generated.js.map +1 -1
- package/dist/cjs/source.d.ts +1 -7
- package/dist/cjs/source.js +2 -3
- package/dist/cjs/source.js.map +1 -1
- package/dist/cjs/stream.d.ts +0 -8
- package/dist/cjs/stream.js +3 -5
- package/dist/cjs/stream.js.map +1 -1
- package/dist/cjs/uns-v2/codec.js +1 -1
- package/dist/cjs/uns-v2/codec.js.map +1 -1
- package/dist/cjs/uns-v2/generated.d.ts +4590 -13315
- package/dist/cjs/uns-v2/generated.js +21 -42
- package/dist/cjs/uns-v2/generated.js.map +1 -1
- package/dist/esm/capabilities.js +2 -2
- package/dist/esm/capabilities.js.map +1 -1
- package/dist/esm/client.d.ts +283 -375
- package/dist/esm/cloud-transport.js +7 -3
- package/dist/esm/cloud-transport.js.map +1 -1
- package/dist/esm/controls.d.ts +19 -7
- package/dist/esm/controls.js +38 -35
- package/dist/esm/controls.js.map +1 -1
- package/dist/esm/data/bootstrap.js +4 -3
- package/dist/esm/data/bootstrap.js.map +1 -1
- package/dist/esm/data/collection.d.ts +22 -0
- package/dist/esm/data/collection.js +10 -10
- package/dist/esm/data/collection.js.map +1 -1
- package/dist/esm/data/schema.js +5 -1
- package/dist/esm/data/schema.js.map +1 -1
- package/dist/esm/files.d.ts +9 -9
- package/dist/esm/mq/broker.d.ts +1 -1
- package/dist/esm/mq/broker.js +1 -1
- package/dist/esm/mq/broker.js.map +1 -1
- package/dist/esm/mq/types.d.ts +1 -1
- package/dist/esm/mq/types.js.map +1 -1
- package/dist/esm/openapi/api.generated.d.ts +417 -541
- package/dist/esm/openapi/api.generated.js +292 -377
- package/dist/esm/openapi/api.generated.js.map +1 -1
- package/dist/esm/openapi/client.js +1 -1
- package/dist/esm/openapi/client.js.map +1 -1
- package/dist/esm/openapi/codecs.generated.d.ts +394 -652
- package/dist/esm/openapi/codecs.generated.js +1 -1
- package/dist/esm/openapi/codecs.generated.js.map +1 -1
- package/dist/esm/openapi/types.generated.d.ts +696 -905
- package/dist/esm/openapi/types.generated.js.map +1 -1
- package/dist/esm/source.d.ts +1 -7
- package/dist/esm/source.js +2 -3
- package/dist/esm/source.js.map +1 -1
- package/dist/esm/stream.d.ts +0 -8
- package/dist/esm/stream.js +3 -5
- package/dist/esm/stream.js.map +1 -1
- package/dist/esm/uns-v2/codec.js +2 -2
- package/dist/esm/uns-v2/codec.js.map +1 -1
- package/dist/esm/uns-v2/generated.d.ts +4590 -13315
- package/dist/esm/uns-v2/generated.js +21 -42
- package/dist/esm/uns-v2/generated.js.map +1 -1
- package/docs/acceptance-2026-10-22.md +3 -1
- package/package.json +2 -2
- package/skills/tier0-sdk-v2/SKILL.md +5 -3
- package/skills/tier0-sdk-v2/tier0-sdk-v2-agent/SKILL.md +4 -4
- package/skills/tier0-sdk-v2/tier0-sdk-v2-controls/SKILL.md +5 -3
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/SKILL.md +2 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/consistency.md +3 -3
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/modeling.md +6 -4
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/read-write.md +13 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-data/references/schema-evolution.md +2 -0
- package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/delete.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-files/references/url.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-members/references/app-members.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-members/references/platform-members.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/references/get.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-notifications/references/send.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/SKILL.md +2 -2
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/changes.md +4 -4
- package/skills/tier0-sdk-v2/tier0-sdk-v2-source/references/read.md +2 -2
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/SKILL.md +4 -4
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/create.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/deploy.md +11 -2
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/lifecycle.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/read.md +25 -5
- package/skills/tier0-sdk-v2/tier0-sdk-v2-stream/references/update.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-system/references/info.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-system/references/whoami.md +1 -1
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/SKILL.md +5 -3
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/create.md +10 -6
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/delete.md +5 -5
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/namespace.md +4 -4
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/read.md +8 -7
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/restore.md +2 -2
- package/skills/tier0-sdk-v2/tier0-sdk-v2-uns/references/update.md +4 -4
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
日期:2026-10-22。包:`@tier0/sdk-v2@0.1.0`。
|
|
4
4
|
|
|
5
|
+
> 历史记录:以下结果仅适用于当时版本。2026-10-27 已退役 Stream 就绪探针及逐 Key Control scopes/codes;当前 SDK 不再导出该探针。不得将下文历史 403 当作 Stream 故障或按旧授权模型要求扩权。后续验收见 [Tier0-doc 新版架构专题](https://github.com/FREEZONEX/Tier0-doc/blob/main/docs/新版架构/03-Cloud新版改造/112-Stream控制就绪探针退役.md)。
|
|
6
|
+
|
|
5
7
|
验收对应 SDK 提交 `5d30d5154354bac94bbbe88402a8303d6c43526d` 的安装包。报告提交时远端已合入其他功能(至 `78f5168`);下列测试数量和业务结论不覆盖那些新增功能。
|
|
6
8
|
|
|
7
9
|
结论:安装包和本地自动化通过;多组真实业务操作通过,但不能宣称“所有功能已可用”。追加验收已完成真实站内通知发送、Stream 发布、当前 release 的真实执行、停用及归档。Source 创建预检、Control 权限、Stream 能力查询、Agent 真实用户身份及文件大分片传输仍有阻断或限制。
|
|
@@ -62,7 +64,7 @@ Source 的 503 是后端返回的统一生命周期错误。对固定版本代
|
|
|
62
64
|
| --- | --- | --- |
|
|
63
65
|
| Source 创建 503 | 当前镜像仍复现;requestId `8b0197c1-3479-4277-ba70-89e131512437`。错误映射将多种内部错误合并为 `cloud lifecycle service unavailable`,现有日志未能将根因关联到此请求 | 服务端在 Source 管理身份刷新、租户解析、凭据绑定预检、事务写入边界增加不含凭据的阶段码和 requestId 关联,再针对确切失败修复。暂不能声称重启、加权限或迁库能解决。未修改部署或数据库 |
|
|
64
66
|
| 大文件分片 PUT 超时 | 追加对照中 1 KiB 的 PUT=200、complete=200;5 MiB 首片仍超过 20 秒。原测试 30/60 秒同样超时;额外把 Blob 转为 Uint8Array 发送,60 秒仍超时。小文件完成后的下载 URL 查询另遇连接错误,文件已删除,大分片会话已 abort | 签名对小分片有效,替换 Blob 发送体未解决。仍需上传路径/OSS 服务端证据定位;仅增大 timeout 不能算修复,须以两片上传、合并及下载 hash 比对为验收 |
|
|
65
|
-
| Control 与 runtime capabilities 403 |
|
|
67
|
+
| 当时的 Control 与 runtime capabilities 403 | 当时部署代码将能力查询放在旧 Control 权限分支 | 历史原因,不适用当前版本。探针现已退役,实际调用归入统一权限,不再要求逐 Key Control scopes/codes |
|
|
66
68
|
| Agent jobs 身份限制 | 当前是 service Key;任务管理明确要求真实用户 | 使用有任务权限的真实成员 personal Key 或该功能支持的会话身份。扩大 service Key scope 不能把它变成真实用户 |
|
|
67
69
|
|
|
68
70
|
ACK 日志另有 `UNS control metadata requires explicit migration before startup`,但尚未证实属于本 Workspace 或此次 Source 请求,不能把该日志当成本次 503 的根因。部署、重启、授权变更和数据库迁移均未执行。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tier0/sdk-v2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Tier0 Cloud new-architecture SDK for TypeScript and JavaScript",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
"scripts": {
|
|
157
157
|
"sync:contracts": "node scripts/sync-contracts.mjs",
|
|
158
158
|
"generate": "node scripts/generate-openapi.mjs && node scripts/generate-uns-v2.mjs",
|
|
159
|
-
"check:contracts": "node scripts/check-contracts.mjs && node scripts/generate-openapi.mjs --check && node scripts/generate-uns-v2.mjs --check",
|
|
159
|
+
"check:contracts": "node scripts/check-contracts.mjs && node --test scripts/retired-stream-probe.test.mjs && node scripts/generate-openapi.mjs --check && node scripts/generate-uns-v2.mjs --check",
|
|
160
160
|
"check:skills": "node scripts/check-skills.mjs && node scripts/check-skill-examples.mjs",
|
|
161
161
|
"typecheck": "tsc --noEmit && tsc -p tsconfig.tests.json",
|
|
162
162
|
"build": "node scripts/build.mjs",
|
|
@@ -5,7 +5,7 @@ description: 使用 @tier0/sdk-v2 开发或迁移 Tier0 云端 TypeScript/JavaSc
|
|
|
5
5
|
|
|
6
6
|
# Tier0 SDK v2 应用集成
|
|
7
7
|
|
|
8
|
-
面向应用代码编写;运行时为 Node.js 20.19+。独立包 `@tier0/sdk-v2`
|
|
8
|
+
面向应用代码编写;运行时为 Node.js 20.19+。独立包 `@tier0/sdk-v2` 的版本以 package.json 为准(UNS v2 契约 5.0.0),是否可从 npm 安装须检查实际发布状态;未发布时安装仓库构建的 tarball。新参数还需要目标环境部署对应后端,不能只凭 SDK 方法存在判断可用。不要改回旧包或旧 Flow API。
|
|
9
9
|
|
|
10
10
|
## 选择业务入口
|
|
11
11
|
|
|
@@ -46,7 +46,7 @@ export async function inspectConnection() {
|
|
|
46
46
|
| 入口 | 成功值 | 失败类型 |
|
|
47
47
|
| --- | --- | --- |
|
|
48
48
|
| Source、Stream、UNS | 完整 `{ code, msg, requestId, data }` | `UnsV2Error` / `UnsV2OutcomeUnknownError` |
|
|
49
|
-
|
|
|
49
|
+
| 平台 v2,如 system、members、agent、mqttAuth | 解包后的 `data` | `ApiError` / `TransportError` |
|
|
50
50
|
| notifications | 直接对象,如 `messageId`、`status` | `ApiError` |
|
|
51
51
|
| controls、capabilities | 专属响应对象 | `ControlError` / `CapabilityError` |
|
|
52
52
|
|
|
@@ -56,7 +56,7 @@ export async function inspectConnection() {
|
|
|
56
56
|
|
|
57
57
|
## 从首版入口迁移
|
|
58
58
|
|
|
59
|
-
- `client.uns.sourceList(body)` → `client.source.list(body)`。
|
|
59
|
+
- `client.uns.sourceList(body)` → `client.source.documents.list(body)`。
|
|
60
60
|
- `client.uns.sourceDocumentGet(body)` → `client.source.documents.get(body)`。
|
|
61
61
|
- `client.uns.streamProgramDeploy(body)` → `client.stream.programs.deploy(body)`。
|
|
62
62
|
- `client.uns.streamDocumentValidate(body)` → `client.stream.documents.validate(body)`。
|
|
@@ -64,3 +64,5 @@ export async function inspectConnection() {
|
|
|
64
64
|
- 低层 `createUnsV2Client` 保留完整生成契约,供契约工具使用;业务主入口不再把 Source/Stream/Control 混入 `client.uns`。
|
|
65
65
|
|
|
66
66
|
React/Vue 示例与验签见 [集成参考](references/integration.md)。完成接入时验证目标入口、真实身份、响应解包和错误分支;SDK 本地测试通过不代表环境联调完成。
|
|
67
|
+
|
|
68
|
+
公开 HTTP 入口统一为 `/openapi/v2`。旧的重复操作已退役,不生成兼容调用或回退。Source 配置用 documents.*,Stream 草稿用 documents.*、发布用 programs.deploy;App 数据层仍提供 insertMany/findOneAnd*/distinct 等便捷方法。历史旧写结果未知时先核对业务状态,不能转换路由后盲目重放。
|
|
@@ -5,7 +5,7 @@ description: 使用 @tier0/sdk-v2 的 client.agent 查询和管理 Agent 作业
|
|
|
5
5
|
|
|
6
6
|
# Agent 作业与结果
|
|
7
7
|
|
|
8
|
-
Agent 是平台应用能力,区别于 Stream 数据处理程序。使用服务端 client.agent
|
|
8
|
+
Agent 是平台应用能力,区别于 Stream 数据处理程序。使用服务端 client.agent;本领域平台 v2 响应已解包,直接读取 list/job/run/result 等字段。
|
|
9
9
|
|
|
10
10
|
## 入口选择
|
|
11
11
|
|
|
@@ -18,10 +18,8 @@ Agent 是平台应用能力,区别于 Stream 数据处理程序。使用服务
|
|
|
18
18
|
| cards | list/get/update/delete,操作画布卡片 |
|
|
19
19
|
| canvases | list,查找画布 |
|
|
20
20
|
| library | list/get/create/update/delete,复用卡片定义 |
|
|
21
|
-
| nodes | searchSemantic/indexSync,语义搜索与索引同步 |
|
|
22
|
-
| relations | list/teach,读取和写入数据关系 |
|
|
23
21
|
|
|
24
|
-
dispatch、trigger
|
|
22
|
+
dispatch、trigger 都有副作用,不能在普通查询流程中悄悄执行。
|
|
25
23
|
|
|
26
24
|
## 查询作业与运行
|
|
27
25
|
|
|
@@ -71,3 +69,5 @@ result.create 的 operationId 由调用方持有;保存超时后可用 `result
|
|
|
71
69
|
cards.update 要带读取时的完整 expectedCardSpec;library.update 要带完整 expectedItem 快照。409 表示内容已变化,应重新读取并合并用户意图,不能自动覆盖。具体示例见 [结果与卡片编辑](references/results.md)。
|
|
72
70
|
|
|
73
71
|
结果附件/图片使用 [文件 Skill](../tier0-sdk-v2-files/SKILL.md) 的持久化 filePath,不保存签名 URL 作为长期资源。失败保留 ApiError.status/code/errorCode;写入 outcomeUnknown 时先查询对应资源,不自动重发。
|
|
72
|
+
|
|
73
|
+
旧 Namespace 节点的语义索引和 path 关系接口未纳入 v2,不再提供 nodes/relations 方法。
|
|
@@ -5,7 +5,9 @@ description: 使用 @tier0/sdk-v2 发现、描述和调用 Tier0 Control 业务
|
|
|
5
5
|
|
|
6
6
|
# Control 契约调用
|
|
7
7
|
|
|
8
|
-
Control 是已发布的业务调用入口;它可由 Stream 提供,但调用方不选择内部 streamId、entryId 或部署版本。使用服务端 client.controls
|
|
8
|
+
Control 是已发布的业务调用入口;它可由 Stream 提供,但调用方不选择内部 streamId、entryId 或部署版本。使用服务端 client.controls,实际调用 `/openapi/v2/uns/controls/discover|describe|invoke`,不重建旧 Flow 调用。
|
|
9
|
+
|
|
10
|
+
调用按服务端现有统一权限及 App 业务策略校验;不配置逐 Key 的 Control scopes/codes。旧 Stream 就绪探针已经退役,不能因为它的历史 403 判断当前入口不可用或要求扩权。
|
|
9
11
|
|
|
10
12
|
## 发现和读取契约
|
|
11
13
|
|
|
@@ -52,12 +54,12 @@ export async function invokePreparedControl(code: string, input: ControlJSON, in
|
|
|
52
54
|
}
|
|
53
55
|
```
|
|
54
56
|
|
|
55
|
-
幂等键非空、不能有首尾空白,最多 128 UTF-8
|
|
57
|
+
幂等键非空、不能有首尾空白,最多 128 UTF-8 字节。输入使用 JSON;需要保留精确数字时可用 UnsV2RawNumber,不传 Date、函数、循环对象、bigint、NaN/Infinity。业务 input 内名为 timeoutMs/streamId 的字段仍只是业务输入;不能借它覆盖服务端绑定、版本或执行超时。
|
|
56
58
|
|
|
57
59
|
## 返回与失败
|
|
58
60
|
|
|
59
61
|
成功值为直接对象:code(Control 标识)、contractVersion、result、runID、status、replayed。这里的 code 不是 HTTP 业务状态码;replayed 只有服务端明确报告重放时才为 true。
|
|
60
62
|
|
|
61
|
-
`ControlError` 含 status/errorCode/runID 等信息,SDK 不自动重试。`ControlResultUnknownError` 表示执行可能已经发生,包括调用响应无法证明最终结果的情况;按业务或平台运行记录对账。本 SDK 未提供通用 `controls.getRun`,不要虚构方法。若业务明确允许重放,保留原 key 和原输入,不能换新 key 重做。
|
|
63
|
+
`ControlError` 含 status/errorCode/runID 与 requestId/execution/retry 等信息,SDK 不自动重试。`ControlResultUnknownError` 表示执行可能已经发生,包括调用响应无法证明最终结果的情况;按业务或平台运行记录对账。本 SDK 未提供通用 `controls.getRun`,不要虚构方法。若业务明确允许重放,保留原 key 和原输入,不能换新 key 重做。
|
|
62
64
|
|
|
63
65
|
`client.capabilities.discover()` 的 control.invoke.v1 就绪只是入口条件,不等于有权调用每一个 Control。执行源发布和内部绑定管理请使用 [Stream Skill](../tier0-sdk-v2-stream/SKILL.md)。
|
|
@@ -32,7 +32,7 @@ export const workOrders = defineCollection({
|
|
|
32
32
|
schema: z.object({
|
|
33
33
|
code: z.string(),
|
|
34
34
|
status: z.enum(['DRAFT', 'RELEASED', 'DONE', 'CANCELLED']),
|
|
35
|
-
targetQty: z.number().int().min(1),
|
|
35
|
+
targetQty: z.number().int().min(1).meta({ format: 'int32' }),
|
|
36
36
|
dueAt: z.string(),
|
|
37
37
|
}),
|
|
38
38
|
indexes: [{ path: 'code', unique: true }, { path: 'status' }],
|
|
@@ -51,6 +51,7 @@ export async function releasedOrders(): Promise<WorkOrder[]> {
|
|
|
51
51
|
|
|
52
52
|
1. 声明文件只从 `@tier0/sdk-v2/data/define` 导入,客户端代码可以安全引用它;全部集合在一个 `collections` 列表里声明(每个 App 最多 64 个),只建一个进程级 client;不要手动 ensure、不要在 import 时访问数据、不要自建“已初始化”标记。
|
|
53
53
|
2. 集合 Schema 是存储 Schema:只能用可存储的 Zod 子集,输入规则(格式、长度、默认值、transform)放在 API 入参 Schema。
|
|
54
|
+
新建数值字段明确选择 int(integer + int32)、float 或 double(number + 对应 format);普通小数选 double,嵌套对象和数组元素同样处理。SDK 会为未标注的 integer/number 补齐 int32/double;直接 MCP 请求必须自行提供 format。
|
|
54
55
|
3. 写入前按声明严格校验,未知字段、类型错误、未声明的更新路径直接抛 `ZodError`;读取不做严格解析,旧版本写入的字段、新枚举值或缺字段都可能出现。
|
|
55
56
|
4. `insertMany` / `bulkWrite` / `transact` 每次最多 200 项且原子;`updateMany` / `deleteMany` 逐条提交、非原子。
|
|
56
57
|
5. 按 `DataError.code` 与 `reason`(`data.reason`)分支,不匹配 message 文本;`status` 是 App 应回给自己调用方的 HTTP 状态。
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
import { z } from 'zod';
|
|
15
15
|
import { createDataClient, defineCollection } from '@tier0/sdk-v2/data';
|
|
16
16
|
|
|
17
|
-
const stock = defineCollection({ alias: 'stock', schema: z.object({ sku: z.string(), available: z.number().int().min(0) }) });
|
|
18
|
-
const reservations = defineCollection({ alias: 'reservations', schema: z.object({ sku: z.string(), qty: z.number().int().min(1), orderId: z.string() }) });
|
|
19
|
-
const counters = defineCollection({ alias: 'counters', schema: z.object({ value: z.number().int() }) });
|
|
17
|
+
const stock = defineCollection({ alias: 'stock', schema: z.object({ sku: z.string(), available: z.number().int().min(0).meta({ format: 'int32' }) }) });
|
|
18
|
+
const reservations = defineCollection({ alias: 'reservations', schema: z.object({ sku: z.string(), qty: z.number().int().min(1).meta({ format: 'int32' }), orderId: z.string() }) });
|
|
19
|
+
const counters = defineCollection({ alias: 'counters', schema: z.object({ value: z.number().int().meta({ format: 'int32' }) }) });
|
|
20
20
|
const data = createDataClient({ collections: [stock, reservations, counters] });
|
|
21
21
|
|
|
22
22
|
/** 扣减库存并写预留:库存不足时整体不提交。 */
|
|
@@ -23,7 +23,7 @@ export const salesOrders = defineCollection({
|
|
|
23
23
|
code: z.string(),
|
|
24
24
|
status: z.enum(['DRAFT', 'CONFIRMED', 'SHIPPED', 'CANCELLED']),
|
|
25
25
|
customer: z.object({ id: z.string(), name: z.string() }),
|
|
26
|
-
lines: z.array(z.object({ sku: z.string(), qty: z.number().int().min(1) })),
|
|
26
|
+
lines: z.array(z.object({ sku: z.string(), qty: z.number().int().min(1).meta({ format: 'int32' }) })),
|
|
27
27
|
notes: z.string().optional(),
|
|
28
28
|
orderedOn: z.string().describe('YYYY-MM-DD'),
|
|
29
29
|
confirmedAt: z.string().optional().describe('ISO-8601 UTC from toISOString()'),
|
|
@@ -63,7 +63,7 @@ export const createSalesOrderInput = salesOrders.schema
|
|
|
63
63
|
|
|
64
64
|
## 字段类型标注
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
新建数值字段必须明确选择 int、float 或 double,普通小数默认 double。需要在 Collection 中明确显示 `int`、`float`、`double`、`datetime` 时,通过 Zod 元数据添加格式声明。传输仍使用 JSON Schema 的 `integer` / `number` / `string`:
|
|
67
67
|
|
|
68
68
|
| 声明 | 传输 Schema | 显示类型 |
|
|
69
69
|
| --- | --- | --- |
|
|
@@ -72,7 +72,7 @@ export const createSalesOrderInput = salesOrders.schema
|
|
|
72
72
|
| `z.number().meta({ format: 'double' })` | `{ type: 'number', format: 'double' }` | `double` |
|
|
73
73
|
| `z.string().meta({ format: 'date-time' })` | `{ type: 'string', format: 'date-time' }` | `datetime` |
|
|
74
74
|
|
|
75
|
-
`format` 当前是类型展示注解,不额外限制数值范围或精度,也不舍入数据。写入仍按原来的 Zod 类型和显式 `.min()` / `.max()`
|
|
75
|
+
`format` 当前是类型展示注解,不额外限制数值范围或精度,也不舍入数据。写入仍按原来的 Zod 类型和显式 `.min()` / `.max()` 校验;需要业务范围时应继续声明边界。SDK 编译时递归为普通 `z.number()` 补 `double`,为 `z.int()` / `z.number().int()` 补 `int32`;显式 float/double 与 date-time 保留,普通字符串不补格式,也不根据样本数值推断精度。只接受上表四种类型与格式组合。
|
|
76
76
|
|
|
77
77
|
`datetime` 仍保存原始字符串,不校验日期是否有效、不解析或转换时区;`"not a date"` 也能通过字符串类型校验。需要日期合法性保证时,在 API 入参 Schema 单独使用 `z.iso.datetime()`;这类带 `pattern` 的验证器不能直接作为可存储的集合声明。新增注解不改变 Sample 外层 `time` 的毫秒时间戳协议、已有校验和业务时间含义。
|
|
78
78
|
|
|
@@ -90,7 +90,7 @@ import { defineCollection } from '@tier0/sdk-v2/data/define';
|
|
|
90
90
|
|
|
91
91
|
export const loginCodes = defineCollection({
|
|
92
92
|
alias: 'login_codes',
|
|
93
|
-
schema: z.object({ phone: z.string(), code: z.string(), issuedAt: z.number().int() }),
|
|
93
|
+
schema: z.object({ phone: z.string(), code: z.string(), issuedAt: z.number().int().meta({ format: 'int32' }) }),
|
|
94
94
|
// issuedAt 存 Date.now();签发 5 分钟后删除。
|
|
95
95
|
indexes: [{ path: 'phone' }, { path: 'issuedAt', expireAfterSeconds: 300 }],
|
|
96
96
|
});
|
|
@@ -111,3 +111,5 @@ export const loginCodes = defineCollection({
|
|
|
111
111
|
- 共享实体按 ID 引用,并快照需要展示的字段(`customer: { id, name }`),不要在读取时 join。`aggregate` 有 `$lookup`,但有行数限制,不要用它搭列表页。
|
|
112
112
|
- 每种业务对象一个集合,而不是每个页面一个集合。
|
|
113
113
|
- “最新优先”用 `_meta.createdAt` / `_meta.updatedAt`,由 UNS 维护。
|
|
114
|
+
|
|
115
|
+
直接通过 MCP 提交 recordSchema/sampleSchema 时必须提供上述 type + format;Zod 编译兜底不处理原始请求。ensure 保留已有字段注解,无格式的存量字段需读取完整 Schema、保留其他约束,通过 schema:replace 先 dryRun 再按明确迁移授权执行。
|
|
@@ -12,7 +12,7 @@ const workOrders = defineCollection({
|
|
|
12
12
|
code: z.string(),
|
|
13
13
|
status: z.enum(['DRAFT', 'RELEASED', 'DONE']),
|
|
14
14
|
line: z.object({ id: z.string(), name: z.string() }),
|
|
15
|
-
targetQty: z.number().int().min(1),
|
|
15
|
+
targetQty: z.number().int().min(1).meta({ format: 'int32' }),
|
|
16
16
|
notes: z.string().optional(),
|
|
17
17
|
}),
|
|
18
18
|
indexes: [{ path: 'code', unique: true }, { path: 'status' }],
|
|
@@ -41,6 +41,16 @@ export async function releasedBadge() {
|
|
|
41
41
|
export async function addNote(id: string, notes: string, revision: number) {
|
|
42
42
|
return orders.updateOne({ _id: id }, { $set: { notes } }, { expectedRevision: revision });
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
export async function createWorkOrder(
|
|
46
|
+
code: string, line: { id: string; name: string }, targetQty: number, intentKey: string,
|
|
47
|
+
) {
|
|
48
|
+
const { value } = await orders.insertOne({ code, status: 'DRAFT', line, targetQty }, {
|
|
49
|
+
returnDocument: 'after', projection: { code: 1, 'line.name': 1 }, idempotencyKey: intentKey,
|
|
50
|
+
});
|
|
51
|
+
// 投影后的业务字段可能缺失,元信息仍必有;revision 可交给下一次更新。
|
|
52
|
+
return { id: value._id, revision: value._meta.revision, code: value.code, lineName: value.line?.name };
|
|
53
|
+
}
|
|
44
54
|
```
|
|
45
55
|
|
|
46
56
|
## 一个页面一次请求:`data.queryBatch`
|
|
@@ -99,6 +109,8 @@ export async function ordersScreen(page: number, selectedId: string) {
|
|
|
99
109
|
|
|
100
110
|
带 `projection` 时,返回类型将业务字段递归标为可选,包括嵌套对象和数组元素的字段;读取前需判断是否存在。`_id` 和 `_meta` 仍然必有。不带 `projection` 的 `after` 保持完整文档类型。
|
|
101
111
|
|
|
112
|
+
上面的 createWorkOrder 在一次记录写入中取得投影和修订;首次使用集合时仍会先 ensure 声明,不代表首次调用总共只有一次 HTTP。用于跨调用恢复时保存 intentKey,并重发同一创建意图;不要把原来的默认返回改为 after 来补取数据。读取权限在首次提交和历史重放时都检查,具体边界见 [UNS 创建快照](../../tier0-sdk-v2-uns/references/create.md)。
|
|
113
|
+
|
|
102
114
|
## 批量与原子性
|
|
103
115
|
|
|
104
116
|
| 调用 | 上限 | 原子 |
|
|
@@ -34,3 +34,5 @@ export function replaceBody(expectedRevision: number) {
|
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Schema 中 `ignored`、`warnings`、`conflicts`、`violations` 的路径用 `.` 连接属性,用 `[]` 表示数组元素(`lines.[].qty`)。
|
|
37
|
+
|
|
38
|
+
新声明的 number/integer 默认带 double/int32 格式;ensure 不改写已有字段注解,原无格式字段仍保持 legacy 显示。已有字段格式迁移需读取并保留完整 Schema,先通过 schema:replace dryRun 检查,再按明确迁移授权执行。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 获取文件访问地址
|
|
2
2
|
|
|
3
|
-
方法:`files.url({filePath,expiredSec?,responseContentDisposition?}, {signal}?)`;GET /openapi/
|
|
3
|
+
方法:`files.url({filePath,expiredSec?,responseContentDisposition?}, {signal}?)`;GET /openapi/v2/assets/files/url。
|
|
4
4
|
|
|
5
5
|
| 字段 | 类型 | 必填 | 说明 |
|
|
6
6
|
| --- | --- | --- | --- |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# App 可用成员
|
|
2
2
|
|
|
3
|
-
方法:`members.listApp(body)`;POST /openapi/
|
|
3
|
+
方法:`members.listApp(body)`;POST /openapi/v2/apps/access-members/list。返回能使用该 App 线上版本的有效成员。`appId` 必填且由调用方显式传入,SDK 不隐式读取 `APP_ID`;查询当前 App 时传 `getCurrentAppId()`。接口只接受 API Key,登录会话不能调用;绑定 App 的凭证只能查自己的 appId,查其他 App 返回 403。
|
|
4
4
|
|
|
5
5
|
| 字段 | 类型 | 说明 |
|
|
6
6
|
| --- | --- | --- |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Workspace 成员查询与选择
|
|
2
2
|
|
|
3
|
-
方法:`members.listWorkspace(body)`;POST /openapi/
|
|
3
|
+
方法:`members.listWorkspace(body)`;POST /openapi/v2/platform/getMembers。查询当前 Key 所属 Workspace;云端需要 uns:read。通知读写权限不自动包含成员查询。
|
|
4
4
|
|
|
5
5
|
| 字段 | 类型 | 说明 |
|
|
6
6
|
| --- | --- | --- |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 查询通知投递状态
|
|
2
2
|
|
|
3
|
-
方法:`notifications.get({messageId})`;POST /openapi/
|
|
3
|
+
方法:`notifications.get({messageId})`;POST /openapi/v2/notifications/get。需要 notifications:read,与 send 权限独立;仅查询当前发送 Key 可见的消息。
|
|
4
4
|
|
|
5
5
|
| 参数/结果 | 类型 | 说明 |
|
|
6
6
|
| --- | --- | --- |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 发送通知
|
|
2
2
|
|
|
3
|
-
方法:`notifications.send(body)`;POST /openapi/
|
|
3
|
+
方法:`notifications.send(body)`;POST /openapi/v2/notifications/send。需要 notifications:send;收件人为当前 Workspace 内可用的成员,按[成员查询](../../tier0-sdk-v2-members/references/platform-members.md)解析。
|
|
4
4
|
|
|
5
5
|
| 字段 | 类型 | 必填 | 说明 |
|
|
6
6
|
| --- | --- | --- | --- |
|
|
@@ -23,7 +23,7 @@ Source 维护连接配置、认证引用与源状态。脚本处理用 [Stream](
|
|
|
23
23
|
|
|
24
24
|
## 核心约束
|
|
25
25
|
|
|
26
|
-
1.
|
|
26
|
+
1. Source 配置统一使用 documents.*,原生文档为 `{name,protocol,config}`。http 原生协议与 http-api adapter 不可互换。
|
|
27
27
|
2. 已有 ID 和 revision 时优先用 documents.update 的 patch,避免额外 get;完整替换 document 前读取完整文档,安全列表摘要不能无损回写。原生 ID 是十进制字符串,revision 原样传递,不转 Number。
|
|
28
28
|
3. 现有 Source 修改、启停、删除都要 expectedRevision。没有任何 Stream 引用时可直接提交;有草稿、活动、历史或不可见引用时仍需 confirmedImpactRevision。先形成精确意图,再读取全部影响分页;回执不可合成、跨意图复用或静默刷新。提供的回执始终严格校验,不自动获取并同意影响。
|
|
29
29
|
4. 配置中保留认证/TLS 引用,不写明文秘密;HTTP 新凭据走创建专用 credentials。
|
|
@@ -33,6 +33,6 @@ Source 维护连接配置、认证引用与源状态。脚本处理用 [Stream](
|
|
|
33
33
|
|
|
34
34
|
所有调用返回完整 code/msg/requestId/data。documents.create/update 的预检返回 validated/sideEffects,提交返回完整 Source view,可直接使用其中的文档和 revision,无需额外 get;批量状态/删除返回 Outcome。只有 committed 且无项错误才可报告提交成功;accepted/jobId 继续查询作业。预检按需使用,不是每次提交的必经步骤。
|
|
35
35
|
|
|
36
|
-
需要查看历史用 source.history({id,beforeRevision,size}),按 nextBeforeRevision 继续;探测用 source.probe
|
|
36
|
+
需要查看历史用 source.history({id,beforeRevision,size}),按 nextBeforeRevision 继续;探测用 source.probe,其外部系统访问应属于当前任务。连接配置修改使用 documents.update,遵守同一影响确认契约。
|
|
37
37
|
|
|
38
38
|
UnsV2Error 表示已知拒绝;UnsV2OutcomeUnknownError 表示可能已写入。保存 requestId、原请求和意图键,先查详情/历史/作业对账。取消等待不撤销服务端操作;SDK 不自动重试。权限不足不能解释为资源不存在。
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
| 字段 | 类型 | 必填 | 说明 |
|
|
6
6
|
| --- | --- | --- | --- |
|
|
7
|
-
| id / expectedRevision | string / integer | 是 | 当前 ID
|
|
7
|
+
| id / expectedRevision | string / integer | 是 | 当前 ID 和最近写回执或读取取得的修订 |
|
|
8
8
|
| action | update/enable/disable/delete | 是 | 精确变更类型 |
|
|
9
|
-
| document | CloudSourceDocument |
|
|
9
|
+
| patch / document | CloudSourceDocumentPatch / CloudSourceDocument | 更新时二选一 | 与随后提交完全相同的补丁或完整文档;其他 action 不传 |
|
|
10
10
|
| offset / size | integer | 否 | 首次 0;size 1–200 |
|
|
11
11
|
| impactRevision | string | 翻页时 | 沿用首次返回的确认值 |
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import { createClient, type Tier0Client, type UnsV2Request } from '@tier0/sdk-v2';
|
|
15
15
|
|
|
16
16
|
export async function collectSourceImpact(
|
|
17
|
-
intent: Pick<UnsV2Request<'sourceImpact'>, 'id' | 'expectedRevision' | 'action' | 'document'>,
|
|
17
|
+
intent: Pick<UnsV2Request<'sourceImpact'>, 'id' | 'expectedRevision' | 'action' | 'patch' | 'document'>,
|
|
18
18
|
client: Tier0Client = createClient(),
|
|
19
19
|
) {
|
|
20
20
|
const first = await client.source.impact({ ...intent, offset: 0, size: 200 });
|
|
@@ -37,4 +37,4 @@ export async function collectSourceImpact(
|
|
|
37
37
|
|
|
38
38
|
data:impactRevision、sourceID/sourceRevision、action、counts(draft/activeRelease/historicalRelease)、restrictedCount、references、nextOffset、expiresAt。nextOffset=0 结束;complete=1 表示计算完成,不表示首页有全部引用。
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
确认值绑定身份、修订、精确意图,不能合成或自动刷新。分析时用 patch,提交时就沿用该 patch;不要另行补齐为 document 或更改字段。评估 counts 和 restrictedCount;有受限引用时不能说“无影响”。Source 更新不会自动替换 Stream 冻结修订。已有明确操作授权时不重复索要确认;影响分析本身不授予额外操作权限。没有任何引用时可直接变更,见 [修改](update.md),不必先执行本流程。
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
| 方法 | POST 路径 | 输入 | data |
|
|
4
4
|
| --- | --- | --- | --- |
|
|
5
5
|
| source.documents.list | /openapi/v2/uns/sources/documents/list | page、size、search、protocol、desiredState、health、archived、includeDocument | list、total、page、hasMore、nextPage |
|
|
6
|
-
| source.documents.get | /openapi/v2/uns/sources/documents/get | id
|
|
6
|
+
| source.documents.get | /openapi/v2/uns/sources/documents/get | id(必填)、view:'summary' 或 'full' | id、revision、状态;full 才包含完整 document |
|
|
7
7
|
| source.runtime.get | /openapi/v2/uns/sources/runtime/get | id(必填) | 运行状态 |
|
|
8
8
|
| source.observations.get | /openapi/v2/uns/sources/observations/get | items:id、expectedRevision | 指定源和修订的观测 |
|
|
9
9
|
|
|
10
|
-
page 从 1 开始,size 1–200
|
|
10
|
+
page 从 1 开始,size 1–200。列表默认安全摘要。get 省略 view 保持旧的 full 行为;summary 需要 uns.source.view 或 uns.source.manage,full 需要 uns.source.manage;API Key 读取完整文档还必须是 full_access(includeDocument:true 同样适用)。未知 revision 时可读取 summary;要完整替换 document 或查看配置时读取 full。已持有写回执中的 ID/revision 时,可直接提交 patch,无需为了编辑再 get;服务端仍会检查版本冲突。摘要不能用于重建完整配置。
|
|
11
11
|
|
|
12
12
|
```ts
|
|
13
13
|
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
@@ -12,7 +12,7 @@ description: 使用 @tier0/sdk-v2 的 client.stream 创建、查询、修改和
|
|
|
12
12
|
| 用户任务 | 参考 | 方法 |
|
|
13
13
|
| --- | --- | --- |
|
|
14
14
|
| 新建并绑定 HTTP Source | [创建](references/create.md) | documents.create({program}) |
|
|
15
|
-
| 列表、完整文档、运行记录 | [查询](references/read.md) | programs.list
|
|
15
|
+
| 列表、完整文档、运行记录 | [查询](references/read.md) | programs.list、documents.get、observations.get、runs.list |
|
|
16
16
|
| 修改草稿、脚本和绑定 | [修改](references/update.md) | documents.validate/update |
|
|
17
17
|
| 发布、停用、版本回滚 | [部署](references/deploy.md) | programs.deploy/rollback、documents.disable |
|
|
18
18
|
| 删除并核验归档 | [删除](references/delete.md) | programs.delete |
|
|
@@ -22,18 +22,18 @@ description: 使用 @tier0/sdk-v2 的 client.stream 创建、查询、修改和
|
|
|
22
22
|
|
|
23
23
|
| 形态 | 完整输入 | 适用入口 |
|
|
24
24
|
| --- | --- | --- |
|
|
25
|
-
| Runtime program | name、sdkVersion、script 字符串、sourceBindings、timeoutMs | documents.create/update/validate({program})
|
|
25
|
+
| Runtime program | name、sdkVersion、script 字符串、sourceBindings、timeoutMs | documents.create/update/validate({program}) |
|
|
26
26
|
| 云端原生文档 | name、model、script 对象、sources、entries | documents.create/get/update/validate |
|
|
27
27
|
|
|
28
28
|
程序必须是完整 `module.exports = api => { ... }`,执行器 API 是 api.sources/api.uns/api.stream,与 npm 包的 client.source 不同。Runtime sourceBindings 为 sourceId/configRevision/acquisition;原生 sources 还使用 alias/resources。连接凭据不进脚本或 acquisition。
|
|
29
29
|
|
|
30
30
|
## 核心约束
|
|
31
31
|
|
|
32
|
-
1.
|
|
32
|
+
1. documents.get({id,view:"summary"}) 返回安全摘要,不含可回写脚本;完整编辑使用 documents.get 或上次 documents.create/update 返回的完整文档。保留未修改的 sources/entries/script 字段。
|
|
33
33
|
2. create/update 保存草稿,不自动发布;documents 没有 deploy,云端 program 发布使用 programs.deploy。不能将已保存报告为已运行。
|
|
34
34
|
3. 所有更新/部署/删除携带当前 expectedRevision。原生停用另需 expectedActiveRelease,避免停掉他人刚发布的版本。
|
|
35
35
|
4. versionId 从 versions.list 取得,不把 release 序号当 ID。expectedSourceRevision 仅用于恰好一个依赖源,不代表多个源的修订。
|
|
36
|
-
5. resources=[]
|
|
36
|
+
5. resources=[] 是空冻结资源集,不是通配符。写入本身由服务端校验,需要预览时单独 validate;当前云端程序 timeoutMs 上限 30000。旧 runtime.capabilities 查询已退役,不作为管理或执行前置检查,不为此增加 Control scope 或逐 Key 控制码授权。
|
|
37
37
|
6. 仅执行用户要求的生命周期步骤;修改脚本不自动授予发布、停用或删除权限。
|
|
38
38
|
|
|
39
39
|
## 成功与异常
|
|
@@ -51,6 +51,6 @@ export async function createHttpStream(
|
|
|
51
51
|
|
|
52
52
|
创建 data 为 CloudStreamDocumentView 或预检结果,实际保存返回 id、revision 和完整 document;预检不生成 ID。需要展示预检时单独调用 documents.validate({program});普通保存无需先校验再保存。当前后端创建/校验需要注册 Worker 可用。TEMPORARILY_UNAVAILABLE 不代表脚本一定错误;不要自动改用旧 Flow。
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
programs.create 已退役,创建统一使用 documents.create。历史创建结局未知时先按已知 ID 或业务标识核对状态,不能将旧请求或幂等键改投 documents.create 重做。
|
|
55
55
|
|
|
56
56
|
原生编辑器形态 `documents.create({dryRun, document})` 的 document 为 name/model/script对象/sources/entries,script 为 `{sdkVersion,code,timeoutMs}`,sources 用 alias/sourceId/configRevision/resources/acquisition。不要把上面的 script 字符串直接塞入原生文档。
|
|
@@ -3,12 +3,21 @@
|
|
|
3
3
|
| 方法 | POST 路径 | 必要参数 |
|
|
4
4
|
| --- | --- | --- |
|
|
5
5
|
| programs.deploy | /openapi/v2/uns/streams/program/deploy | id、dryRun;建议 expectedRevision |
|
|
6
|
-
| programs.disable | /openapi/v2/uns/streams/program/disable | id、dryRun;建议 expectedRevision |
|
|
7
6
|
| programs.rollback | /openapi/v2/uns/streams/program/rollback | id、versionId、dryRun;建议 expectedRevision |
|
|
8
7
|
| documents.disable | /openapi/v2/uns/streams/documents/disable | id、expectedRevision、expectedActiveRelease、dryRun |
|
|
9
8
|
|
|
10
9
|
全部写操作使用各自的 idempotencyKey。expectedSourceRevision 只适用于恰好一个 Source 依赖,且同时保护草稿冻结修订与当前 Source head;多源不能塞入单个修订值。原生文档没有 documents.deploy,当前云端 program 模型发布走 programs.deploy。
|
|
11
10
|
|
|
11
|
+
发布、停用和回滚需要 uns.stream.manage;相关 Source 访问还受各自授权约束。保存回执中的 revision、发布回执中的 activeVersion 与 activeRelease 分别用于不同目的:
|
|
12
|
+
|
|
13
|
+
| 字段 | 含义与用途 |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| revision | 草稿修订;传给下次写入的 expectedRevision,冲突时显式处理 |
|
|
16
|
+
| activeVersion | 不可变发布版本 ID;回滚的 versionId 使用这个 ID,不使用发布序号 |
|
|
17
|
+
| activeRelease | 本次事务记录的正整数发布序号;与 runs.list 中的 release 对照;无活跃发布或旧回执未记录时省略 |
|
|
18
|
+
|
|
19
|
+
programs 回执的 activeVersion:'0' 表示无活跃版本;新增 activeRelease 不用 0 表示未发布。原生 documents 回执的既有 activeRelease 约定不变。
|
|
20
|
+
|
|
12
21
|
```ts
|
|
13
22
|
import { createClient, type Tier0Client, type CloudStreamDocumentView } from '@tier0/sdk-v2';
|
|
14
23
|
|
|
@@ -44,7 +53,7 @@ export async function disableStream(id: string, intentKey: string, client: Tier0
|
|
|
44
53
|
}
|
|
45
54
|
```
|
|
46
55
|
|
|
47
|
-
将创建或更新回执的 current 传给 deployStream,只发一次发布请求。只有手上没有草稿快照时才先 documents.get
|
|
56
|
+
将创建或更新回执的 current 传给 deployStream,只发一次发布请求。只有手上没有草稿快照时才先 documents.get。使用 [按发布号查询运行记录](read.md#观察本次发布) 才能观察这次发布,观察窗口汇总不能证明该版本运行。发布成功不表示外部连接健康或执行成功。停用保留草稿。仅修改草稿的任务不额外发布/停用。
|
|
48
57
|
|
|
49
58
|
## 回滚到明确版本
|
|
50
59
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Stream 样例测试与流程衔接
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
创建并发布时,将 [创建](create.md) 或 [修改](update.md) 回执中的草稿直接交给 [发布](deploy.md),再用发布回执的 activeRelease [观察运行](read.md#观察本次发布),无需在发布前后各 get 一次。只有缺少当前草稿、处理版本冲突或需要最新状态时才 [查询](read.md)。停用、回滚和 [删除](delete.md) 按任务选择,不自动执行整套生命周期。
|
|
4
4
|
|
|
5
5
|
## 原生文档样例测试
|
|
6
6
|
|
|
@@ -3,22 +3,20 @@
|
|
|
3
3
|
| 方法 | POST 路径 | 输入 | 结果 |
|
|
4
4
|
| --- | --- | --- | --- |
|
|
5
5
|
| programs.list | /openapi/v2/uns/streams/program/list | page、size、search、sourceId、model、status、archived | list、total、hasMore、nextPage |
|
|
6
|
-
|
|
|
7
|
-
| documents.get | /openapi/v2/uns/streams/documents/get | id | 完整草稿、revision、status、activeRelease、可选 activeDocument |
|
|
6
|
+
| documents.get | /openapi/v2/uns/streams/documents/get | id;可选 view:summary/full | summary 返回摘要;full 返回完整草稿、revision、status、activeRelease、可选 activeDocument |
|
|
8
7
|
| observations.get | /openapi/v2/uns/streams/observation/get | id | 运行观测 |
|
|
9
8
|
| runs.list | /openapi/v2/uns/streams/runs/list | id、size、cursor | 执行记录 |
|
|
10
9
|
| programs.versions.list | /openapi/v2/uns/streams/program/versions/list | id、page、size | list、total,含 versionId |
|
|
11
10
|
|
|
12
|
-
page 从 1 开始,size 最大 200
|
|
11
|
+
page 从 1 开始,size 最大 200。summary 只需 uns.stream.view 或 uns.stream.manage;full 或省略 view 需要 uns.stream.manage,API Key 还必须是 full_access。摘要不含脚本,不能据此重建草稿。已有创建或更新回执时可复用其文档与 revision,不必再读取。
|
|
13
12
|
|
|
14
13
|
```ts
|
|
15
14
|
import { createClient, type Tier0Client } from '@tier0/sdk-v2';
|
|
16
15
|
|
|
17
16
|
export async function readStream(id: string, client: Tier0Client = createClient()) {
|
|
18
17
|
const draft = await client.stream.documents.get({ id });
|
|
19
|
-
const summary = await client.stream.programs.get({ id });
|
|
20
18
|
const observation = await client.stream.observations.get({ id });
|
|
21
|
-
return { draft: draft.data,
|
|
19
|
+
return { draft: draft.data, observation: observation.data };
|
|
22
20
|
}
|
|
23
21
|
export async function* listStreams(client: Tier0Client = createClient()) {
|
|
24
22
|
let page = 1;
|
|
@@ -33,3 +31,25 @@ export async function* listStreams(client: Tier0Client = createClient()) {
|
|
|
33
31
|
```
|
|
34
32
|
|
|
35
33
|
保存、发布、某次执行成功是三个事实。显示实际 revision/activeVersion/release,不用旧 runs 证明新版本生效。版本列表不保证与普通列表相同分页结构;按其 list/total/page/size 读取,versionId 不是 release 序号。
|
|
34
|
+
|
|
35
|
+
## 观察本次发布
|
|
36
|
+
|
|
37
|
+
把 deploy 回执的 activeRelease 原样传入,不需要先读取当前 head。runs.list 需要 uns.stream.view 或 uns.stream.manage;它没有服务端 release 过滤参数,按返回的 nextCursor 继续翻页并在客户端匹配发布号:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { createClient, type Tier0Client, type UnsV2Integer } from '@tier0/sdk-v2';
|
|
41
|
+
|
|
42
|
+
export async function readPublishedRuns(
|
|
43
|
+
id: string, release: UnsV2Integer, cursor?: string,
|
|
44
|
+
client: Tier0Client = createClient(),
|
|
45
|
+
) {
|
|
46
|
+
if (typeof release === 'number' && !Number.isSafeInteger(release)) {
|
|
47
|
+
throw new Error('发布号必须保留回执中的精确整数,不能传已失真的 number');
|
|
48
|
+
}
|
|
49
|
+
if (BigInt(String(release)) <= 0n) throw new Error('需要发布回执中的正整数发布号');
|
|
50
|
+
const { data } = await client.stream.runs.list({ id, size: 100, ...(cursor ? { cursor } : {}) });
|
|
51
|
+
return { ...data, items: data.items.filter(run => run.release === String(release)) };
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
此函数只读一页。items 为空但 nextCursor 非空时,下一页仍可能有匹配记录;达到调用方的观察时限就报告“尚未观察到”。匹配记录也要检查 status、entryId 和时间,不能把存在记录当成执行成功。历史幂等回执若缺少 activeRelease,应保留为未确认,不能用当前 head 的发布号代替。
|
|
@@ -29,6 +29,6 @@ export async function updateStreamDescription(
|
|
|
29
29
|
}
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
代码应用可直接用 documents.update({id, expectedRevision, program, dryRun:false, idempotencyKey}),由服务端编译入口和绑定。编辑完整文档时保留 sdkVersion/timeoutMs,并同步 entries/sources;写入本身执行校验,只有需要提前展示问题时才单独 validate
|
|
32
|
+
代码应用可直接用 documents.update({id, expectedRevision, program, dryRun:false, idempotencyKey}),由服务端编译入口和绑定。编辑完整文档时保留 sdkVersion/timeoutMs,并同步 entries/sources;写入本身执行校验,只有需要提前展示问题时才单独 validate。不要对documents.get 的 summary 做展开更新。
|
|
33
33
|
|
|
34
34
|
响应是完整 CloudStreamDocumentView 或预检结果;把 saved.data 直接传给下一步[发布示例](deploy.md),无需为了 revision 再读取。已有当前完整文档时可省去示例最初的 get。保存草稿不会自动部署,activeDocument 可能仍是旧发布版本。VERSION_CONFLICT 后重新读取、比较并决策;不无条件覆盖。
|
|
@@ -13,7 +13,7 @@ UNS 管数据命名空间、集合、Record 和 Sample;外部连接与脚本
|
|
|
13
13
|
| --- | --- | --- |
|
|
14
14
|
| 创建集合、定义 Schema、新增记录 | [创建](references/create.md) | metadataInsertOne/Many、recordInsertOne |
|
|
15
15
|
| 查询集合、筛选/排序记录 | [查询](references/read.md) | dataAppContext、metadataFind/FindOne(非 App 凭证)、collectionDescribe、recordFind |
|
|
16
|
-
| 改记录、集合名称、扩展 Schema | [修改](references/update.md) | recordUpdateOne、metadataUpdateOne/Many
|
|
16
|
+
| 改记录、集合名称、扩展 Schema | [修改](references/update.md) | recordUpdateOne、metadataUpdateOne/Many |
|
|
17
17
|
| 删记录、软删除集合 | [删除](references/delete.md) | recordDeleteOne、metadataDeleteOne/Many |
|
|
18
18
|
| 恢复集合或记录 | [恢复](references/restore.md) | metadataRestore、recordRestore |
|
|
19
19
|
| 分页、历史采样、事务、写入结果 | [数据工作流](references/data-workflows.md) | sampleFind、recordTransactionExecute |
|
|
@@ -42,14 +42,16 @@ export async function findAppCollection(alias: string) {
|
|
|
42
42
|
## 核心约束
|
|
43
43
|
|
|
44
44
|
1. 记录行是 id/data/revision;filter 与 update 的业务路径用 name、customer.name,不加 data.;系统路径用 _id、_meta.revision。
|
|
45
|
-
2.
|
|
45
|
+
2. 改/删使用最近写回执或读取取得的 revision 作为 expectedRevision;创建时可用 returnDocument:'after' 取得快照。历史重放不是当前最新版本,冲突时显式处理;不同操作使用独立意图键,长度上限以当前操作契约为准。
|
|
46
46
|
3. metadataUpdateOne 的 $set.recordSchema 替换完整 Schema,不迁移已有记录;未更新的 sampleSchema/indexes 保留。先预检兼容性。
|
|
47
47
|
4. 集合无硬删除入口,用 metadataDeleteOne/Many 软删除;Record 删除会物理删除关联 Sample,恢复 Record 不会恢复这些 Sample。
|
|
48
48
|
5. recordFind 使用 pageInfo.hasMore/nextCursor,limit 1–200;sort 为 [['field',1]]。单页不是全量,跨页不是稳定快照。
|
|
49
49
|
6. Sample 的时间是 Unix 毫秒,查询范围 [from,to)。Record 代表业务实体,不用覆盖它来保存历史。
|
|
50
50
|
|
|
51
|
+
7. 新建 recordSchema/sampleSchema 数值字段必须明确格式:int 用 `{ type: 'integer', format: 'int32' }`,float/double 用 `{ type: 'number', format: 'float'/'double' }`;普通小数默认选 double。递归覆盖嵌套对象和数组元素,不创建无 format 的 legacy number/integer;不把 type 写成 int/float/double。已有字段迁移先 dryRun 校验。
|
|
52
|
+
|
|
51
53
|
## 结果与异常
|
|
52
54
|
|
|
53
|
-
响应为 code/msg/requestId/data。元数据 find 返回 items/pageInfo
|
|
55
|
+
响应为 code/msg/requestId/data。元数据 find 返回 items/pageInfo;单条 updateOne/replaceOne/deleteOne 请求 returnDocument 时附带 value;普通写入默认返回对应计数和 ID。metadataTransact 的 results 按 opId 对应。检查 committed、每项错误和实际计数;dryRun 只校验。metadataBulkWrite 默认原子,显式非原子时必须逐项检查 results/errors;跨 kind 的依赖写入使用 metadataTransact。recordBulkWrite 不保证跨集合事务。
|
|
54
56
|
|
|
55
57
|
大整数与 JSON 精确数字可能为 bigint/UnsV2RawNumber;保留读取到的 revision 类型,不用 Number 或普通 JSON.stringify 做无损往返。错误带 execution(notStarted / rolledBack / committed / unknown)与 retry(safe、afterMs)。UnsV2OutcomeUnknownError(execution 为 unknown)先读回核对内容;retry.safe 时可以用同一请求、同一幂等键原样重发。取消请求不撤销写入;client.uns 不自动重试。
|