@guandata/guanwf 0.1.7 → 0.1.820

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## @guandata/guanwf 0.1.820 - 2026-07-14
6
+
7
+ - 新增工作流参数 DSL、运行时 `--param` 覆盖和参数三方合并。
8
+ - 定时调度与事件调度新增可重复的 `--param key=value`,更新单个参数时保留其他显式值和工作流默认值。
9
+ - 新增 Dataset、Shell、HTTP、SQL、参数赋值、Switch、Loop 的结构化 TaskNode DSL 与无损 passthrough。
10
+ - 修复 8.2.0 DATASET 节点错误接受空 `datasetId` 的问题;该节点只刷新已有数据集,创建/写入目标数据集需使用 DATAFLOW/DB_DATAFLOW。
11
+ - 新增 `instance list/tasks/logs/latest`、完整日志分页和失败子工作流递归日志。
12
+ - 扩展 SHELL/HTTP/SQL 初始工作流及 `node add` 节点脚手架。
13
+ - 所有 `run` 操作新增 mutation 安全门:先用 `--dry-run` 查看计划,实际执行必须追加 `--confirm`(兼容 `--yes`);既有自动化脚本需要同步更新。
14
+ - 修复工作流三方合并、敏感凭据落盘、实例状态与日志、JSON 输出和跨平台原子写入问题。
15
+ - 精确合并快照会自动加入工作区 `.gitignore`;所有 `task.json` 统一使用当前用户受限权限,HTTP URL 查询凭据不会进入普通权限源码,日志中的常见键值凭据统一脱敏。
16
+ - 按 8.2.0 后端能力收口:SHELL/LOOP 在创建、导出和保存前明确拒绝;离线开发输出 DatasetNode、直连数据集参数赋值在提交前给出可执行替代方案。
17
+ - 修复参数赋值在 DATABASE/DATASET 来源切换后残留另一来源账号或数据集字段的问题。
18
+ - 修复 8.2.0 DB Dataflow 预览误用普通数据流 v1 接口、任务长期停留在 PROCESSING 的问题;改用 Core v2 提交和通用任务轮询/取消接口。
19
+
3
20
  ## @guandata/guanwf 0.1.7 - 2026-07-08
4
21
 
5
22
  - 工作流离线开发能力增强,支持文件夹、实例、权限、告警和调度相关命令。
package/README.md CHANGED
@@ -16,13 +16,25 @@ npm link
16
16
 
17
17
  ```bash
18
18
  guanwf create --name "我的数据流" --parent-dir <dirId>
19
+ guanwf create --name "HTTP作业" --type HTTP --parent-dir <dirId>
20
+ guanwf create --name "SQL作业" --type SQL --parent-dir <dirId>
19
21
  guanwf edit <parentWorkflowId>
20
22
  guanwf export --dir <workdir>
21
23
  guanwf preview --dir <workdir>
22
- guanwf save --dir <workdir>
23
- guanwf run --wait --dir <workdir>
24
+ guanwf save --dir <workdir> --dry-run
25
+ guanwf save --dir <workdir> --confirm
26
+ guanwf run --wait --dir <workdir> --dry-run
27
+ guanwf run --wait --dir <workdir> --confirm
28
+ guanwf run --dir <workdir> --param biz_date=2026-07-14 --confirm
29
+ guanwf schedule set --cron "0 0 2 * * ?" --param biz_date=2026-07-14 --dir <workdir> --confirm
30
+ guanwf schedule event set --rule <datasetId>:<taskName> --param biz_date=2026-07-14 --dir <workdir> --confirm
31
+ guanwf instance latest --dir <workdir> --logs -f json
24
32
  ```
25
33
 
34
+ 8.2.0 兼容说明:SHELL/LOOP 后端未注册,CLI 会提前拒绝;离线开发输出数据集不能作为
35
+ DatasetNode 刷新目标,应使用 SubWorkflowNode 调用产出工作流。参数赋值查询 StarRocks
36
+ 直连表时使用 DATABASE 来源,不要把直连数据集作为 DATASET 来源。
37
+
26
38
  说明:npm 包名为 `@guandata/guanwf`,用户侧 CLI 命令统一为 `guanwf`。
27
39
 
28
40
  也可以为 AI Coding Assistant 安装 Skill:
@@ -33,6 +45,12 @@ guanwf install-skill
33
45
 
34
46
  ## 版本更新
35
47
 
48
+ ### @guandata/guanwf 0.1.820
49
+
50
+ - 8.2.0 专用兼容版本;请勿与面向 master 的 CLI 版本混用。
51
+ - 新增结构化工作流节点、参数、实例诊断和安全 mutation 门,并修复 8.2.0 保存、预览、运行及恢复链路问题。
52
+ - 对 8.2.0 不支持的 SHELL、LOOP、PROCESS 事件源等能力在提交前给出明确阻断。
53
+
36
54
  ### @guandata/guanwf 0.1.7
37
55
 
38
56
  - 工作流离线开发能力增强,支持文件夹、实例、权限、告警和调度相关命令。
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guandata/guanwf",
3
- "version": "0.1.7",
3
+ "version": "0.1.820",
4
4
  "description": "观远工作流数据流编辑工具 - 创建、编辑、导出、预览、保存数据流",
