@pipefy/pipefy-process-coder 0.1.0 → 0.1.1

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.
Files changed (159) hide show
  1. package/.agents/skills/ppc-pipefy-flow-authoring/SKILL.md +262 -262
  2. package/.agents/skills/ppc-pipefy-flow-authoring/examples/01-main-2-danfe-consulta.json +247 -247
  3. package/.agents/skills/ppc-pipefy-flow-authoring/examples/01-main-2-webhook-retorno-consulta.json +589 -589
  4. package/.agents/skills/ppc-pipefy-flow-authoring/examples/01-main-4-recebimento-barramento.json +1391 -1391
  5. package/.agents/skills/ppc-pipefy-flow-authoring/examples/02-subflow-2-danfe-retorno.json +623 -623
  6. package/.agents/skills/ppc-pipefy-flow-authoring/examples/02-subflow-4-criacao-operacao.json +636 -636
  7. package/.agents/skills/ppc-pipefy-flow-authoring/examples/03-subflow-4-criacao-titulo.json +3642 -3642
  8. package/.agents/skills/ppc-pipefy-flow-authoring/examples/04-subflow-4-criacao-cedente.json +863 -863
  9. package/.agents/skills/ppc-pipefy-flow-authoring/examples/04-subflow-4-criacao-sacado.json +799 -799
  10. package/.agents/skills/ppc-pipefy-flow-authoring/examples/README.md +42 -42
  11. package/.agents/skills/ppc-pipefy-flow-authoring/examples/hml-01-subflow-1-titulo-acompanhamento-cobranca.json +581 -581
  12. package/.agents/skills/ppc-pipefy-flow-authoring/examples/hml-01-subflow-1-titulo-nfe-monitoramento.json +503 -503
  13. package/.agents/skills/ppc-pipefy-flow-authoring/examples/hml-01-subflow-1-titulo-retorno-bancario.json +562 -562
  14. package/.agents/skills/ppc-pipefy-flow-authoring/examples/hml-02-subflow-2-retorno-consulta-cedente.json +557 -557
  15. package/.agents/skills/ppc-pipefy-flow-authoring/examples/hml-02-subflow-2-retorno-consulta-sacado.json +609 -609
  16. package/.agents/skills/ppc-pipefy-pipe-authoring/SKILL.md +146 -146
  17. package/.agents/skills/ppc-pipefy-process-design/SKILL.md +127 -127
  18. package/.agents/skills/ppc-pipefy-workspace/SKILL.md +91 -91
  19. package/AGENTS.md +465 -456
  20. package/README.md +825 -807
  21. package/bin/pipe.js +25 -4
  22. package/dist/apply/adopt.js +128 -0
  23. package/dist/apply/agentops.js +42 -0
  24. package/dist/apply/compile.js +722 -0
  25. package/dist/apply/execute.js +277 -0
  26. package/dist/apply/flowops.js +293 -0
  27. package/dist/apply/idmap.js +233 -0
  28. package/dist/apply/mutations.js +704 -0
  29. package/dist/apply/registry.js +348 -0
  30. package/dist/apply/types.js +18 -0
  31. package/dist/cli/args.js +79 -0
  32. package/dist/cli.js +187 -0
  33. package/dist/codec/flow.js +164 -0
  34. package/dist/codec/pack.js +88 -0
  35. package/dist/codec/roundtrip.js +86 -0
  36. package/dist/codec/unpack.js +181 -0
  37. package/dist/commands/agents.js +145 -0
  38. package/dist/commands/apply.js +982 -0
  39. package/dist/commands/context.js +79 -0
  40. package/dist/commands/create.js +63 -0
  41. package/dist/commands/diff.js +294 -0
  42. package/dist/commands/flows.js +348 -0
  43. package/dist/commands/misc.js +528 -0
  44. package/dist/commands/plan.js +301 -0
  45. package/dist/commands/pull.js +511 -0
  46. package/dist/commands/runs.js +74 -0
  47. package/dist/commands/skills.js +131 -0
  48. package/dist/commands/verify.js +205 -0
  49. package/dist/config.js +125 -0
  50. package/dist/diff/agents.js +80 -0
  51. package/dist/diff/diff.js +983 -0
  52. package/dist/diff/flow.js +258 -0
  53. package/{src/diff/html.ts → dist/diff/html.js} +274 -322
  54. package/dist/diff/render.js +90 -0
  55. package/dist/model/payload.js +84 -0
  56. package/dist/model/tree.js +7 -0
  57. package/dist/model/volatile.js +54 -0
  58. package/dist/pipefy/agents.js +122 -0
  59. package/dist/pipefy/automations.js +155 -0
  60. package/dist/pipefy/capability.js +84 -0
  61. package/dist/pipefy/client.js +204 -0
  62. package/dist/pipefy/discovery.js +148 -0
  63. package/dist/pipefy/internal.js +315 -0
  64. package/dist/pipefy/ipaas.js +269 -0
  65. package/dist/pipefy/reconstruct.js +674 -0
  66. package/dist/pipefy/reference.js +172 -0
  67. package/dist/pipefy/snapshot.js +185 -0
  68. package/dist/pipefy/toolkit.js +158 -0
  69. package/dist/report/integrations.js +165 -0
  70. package/dist/report/run.js +355 -0
  71. package/dist/util/fsx.js +50 -0
  72. package/dist/util/git.js +25 -0
  73. package/dist/util/json.js +56 -0
  74. package/dist/util/log.js +69 -0
  75. package/dist/util/pool.js +42 -0
  76. package/dist/util/slug.js +23 -0
  77. package/dist/util/tui.js +287 -0
  78. package/dist/validate/index.js +86 -0
  79. package/dist/validate/integrity.js +370 -0
  80. package/dist/validate/reference.js +120 -0
  81. package/dist/validate/schema.js +278 -0
  82. package/dist/workspace/agents.js +245 -0
  83. package/{src/workspace/docs.ts → dist/workspace/docs.js} +367 -407
  84. package/dist/workspace/flows.js +149 -0
  85. package/dist/workspace/layout.js +146 -0
  86. package/dist/workspace/lock.js +83 -0
  87. package/dist/workspace/read.js +168 -0
  88. package/dist/workspace/reference.js +24 -0
  89. package/dist/workspace/stamp.js +234 -0
  90. package/dist/workspace/write.js +194 -0
  91. package/package.json +37 -35
  92. package/src/apply/adopt.ts +0 -150
  93. package/src/apply/agentops.ts +0 -71
  94. package/src/apply/compile.ts +0 -875
  95. package/src/apply/execute.ts +0 -336
  96. package/src/apply/flowops.ts +0 -399
  97. package/src/apply/idmap.ts +0 -241
  98. package/src/apply/mutations.ts +0 -955
  99. package/src/apply/registry.ts +0 -430
  100. package/src/apply/types.ts +0 -134
  101. package/src/cli/args.ts +0 -88
  102. package/src/cli.ts +0 -211
  103. package/src/codec/flow.ts +0 -199
  104. package/src/codec/pack.ts +0 -103
  105. package/src/codec/roundtrip.ts +0 -94
  106. package/src/codec/unpack.ts +0 -198
  107. package/src/commands/agents.ts +0 -184
  108. package/src/commands/apply.ts +0 -1144
  109. package/src/commands/context.ts +0 -119
  110. package/src/commands/create.ts +0 -79
  111. package/src/commands/diff.ts +0 -314
  112. package/src/commands/flows.ts +0 -414
  113. package/src/commands/misc.ts +0 -644
  114. package/src/commands/plan.ts +0 -331
  115. package/src/commands/pull.ts +0 -567
  116. package/src/commands/runs.ts +0 -83
  117. package/src/commands/skills.ts +0 -137
  118. package/src/commands/verify.ts +0 -253
  119. package/src/config.ts +0 -168
  120. package/src/diff/agents.ts +0 -122
  121. package/src/diff/diff.ts +0 -1130
  122. package/src/diff/flow.ts +0 -318
  123. package/src/diff/render.ts +0 -101
  124. package/src/model/payload.ts +0 -154
  125. package/src/model/tree.ts +0 -99
  126. package/src/model/volatile.ts +0 -55
  127. package/src/pipefy/agents.ts +0 -165
  128. package/src/pipefy/automations.ts +0 -219
  129. package/src/pipefy/capability.ts +0 -119
  130. package/src/pipefy/client.ts +0 -267
  131. package/src/pipefy/discovery.ts +0 -209
  132. package/src/pipefy/internal.ts +0 -380
  133. package/src/pipefy/ipaas.ts +0 -365
  134. package/src/pipefy/reconstruct.ts +0 -775
  135. package/src/pipefy/reference.ts +0 -251
  136. package/src/pipefy/snapshot.ts +0 -245
  137. package/src/pipefy/toolkit.ts +0 -200
  138. package/src/report/integrations.ts +0 -231
  139. package/src/report/run.ts +0 -475
  140. package/src/util/fsx.ts +0 -45
  141. package/src/util/git.ts +0 -32
  142. package/src/util/json.ts +0 -55
  143. package/src/util/log.ts +0 -76
  144. package/src/util/pool.ts +0 -48
  145. package/src/util/slug.ts +0 -26
  146. package/src/util/tui.ts +0 -335
  147. package/src/validate/index.ts +0 -123
  148. package/src/validate/integrity.ts +0 -387
  149. package/src/validate/reference.ts +0 -136
  150. package/src/validate/schema.ts +0 -328
  151. package/src/workspace/agents.ts +0 -290
  152. package/src/workspace/flows.ts +0 -191
  153. package/src/workspace/layout.ts +0 -165
  154. package/src/workspace/lock.ts +0 -148
  155. package/src/workspace/read.ts +0 -165
  156. package/src/workspace/reference.ts +0 -24
  157. package/src/workspace/stamp.ts +0 -301
  158. package/src/workspace/write.ts +0 -225
  159. /package/{src → dist}/pipefy/toolkit_bearer.py +0 -0
