mcpField
A
action-creator

action-creator

github.com/datex开发92 次安装
代码仓库

关于 action-creator

action-creator 是用于在 Datex Studio 分支上创建或修改服务端操作的技能。它聚焦于事务边界内组合实体 CRUD 与其他操作,并通过函数提供 UI 调用桥接。

主要功能

  1. 01创建或修改服务端操作
  2. 02组合实体 CRUD 与其他操作
  3. 03配置事务提交与回滚逻辑
  4. 04通过 CLI 验证并提交配置
  5. 05检查调用方参数契约

适用场景

  1. 01实现需要原子提交或回滚的写入
  2. 02编排多个操作完成事务流程
  3. 03为 UI 操作创建函数调用桥接

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/datex/skills --skill action-creator

安装后在 Claude Code 中输入/action-creator确认已加载。

附带文件evals/evals.jsonreferences/actions.md

详细介绍

Action Creator

在分支上创建或修改 Datex Studio action(configurationTypeId=18)——在单个提交/回滚边界内组合实体 CRUD 和其他 action 的服务器端事务流。UI 不会直接调用 action——需要用函数包装 action 调用,作为 UI → action 桥接。

参考资料

依赖项

  • requirements-gathering 技能 — 如果当前对话上下文中尚无需求简报,则调用该技能生成一份
  • function-creator 技能 — 如果尚不存在包装 UI 函数(UI→action 桥接),或需求实际上是非事务性的(action 与 function 的选择更倾向于 function),则调用该技能
  • datasource-creator 技能 — 如果 action 需要的 -footprintDatasource.json(FPDS)在当前分支上尚不存在,则调用该技能
  • component-wiring-check 技能 — 推送前审查 action 调用方的 configParameters ↔ 目标 inParams 契约
  • backend-test-creator 技能 — 编写 mocha 测试套件来覆盖 action 时调用该技能(这是正确的做法,避免滥用 action 作为临时测试工具)
  • impact-analysis 技能 — 修改现有 action 的 inParams / outParams 时调用该技能(检测签名变更是否造成破坏)

CLI 生命周期

Action 的编写通过 dxs configuration 完成——这是适用于所有平台配置类型的通用 CRUD 基元。没有 dxs action 子命令,也不支持字段级补丁;需要构建(或获取并提取)完整 JSON 主体,编辑后再将其整体推送回去。CLI 中的类型标识符是 footprintflow(小写,与 ConfigurationEndpoints.normalize_type 的输出一致),而不是 footprintFlow。

创建新 action:

# 1. Build body.json from scratch (see references/actions.md → Minimal Valid Skeleton)
# 2. Validate — gates the push. Exit 1 = errors found (read validation_errors, fix, re-run), not a broken CLI
dxs configuration validate footprintflow -b <branchId> -D body.json
# 3. Create
dxs configuration upsert footprintflow -b <branchId> -D body.json

编辑现有 action:

# 1. Fetch — note the envelope wrapper
dxs configuration get footprintflow <configId> -b <branchId> -O envelope.json
# 2. EXTRACT THE INNER BODY (round-trip footgun guard — see "Round-trip rule" below)
jq .json envelope.json > body.json
# 3. Edit body.json
# 4. Validate — gates the push. Exit 1 = errors found (read validation_errors, fix, re-run), not a broken CLI
dxs configuration validate footprintflow -b <branchId> -D body.json
# 5. Push
dxs configuration upsert footprintflow -b <branchId> -D body.json
往返规则(关键)

编辑现有配置时,绝不要将 envelope.json 直接通过管道传入 dxs configuration upsert——这会悄无声息地破坏配置内容。上面更正后的步骤(先用 jq 提取内部的 .json,再进行编辑)是所有往返操作的强制要求。规范的往返流程及其背后的错误,请参阅 ../datex-studio-shared/configuration-roundtrip.md。

对于操作,这条规则尤为重要,因为操作 JSON 包含两个 code 字段——Datex Studio 执行的运行时字段是 nodes[0].stepConfig.executeCodeConfig.code;顶层的 action['code'] 是一个反规范化副本。只写入其中一个字段,用 grep 检查时可能看不出来,但会破坏运行时。请参阅 references/actions.md → 上线前检查清单第 5 项。

工作流

[Phase 1: Setup + Requirements]
Follow branch-setup.md for branch/connection selection
        |
[requirements brief in context?]
  +-----+-----+
  |            |
 YES          NO -> invoke `requirements-gathering`
  |            |
  +-----+------+
        |
