fix(wizard): match real EA2 apply-batch contract

Wizard was sending ops in the SDX-era shape:
  { collection, op: 'insert', flow_key, _key, ... }
with actor + flow_key duplicated at the request root.

Real EA2 contract (verified against ea2.baseline.svc/openapi.json):
  POST /api/ea2/apply-batch
  body: { request_id (8..128), ops: BatchOp[] (1..500), description? }
  additionalProperties=false at request root
  ops are a discriminated union by 'op':
    create / update / delete (nodes by coll+key+data)
    create_edge / delete_edge (edges by edge_coll+from+to)
  actor/tenant resolved from Bearer token, not body.

Adds typed CreateOp/UpdateOp/DeleteOp/CreateEdgeOp/DeleteEdgeOp + wizardApi.ops
helpers (createNode, createEdge, publishFlow) so call sites don't have to
remember the discriminator shape.

Wizard.handleStructureSave + handlePublish updated to use the helpers.
This commit is contained in:
2026-06-14 12:14:09 +04:00
parent fab3b988b4
commit 82de744985
2 changed files with 115 additions and 62 deletions
+14 -26
View File
@@ -103,24 +103,19 @@ export default function Wizard() {
if (!draft.flowKey || !actor) return;
setWorking(true);
try {
const ops: BatchOperation[] = draft.nodes.map(n => ({
collection: "ea2_node",
op: "insert",
flow_key: draft.flowKey,
...n
}));
// Link them sequentially
for (let i = 0; i < draft.nodes.length - 1; i++) {
ops.push({
collection: "ea2_edge",
op: "insert",
flow_key: draft.flowKey,
_from: `ea2_node/${draft.nodes[i]._key}`,
_to: `ea2_node/${draft.nodes[i+1]._key}`,
kind: "next"
});
}
const ops: BatchOperation[] = [
...draft.nodes.map(n =>
wizardApi.ops.createNode(draft.flowKey!, {
_key: n._key,
display_name: n.display_name,
dispatch_kind: n.dispatch_kind,
agent_capability: n.agent_capability,
})
),
...draft.nodes.slice(0, -1).map((n, i) =>
wizardApi.ops.createEdge(draft.flowKey!, n._key, draft.nodes[i + 1]._key, "next")
),
];
await wizardApi.applyBatch(draft.flowKey, ops, actor);
updateDraft({ step: "Generate" });
@@ -170,14 +165,7 @@ export default function Wizard() {
if (!draft.flowKey || !actor) return;
setWorking(true);
try {
const ops: BatchOperation[] = [
{
collection: "ea2_flow",
op: "update",
_key: draft.flowKey,
status: "published"
}
];
const ops: BatchOperation[] = [wizardApi.ops.publishFlow(draft.flowKey)];
await wizardApi.applyBatch(draft.flowKey, ops, actor);
updateDraft({ step: "Publish" });
setPublishedKey(draft.flowKey);