@@ -0,0 +1,258 @@
1
+ import { canonicalString } from "../util/json.js";
2
+ import { flowIdOf, isNewFlow } from "../workspace/flows.js";
3
+ /**
4
+ * Keys that never carry intent and must not produce a change.
5
+ *
6
+ * `sampleData` is generated by testing a step, `lastUpdatedDate` moves on every
7
+ * write, and the server-minted ids move whenever a version is created. Comparing
8
+ * them would make every flow permanently dirty.
9
+ */
10
+ const VOLATILE_NODE_KEYS = new Set(['sampleData', 'lastUpdatedDate']);
11
+ const VOLATILE_FLOW_KEYS = new Set([
12
+ 'created',
13
+ 'updated',
14
+ 'publishedVersionId',
15
+ 'operationStatus',
16
+ 'timeSavedPerRun',
17
+ 'createdBy',
18
+ 'updatedBy',
19
+ 'ownerId',
20
+ 'externalId',
21
+ 'id',
22
+ 'flowId',
23
+ 'projectId',
24
+ 'templateId',
25
+ 'backupFiles',
26
+ /**
27
+ * Derived by the API from the inline `{{connections[...]}}` references rather
28
+ * than supplied, so it is an echo of the nodes and never an intent of its own.
29
+ */
30
+ 'connectionIds',
31
+ 'state',
32
+ ]);
33
+ const comparableNode = (n) => {
34
+ const out = {};
35
+ for (const [k, v] of Object.entries(n)) {
36
+ if (VOLATILE_NODE_KEYS.has(k))
37
+ continue;
38
+ if (k.startsWith('_'))
39
+ continue; // link metadata is compared separately, as structure
40
+ if (k === 'settings' && v && typeof v === 'object') {
41
+ const s = {};
42
+ for (const [sk, sv] of Object.entries(v)) {
43
+ if (VOLATILE_NODE_KEYS.has(sk))
44
+ continue;
45
+ s[sk] = sv;
46
+ }
47
+ out[k] = s;
48
+ continue;
49
+ }
50
+ out[k] = v;
51
+ }
52
+ return out;
53
+ };
54
+ const nodeDeltas = (before, after) => {
55
+ const a = comparableNode(before);
56
+ const b = comparableNode(after);
57
+ const keys = [...new Set([...Object.keys(a), ...Object.keys(b)])].sort();
58
+ const out = [];
59
+ for (const k of keys) {
60
+ if (canonicalString(a[k]) !== canonicalString(b[k]))
61
+ out.push({ key: k, before: a[k], after: b[k] });
62
+ }
63
+ // Structure: a node whose place in the chain moved is a change even when its
64
+ // settings are identical.
65
+ for (const link of ['_nextAction', '_firstLoopAction', '_children']) {
66
+ if (canonicalString(before[link]) !== canonicalString(after[link])) {
67
+ out.push({ key: link, before: before[link], after: after[link] });
68
+ }
69
+ }
70
+ return out;
71
+ };
72
+ const flowLabel = (tree) => String(tree.version['displayName'] ?? flowIdOf(tree) ?? 'flow');
73
+ /** Match flows by id, then by display name for one the workspace is creating. */
74
+ const matchFlows = (before, after) => {
75
+ const pairs = [];
76
+ const added = [];
77
+ const removed = [...before];
78
+ for (const a of after) {
79
+ const id = flowIdOf(a);
80
+ let hitAt = id ? removed.findIndex((b) => flowIdOf(b) === id) : -1;
81
+ if (hitAt < 0 && isNewFlow(a)) {
82
+ hitAt = removed.findIndex((b) => flowLabel(b) === flowLabel(a));
83
+ }
84
+ if (hitAt >= 0) {
85
+ pairs.push([removed[hitAt], a]);
86
+ removed.splice(hitAt, 1);
87
+ }
88
+ else {
89
+ added.push(a);
90
+ }
91
+ }
92
+ return { pairs, added, removed };
93
+ };
94
+ export const diffFlows = (before, after) => {
95
+ const changes = [];
96
+ const skipped = [];
97
+ if (!before || !after) {
98
+ return { changes, skipped: [{ reason: 'one side has no flows section, so flows are not diffed' }] };
99
+ }
100
+ if (before.meta.coverage !== 'complete' || after.meta.coverage !== 'complete') {
101
+ /**
102
+ * The whole reason coverage exists. A pipe whose iPaaS could not be reached
103
+ * reports zero flows, and diffing that against a workspace that has some would
104
+ * propose deleting every one of them.
105
+ */
106
+ return {
107
+ changes,
108
+ skipped: [
109
+ {
110
+ reason: `flows coverage is ${before.meta.coverage}/${after.meta.coverage}, not complete — ` +
111
+ 'not diffed, because absence here is not evidence of absence',
112
+ },
113
+ ],
114
+ };
115
+ }
116
+ const { pairs, added, removed } = matchFlows(before.flows, after.flows);
117
+ for (const tree of added) {
118
+ changes.push({
119
+ op: 'flow.create',
120
+ key: `flow:new:${flowLabel(tree)}`,
121
+ label: `create flow "${flowLabel(tree)}" (${tree.nodes.length} nodes)`,
122
+ flowId: null,
123
+ flowName: flowLabel(tree),
124
+ afterFlow: tree,
125
+ deltas: [],
126
+ flags: [],
127
+ });
128
+ }
129
+ for (const tree of removed) {
130
+ changes.push({
131
+ op: 'flow.delete',
132
+ key: `flow:${flowIdOf(tree)}`,
133
+ label: `delete flow "${flowLabel(tree)}"`,
134
+ flowId: flowIdOf(tree),
135
+ flowName: flowLabel(tree),
136
+ beforeFlow: tree,
137
+ deltas: [],
138
+ flags: ['destructive'],
139
+ });
140
+ }
141
+ for (const [b, a] of pairs) {
142
+ const flowId = flowIdOf(a) ?? flowIdOf(b);
143
+ const name = flowLabel(a);
144
+ if (flowLabel(b) !== flowLabel(a)) {
145
+ changes.push({
146
+ op: 'flow.rename',
147
+ key: `flow:${flowId}:name`,
148
+ label: `rename flow "${flowLabel(b)}" → "${flowLabel(a)}"`,
149
+ flowId,
150
+ flowName: name,
151
+ deltas: [{ key: 'displayName', before: flowLabel(b), after: flowLabel(a) }],
152
+ flags: [],
153
+ });
154
+ }
155
+ if (String(b.flow['status'] ?? '') !== String(a.flow['status'] ?? '')) {
156
+ changes.push({
157
+ op: 'flow.status',
158
+ key: `flow:${flowId}:status`,
159
+ label: `flow "${name}" ${b.flow['status']} → ${a.flow['status']}`,
160
+ flowId,
161
+ flowName: name,
162
+ deltas: [{ key: 'status', before: b.flow['status'], after: a.flow['status'] }],
163
+ // Enabling a flow arms it against live traffic. That is never incidental.
164
+ flags: String(a.flow['status']) === 'ENABLED' ? ['arms-flow'] : [],
165
+ });
166
+ }
167
+ const beforeNodes = new Map(b.nodes.map((n) => [n.name, n]));
168
+ const afterNodes = new Map(a.nodes.map((n) => [n.name, n]));
169
+ for (const [nodeName, node] of afterNodes) {
170
+ const prior = beforeNodes.get(nodeName);
171
+ if (!prior) {
172
+ changes.push({
173
+ op: 'node.create',
174
+ key: `flow:${flowId}:node:${nodeName}`,
175
+ label: `flow "${name}": add ${nodeName} [${node.type}] ${String(node['displayName'] ?? '')}`.trim(),
176
+ flowId,
177
+ flowName: name,
178
+ nodeName,
179
+ after: node,
180
+ /**
181
+ * The whole intended tree, not just the node: `ADD_ACTION` needs the
182
+ * parent this node hangs from, and that is a property of where `node`
183
+ * sits in the chain — found by scanning every node's `_nextAction` /
184
+ * `_firstLoopAction` / `_children` for `nodeName` (apply/flowops.ts
185
+ * `parentOf`), the same lookup a brand-new flow's build already uses.
186
+ */
187
+ afterFlow: a,
188
+ deltas: [],
189
+ flags: [],
190
+ });
191
+ continue;
192
+ }
193
+ const deltas = nodeDeltas(prior, node);
194
+ if (!deltas.length)
195
+ continue;
196
+ const isTrigger = nodeName === 'trigger';
197
+ changes.push({
198
+ op: isTrigger ? 'trigger.update' : 'node.update',
199
+ key: `flow:${flowId}:node:${nodeName}`,
200
+ label: `flow "${name}": ${isTrigger ? 'trigger' : nodeName} — ${deltas.map((d) => d.key).join(', ')}`,
201
+ flowId,
202
+ flowName: name,
203
+ nodeName,
204
+ before: prior,
205
+ after: node,
206
+ deltas,
207
+ flags: [],
208
+ });
209
+ }
210
+ for (const [nodeName, node] of beforeNodes) {
211
+ if (afterNodes.has(nodeName))
212
+ continue;
213
+ changes.push({
214
+ op: 'node.delete',
215
+ key: `flow:${flowId}:node:${nodeName}`,
216
+ label: `flow "${name}": delete ${nodeName} [${node.type}]`,
217
+ flowId,
218
+ flowName: name,
219
+ nodeName,
220
+ before: node,
221
+ deltas: [],
222
+ flags: ['destructive'],
223
+ });
224
+ }
225
+ }
226
+ return { changes, skipped };
227
+ };
228
+ export const renderFlowChanges = (cs) => {
229
+ const lines = [];
230
+ for (const s of cs.skipped)
231
+ lines.push(` flows not diffed: ${s.reason}`);
232
+ if (!cs.changes.length) {
233
+ if (!cs.skipped.length)
234
+ lines.push(' flows: no changes');
235
+ return lines.join('\n');
236
+ }
237
+ const byFlow = new Map();
238
+ for (const c of cs.changes) {
239
+ const k = c.flowId ?? `new:${c.flowName}`;
240
+ byFlow.set(k, [...(byFlow.get(k) ?? []), c]);
241
+ }
242
+ for (const [, group] of byFlow) {
243
+ lines.push('');
244
+ lines.push(` ${group[0]?.flowName ?? 'flow'}`);
245
+ for (const c of group) {
246
+ const mark = c.flags.includes('destructive') ? '-' : c.op.endsWith('create') ? '+' : '~';
247
+ lines.push(` ${mark} ${c.label}`);
248
+ for (const d of c.deltas.slice(0, 6)) {
249
+ const short = (v) => {
250
+ const s = canonicalString(v);
251
+ return s.length > 90 ? `${s.slice(0, 90)}…` : s;
252
+ };
253
+ lines.push(` ${d.key}: ${short(d.before)} -> ${short(d.after)}`);
254
+ }
255
+ }
256
+ }
257
+ return lines.join('\n');
258
+ };