[Phase 2: Action vs Function decision]
Consult references/actions.md → "Purpose & When to Use":
  - transactional / entity CRUD / FPDS access -> action
  - pure read/transform / UI-facing / no atomicity -> function
If function -> invoke `function-creator` instead and stop here.
If action but UI needs to invoke it -> the UI calls a function
that wraps the action; invoke `function-creator` for the wrapper
in addition to authoring this action.
        |
[Phase 3: Author action body]
Build body.json:
  - File shape (configurationTypeId=18, apiSettingName=FootprintApi,
    referenceName ends _action, file suffix -footprintFlow.json)
  - Step graph (ExecuteCodeActivity in nodes[0])
  - inParams/outParams with FULL fat parameter-descriptor boilerplate
  - code string with \r\n line endings inside the JSON
  - Error handling: every try/catch either format-and-rethrows
    or is REMOVED. Bare swallows leave the transaction unresolved
    and surface elsewhere as "Transaction must begin first".
  - $datasources.* targets FPDS only; no $db; no $apis
  - Invoke `datasource-creator` if an FPDS dependency is missing
  - Invoke `component-wiring-check` to audit callers' configParameters
        |
[Phase 4: Validate + push]
dxs configuration validate footprintflow -b <branchId> -D body.json
        |
   +----+----+
   |         |
  CREATE   MODIFY-EXISTING
   |         |
   |         use the corrected round-trip
   |         (get -O envelope -> jq .json -> body)
   |         |
   |         if inParams/outParams changed:
   |           invoke `impact-analysis`
   |         |
   +----+----+
        |
        v
dxs configuration upsert footprintflow -b <branchId> -D body.json
   (upsert creates or updates by referenceName — one command for both)
        |
[Phase 5: Verify in Studio (optional)]
Exercise the action via its wrapping function (or via a
backend-test-creator mocha suite). Watch for delayed
"Transaction must begin first" symptoms in unrelated flows
— that's the silent-swallow signature.
        |
[invoke `post-edit-verification`; then `component-validator`]

阶段详情

阶段 1:设置 + 需求
  1. 按照 ../datex-studio-shared/branch-setup.md 选择分支和连接。绝不要猜测分支 ID——请用户确认。
  2. 检查对话上下文中是否已有需求简报(由 requirements-gathering 或其他调用技能生成)。
    • 已有简报——使用该简报。简报应说明原子性需求(操作是否需要作为一个整体回滚?)、涉及的实体/数据源,以及操作的调用方式(函数包装器、另一个操作、后端测试)。
    • 没有简报——先调用 requirements-gathering 技能。原子性问题是下一阶段决定使用操作还是函数的关键依据。
阶段 2:决定使用操作还是函数

编写前,请参阅 references/actions.md → 用途与适用场景。这并非风格上的选择——操作和函数位于不同层级,运行时能力也不可互换。

符合以下情况时,选择操作:

  • 工作必须是原子的(实体写入要么全部提交,要么全部回滚)。
  • 逻辑需要组合其他操作或实体 CRUD。
  • 代码需要访问 -footprintDatasource.json(FPDS)数据源——这类数据源仅限操作层使用。

符合以下情况时,改用函数:

如果答案是“函数”,请停止并调用 function-creator。如果答案是“操作,但 UI 需要触发它”,仍然需要一个函数——UI 调用函数,函数再通过 $apis.<Package>.FootprintApi.extendedActions.<action_name>({ ... }) 调用操作。在此处编写操作,并调用 function-creator 创建包装器。

阶段 3:编写 action 主体

