@bpmnkit/core 0.1.1 → 0.1.2

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 (56) hide show
  1. package/README.md +2 -0
  2. package/dist/bpmn/agentic.d.ts +121 -0
  3. package/dist/bpmn/agentic.js +97 -0
  4. package/dist/bpmn/auto-layout.d.ts +5 -5
  5. package/dist/bpmn/auto-layout.js +592 -36
  6. package/dist/bpmn/bpmn-builder.d.ts +56 -0
  7. package/dist/bpmn/bpmn-builder.js +148 -182
  8. package/dist/bpmn/bpmn-model.d.ts +4 -0
  9. package/dist/bpmn/bpmn-parser.js +9 -1
  10. package/dist/bpmn/bpmn-serializer.js +6 -0
  11. package/dist/bpmn/optimize/agentic.d.ts +10 -0
  12. package/dist/bpmn/optimize/agentic.js +88 -0
  13. package/dist/bpmn/optimize/deploy.d.ts +16 -0
  14. package/dist/bpmn/optimize/deploy.js +143 -0
  15. package/dist/bpmn/optimize/feel-syntax.d.ts +12 -0
  16. package/dist/bpmn/optimize/feel-syntax.js +87 -0
  17. package/dist/bpmn/optimize/feel.js +5 -2
  18. package/dist/bpmn/optimize/flow.js +22 -2
  19. package/dist/bpmn/optimize/index.js +20 -9
  20. package/dist/bpmn/optimize/types.d.ts +10 -1
  21. package/dist/bpmn/zeebe-extensions.d.ts +27 -0
  22. package/dist/bpmn/zeebe-extensions.js +38 -0
  23. package/dist/index.d.ts +6 -1
  24. package/dist/index.js +2 -0
  25. package/dist/layout/annotations.js +36 -1
  26. package/dist/layout/collaboration/alignment.d.ts +26 -0
  27. package/dist/layout/collaboration/alignment.js +66 -0
  28. package/dist/layout/collaboration/ordering.d.ts +21 -0
  29. package/dist/layout/collaboration/ordering.js +102 -0
  30. package/dist/layout/index.d.ts +1 -0
  31. package/dist/layout/layout-engine.d.ts +13 -3
  32. package/dist/layout/layout-engine.js +9 -4
  33. package/dist/layout/semantic/bands.d.ts +19 -0
  34. package/dist/layout/semantic/bands.js +324 -0
  35. package/dist/layout/semantic/graph.d.ts +29 -0
  36. package/dist/layout/semantic/graph.js +217 -0
  37. package/dist/layout/semantic/index.d.ts +13 -0
  38. package/dist/layout/semantic/index.js +181 -0
  39. package/dist/layout/semantic/place.d.ts +40 -0
  40. package/dist/layout/semantic/place.js +271 -0
  41. package/dist/layout/semantic/route.d.ts +14 -0
  42. package/dist/layout/semantic/route.js +454 -0
  43. package/dist/layout/types.d.ts +17 -0
  44. package/dist/plan/compile.d.ts +39 -0
  45. package/dist/plan/compile.js +380 -0
  46. package/dist/plan/extract.d.ts +31 -0
  47. package/dist/plan/extract.js +248 -0
  48. package/dist/plan/index.d.ts +6 -0
  49. package/dist/plan/index.js +5 -0
  50. package/dist/plan/merge.d.ts +13 -0
  51. package/dist/plan/merge.js +80 -0
  52. package/dist/plan/slug.d.ts +5 -0
  53. package/dist/plan/slug.js +22 -0
  54. package/dist/plan/types.d.ts +225 -0
  55. package/dist/plan/types.js +13 -0
  56. package/package.json +2 -2
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Applies a `ProcessPlan` delta onto an already-compiled `BpmnDefinitions`
3
+ * process — an id-based structural merge, not a byte-stable patch: elements
4
+ * whose id already exists are replaced, new elements are appended, and
5
+ * auto-layout re-runs over the whole diagram (so untouched elements keep
6
+ * their meaning but not necessarily their exact DI coordinates).
7
+ */
8
+ import { applyAutoLayout } from "../bpmn/auto-layout.js";
9
+ import { Bpmn } from "../bpmn/index.js";
10
+ import { optimize } from "../bpmn/optimize/index.js";
11
+ import { compilePlan } from "./compile.js";
12
+ /**
13
+ * Compiles `delta` standalone, then merges its elements/flows into
14
+ * `existing`'s matching process by id (matching ids are replaced, new ids
15
+ * are appended). `delta.steps[0]` must still be a `start` step — the merge
16
+ * only uses `delta`'s flow elements and sequence flows, and drops the
17
+ * delta's own start/end events when a same-id start/end already exists in
18
+ * `existing`.
19
+ */
20
+ export function mergePlan(existing, delta, opts = {}) {
21
+ const deltaResult = compilePlan(delta, { ...opts, skipAutoFix: true });
22
+ if (!deltaResult.defs)
23
+ return deltaResult;
24
+ const targetProcess = existing.processes.find((p) => p.id === delta.process.id) ?? existing.processes[0];
25
+ const deltaProcess = deltaResult.defs.processes[0];
26
+ if (!targetProcess || !deltaProcess) {
27
+ return { problems: [{ path: "process", message: "Could not resolve a process to merge into" }] };
28
+ }
29
+ const problems = [];
30
+ for (const el of deltaProcess.flowElements) {
31
+ const existingIndex = targetProcess.flowElements.findIndex((e) => e.id === el.id);
32
+ if (existingIndex >= 0)
33
+ targetProcess.flowElements[existingIndex] = el;
34
+ else
35
+ targetProcess.flowElements.push(el);
36
+ }
37
+ // Sequence-flow ids aren't stable across compiles, so merging by flow id
38
+ // would leave stale flows around any element the delta re-wires. Instead:
39
+ // drop every existing flow touching an element the delta redefines, then
40
+ // add the delta's flows fresh. Flows between two untouched elements are
41
+ // left alone.
42
+ const deltaElementIds = new Set(deltaProcess.flowElements.map((e) => e.id));
43
+ targetProcess.sequenceFlows = targetProcess.sequenceFlows.filter((f) => !deltaElementIds.has(f.sourceRef) && !deltaElementIds.has(f.targetRef));
44
+ targetProcess.sequenceFlows.push(...deltaProcess.sequenceFlows);
45
+ // Pull in any new root error/message/signal/escalation definitions the delta introduced.
46
+ for (const err of deltaResult.defs.errors) {
47
+ if (!existing.errors.some((e) => e.id === err.id))
48
+ existing.errors.push(err);
49
+ }
50
+ for (const msg of deltaResult.defs.messages) {
51
+ if (!existing.messages.some((m) => m.id === msg.id))
52
+ existing.messages.push(msg);
53
+ }
54
+ for (const sig of deltaResult.defs.signals) {
55
+ if (!existing.signals.some((s) => s.id === sig.id))
56
+ existing.signals.push(sig);
57
+ }
58
+ for (const esc of deltaResult.defs.escalations) {
59
+ if (!existing.escalations.some((e) => e.id === esc.id))
60
+ existing.escalations.push(esc);
61
+ }
62
+ let laidOut = applyAutoLayout(existing);
63
+ if (!opts.skipAutoFix) {
64
+ const report = optimize(laidOut);
65
+ for (const finding of report.findings)
66
+ finding.applyFix?.(laidOut);
67
+ laidOut = applyAutoLayout(laidOut);
68
+ }
69
+ const finalReport = optimize(laidOut);
70
+ for (const finding of finalReport.findings) {
71
+ if (finding.severity === "error") {
72
+ problems.push({
73
+ path: finding.elementIds.length > 0 ? `element:${finding.elementIds.join(",")}` : "process",
74
+ message: finding.message,
75
+ });
76
+ }
77
+ }
78
+ return { defs: laidOut, xml: Bpmn.export(laidOut), problems };
79
+ }
80
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1,5 @@
1
+ /** Derives a stable, readable element id from a step name, deduping against ids already used in this plan. */
2
+ export declare function slugify(text: string): string;
3
+ /** Returns a unique id: `base`, or `base_2`, `base_3`, … if `base` is already taken. */
4
+ export declare function uniqueId(base: string, taken: Set<string>): string;
5
+ //# sourceMappingURL=slug.d.ts.map
@@ -0,0 +1,22 @@
1
+ /** Derives a stable, readable element id from a step name, deduping against ids already used in this plan. */
2
+ export function slugify(text) {
3
+ const slug = text
4
+ .trim()
5
+ .replace(/[^a-zA-Z0-9]+/g, "_")
6
+ .replace(/^_+|_+$/g, "");
7
+ return slug.length > 0 ? slug : "element";
8
+ }
9
+ /** Returns a unique id: `base`, or `base_2`, `base_3`, … if `base` is already taken. */
10
+ export function uniqueId(base, taken) {
11
+ if (!taken.has(base)) {
12
+ taken.add(base);
13
+ return base;
14
+ }
15
+ let n = 2;
16
+ while (taken.has(`${base}_${n}`))
17
+ n++;
18
+ const id = `${base}_${n}`;
19
+ taken.add(id);
20
+ return id;
21
+ }
22
+ //# sourceMappingURL=slug.js.map
@@ -0,0 +1,225 @@
1
+ /**
2
+ * ProcessPlan — the typed intermediate representation Claude (or any LLM)
3
+ * authors instead of BPMN XML. `compilePlan()` turns a plan into valid,
4
+ * laid-out, executable BPMN via the `@bpmnkit/core` builder; the model never
5
+ * touches XML, DI, element IDs, or connector property keys directly.
6
+ *
7
+ * Every string field documented as FEEL follows this SDK's existing
8
+ * convention throughout: a leading "=" makes it a FEEL expression, its
9
+ * absence makes it a literal string. This matches how `zeebe:input`/`output`
10
+ * `source` values already work in `@bpmnkit/core`.
11
+ */
12
+ /** A connector reference — resolved against `@bpmnkit/connectors` (or an equivalent resolver) at compile time. */
13
+ export interface PlanConnectorRef {
14
+ /** Bundled template id, e.g. "io.camunda.connectors.Slack.v1". */
15
+ template: string;
16
+ /** Values keyed by the template's input keys — see `ConnectorSummary.requiredInputs`/`optionalInputs`. */
17
+ values?: Record<string, string>;
18
+ }
19
+ /** An error boundary attached to a step that can throw a BPMN error. */
20
+ export interface PlanErrorBoundary {
21
+ /**
22
+ * BPMN error code this boundary catches. Required: the underlying builder
23
+ * only emits an `errorEventDefinition` when a code is given, so an
24
+ * omitted `errorCode` produces an untyped (non-functional) boundary event.
25
+ */
26
+ errorCode: string;
27
+ /** Steps to run when the error is caught. */
28
+ steps: PlanStep[];
29
+ /** False = non-interrupting boundary event (default true). */
30
+ interrupting?: boolean;
31
+ }
32
+ /** A timer boundary attached to a step. */
33
+ export interface PlanTimerBoundary {
34
+ duration?: string;
35
+ date?: string;
36
+ cycle?: string;
37
+ steps: PlanStep[];
38
+ interrupting?: boolean;
39
+ }
40
+ interface PlanStepBase {
41
+ /** Stable element id. Auto-derived from `name` (slugified, deduped) if omitted. */
42
+ id?: string;
43
+ name?: string;
44
+ /** Shown as documentation on the element; becomes the AI Agent tool description for tools inside an `aiAgent` step. */
45
+ documentation?: string;
46
+ errorBoundary?: PlanErrorBoundary;
47
+ timerBoundary?: PlanTimerBoundary;
48
+ }
49
+ export interface PlanStartStep extends PlanStepBase {
50
+ kind: "start";
51
+ timer?: {
52
+ duration?: string;
53
+ date?: string;
54
+ cycle?: string;
55
+ };
56
+ message?: {
57
+ name: string;
58
+ };
59
+ /** Inbound connector template (e.g. a webhook start event). */
60
+ connector?: PlanConnectorRef;
61
+ }
62
+ export interface PlanConnectorStep extends PlanStepBase {
63
+ kind: "connector";
64
+ connector: PlanConnectorRef;
65
+ retries?: string;
66
+ }
67
+ export interface PlanServiceTaskStep extends PlanStepBase {
68
+ kind: "serviceTask";
69
+ jobType: string;
70
+ inputs?: Record<string, string>;
71
+ outputs?: Record<string, string>;
72
+ taskHeaders?: Record<string, string>;
73
+ retries?: string;
74
+ }
75
+ export interface PlanUserTaskStep extends PlanStepBase {
76
+ kind: "userTask";
77
+ formId?: string;
78
+ assignee?: string;
79
+ candidateGroups?: string;
80
+ candidateUsers?: string;
81
+ dueDate?: string;
82
+ followUpDate?: string;
83
+ priority?: number;
84
+ }
85
+ export interface PlanBusinessRuleTaskStep extends PlanStepBase {
86
+ kind: "businessRuleTask";
87
+ decisionId: string;
88
+ resultVariable?: string;
89
+ }
90
+ export interface PlanScriptTaskStep extends PlanStepBase {
91
+ kind: "scriptTask";
92
+ expression: string;
93
+ resultVariable: string;
94
+ }
95
+ export interface PlanSendTaskStep extends PlanStepBase {
96
+ kind: "sendTask";
97
+ messageName: string;
98
+ }
99
+ export interface PlanReceiveTaskStep extends PlanStepBase {
100
+ kind: "receiveTask";
101
+ messageName: string;
102
+ correlationKey?: string;
103
+ }
104
+ export interface PlanCallActivityStep extends PlanStepBase {
105
+ kind: "callActivity";
106
+ processId: string;
107
+ propagateAllChildVariables?: boolean;
108
+ }
109
+ /** One tool available to an `aiAgent` step. */
110
+ export interface PlanAgentTool {
111
+ id: string;
112
+ description: string;
113
+ /** A connector-backed tool. */
114
+ connector?: PlanConnectorRef;
115
+ /** A plain job-worker tool (mutually exclusive with `connector`). */
116
+ jobType?: string;
117
+ params?: Array<{
118
+ name: string;
119
+ description: string;
120
+ type?: "string" | "number" | "boolean" | "integer" | "array" | "object";
121
+ required?: boolean;
122
+ schema?: Record<string, unknown>;
123
+ /** Input-mapping target on the tool activity (default: same as `name`). */
124
+ target?: string;
125
+ }>;
126
+ resultExpression?: string;
127
+ }
128
+ export interface PlanAiAgentStep extends PlanStepBase {
129
+ kind: "aiAgent";
130
+ provider: string;
131
+ model: string;
132
+ /** Extra dotted zeebe:input bindings — auth, endpoint, region, etc. Keys match the bundled template's input keys. */
133
+ providerInputs?: Record<string, string>;
134
+ systemPrompt: string;
135
+ userPrompt: string;
136
+ memoryStorageType?: string;
137
+ maxModelCalls?: number;
138
+ outputVariable?: string;
139
+ tools: PlanAgentTool[];
140
+ completionCondition?: string;
141
+ cancelRemainingInstances?: boolean;
142
+ retries?: string;
143
+ }
144
+ export interface PlanBranch {
145
+ name?: string;
146
+ /** FEEL condition (required unless `default` is set). */
147
+ condition?: string;
148
+ default?: boolean;
149
+ steps: PlanStep[];
150
+ }
151
+ export interface PlanGatewayStep extends PlanStepBase {
152
+ kind: "gateway";
153
+ gatewayType: "exclusive" | "parallel" | "inclusive" | "eventBased";
154
+ branches: PlanBranch[];
155
+ }
156
+ export interface PlanSubProcessStep extends PlanStepBase {
157
+ kind: "subProcess";
158
+ steps: PlanStep[];
159
+ multiInstance?: {
160
+ isSequential?: boolean;
161
+ collection: string;
162
+ elementVariable?: string;
163
+ completionCondition?: string;
164
+ };
165
+ }
166
+ export interface PlanWaitStep extends PlanStepBase {
167
+ kind: "wait";
168
+ timer?: {
169
+ duration?: string;
170
+ date?: string;
171
+ cycle?: string;
172
+ };
173
+ message?: {
174
+ name: string;
175
+ correlationKey: string;
176
+ };
177
+ }
178
+ export interface PlanEndStep extends PlanStepBase {
179
+ kind: "end";
180
+ errorCode?: string;
181
+ terminate?: boolean;
182
+ }
183
+ /** Escape hatch for anything the plan format can't express yet — a raw builder-options object, applied as-is. */
184
+ export interface PlanRawStep extends PlanStepBase {
185
+ kind: "raw";
186
+ elementType: string;
187
+ options?: Record<string, unknown>;
188
+ }
189
+ export type PlanStep = PlanStartStep | PlanConnectorStep | PlanServiceTaskStep | PlanUserTaskStep | PlanBusinessRuleTaskStep | PlanScriptTaskStep | PlanSendTaskStep | PlanReceiveTaskStep | PlanCallActivityStep | PlanAiAgentStep | PlanGatewayStep | PlanSubProcessStep | PlanWaitStep | PlanEndStep | PlanRawStep;
190
+ export interface PlanInputVariable {
191
+ name: string;
192
+ type: string;
193
+ required?: boolean;
194
+ description?: string;
195
+ }
196
+ export interface PlanScenario {
197
+ name: string;
198
+ inputs?: Record<string, unknown>;
199
+ /** jobType → { outputs } or { error: { code, message? } } */
200
+ mocks?: Record<string, {
201
+ outputs?: Record<string, unknown>;
202
+ } | {
203
+ error: {
204
+ code: string;
205
+ message?: string;
206
+ };
207
+ }>;
208
+ expect?: {
209
+ path?: string[];
210
+ variables?: Record<string, unknown>;
211
+ };
212
+ }
213
+ export interface ProcessPlan {
214
+ version: 1;
215
+ process: {
216
+ id: string;
217
+ name?: string;
218
+ versionTag?: string;
219
+ };
220
+ inputs?: PlanInputVariable[];
221
+ steps: PlanStep[];
222
+ tests?: PlanScenario[];
223
+ }
224
+ export {};
225
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * ProcessPlan — the typed intermediate representation Claude (or any LLM)
3
+ * authors instead of BPMN XML. `compilePlan()` turns a plan into valid,
4
+ * laid-out, executable BPMN via the `@bpmnkit/core` builder; the model never
5
+ * touches XML, DI, element IDs, or connector property keys directly.
6
+ *
7
+ * Every string field documented as FEEL follows this SDK's existing
8
+ * convention throughout: a leading "=" makes it a FEEL expression, its
9
+ * absence makes it a literal string. This matches how `zeebe:input`/`output`
10
+ * `source` values already work in `@bpmnkit/core`.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=types.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bpmnkit/core",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -17,7 +17,7 @@
17
17
  "dist/**/*.d.ts"
18
18
  ],
19
19
  "dependencies": {
20
- "@bpmnkit/feel": "0.0.19"
20
+ "@bpmnkit/feel": "0.0.20"
21
21
  },
22
22
  "description": "TypeScript-first BPMN 2.0 SDK — parse, build, layout, and optimize diagrams",
23
23
  "keywords": [