a3s-flow CLI
a3s-flow 随 @a3s-lab/flow-ui 发布。它读取包内同一份节点 manifest,因此命令行、网页节点卡片、配置面板和文档使用一致的字段、端口与默认值。CLI 只处理工作流文档和标准输入输出,不连接模型服务,不读取凭据,也不替宿主执行任务。
安装与确认
第二条命令应返回 ok 为 true 的 JSON,并列出 nodes、new、create、read、update、delete、validate、compile 和 digest。如果终端找不到命令,先确认依赖安装在当前项目,再通过 npx 或项目脚本调用本地二进制。
项目脚本可以直接调用本地二进制。
所有命令都输出 JSON。退出码 0 表示命令成功,退出码 1 表示工作流结构或节点配置没有通过校验。参数、文件读取或 CLI 调用本身有问题时,进程以 2 退出。自动化脚本应同时检查退出码和输出中的 ok 字段。
命令清单
--pretty 让输出便于阅读。--output <file> 把 JSON 写入文件。文件参数使用 - 时从标准输入读取。--include-internal 仅用于 nodes 和 node,它会显示容器内部的 iteration-start 与 loop-start,这两个类型不能通过 new 作为公开节点创建。
查询与创建节点
先查目录,再查目标节点,最后创建带稳定 ID 的实例。
node 输出是字段和端口的事实来源。编辑器或脚本不应自行拼写字段名、枚举值和连接句柄。new 会填入 manifest 默认值,并保留运行所需的数据结构。节点 ID 在运行创建后属于持久身份,修改它可能让历史中的步骤、Hook、进度或子运行无法对应到新图。
工作流文件 CRUD
新建文件时使用 create(也可以传入 --from <file|-> 复制并校验已有 DSL)。除非明确传入 --overwrite,它不会覆盖已有路径;同时会创建父目录,并通过同目录临时文件加 rename 完成原子写入。read 一次返回校验后的 DSL、确定性计划、数量和两个摘要。
update 每次可接受一个聚焦操作;需要多次图修改一起提交时,使用 --operations '<json-array>'。对于生成器或较大的变更流,可使用 --operations -,从 stdin 逐行输入一个 JSON operation(NDJSON),也可以使用 --operations @operations.ndjson 直接流式读取 NDJSON 文件,避免把内容放进命令行参数。Flow 会边到达边解析和应用,最后只在完整校验通过后原子发布一个快照。节点配置使用 JSON,只修改 manifest 拥有的字段,未知语义扩展和展示字段会保留。使用 --if-digest <sha256> 可以拒绝基线已经变化的过期写入者。候选文档通过校验后才会原子替换,因此失败或冲突更新不会改动原文件。加上 --dry-run 可以只查看候选摘要而不写盘。
JSON 数组、NDJSON 流和 typed 直接调用共享最多 10,000 条 operation;每条 NDJSON 记录(包括被忽略的空白记录)最多 1 MiB。工作流文件以及文本/字节混合流均使用严格 UTF-8 解码,输入异常会在候选发布前被拒绝。
与所选 operation 不匹配的参数会直接报错,不会被静默忽略。
命令级参数也会执行同样的白名单校验,避免拼写错误在另一个命令上变成成功的空操作。
如果托管适配器需要从 operation 计算幂等键,应先使用包中的
canonicalizeFlowCliWorkflowUpdate(或 Flow 的 Rust
canonical_workflow_authoring_operation)规范化 operation,再写入日志。
它输出紧凑且确定性的 UTF-8 JSON,只统一语义等价的默认值;图相关的最终校验
仍由 update 边界负责。
使用 --set-edge <id> --source <id> --target <id> 可以原地重定向已有连线。传入 --source-handle 或 --target-handle 时只替换对应句柄;省略的句柄、连线 ID 以及未知语义/展示字段都会保留。需要显式删除句柄时使用 --clear-source-handle 或 --clear-target-handle(JSON operation 中使用 null)。这样不需要先删除再新增,也不会破坏对连线 ID 的引用。
使用 --add-node 时可通过 --parent <container-id> 把公开节点放入已有的
iteration 或 loop 作用域。新容器只有在匹配的内部起点和至少一个可执行子节点
都加入后才能发布,因此应把这些依赖操作放在同一个 JSON operation 数组或 NDJSON
流中;JSON operation 使用 parentId。注册表契约是唯一依据。iteration 只能接收
iteration-start,loop 只能接收 loop-start。不完整的中间容器只存在于候选副本中,
不会写入磁盘。
使用 --move-node <id> --parent <container-id> 可以在保留稳定节点 ID、配置、展示字段和未知扩展字段的前提下移动已有公开节点。省略 --parent 可将节点移回顶层。JSON/NDJSON 使用 {"kind":"move-node","id":"node-id","parentId":"container-id"};移回顶层时使用 parentId: null。内部起点必须留在匹配的容器中,父子循环会在发布前被拒绝。
删除必须显式确认。重复执行是幂等的,文件已不存在时返回 deleted: false。
生成工作流样例
样例只注册图结构,不会执行 task.run。宿主需要提供同名任务处理器,再选择事件存储、调度器和 worker。把样例用于新项目时,应先修改工作流名称和节点 ID,再开始创建真实运行。
校验、编译与摘要
每次修改语义字段或连线以后,按下面的顺序运行。
校验会检查文档外壳、节点类型、字段约束、端口连接、重复 ID、悬空边、自环、普通环路和容器作用域。编译成功说明顶层图以及每个遍历或循环子画布都有稳定顺序。摘要会忽略画布位置、标题、说明和选择状态,但会绑定影响执行的节点配置与连线。宿主需要完整性固定值时,应把摘要保存在发布记录中,不要反写进工作流文档。
标准输入与 CI
CI 中建议先运行校验,再把编译计划和摘要作为构建产物保存。失败输出中的每个问题都包含 code、path 和 message。修复应落在对应字段或边上,不要删除未知扩展字段来绕过错误。工作流来自外部来源时,还应审查任务名称、运行入口、公开回调和宿主绑定,CLI 不替代权限与凭据审核。
自定义节点边界
CLI 只携带官方内置 registry,也不会加载宿主应用模块。包含自定义类型的文档会收到 flow.node.unknown_type,项目不应关闭这项检查。使用自定义节点的项目需要提供类型化发布命令,导入项目 catalog,再调用 compileA3SFlowWorkflowDagForPublication。自定义节点列出了注册与发布契约。
常见错误
unknown_node 说明当前安装版本没有这个公开类型,先运行 nodes 核对清单。flow.node.internal_scope_required 说明内部入口离开了匹配容器。图校验问题通常来自错误端口、跨作用域连线或回边。字段问题会指向 workflow.graph.nodes 下的具体节点数据。
文件读取失败时,先检查命令所在目录和传入路径。标准输入一直等待时,说明上游命令还没有关闭输出,可以先把文档写入临时文件再单独运行校验。修复完成后重新执行校验、编译和摘要,最终计划应与准备发布的文档来自同一次检查。