根据 references/actions.md → 最小有效骨架 中的骨架构建 body.json。要点:

  1. 文件基础信息。 configurationTypeId: 18。apiSettingName: "FootprintApi"。referenceName 以 _action 结尾(例如 update_task_status_action)。非对称命名:文件后缀为 -footprintFlow.json(不是 -action.json);_action 标识仅位于 referenceName 中 — 另请参阅通用检查项(../datex-studio-conventions/universal-checklist.md)。详见 references/actions.md → 文件位置与命名 和 ../datex-studio-conventions/naming-conventions.md。

  2. inParams / outParams 样板结构。 每个条目都使用完整的参数描述符 — 共 14 个字段,不可省略。缺少字段是导入被拒的常见原因。确切结构请参阅最小有效骨架。

  3. code 字符串。 步骤图通常只有一个位于 nodes[0] 的 ExecuteCodeActivity。在 JSON 内,换行符转义为 \\r\\n(解码为 \r\n)。编辑嵌入代码时,优先使用 Python 的 json.load/json.dump,不要直接替换原始字符串。

  4. Action JSON 中有两个 code 字段;只有内层字段会运行。 运行时字段是 nodes[0].stepConfig.executeCodeConfig.code。顶层的 action['code'] 是反规范化镜像 — 只写入该字段不会影响运行时,但通过 json.load 和 grep 查看文件时看起来仍然正确。重新打包时,同时写入两个字段并断言它们一致。详见 references/actions.md → 推送前检查清单第 5 项。

  5. 错误处理会影响运行。 Action 在事务中运行。悄悄吞掉错误会导致事务无法解决,随后调用的无关 action 会报出误导性的 "Transaction must begin first"。这是最常见的 action 错误。

    规则:

    • 除非 catch 能带来价值,否则不要捕获。 只吞掉错误或直接重新抛出的 try/catch,严格来说比不使用 try/catch 更糟 — 删除它,让异常继续传播。
    • 捕获时,格式化错误后重新抛出。 仅在需要补充正在尝试执行的操作以及涉及的 key/id 时才捕获,然后 throw new Error(...)。
    // Good — enriches with context and rethrows
    try {
      await $flows.Utilities.crud_update_entity({ entity: 'Tasks', keys, properties });
    } catch (e) {
      throw new Error(`Failed to update task ${keys[0].value}: ${e.message}`);
    }
    
    // Bad — swallows; transaction never closes; next action throws "Transaction must begin first"
    try { await $flows.Utilities.crud_update_entity(...); } catch (e) { /* nothing */ }
    
    // Bad — pointless rewrap; just delete the try/catch
    try { await $flows.Utilities.crud_update_entity(...); } catch (e) { throw e; }
    

    诊断 "Transaction must begin first" 错误时,问题几乎从不出在抛出该错误的 action 中 — 而是出在之前某个不同代码路径上吞掉错误的 action 中。通过 impact-analysis / dxs source explore 枚举该分支上的功能相关 action,并检查每个 action 是否存在裸 catch 块,将其作为首要诊断步骤。

  6. code 字符串中的层级合规性。 使用 $flows.<Package>.<action_name> 调用另一个 action。$datasources.<Package>.<name>.get({...}) 只能用于 FPDS(-footprintDatasource.json)— 在 action 中调用 -datasource.json 属于跨层级违规。Action 中无法使用 $db(仅限函数层级)。Action 中很少使用 $apis(这是函数→action 的调用方向)。详见 ../datex-studio-runtime/runtime-globals.md 和 ../datex-studio-runtime/calling-conventions.md。

  7. 如果缺少 FPDS 依赖项, 在推送 action 之前调用 datasource-creator 添加该依赖项。

  8. 调用方契约审计。 此 action 的每个调用方都必须声明完整的 configParameters 契约 — 此 action 声明的每个 inParam 都必须在调用方中有对应条目,包括未使用且 value: null 的条目。推送前调用 component-wiring-check 审计引用契约。详见 ../component-wiring-check/references/component-wiring.md。

阶段 4:验证并推送
# Validate the body locally against the branch. Exit 1 = validation found errors
# (read validation_errors, fix body.json, re-run) — not a broken CLI. Do not push on exit 1.
dxs configuration validate footprintflow -b <branchId> -D body.json

# For a new action
dxs configuration upsert footprintflow -b <branchId> -D body.json

# For modify-existing (round-trip — never skip the jq extract)
dxs configuration get footprintflow <configId> -b <branchId> -O envelope.json
jq .json envelope.json > body.json
# ... edit body.json ...
dxs configuration upsert footprintflow -b <branchId> -D body.json

如果要更改现有操作的 inParams / outParams,请在推送前调用 impact-analysis 技能,找出所有调用方;在同一轮编辑中逐一协调处理(函数、其他操作、后端测试),或者取得用户对破坏性更改的明确批准。

验证会在推送前发现缺少必填字段、参数描述符形状错误和引用错误。它无法捕获静默吞掉错误 / "Transaction must begin first" 这一类问题——这是行为问题,只会在运行时显现。推送前请逐项检查 references/actions.md → 推送前检查清单,尤其要注意不得静默吞掉错误的 try/catch 项。

阶段 5:在 Studio 中验证(可选)