5
5
  "bin": {
6
6
  "guanwf": "bin/run.js"
@@ -11,7 +11,8 @@ compatibility: "Requires Node.js 14+. Install via npm link (local) or npm instal
11
11
 
12
12
  这是一个执行型 skill,不是只读分析 skill。
13
13
 
14
- - `guancli workflow` 负责查询工作流、数据流、目录和线上结构。
14
+ - `guancli workflow` 负责通用工作流、数据流、目录和线上结构查询;v0.1.820(8.2.0 兼容线)实例诊断使用
15
+ `guanwf instance list/tasks/logs/latest`,可直接解析 `--dir` 工作区。
15
16
  - `guanwf` 负责把目标工作流拉到本地工作目录,修改事实源,再完成 `export -> preview/validate -> save-draft/save -> run`。
16
17
 
17
18
  ## 核心概念
@@ -22,6 +23,14 @@ compatibility: "Requires Node.js 14+. Install via npm link (local) or npm instal
22
23
  - **Python 节点 (SECURE_PYTHON)**: 工作流级 Python 任务,沙箱内运行脚本,可读输入数据集并创建输出数据集
23
24
  - **子工作流节点 (SUB_PROCESS + PROCESS)**: 引用另一个已存在的工作流作为节点,用于把一批作业编排成统一调度的主工作流
24
25
  - **节点依赖**: 节点间用 `After`(成功后)/ `AfterFailure`(失败后)/ `AfterAny`(完成后)声明执行顺序
26
+ - **工作流参数**: `Workflow.Params` 声明,使用 `ParamRef` / `DynamicParamRef` / `DataDrivenParamRef` 引用
27
+ - **结构化任务节点**: DATASET、HTTP、SQL、PARAMETER_ASSIGNMENT、SWITCH 均有 8.2.0 可执行的强类型 DSL,未知字段由 `task.json` 保留;SHELL/LOOP 仅保留导入模型,8.2.0 不可创建、导出、保存或运行
28
+
29
+ ### 8.2.0 兼容边界
30
+
31
+ - 8.2.0 后端没有注册 `SHELL`、`LOOP` TaskParameters,CLI 会在脚手架、导出、保存前明确拒绝。
32
+ - `DatasetNode` 可刷新数据库抽取/直连数据集;不能刷新 `DATA_SET_OFFLINE_DEV`,该路径在 8.2.0 会把 BI 文本响应误当 JSON。需要更新离线开发产出时,使用 `SubWorkflowNode` 调用产出工作流。
33
+ - `ParameterAssignmentNode` 的 `DATASET` 来源不能选数据库直连数据集(BI 返回 60006);三张 StarRocks 表应使用 `DataSourceType: "DATABASE"` 和数据账户。抽取/产出数据集可使用 `DATASET` 来源及 `input1` 查询。
25
34
 
26
35
  ## 关键不变式
27
36
 
@@ -53,18 +62,23 @@ compatibility: "Requires Node.js 14+. Install via npm link (local) or npm instal
53
62
  node_*.json # 可编辑事实源:LoadNodeFromFile 透传节点配置
54
63
  script.py # 可编辑事实源:PYTHON 节点脚本正文
55
64
  python.json # 服务端字段透传(edit 生成,勿手改;改配置去 workflow.go 的 PythonConfig)
56
- task.json # 可编辑事实源:RAW 透传节点完整 TaskNode JSON
65
+ task.json # 0600/当前用户 ACL;RAW 节点为完整事实源,结构化节点保留未知字段
66
+ script.sh # SHELL 节点脚本
67
+ query.sql # SQL / PARAMETER_ASSIGNMENT 节点 SQL
68
+ body.json/body.txt # HTTP 请求体
57
69
  _input.json / meta.json # 导入快照/派生产物,不手改
58
70
  _layout.json # 画布坐标(edit 保留线上坐标;新节点自动布局补位)
59
71
  _wf_state.json # 系统状态,不手改
60
- _parent_snapshot.json # 服务端快照,不手改;save 时重新拉取最新版本合并
72
+ _parent_snapshot.json # 脱敏服务端快照,不手改
73
+ _parent_merge_snapshot.json # 受限权限的精确三方合并基线,不手改
74
+ .gitignore # 自动忽略含原始凭据的精确合并基线
61
75
  _exported_workflow.json # 派生产物,不手改;由 export 重新生成
62
76
  ```
63
77
 
64
78
  ### 禁止的偷懒路径
65
79
 
66
80
  - 不要直接编辑 `_exported_workflow.json` 来"修好"预览或保存。
67
- - 不要直接编辑 `_parent_snapshot.json` 来拼保存 payload。
81
+ - 不要直接编辑 `_parent_snapshot.json` 或 `_parent_merge_snapshot.json` 来拼保存 payload。
68
82
  - 不要手改 `python.json`;输入/输出/资源配置改 `workflow.go` 的 `PythonConfig`。
69
83
  - 不要跳过 `export`,拿上一次的导出结果去 `preview` 或 `save`。
70
84
 
@@ -84,11 +98,27 @@ guancli auth status # 检查连接状态
84
98
  ### 0. 先分场景
85
99
 
86
100
  - `只读查询`: 用 `guancli workflow`,不要创建工作目录。
87
- - `新建工作流`: `guanwf create --name ... --parent-dir ...`(`--type DATAFLOW/DB_DATAFLOW/PYTHON/ORCHESTRATION` 控制初始骨架),然后编辑 `workflow.go` 和 `nodes/`。
101
+ - `新建工作流`: `guanwf create --name ... --parent-dir ...`(8.2.0 支持 `--type DATAFLOW/DB_DATAFLOW/PYTHON/HTTP/SQL/ORCHESTRATION`),然后编辑 `workflow.go` 和 `nodes/`。
88
102
  - `编辑已有工作流`: `guanwf edit <workflowId>` 导入整个工作流(数据流节点 → etl.go,Python 节点 → script.py)。
89
103
  - `编排一批作业`: `guanwf create --type ORCHESTRATION` + `guanwf deps plan` 从血缘自动生成依赖,见「编排工作流」一节。
90
104
  - `修复失败`: 先定位失败发生在 `export`、`preview`、`save` 还是 `run`,只修最小责任源文件。
91
105
 
106
+ ### v0.1.820 参数、节点和实例命令
107
+
108
+ ```bash
109
+ guanwf node add http --id http_1 --name "通知下游" --dir <workdir>
110
+ guanwf node add sql --id sql_1 --name "执行SQL" --dir <workdir>
111
+
112
+ guanwf run --dir <workdir> --param biz_date=2026-07-14 --confirm
113
+ guanwf instance list --dir <workdir> --state FAILURE -f json
114
+ guanwf instance tasks <instanceId> --dir <workdir> -f json
115
+ guanwf instance logs <instanceId> --dir <workdir> --node "<节点名>" --full --log-type ALL -f json
116
+ guanwf instance latest --dir <workdir> --logs -f json
117
+ ```
118
+
119
+ `node add` 只生成节点目录和可粘贴 DSL 片段,不自动修改 `workflow.go` AST。节点真实字段、
120
+ 参数类型兼容和外置文件约定见 `references/TASK_NODE_CONTRACTS.md`。
121
+
92
122
  ### 1. 缺上下文先查,不要猜
93
123
 
94
124
  查询工作流和数据流定义时使用 `guancli workflow`。工作流/数据流由独立的 workflow 引擎管理。
@@ -130,9 +160,9 @@ guancli workflow get <id> -f json # JSON 格式输出
130
160
 
131
161
  1. `guanwf export --dir <workdir>`
132
162
  2. 数据流节点要看数据结果时 `guanwf preview --dir <workdir>`;Python 节点要校验时
133
- `guanwf run --node "<节点名>" --validate --dir <workdir>`(需先 save-draft)
134
- 3. 确认无误后才 `guanwf save-draft --dir <workdir>` 或 `guanwf save --dir <workdir>`
135
- 4. 需要执行时再 `guanwf run --wait --dir <workdir>`
163
+ `guanwf run --node "<节点名>" --validate --dir <workdir> --dry-run`,确认计划后追加 `--confirm`(需先保存草稿)
164
+ 3. 先用 `guanwf save-draft --dir <workdir> --dry-run` 或 `guanwf save --dir <workdir> --dry-run` 查看计划,确认后追加 `--confirm`
165
+ 4. 需要执行时先运行 `guanwf run --wait --dir <workdir> --dry-run`,确认后追加 `--confirm`
136
166
 
137
167
  如果 `export` 没过,不要直接 `preview` 或 `save`。
138
168
 
@@ -146,10 +176,11 @@ guanwf create --name "Python清洗" --type PYTHON --parent-dir <dirId> --dir <wo
146
176
 
147
177
  # 编辑 workflow.go(节点 + 依赖)和 nodes/ 下源文件后:
148
178
  guanwf export --dir <workdir>
149
- guanwf save-draft --dir <workdir>
179
+ guanwf save-draft --dir <workdir> --dry-run
180
+ guanwf save-draft --dir <workdir> --confirm
150
181
  guanwf preview --dir <workdir> # 数据流节点:预览数据
151
- guanwf run --node "<节点名>" --validate --dir <workdir> # Python 节点:校验(不创建输出数据集)
152
- guanwf save --dir <workdir> # 正式发布
182
+ guanwf run --node "<节点名>" --validate --dir <workdir> --confirm # Python 节点:校验(不创建输出数据集)
183
+ guanwf save --dir <workdir> --confirm # 正式发布
153
184
  ```
154
185
 
155
186
  ### 编辑已有工作流
@@ -175,18 +206,22 @@ guanwf edit <workflowId> --dir <workdir>
175
206
  ### 运行工作流
176
207
 
177
208
  ```bash
178
- guanwf run --dir <workdir> # 触发运行(已发布版本)
179
- guanwf run --wait --dir <workdir> # 等待完成
180
- guanwf run --wait --timeout 600 --dir <workdir> # 自定义超时
181
- guanwf run --wait --logs --dir <workdir> # 完成后输出任务日志
182
- guanwf run --node "<节点名>" --validate --dir <workdir> # 校验 Python 脚本(不创建输出数据集)
183
- guanwf run --node "<节点名>" --draft --wait --logs --dir <workdir> # 单节点真实运行草稿
184
- guanwf run --recover --wait --dir <workdir> # 从最近失败实例的失败节点续跑
209
+ guanwf run --dir <workdir> --confirm # 触发运行(已发布版本)
210
+ guanwf run --wait --dir <workdir> --dry-run # 查看执行计划
211
+ guanwf run --wait --dir <workdir> --confirm # 确认并等待完成
212
+ guanwf run --wait --timeout 600 --dir <workdir> --confirm # 自定义超时
213
+ guanwf run --wait --logs --dir <workdir> --confirm # 完成后输出任务日志
214
+ guanwf run --node "<节点名>" --validate --dir <workdir> --confirm # 校验 Python 脚本(不创建输出数据集)
215
+ guanwf run --node "<节点名>" --draft --wait --logs --dir <workdir> --confirm # 单节点真实运行草稿
216
+ guanwf run --recover --wait --dir <workdir> --confirm # 从最近失败实例的失败节点续跑
217
+ guanwf instance resume-failed <instanceId> --dom-id <domId> --wait --timeout 900 --confirm
185
218
  ```
186
219
 
187
220
  `--node` 按节点显示名只运行指定节点(TASK_ONLY);`--draft` 运行 save-draft 的草稿版本;
188
221
  `--logs` 输出任务实例日志(失败时自动拉取,失败的子工作流节点自动下钻子实例日志);
189
222
  `--recover` 从失败处续跑(见「失败恢复」一节)。
223
+ `run --recover` 和 `instance resume-failed` 的最外层实例只有传 `--wait` 才等待完成;嵌套
224
+ PROCESS 子实例始终等待成功后才恢复父实例。长任务用 `--timeout` 调整等待上限。
190
225
 
191
226
  **`--validate` 是验证 Python 脚本的默认方法**:临时草稿中把 `save_outputN` 替换为只打印
192
227
  dtypes/head 的 stub,脚本完整执行但不写输出文件,服务端跳过数据集注册(不创建真实数据集),
@@ -234,13 +269,15 @@ guanwf export --dir <workdir>
234
269
  guanwf deps verify --dir <workdir>
235
270
 
236
271
  # 4. 保存并运行
237
- guanwf save --dir <workdir>
238
- guanwf run --wait --dir <workdir>
272
+ guanwf save --dir <workdir> --confirm
273
+ guanwf run --wait --dir <workdir> --confirm
239
274
  ```
240
275
 
241
276
  ```bash
242
277
  # 5. 配置定时调度并上线
243
- guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir>
278
+ guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir> --confirm
279
+ guanwf schedule set --cron "0 0 2 * * ?" --param biz_date=2026-07-14 --dir <workdir> --confirm
280
+ guanwf schedule event set --rule <datasetId>:<taskName> --param biz_date=2026-07-14 --dir <workdir> --confirm
244
281
  ```
245
282
 
246
283
  规则要点:
@@ -249,9 +286,10 @@ guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir>
249
286
  - A 读 B 的产出则编排中必须有 B→A 路径,否则 verify 报 MISSING_EDGE;
250
287
  刻意读上一批(T-1)产物时在 `Workflow.CrossBatch` 中声明,verify 降级为 INFO。
251
288
  - 子作业失败 → 主实例失败,下游不执行;失败日志会自动下钻到子实例定位真实报错。
252
- - **失败恢复**:修复失败作业并 `guanwf save` 后,在编排目录执行
253
- `guanwf run --recover --wait`——自底向上恢复失败的子实例和主实例,
254
- 已成功节点不重跑(job_a/job_b 成功、job_c 失败时只重跑 job_c)。
289
+ - **失败恢复**:修复失败作业并 `guanwf save --confirm` 后,在编排目录执行
290
+ `guanwf run --recover --wait --confirm`——自底向上恢复失败的子实例和主实例,
291
+ 成功祖先和无关分支不重跑;恢复节点的全部 DAG 后继会重跑(包括先前为 SUCCESS 的后继)。
292
+ 例如 job_a/job_b 是 job_c 的成功祖先、job_c 失败时只从 job_c 及其后继开始重跑。
255
293
  - 修改编排结构改 `workflow.go`(`SubWorkflowNode` / `After` / `CrossBatch`),
256
294
  不要去改被引用作业的内容;作业内容问题回作业自己的工作目录修。
257
295
 
@@ -262,31 +300,35 @@ guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir>
262
300
 
263
301
  ```bash
264
302
  guanwf schedule info --dir <workdir> # 查看当前调度
265
- guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir> # 创建/更新并上线
266
- guanwf schedule set --cron "0 0 2 * * ?" --offline --dir <workdir> # 只保存不上线
267
- guanwf schedule enable --dir <workdir> # 上线
268
- guanwf schedule disable --dir <workdir> # 下线
303
+ guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir> --confirm # 创建/更新并上线
304
+ guanwf schedule set --cron "0 0 2 * * ?" --offline --dir <workdir> --confirm # 只保存不上线
305
+ guanwf schedule enable --dir <workdir> --confirm # 上线
306
+ guanwf schedule disable --dir <workdir> --confirm # 下线
269
307
  ```
270
308
 
271
309
  - crontab 是 Quartz 6/7 段表达式(秒 分 时 日 月 周 [年]),如 `0 30 6 * * ?` 每天 06:30。
272
310
  - `set` 可选 `--failure-strategy CONTINUE|END`(默认 CONTINUE)、
273
311
  `--warning NONE|SUCCESS|FAILURE|ALL`(默认 FAILURE)、`--start/--end` 生效区间、
274
312
  `--auto-cancel-queued`(上一批未跑完时自动取消堆积实例)。
275
- - 已有调度时未指定的参数保留现状;事件调度(EVENT_SCHEDULE)不在本命令范围。
313
+ - 已有调度时未指定的参数保留现状;事件调度使用 `guanwf schedule event get/set/disable`。
276
314
 
277
315
  ## 失败恢复(run --recover)
278
316
 
279
317
  ```bash
280
- guanwf run --recover --wait --dir <workdir>
318
+ guanwf run --recover --wait --dir <workdir> --confirm
281
319
  ```
282
320
 
283
- 找到最近一次 FAILURE 实例,从失败节点处续跑,已成功节点不重跑。适用于长链路编排中
284
- 个别作业失败:先回失败作业的工作目录修复并 `guanwf save`,再回编排目录 `--recover`。
321
+ 找到最近一次 FAILURE 实例,从恢复节点处续跑;成功祖先和无关分支不重跑,恢复节点的
322
+ 全部 DAG 后继会重跑。8.2.0 的恢复种子状态包括 FAILURE、STOP、KILL、
323
+ NEED_FAULT_TOLERANCE。适用于长链路编排中
324
+ 个别作业失败:先回失败作业的工作目录修复并 `guanwf save --confirm`,再回编排目录 `--recover --confirm`。
285
325
 
286
326
  平台语义(已实测):失败的子工作流节点会复用原子实例,且子实例持有失败时的旧定义快照。
287
- `--recover` 已处理这一点——自底向上先恢复失败子实例(`update=true` 吸收最新发布定义),
288
- 再恢复父实例。若编排 DAG 结构已变更(加减节点/改依赖),平台会拒绝恢复,此时直接
289
- `guanwf run` 重跑整链。
327
+ `--recover` 已处理这一点——自底向上先恢复失败子实例(`update=true` 吸收失败节点及后继
328
+ 的最新发布定义),并对恢复范围内已成功的 PROCESS 后继显式执行 `REPEAT_RUNNING`,再恢复
329
+ 父实例。若子工作流引用已切换、编排 DAG 结构已变更(加减节点/改依赖),CLI/平台会拒绝
330
+ 恢复,此时直接
331
+ `guanwf run --confirm` 重跑整链。
290
332
 
291
333
  ## save 的工作机制
292
334
 
@@ -295,7 +337,7 @@ guanwf run --recover --wait --dir <workdir>
295
337
  1. 读取本地 `_exported_workflow.json`(必须由 `export` 重新生成)
296
338
  2. 从服务端重新拉取工作流最新版本作为基底
297
339
  3. tasks 按节点 id 做字段级合并:本地定义的字段覆盖,服务端独有字段(dsId、运行时注册信息等)保留
298
- 4. 节点成员按三方判断(服务端最新 + 本地 `_parent_snapshot.json` + 本地导出):
340
+ 4. 节点成员按三方判断(服务端最新 + 本地 `_parent_merge_snapshot.json` + 本地导出):
299
341
  本地快照里有、导出里删了的节点 → 删除;服务端有、本地快照不知道的节点(他人并发新增)→
300
342
  保留并打印提示
301
343
  5. dataflowJson 按 dataflow id 经 etlmerge 做 actions 字段级合并(成员判断同上)
@@ -318,9 +360,10 @@ guanwf run --recover --wait --dir <workdir>
318
360
  | 查询详情 | GET | `/api/offline-dev/process/{id}/select-by-id` |
319
361
  | 保存草稿 | POST | `/api/offline-dev/process/save-draft` |
320
362
  | 保存发布 | POST | `/api/offline-dev/process/save` |
321
- | 预览数据流 | POST | `/api/offline-dev/dataflow/preview-async` |
322
- | 查询预览任务 | GET | `/api/offline-dev/dataflow/task/{taskId}` |
323
- | 取消预览 | POST | `/api/offline-dev/dataflow/task/{taskId}/cancel` |
363
+ | 预览普通数据流 | POST | `/api/offline-dev/dataflow/preview-async` |
364
+ | 查询/取消普通预览 | GET/POST | `/api/offline-dev/dataflow/task/{taskId}`、`/cancel` |
365
+ | 预览 DB Dataflow | POST | `/api/offline-dev/dataflow/v2/preview-async` |
366
+ | 查询/取消 DB Dataflow 预览 | GET/POST | `/api/task/{taskId}`、`/cancel` |
324
367
  | 运行工作流 | POST | `/api/offline-dev/process/{id}/start-process-instance` |
325
368
  | 查询运行实例 | GET | `/api/offline-dev/process/instance/{id}/select-by-id?domId=<domId>` |
326
369
  | 实例任务列表 | GET | `/api/offline-dev/process/instance/{id}/task-list-by-process-id?domId=<domId>` |
@@ -0,0 +1,64 @@
1
+ # 工作流 TaskNode 合约(v0.1.820 / 8.2.0)
2
+
3
+ 本文件记录 `guanwf` 结构化 DSL 的平台事实源。合约来自当前 `workflow_web` 节点定义和
4
+ `guandata-workflow` DTO/校验逻辑;未知或版本新增字段由 `nodes/<id>/task.json` 无损保留。
5
+
6
+ ## 通用字段
7
+
8
+ 所有结构化节点导出 `id/name/type/desc/params/preTasks/preTaskScheduleTypes`,并带平台默认的
9
+ `runFlag/retryEnabled/maxRetryTimes/retryInterval/workerGroupId/taskTimeoutParameter`。Go DSL
10
+ 字段覆盖 `task.json`,base-only 字段保留。依赖始终以 `workflow.go` 为准。
11
+
12
+ ## 工作流参数
13
+
14
+ `Workflow.Params` 保存到 `processDefinitionJson.globalParams`。平台识别:
15
+
16
+ - `STRING`、`NUMBER`、`DATE`;bool 兼容为 STRING,日期时间/时间宏兼容为 DATE。
17
+ - 字段:`name/description/valueType/defaultValue/optionValue/customize/multiple/freeze/paramType`。
18
+ - 引用:`[WORKFLOW_PARAMS.name]`、`[DYNAMIC_PARAMS.name]`、
19
+ `[DATADRIVEN_PARAMS.name]`、`[BUILTIN_PARAMS.name]`。
20
+ - `run --param key=value` 复制完整参数对象并只覆盖 `value`。
21
+
22
+ `required` 是本地 DSL 元数据,当前平台没有同名持久化字段;因此
23
+ `ParamRequired()` 会在本地导出校验时要求提供非空 `DefaultValue`,确保保存到平台后仍有可执行值。
24
+
25
+ ## 节点 params
26
+
27
+ | TaskNode.type | 结构化 DSL | 已确认 params |
28
+ |---|---|---|
29
+ | `DATASET` | `DatasetNode` | `datasetId/datasetName/dbAccount/dbType/dirPath/displayType/schemaSql/uniformResourceType/updateSql` |
30
+ | `SHELL` | `ShellNode` | 仅模型保留;8.2.0 后端未注册,CLI 拒绝保存 |
31
+ | `HTTP` | `HTTPNode` | `connectionConfig{type,url,headers,parameters,body,authentication}`,以及递归轮询配置 |
32
+ | `SQL` | `SQLNode` | `cnId/acId/sql/preSqlList/postSqlList/fieldConfigs` |
33
+ | `PARAMETER_ASSIGNMENT` | `ParameterAssignmentNode` | `dataSourceType/sql/fieldConfigs`;DATABASE 使用 `cnId/acId`,DATASET 使用 `dsId/dsName/dirPath/displayType` |
34
+ | `SWITCH` | `SwitchNode` | `switchResult.dependTaskList[]`,每项含 `nextNode/combineType/conditions` |
35
+ | `LOOP` | `LoopNode` | 仅模型保留;8.2.0 后端未注册,CLI 拒绝保存 |
36
+ | `SUB_PROCESS+PROCESS` | `SubWorkflowNode` / `SubTaskNode` | `subProcessId/subProcessName/subProcessParams/subProcessDynamicParams/runTimeParams` |
37
+
38
+ ## 关键语义
39
+
40
+ - `PARAMETER_ASSIGNMENT` 是查询结果列到数据驱动参数的映射,不是任意 key/value 赋值。
41
+ - DATASET 必须使用已有数据集的 `datasetId`。8.2.0 的 DATASET 执行器只会按 ID 触发 BI
42
+ 数据集刷新,不会根据 `datasetName + schemaSql` 创建数据集;需要创建/写入目标数据集时,
43
+ 应使用 DATAFLOW/DB_DATAFLOW 的输出节点。`DATA_SET_OFFLINE_DEV` 不能用于 DatasetNode:8.2.0
44
+ 会把刷新接口的文本响应当 JSON,CLI 会提前阻断并提示改用产出工作流的 SubWorkflowNode。
45
+ - 参数赋值的 `DATASET` 来源遵守 8.2.0 后端 SQL 执行契约。数据库直连数据集会返回 60006,
46
+ CLI 会提前阻断;查询 StarRocks 表请改用 `DATABASE` 来源。后端支持的非直连抽取/离线开发
47
+ 产出数据集可使用 `DATASET` 来源(这是 CLI 相对页面选择器的明确扩展),SQL 中表名为 `input1`。
48
+ - `SWITCH.nextNode` 必须是 Switch 的直接 DAG 下游节点。
49
+ - SHELL/LOOP 的字段模型供兼容导入和后续版本使用,不代表 8.2.0 可执行能力。
50
+ - Switch/条件 Loop 的 `combineType` 仅支持 `AND/OR`,FilterType 与 FieldType 必须是 BI
51
+ 条件评估接口支持的枚举,参数来源和值不能为空。
52
+ - `LOOP` 循环调用另一个工作流,不内嵌任意节点;模式为 `ITERATE` 或 `CONDITION`,
53
+ `maxLoopTimes` 为 2–500,默认 128;遍历项必须提供 `prop/type`。
54
+ - HTTP 当前确认 GET/POST。认证值只保存在权限为 0600 的 `task.json`;导入不把明文凭据复制到
55
+ `workflow.go`。
56
+ - SQL TaskNode 与数据流内部 `SQL_SCRIPT` 是两类节点。
57
+ - 无法满足当前合约的旧 payload 自动回退 `RawTask`,避免导入时虚构字段或破坏保存结果。
58
+
59
+ ## 外置文件
60
+
61
+ - SHELL: `script.sh`
62
+ - SQL / PARAMETER_ASSIGNMENT: `query.sql`
63
+ - HTTP: `body.json` 或 `body.txt`;递归请求体为 `recursion-body.txt`
64
+ - 所有路径必须位于对应节点目录内,禁止 `..` 或绝对路径逃逸。
@@ -17,9 +17,14 @@
17
17
  etl.go # DATAFLOW/DB_DATAFLOW 节点:guanetl DSL(可附 *.sql、node_*.json)
18
18
  script.py # PYTHON 节点:脚本正文
19
19
  python.json # PYTHON 节点:服务端字段透传(edit 生成,勿手改)
20
- task.json # RAW 透传节点:完整 TaskNode JSON
20
+ task.json # 0600/当前用户 ACL;RAW 透传节点为完整 TaskNode JSON
21
+ script.sh # SHELL 节点脚本
22
+ query.sql # SQL / PARAMETER_ASSIGNMENT 节点 SQL
23
+ body.json/body.txt # HTTP 请求体
21
24
  _wf_state.json # 系统状态(mode=workflow),不手改
22
- _parent_snapshot.json # 服务端快照,不手改
25
+ _parent_snapshot.json # 脱敏服务端快照,不手改
26
+ _parent_merge_snapshot.json # 0600/当前用户 ACL 的精确合并基线,不手改
27
+ .gitignore # 自动忽略含原始凭据的精确合并基线
23
28
  _layout.json # 节点画布坐标(edit 时保留线上坐标),可不存在
24
29
  _exported_workflow.json # export 派生产物,不手改
25
30
  ```
@@ -63,14 +68,41 @@ func DefineWorkflow() Workflow {
63
68
  | `DBDataflowNode(id, name, DataflowConfig, deps...)` | SUB_PROCESS(DB 数据流,SQL 下推) | `nodes/<id>/etl.go` |
64
69
  | `PythonNode(id, name, PythonConfig, deps...)` | SECURE_PYTHON | `nodes/<id>/script.py`(+ `python.json` 透传) |
65
70
  | `SubWorkflowNode(id, name, SubWorkflowConfig, deps...)` | SUB_PROCESS(子工作流) | 无(引用已存在的工作流 ID) |
71
+ | `DatasetNode(id, name, DatasetConfig, deps...)` | DATASET | `task.json` passthrough base |
72
+ | `ShellNode(id, name, ShellConfig, deps...)` | SHELL | 仅导入模型;8.2.0 不支持执行 |
73
+ | `HTTPNode(id, name, HTTPConfig, deps...)` | HTTP | `body.json/body.txt` + `task.json` base |
74
+ | `SQLNode(id, name, SQLConfig, deps...)` | SQL | `query.sql` + `task.json` base |
75
+ | `ParameterAssignmentNode(...)` | PARAMETER_ASSIGNMENT | `query.sql` + `task.json` base |
76
+ | `SwitchNode(...)` | SWITCH | `task.json` passthrough base |
77
+ | `LoopNode(...)` | LOOP | 仅导入模型;8.2.0 不支持执行 |
66
78
  | `RawTask(id, deps...)` | 任意(透传) | `nodes/<id>/task.json` |
67
79
 
68
80
  - `id`:节点目录名,也是 TaskNode 的 id。同一工作流内唯一,建议用 `python_1`、`dataflow_1`
69
81
  这类稳定短名;edit 回读的节点保留线上原 id。
70
82
  - `name`:节点显示名。**同一工作流内必须唯一**(后端 preTasks 依赖按名字引用)。
71
- - `RawTask` 不带 name 参数,名称从 `task.json` 的 `name` 字段读取。用于 DSL 未结构化建模的
72
- 节点类型(PARAMETER_ASSIGNMENT、SHELL、HTTP、SWITCH、旧版 PYTHON 等),除依赖外全部透传。
83
+ - `RawTask` 不带 name 参数,名称从 `task.json` 的 `name` 字段读取。用于未知类型或不符合当前
84
+ 结构化合约的旧 payload,除依赖外全部透传。
73
85
  - `SubWorkflowNode` 用于编排工作流,见下文「编排工作流」一节。
86
+ - 8.2.0 的后端 TaskParameters 注册表不含 SHELL/LOOP,因此 CLI 会在创建、导出或保存时拒绝这两类节点;循环/脚本能力不能作为本版本 POC 的可用能力承诺。
87
+
88
+ ### 工作流参数与引用
89
+
90
+ ```go
91
+ return Workflow{
92
+ Name: "每日加工",
93
+ Params: []Param{
94
+ StringParam("biz_date", "${yyyy-MM-dd-1}", ParamDesc("业务日期")),
95
+ NumberParam("batch", 1),
96
+ },
97
+ Nodes: []*WfNode{node},
98
+ }
99
+ ```
100
+
101
+ `ParamRef("biz_date")`、`DynamicParamRef("system.biz")`、
102
+ `DataDrivenParamRef("result")` 和 `BuiltinParamRef("looptimes")` 只生成平台引用表达式,不在本地求值。
103
+ 平台持久化类型为 STRING/NUMBER/DATE;BoolParam 兼容 STRING,TimeParam 兼容 DATE。
104
+
105
+ 完整 TaskNode 字段见 `TASK_NODE_CONTRACTS.md`。
74
106
 
75
107
  ### 依赖与执行条件
76
108
 
@@ -165,8 +197,8 @@ print("rows:", len(result)) # print 输出会出现在任务日志里,可用
165
197
 
166
198
  ```bash
167
199
  guanwf export --dir <workdir> # 1. 导出验证 DSL
168
- guanwf save-draft --dir <workdir> # 2. 保存草稿(不影响已发布版本)
169
- guanwf run --dir <workdir> --node "<节点名>" --validate # 3. 校验运行
200
+ guanwf save-draft --dir <workdir> --confirm # 2. 保存草稿(不影响已发布版本)
201
+ guanwf run --dir <workdir> --node "<节点名>" --validate --confirm # 3. 校验运行
170
202
  ```
171
203
 
172
204
  `--validate` 的工作机制:
@@ -189,7 +221,7 @@ guanwf run --dir <workdir> --node "<节点名>" --validate # 3. 校验运行
189
221
  AI 应根据 dtypes/head 检查输出 schema 是否符合预期,确认后用 `save` 发布并正式
190
222
  `run`(正式运行才会真实创建输出数据集)。
191
223
 
192
- 如果校验中途断掉导致草稿仍带 stub,重新执行 `guanwf save-draft` 即可恢复(命令结束时
224
+ 如果校验中途断掉导致草稿仍带 stub,重新执行 `guanwf save-draft --confirm` 即可恢复(命令结束时
193
225
  会有显式警告)。
194
226
 
195
227
  `--validate` 必须搭配 `--node`(节点**显示名**不是 id),隐含 `--draft --wait --logs`。
@@ -291,13 +323,14 @@ INPUT_DATASET / OUTPUT_DATASET / INCREMENT_OUTPUT_DATASET)、嵌套子工作
291
323
 
292
324
  ### 编排的运行与失败语义
293
325
 
294
- - `guanwf run --wait --dir <workdir>` 运行主工作流,按边的顺序触发各作业子实例。
326
+ - `guanwf run --wait --dir <workdir> --confirm` 运行主工作流,按边的顺序触发各作业子实例。
295
327
  - 子作业失败 → 主实例失败,其 `After` 下游不执行;已成功的作业产出保留。
296
328
  - 失败时 `run` 自动拉日志:失败的 SUB_PROCESS 节点 UI 日志为空,会自动下钻到
297
329
  子实例逐任务打印(含 Python traceback 脚本输出),无需手动定位子实例。
298
330
  - **推荐修复方式(增量恢复)**:修好失败作业(在作业自己的工作目录里改、save),
299
- 回编排目录 `guanwf run --recover --wait`——从失败节点续跑,已成功作业不重跑。
300
- - 整链重跑:`guanwf run --wait`(已成功作业也会重跑;作业输出是 OVERWRITE 时幂等)。
331
+ 回编排目录 `guanwf run --recover --wait --confirm`——从恢复节点续跑;成功祖先和无关
332
+ 分支不重跑,但恢复节点的全部 DAG 后继会重跑(即使后继先前为 SUCCESS)。
333
+ - 整链重跑:`guanwf run --wait --confirm`(已成功作业也会重跑;作业输出是 OVERWRITE 时幂等)。
301
334
  - 作业节点的重试/超时用 `SubWorkflowConfig` 所在 TaskNode 的通用字段(edit 回读后在
302
335
  task 层,当前 DSL 不展开;需要精细重试策略时在作业工作流内部配)。
303
336
 
@@ -305,22 +338,32 @@ INPUT_DATASET / OUTPUT_DATASET / INCREMENT_OUTPUT_DATASET)、嵌套子工作
305
338
 
306
339
  `--recover` 找到最近一次 FAILURE 实例并自底向上恢复:
307
340
 
308
- 1. 列出失败节点;对失败的 SUB_PROCESS 节点,经 `select-sub-process` 定位失败子实例。
341
+ 1. 列出恢复节点(FAILURE / STOP / KILL / NEED_FAULT_TOLERANCE);对其中的
342
+ SUB_PROCESS 节点,经 `select-sub-process` 定位子实例。
309
343
  2. 递归先恢复子实例(`execute` + `START_FAILURE_TASK_PROCESS` + `update=true`,
310
344
  使子实例吸收作业最新发布定义——否则会用失败时的旧定义快照重跑)。
311
- 3. 子实例成功后恢复父实例,父实例吸收子实例成功状态,只重跑未成功节点(秒级)。
345
+ 3. 子实例成功后恢复父实例。8.2.0 会重跑恢复节点及其全部 DAG 后继;成功祖先和
346
+ 无关分支保留原状态。
347
+
348
+ 最外层实例只有传 `--wait` 才等待完成;嵌套 PROCESS 子实例为保证自底向上顺序始终等待。
349
+ `guanwf instance resume-failed <instanceId> --wait --timeout 900 --confirm` 可对指定实例使用
350
+ 相同恢复器并调整长任务超时。若子工作流引用已从 A 改为 B,CLI 会阻止复用 A 的旧实例,
351
+ 应直接新运行整条工作流。
312
352
 
313
353
  限制:只有 FAILURE 状态的最近实例可恢复;若编排 DAG 结构已变更(加减节点/改依赖),
314
- 平台 `checkProcessChange` 会拒绝,此时直接 `guanwf run` 重跑整链。
354
+ 平台 `checkProcessChange` 会拒绝,此时直接 `guanwf run --confirm` 重跑整链。
315
355
  不可与 `--node` / `--draft` / `--validate` 同用。
316
356
 
317
357
  ### 编排的定时调度
318
358
 
319
359
  ```bash
320
360
  guanwf schedule info --dir <workdir>
321
- guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir> # 创建/更新并上线
322
- guanwf schedule set --cron "0 0 2 * * ?" --offline --dir <workdir> # 只保存不上线
323
- guanwf schedule enable / disable --dir <workdir>
361
+ guanwf schedule set --cron "0 0 2 * * ?" --dir <workdir> --confirm # 创建/更新并上线
362
+ guanwf schedule set --cron "0 0 2 * * ?" --param biz_date=2026-07-14 --dir <workdir> --confirm
363
+ guanwf schedule set --cron "0 0 2 * * ?" --offline --dir <workdir> --confirm # 只保存不上线
364
+ guanwf schedule event set --rule <datasetId>:<taskName> --param biz_date=2026-07-14 --dir <workdir> --confirm
365
+ guanwf schedule enable --dir <workdir> --confirm
366
+ guanwf schedule disable --dir <workdir> --confirm
324
367
  ```
325
368
 
326
369
  - crontab 为 Quartz 表达式(秒 分 时 日 月 周 [年]),服务端校验合法性。
@@ -343,9 +386,9 @@ guanwf create --name "我的工作流" --parent-dir <工作流目录ID> --dir <w
343
386
 
344
387
  # 编辑 workflow.go 和节点源文件后:
345
388
  guanwf export --dir <workdir>
346
- guanwf save-draft --dir <workdir>
347
- guanwf run --dir <workdir> --node "<节点名>" --validate # 校验(不创建真实输出数据集)
348
- guanwf save --dir <workdir> # 正式发布
389
+ guanwf save-draft --dir <workdir> --confirm
390
+ guanwf run --dir <workdir> --node "<节点名>" --validate --confirm # 校验(不创建真实输出数据集)
391
+ guanwf save --dir <workdir> --confirm # 正式发布
349
392
  ```
350
393
 
351
394
  新增数据流节点时:`mkdir -p nodes/<节点ID>`,创建 `nodes/<节点ID>/etl.go`(guanetl DSL,
@@ -359,7 +402,7 @@ guanwf edit <workflowId> --dir <workdir>
359
402
 
360
403
  回读生成:
361
404
 
362
- - `workflow.go`:节点 + 依赖结构(PARAMETER_ASSIGNMENT 等未建模类型生成 `RawTask` + 注释)
405
+ - `workflow.go`:节点 + 依赖结构(当前合约外或不满足结构化校验的节点生成 `RawTask` + 注释)
363
406
  - 数据流节点 → `nodes/<id>/etl.go`(经 guanetl json2go,SQL 外置为 `*.sql`)
364
407
  - Python 节点 → `nodes/<id>/script.py` + `nodes/<id>/python.json`
365
408
  - 其他节点 → `nodes/<id>/task.json`
@@ -370,13 +413,16 @@ guanwf edit <workflowId> --dir <workdir>
370
413
  ### 运行
371
414
 
372
415
  ```bash
373
- guanwf run --dir <workdir> # 触发整个工作流(已发布版本)
374
- guanwf run --dir <workdir> --wait # 等待完成
375
- guanwf run --dir <workdir> --wait --logs # 完成后输出任务日志
376
- guanwf run --dir <workdir> --node "<节点名>" --validate # 校验运行(不创建输出数据集)
377
- guanwf run --dir <workdir> --node "<节点名>" --draft --wait --logs # 单节点真实运行草稿
416
+ guanwf run --dir <workdir> --confirm # 触发整个工作流(已发布版本)
417
+ guanwf run --dir <workdir> --wait --confirm # 等待完成
418
+ guanwf run --dir <workdir> --wait --logs --confirm # 完成后输出任务日志
419
+ guanwf run --dir <workdir> --node "<节点名>" --validate --confirm # 校验运行(不创建输出数据集)
420
+ guanwf run --dir <workdir> --node "<节点名>" --draft --wait --logs --confirm # 单节点真实运行草稿
378
421
  ```
379
422
 
423
+ `run` 会创建线上执行实例,升级后必须显式传 `--confirm`(兼容别名 `--yes`);
424
+ 自动化脚本可先执行 `--dry-run` 检查目标、参数和请求计划。
425
+
380
426
  ### 预览数据流节点
381
427
 
382
428
  ```bash
@@ -394,11 +440,11 @@ Python 节点没有 preview API,校验用 `run --node "<节点名>" --validate
394
440
  1. 读取 `_exported_workflow.json`(必须由 `export` 重新生成)
395
441
  2. 从服务端拉取父工作流最新版本作为基底
396
442
  3. tasks 按节点 id 做字段级合并:本地定义的字段覆盖,服务端独有字段(dsId、运行时注册信息等)保留
397
- 4. 节点成员按三方判断(服务端最新 + 本地 `_parent_snapshot.json` + 本地导出):
443
+ 4. 节点成员按三方判断(服务端最新 + 本地 `_parent_merge_snapshot.json` + 本地导出):
398
444
  本地快照里有、导出里删了的节点 → 删除;服务端有、本地快照不知道的节点(他人并发新增)→
399
445
  保留并打印提示
400
446
  5. dataflowJson 按 dataflow id 经 etlmerge 做 actions 字段级合并(成员判断同上)
401
- 6. 保存成功后刷新本地 `_parent_snapshot.json`,并把服务端回写的 Python 参数同步进 `python.json`
447
+ 6. 保存成功后刷新本地脱敏 `_parent_snapshot.json` 与受限权限 `_parent_merge_snapshot.json`,并把服务端回写的 Python 参数同步进 `python.json`
402
448
 
403
449
  因此多人/多端并发修改同一工作流时,以服务端最新版本为基底合并,不会把别人新加的节点冲掉;
404
450
  但同一节点的并发修改仍是后保存者覆盖。