通过常规调用路径测试操作:

  • 通过封装函数(UI 桥接)——打开触发该函数的屏幕,并确认操作按设计提交 / 回滚。
  • 通过另一项操作——从编排操作的流程中调用,并验证组合事务能成功或原子性回滚。
  • 通过 mocha 测试套件——使用 backend-test-creator 编写。与其滥用操作作为临时测试工具,这才是正确的替代方案。

留意下游流程中无关位置出现的延迟 "Transaction must begin first" 症状——这是静默吞掉错误的特征。如果发现此问题,请返回阶段 3 的步骤 5,审查刚刚编辑的操作(以及它组合调用的任何操作)中的 try/catch 块。

如果运行中的应用不可用,请重新获取配置(使用修正后的 jq .json 提取模式),并与 body.json 比对,确认推送已生效。

推送前检查清单

推送前,请完整检查 references/actions.md → 推送前检查清单。快速版如下:

  1. 命名不对称。 文件后缀为 -footprintFlow.json。referenceName 以 _action 结尾。两者不同——不要将它们统一。
  2. 顶层常量。 configurationTypeId: 18、apiSettingName: "FootprintApi"、description 非空且不超过 100 个字符,并且已设置 accessModifier。
  3. 每个 inParams/outParams 条目都使用完整的参数描述符样板——共 14 个字段,不得省略。
  4. code 的行尾符在解码后的字符串中为 \r\n(JSON 层会转义为 \\r\\n)。
  5. 两个 code 字段均已写入且内容一致——顶层镜像与 nodes[0].stepConfig.executeCodeConfig.code 必须一致;只有嵌套字段会运行。
  6. 所有 $datasources.* 调用均指向 FPDS(-footprintDatasource.json)。不得使用 $db.*(仅限函数层)。
  7. 每个 try/catch 要么格式化错误后重新抛出,要么移除。 不得静默吞掉错误,也不得直接使用 throw e。这是最重要的一条规则。
  8. 调用方声明完整的 configParameters 合约——此操作声明的每个 inParam 都必须在调用方中有对应条目,包括未使用且 value: null 的参数。使用 component-wiring-check 进行审查。

常见错误

错误修正方法
使用会吞掉错误或直接重新抛出错误的 try/catch删除此代码块。事务会保持打开状态;下一个无关操作会抛出 "Transaction must begin first"。仅在需要添加上下文信息以格式化错误并重新抛出时才使用 catch。
通过读取抛出 "Transaction must begin first" 的操作来诊断此错误问题几乎总是出在上游——之前某个操作在另一条代码路径上吞掉了错误。使用 impact-analysis 枚举分支上该功能的操作,然后逐一检查是否存在裸 catch 代码块。
文件名使用 *-action.json,而不是 *-footprintFlow.json命名不对称:_action 标识仅出现在 referenceName 中;文件后缀仍为 -footprintFlow.json。
在操作代码中通过 $datasources 调用 -datasource.json违反层级规则。操作层只能访问 -footprintDatasource.json(FPDS)。如有需要,使用 datasource-creator 添加 FPDS 变体。
在操作代码中调用 $db.*$db 仅限函数层使用。将读取操作移到函数中,并从包装函数调用该函数。
只写入顶层 action['code'] 镜像,而不更新 nodes[0].stepConfig.executeCodeConfig.code运行时无法识别——运行时执行的是嵌套字段。两处都要写入,并断言两者一致。
UI 流程尝试直接调用操作UI 无法调用操作。编写一个包装该操作的函数,并让 UI 调用此函数。调用 function-creator 创建包装函数。
将 dxs configuration get -O envelope.json 的输出直接传入 dxs configuration upsert -D envelope.json这会静默破坏配置内容。编辑前务必先运行 jq .json envelope.json > body.json。请参阅上文“往返规则”。
使用简写的 inParams/outParams 描述符(省略 objectTypeDef、isCollection 等字段)导入会被拒绝——参数描述符的模板包含 14 个字段,要求非常严格。请使用骨架中的完整结构。
description 超过 100 个字符SQL 列长度有限制——推送时验证会失败。请精简。
修改现有操作的 inParams/outParams,但未检查调用方会悄无声息地或明显地破坏所有调用方。先调用 impact-analysis;并在同一次编辑中协调好调用方。

编辑后,调用 post-edit-verification,以发现 description/JSON/schema 违规问题。最终审核时,调用 component-validator。

评论

支持 Markdown