@boboddy/sdk 0.3.1 → 0.4.0

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.
package/dist/index.js CHANGED
@@ -1069,7 +1069,7 @@ class StepExecutions extends HeyApiClient {
1069
1069
  class PipelineDefinitions extends HeyApiClient {
1070
1070
  createPipelineDefinition(options) {
1071
1071
  return (options.client ?? this.client).post({
1072
- url: "/api/linear-pipeline-definitions",
1072
+ url: "/api/pipeline-definitions",
1073
1073
  ...options,
1074
1074
  headers: {
1075
1075
  "Content-Type": "application/json",
@@ -1079,7 +1079,7 @@ class PipelineDefinitions extends HeyApiClient {
1079
1079
  }
1080
1080
  upsertPipelineDefinition(options) {
1081
1081
  return (options.client ?? this.client).put({
1082
- url: "/api/linear-pipeline-definitions",
1082
+ url: "/api/pipeline-definitions",
1083
1083
  ...options,
1084
1084
  headers: {
1085
1085
  "Content-Type": "application/json",
@@ -1088,14 +1088,14 @@ class PipelineDefinitions extends HeyApiClient {
1088
1088
  });
1089
1089
  }
1090
1090
  archivePipelineDefinition(options) {
1091
- return (options.client ?? this.client).put({ url: "/api/linear-pipeline-definitions/{linearPipelineDefinitionId}/archive", ...options });
1091
+ return (options.client ?? this.client).put({ url: "/api/pipeline-definitions/{pipelineDefinitionId}/archive", ...options });
1092
1092
  }
1093
1093
  unarchivePipelineDefinition(options) {
1094
- return (options.client ?? this.client).put({ url: "/api/linear-pipeline-definitions/{linearPipelineDefinitionId}/unarchive", ...options });
1094
+ return (options.client ?? this.client).put({ url: "/api/pipeline-definitions/{pipelineDefinitionId}/unarchive", ...options });
1095
1095
  }
1096
1096
  addPipelineStep(options) {
1097
1097
  return (options.client ?? this.client).post({
1098
- url: "/api/linear-pipeline-definitions/{linearPipelineDefinitionId}/steps",
1098
+ url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps",
1099
1099
  ...options,
1100
1100
  headers: {
1101
1101
  "Content-Type": "application/json",
@@ -1104,11 +1104,11 @@ class PipelineDefinitions extends HeyApiClient {
1104
1104
  });
1105
1105
  }
1106
1106
  removePipelineStep(options) {
1107
- return (options.client ?? this.client).delete({ url: "/api/linear-pipeline-definitions/{linearPipelineDefinitionId}/steps/{linearPipelineStepDefinitionId}", ...options });
1107
+ return (options.client ?? this.client).delete({ url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps/{pipelineStepDefinitionId}", ...options });
1108
1108
  }
1109
1109
  updatePipelineStep(options) {
1110
1110
  return (options.client ?? this.client).put({
1111
- url: "/api/linear-pipeline-definitions/{linearPipelineDefinitionId}/steps/{linearPipelineStepDefinitionId}",
1111
+ url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps/{pipelineStepDefinitionId}",
1112
1112
  ...options,
1113
1113
  headers: {
1114
1114
  "Content-Type": "application/json",
@@ -1118,7 +1118,7 @@ class PipelineDefinitions extends HeyApiClient {
1118
1118
  }
1119
1119
  setPipelineStepAdvancementPolicy(options) {
1120
1120
  return (options.client ?? this.client).put({
1121
- url: "/api/linear-pipeline-definitions/{linearPipelineDefinitionId}/steps/{linearPipelineStepDefinitionId}/advancement-policy",
1121
+ url: "/api/pipeline-definitions/{pipelineDefinitionId}/steps/{pipelineStepDefinitionId}/advancement-policy",
1122
1122
  ...options,
1123
1123
  headers: {
1124
1124
  "Content-Type": "application/json",
@@ -1127,20 +1127,20 @@ class PipelineDefinitions extends HeyApiClient {
1127
1127
  });
1128
1128
  }
1129
1129
  getPipelineDefinition(options) {
1130
- return (options.client ?? this.client).get({ url: "/api/linear-pipeline-definitions/{linearPipelineDefinitionId}", ...options });
1130
+ return (options.client ?? this.client).get({ url: "/api/pipeline-definitions/{pipelineDefinitionId}", ...options });
1131
1131
  }
1132
1132
  listPipelineDefinitions(options) {
1133
- return (options.client ?? this.client).get({ url: "/api/projects/{projectId}/linear-pipeline-definitions", ...options });
1133
+ return (options.client ?? this.client).get({ url: "/api/projects/{projectId}/pipeline-definitions", ...options });
1134
1134
  }
1135
1135
  }
1136
1136
 
1137
1137
  class PipelineExecutions extends HeyApiClient {
1138
1138
  listPipelineExecutions(options) {
1139
- return (options.client ?? this.client).get({ url: "/api/linear-pipeline-executions", ...options });
1139
+ return (options.client ?? this.client).get({ url: "/api/pipeline-executions", ...options });
1140
1140
  }
1141
1141
  createPipelineExecution(options) {
1142
1142
  return (options.client ?? this.client).post({
1143
- url: "/api/linear-pipeline-executions",
1143
+ url: "/api/pipeline-executions",
1144
1144
  ...options,
1145
1145
  headers: {
1146
1146
  "Content-Type": "application/json",
@@ -1149,17 +1149,17 @@ class PipelineExecutions extends HeyApiClient {
1149
1149
  });
1150
1150
  }
1151
1151
  startPipelineExecution(options) {
1152
- return (options.client ?? this.client).put({ url: "/api/linear-pipeline-executions/{linearPipelineExecutionId}/start", ...options });
1152
+ return (options.client ?? this.client).put({ url: "/api/pipeline-executions/{pipelineExecutionId}/start", ...options });
1153
1153
  }
1154
1154
  queueFirstPipelineStepRun(options) {
1155
- return (options.client ?? this.client).post({ url: "/api/linear-pipeline-executions/{linearPipelineExecutionId}/step-runs/first", ...options });
1155
+ return (options.client ?? this.client).post({ url: "/api/pipeline-executions/{pipelineExecutionId}/step-runs/first", ...options });
1156
1156
  }
1157
1157
  markPipelineStepRunRunning(options) {
1158
- return (options.client ?? this.client).put({ url: "/api/linear-pipeline-executions/{linearPipelineExecutionId}/step-runs/{linearPipelineStepRunId}/running", ...options });
1158
+ return (options.client ?? this.client).put({ url: "/api/pipeline-executions/{pipelineExecutionId}/step-runs/{pipelineStepRunId}/running", ...options });
1159
1159
  }
1160
1160
  applyPipelineStepResult(options) {
1161
1161
  return (options.client ?? this.client).post({
1162
- url: "/api/linear-pipeline-executions/{linearPipelineExecutionId}/step-runs/{linearPipelineStepRunId}/results",
1162
+ url: "/api/pipeline-executions/{pipelineExecutionId}/step-runs/{pipelineStepRunId}/results",
1163
1163
  ...options,
1164
1164
  headers: {
1165
1165
  "Content-Type": "application/json",
@@ -1169,7 +1169,17 @@ class PipelineExecutions extends HeyApiClient {
1169
1169
  }
1170
1170
  acceptPipelineStepRun(options) {
1171
1171
  return (options.client ?? this.client).post({
1172
- url: "/api/linear-pipeline-executions/{linearPipelineExecutionId}/step-runs/{linearPipelineStepRunId}/accept",
1172
+ url: "/api/pipeline-executions/{pipelineExecutionId}/step-runs/{pipelineStepRunId}/accept",
1173
+ ...options,
1174
+ headers: {
1175
+ "Content-Type": "application/json",
1176
+ ...options.headers
1177
+ }
1178
+ });
1179
+ }
1180
+ acceptPipelineCohort(options) {
1181
+ return (options.client ?? this.client).post({
1182
+ url: "/api/pipeline-executions/{pipelineExecutionId}/cohorts/{originNodeDefinitionId}/accept",
1173
1183
  ...options,
1174
1184
  headers: {
1175
1185
  "Content-Type": "application/json",
@@ -1179,7 +1189,7 @@ class PipelineExecutions extends HeyApiClient {
1179
1189
  }
1180
1190
  rerunPipelineExecution(options) {
1181
1191
  return (options.client ?? this.client).post({
1182
- url: "/api/linear-pipeline-executions/{linearPipelineExecutionId}/rerun",
1192
+ url: "/api/pipeline-executions/{pipelineExecutionId}/rerun",
1183
1193
  ...options,
1184
1194
  headers: {
1185
1195
  "Content-Type": "application/json",
@@ -1188,19 +1198,22 @@ class PipelineExecutions extends HeyApiClient {
1188
1198
  });
1189
1199
  }
1190
1200
  cancelPipelineExecution(options) {
1191
- return (options.client ?? this.client).put({ url: "/api/linear-pipeline-executions/{linearPipelineExecutionId}/cancel", ...options });
1201
+ return (options.client ?? this.client).put({ url: "/api/pipeline-executions/{pipelineExecutionId}/cancel", ...options });
1192
1202
  }
1193
1203
  getPipelineExecution(options) {
1194
- return (options.client ?? this.client).get({ url: "/api/linear-pipeline-executions/{linearPipelineExecutionId}", ...options });
1204
+ return (options.client ?? this.client).get({ url: "/api/pipeline-executions/{pipelineExecutionId}", ...options });
1205
+ }
1206
+ getPipelineExecutionRoutedChain(options) {
1207
+ return (options.client ?? this.client).get({ url: "/api/pipeline-executions/{pipelineExecutionId}/routed-chain", ...options });
1195
1208
  }
1196
1209
  countPipelineExecutionsByPipeline(options) {
1197
- return (options.client ?? this.client).get({ url: "/api/linear-pipeline-executions/counts/by-pipeline", ...options });
1210
+ return (options.client ?? this.client).get({ url: "/api/pipeline-executions/counts/by-pipeline", ...options });
1198
1211
  }
1199
1212
  listPipelineDefinitionStepRollups(options) {
1200
- return (options.client ?? this.client).get({ url: "/api/linear-pipeline-executions/step-rollups/by-definition/{linearPipelineDefinitionId}", ...options });
1213
+ return (options.client ?? this.client).get({ url: "/api/pipeline-executions/step-rollups/by-definition/{pipelineDefinitionId}", ...options });
1201
1214
  }
1202
1215
  listPipelineDefinitionStepRuns(options) {
1203
- return (options.client ?? this.client).get({ url: "/api/linear-pipeline-executions/step-runs/by-definition/{linearPipelineDefinitionId}", ...options });
1216
+ return (options.client ?? this.client).get({ url: "/api/pipeline-executions/step-runs/by-definition/{pipelineDefinitionId}", ...options });
1204
1217
  }
1205
1218
  }
1206
1219
 
@@ -16326,6 +16339,140 @@ function extractInlineComputedSignals(policy) {
16326
16339
  return [...byKey.values()];
16327
16340
  }
16328
16341
 
16342
+ // src/definitions/advancement-policies/cohort-advancement-policy.ts
16343
+ var cohortAdvancementEventTypeValues = ["continue", "block"];
16344
+ function serializeCohortCondition(condition) {
16345
+ if (condition._tag === "signal") {
16346
+ return {
16347
+ fact: typeof condition.signal === "string" ? condition.signal : condition.signal.key,
16348
+ operator: condition.operator,
16349
+ value: condition.value
16350
+ };
16351
+ }
16352
+ if (condition._tag === "all") {
16353
+ return { all: condition.conditions.map(serializeCohortCondition) };
16354
+ }
16355
+ return { any: condition.conditions.map(serializeCohortCondition) };
16356
+ }
16357
+ function serializeCohortRule(rule) {
16358
+ return {
16359
+ conditions: { [rule.mode]: rule.conditions.map(serializeCohortCondition) },
16360
+ event: {
16361
+ type: rule.outcome,
16362
+ ...rule.outcomeJson ? { params: rule.outcomeJson } : {}
16363
+ }
16364
+ };
16365
+ }
16366
+ function serializeCohortAdvancementPolicy(policy) {
16367
+ if (!policy) {
16368
+ return { rules: [], defaultEventType: "continue", defaultEventParamsJson: null };
16369
+ }
16370
+ return {
16371
+ rules: (policy.rules ?? []).map(serializeCohortRule),
16372
+ defaultEventType: policy.default,
16373
+ defaultEventParamsJson: policy.defaultParamsJson ?? null
16374
+ };
16375
+ }
16376
+ function visitCohortSignalConditions(conditions, visit) {
16377
+ for (const c of conditions) {
16378
+ if (c._tag === "signal") {
16379
+ visit(c);
16380
+ } else {
16381
+ visitCohortSignalConditions(c.conditions, visit);
16382
+ }
16383
+ }
16384
+ }
16385
+ function isSameStepSignalsListDefinition(a, b) {
16386
+ return JSON.stringify(a.ops) === JSON.stringify(b.ops) && JSON.stringify(a.reducer) === JSON.stringify(b.reducer);
16387
+ }
16388
+ function extractInlineStepSignalsListDefinitions(policy) {
16389
+ if (!policy?.rules)
16390
+ return [];
16391
+ const byKey = new Map;
16392
+ for (const rule of policy.rules) {
16393
+ visitCohortSignalConditions(rule.conditions, (cond) => {
16394
+ if (typeof cond.signal === "string")
16395
+ return;
16396
+ const inline = cond.signal;
16397
+ const def = {
16398
+ key: inline.key,
16399
+ ops: inline.ops,
16400
+ reducer: inline.reducer
16401
+ };
16402
+ const existing = byKey.get(def.key);
16403
+ if (existing) {
16404
+ if (!isSameStepSignalsListDefinition(existing, def)) {
16405
+ throw new Error(`Conflicting inline stepSignalsList definitions for key "${def.key}"`);
16406
+ }
16407
+ return;
16408
+ }
16409
+ byKey.set(def.key, def);
16410
+ });
16411
+ }
16412
+ return [...byKey.values()];
16413
+ }
16414
+
16415
+ // src/definitions/pipelines/chain-graph.ts
16416
+ function tryOrderChainNodeDefinitions(nodeDefinitions, dependencyEdges) {
16417
+ const nodesByKey = new Map;
16418
+ for (const nodeDefinition of nodeDefinitions) {
16419
+ nodesByKey.set(nodeDefinition.nodeKey, nodeDefinition);
16420
+ }
16421
+ const outgoing = new Map;
16422
+ const incomingCount = new Map;
16423
+ for (const nodeDefinition of nodeDefinitions) {
16424
+ incomingCount.set(nodeDefinition.nodeKey, 0);
16425
+ }
16426
+ for (const edge of dependencyEdges) {
16427
+ if (!nodesByKey.has(edge.fromNodeKey) || !nodesByKey.has(edge.toNodeKey)) {
16428
+ return null;
16429
+ }
16430
+ if (outgoing.has(edge.fromNodeKey))
16431
+ return null;
16432
+ outgoing.set(edge.fromNodeKey, edge.toNodeKey);
16433
+ incomingCount.set(edge.toNodeKey, (incomingCount.get(edge.toNodeKey) ?? 0) + 1);
16434
+ }
16435
+ for (const count of incomingCount.values()) {
16436
+ if (count > 1)
16437
+ return null;
16438
+ }
16439
+ if (nodeDefinitions.length === 0)
16440
+ return [];
16441
+ const roots = nodeDefinitions.filter((nodeDefinition) => (incomingCount.get(nodeDefinition.nodeKey) ?? 0) === 0);
16442
+ if (roots.length !== 1)
16443
+ return null;
16444
+ const rootNode = roots[0];
16445
+ if (!rootNode)
16446
+ return null;
16447
+ const ordered = [];
16448
+ const visited = new Set;
16449
+ let currentKey = rootNode.nodeKey;
16450
+ while (currentKey !== undefined) {
16451
+ if (visited.has(currentKey))
16452
+ return null;
16453
+ visited.add(currentKey);
16454
+ const currentNode = nodesByKey.get(currentKey);
16455
+ if (!currentNode)
16456
+ return null;
16457
+ ordered.push(currentNode);
16458
+ currentKey = outgoing.get(currentKey);
16459
+ }
16460
+ if (ordered.length !== nodeDefinitions.length)
16461
+ return null;
16462
+ return ordered;
16463
+ }
16464
+ function buildChainDependencyEdges(orderedNodes) {
16465
+ const dependencyEdges = [];
16466
+ for (let index = 0;index < orderedNodes.length - 1; index += 1) {
16467
+ const from = orderedNodes[index];
16468
+ const to = orderedNodes[index + 1];
16469
+ if (!from || !to)
16470
+ continue;
16471
+ dependencyEdges.push({ fromNodeKey: from.nodeKey, toNodeKey: to.nodeKey });
16472
+ }
16473
+ return dependencyEdges;
16474
+ }
16475
+
16329
16476
  // src/definitions/pipelines/define-pipeline.ts
16330
16477
  function serializeBinding(binding) {
16331
16478
  if (binding.source === "pipeline_input") {
@@ -16344,15 +16491,42 @@ function serializeBinding(binding) {
16344
16491
  if (binding.source === "literal") {
16345
16492
  return { source: "literal", value: binding.value };
16346
16493
  }
16494
+ if (binding.source === "signals_list") {
16495
+ return { source: "signals_list", stepKey: binding.fanOutStep.key };
16496
+ }
16497
+ if (binding.source === "fan_out_item") {
16498
+ return { source: "fan_out_item" };
16499
+ }
16347
16500
  return { source: "step_output", stepKey: binding.step.key };
16348
16501
  }
16502
+ var isFanOutConfig = (node) => ("nodeType" in node) && node.nodeType === "fanOut";
16503
+ var isCohortGateConfig = (node) => ("nodeType" in node) && node.nodeType === "cohortGate";
16504
+ function serializeInputBindings(input, pipelineInputBindings) {
16505
+ const autoBindings = {
16506
+ workItemTitle: { source: "work_item", field: "title" },
16507
+ workItemDescription: { source: "work_item", field: "description" }
16508
+ };
16509
+ const pipelineBindings = {};
16510
+ for (const [key, binding] of Object.entries(pipelineInputBindings ?? {})) {
16511
+ pipelineBindings[key] = serializeBinding(binding);
16512
+ }
16513
+ const explicitBindings = Object.fromEntries(Object.entries(input ?? {}).filter((entry) => entry[1] !== undefined).map(([key, binding]) => [key, serializeBinding(binding)]));
16514
+ return { ...autoBindings, ...pipelineBindings, ...explicitBindings };
16515
+ }
16349
16516
  function buildPipelineSpec(config2) {
16350
- const steps = config2.steps;
16517
+ const nodes = config2.nodes;
16351
16518
  const stepDefMap = new Map;
16352
- for (const stepConfig of steps) {
16353
- const mapKey = `${stepConfig.step.key}@v${String(stepConfig.step.version)}`;
16519
+ const registerStepDef = (step) => {
16520
+ const mapKey = `${step.key}@v${String(step.version)}`;
16354
16521
  if (!stepDefMap.has(mapKey)) {
16355
- stepDefMap.set(mapKey, stepConfig.step);
16522
+ stepDefMap.set(mapKey, step);
16523
+ }
16524
+ };
16525
+ for (const node of nodes) {
16526
+ if (isFanOutConfig(node)) {
16527
+ registerStepDef(node.fanOutStep);
16528
+ } else if (!isCohortGateConfig(node)) {
16529
+ registerStepDef(node.step);
16356
16530
  }
16357
16531
  }
16358
16532
  let inputSchemaJson = null;
@@ -16363,6 +16537,46 @@ function buildPipelineSpec(config2) {
16363
16537
  inputSchemaJson = null;
16364
16538
  }
16365
16539
  }
16540
+ const nodeDefinitions = nodes.map((node) => {
16541
+ if (isCohortGateConfig(node)) {
16542
+ const serializedPolicy = serializeCohortAdvancementPolicy(node.advanceAll);
16543
+ const inlineStepSignalsListDefinitions = extractInlineStepSignalsListDefinitions(node.advanceAll);
16544
+ return {
16545
+ nodeKey: node.nodeKey,
16546
+ kind: "cohortGate",
16547
+ advanceAllPolicyDefinition: serializedPolicy,
16548
+ stepSignalsListDefinitions: [
16549
+ ...inlineStepSignalsListDefinitions,
16550
+ ...node.stepSignalsListDefinitions ?? []
16551
+ ]
16552
+ };
16553
+ }
16554
+ if (isFanOutConfig(node)) {
16555
+ return {
16556
+ nodeKey: node.fanOutStep.key,
16557
+ kind: "fanOut",
16558
+ stepKey: node.fanOutStep.key,
16559
+ stepName: node.fanOutStep.name,
16560
+ stepDescription: node.fanOutStep.description,
16561
+ inputBindingsJson: serializeInputBindings(node.input, config2.pipelineInputBindings),
16562
+ timeoutSeconds: node.timeout ?? null,
16563
+ overSignalKey: node.overSignalKey,
16564
+ advanceEachPolicyDefinition: serializeCohortAdvancementPolicy(node.advanceEach)
16565
+ };
16566
+ }
16567
+ return {
16568
+ nodeKey: node.step.key,
16569
+ kind: "step",
16570
+ stepKey: node.step.key,
16571
+ stepName: node.step.name,
16572
+ stepDescription: node.step.description,
16573
+ inputBindingsJson: serializeInputBindings(node.input, config2.pipelineInputBindings),
16574
+ timeoutSeconds: node.timeout ?? null,
16575
+ advancementPolicyDefinition: serializeAdvancementPolicy(node.advancement),
16576
+ computedSignalDefinitions: extractInlineComputedSignals(node.advancement)
16577
+ };
16578
+ });
16579
+ const dependencyEdges = buildChainDependencyEdges(nodeDefinitions);
16366
16580
  return {
16367
16581
  key: config2.key,
16368
16582
  name: config2.name,
@@ -16371,31 +16585,8 @@ function buildPipelineSpec(config2) {
16371
16585
  status: config2.status ?? "active",
16372
16586
  inputSchemaJson,
16373
16587
  _stepDefinitions: [...stepDefMap.values()],
16374
- steps: steps.map((stepConfig, index) => {
16375
- const autoBindings = {
16376
- workItemTitle: { source: "work_item", field: "title" },
16377
- workItemDescription: { source: "work_item", field: "description" }
16378
- };
16379
- const pipelineBindings = {};
16380
- for (const [key, binding] of Object.entries(config2.pipelineInputBindings ?? {})) {
16381
- pipelineBindings[key] = serializeBinding(binding);
16382
- }
16383
- const explicitStepBindings = Object.fromEntries(Object.entries(stepConfig.input ?? {}).filter((entry) => entry[1] !== undefined).map(([key, binding]) => [key, serializeBinding(binding)]));
16384
- return {
16385
- stepKey: stepConfig.step.key,
16386
- stepName: stepConfig.step.name,
16387
- stepDescription: stepConfig.step.description,
16388
- position: index + 1,
16389
- inputBindingsJson: {
16390
- ...autoBindings,
16391
- ...pipelineBindings,
16392
- ...explicitStepBindings
16393
- },
16394
- timeoutSeconds: stepConfig.timeout ?? null,
16395
- advancementPolicyDefinition: serializeAdvancementPolicy(stepConfig.advancement),
16396
- computedSignalDefinitions: extractInlineComputedSignals(stepConfig.advancement)
16397
- };
16398
- })
16588
+ nodeDefinitions,
16589
+ dependencyEdges
16399
16590
  };
16400
16591
  }
16401
16592
  // src/definitions/advancement-policies/fluent-rules.ts
@@ -16566,7 +16757,10 @@ function makeStepInputCtx(inputSchema) {
16566
16757
  output(step) {
16567
16758
  return { source: "step_output", step };
16568
16759
  },
16569
- literal: literal2
16760
+ literal: literal2,
16761
+ signalsList(fanOutStep) {
16762
+ return { source: "signals_list", fanOutStep };
16763
+ }
16570
16764
  };
16571
16765
  }
16572
16766
  function literal2(value) {
@@ -16611,61 +16805,247 @@ function mergeStepBindings(pipelineBindings, explicitBindings) {
16611
16805
  return Object.keys(merged).length > 0 ? merged : undefined;
16612
16806
  }
16613
16807
 
16614
- // src/definitions/pipelines/builder.ts
16615
- class PipelineStepAdvancementBuilder {
16616
- inputSchema;
16617
- meta;
16618
- steps;
16619
- pipelineInputBindings;
16620
- pipelineStepInputBindings;
16621
- constructor(inputSchema, meta3, steps, pipelineInputBindings = {}, pipelineStepInputBindings = {}) {
16622
- this.inputSchema = inputSchema;
16623
- this.meta = meta3;
16624
- this.steps = steps;
16625
- this.pipelineInputBindings = pipelineInputBindings;
16626
- this.pipelineStepInputBindings = pipelineStepInputBindings;
16627
- }
16628
- advance(callback) {
16629
- const last = this.steps.at(-1);
16630
- if (!last)
16631
- throw new Error("Internal error: no steps available");
16632
- const ctx = makeAdvanceCtx();
16633
- const result = callback(ctx);
16634
- const policy = {
16635
- defaultOutcome: result.default,
16636
- ...result.rules !== undefined ? { rules: result.rules } : {}
16808
+ // src/definitions/advancement-policies/cohort-fluent-rules.ts
16809
+ var LEAF_BRAND2 = Symbol("boboddy.cohortRule.leaf");
16810
+ var GROUP_BRAND2 = Symbol("boboddy.cohortRule.group");
16811
+ function createCohortSignalRef(signal2) {
16812
+ const leaf = (operator, value) => {
16813
+ const condition = {
16814
+ _tag: "signal",
16815
+ signal: signal2,
16816
+ operator,
16817
+ value
16637
16818
  };
16638
- last.advancement = policy;
16639
- return new PipelineStepBuilder(this.inputSchema, this.meta, this.steps, this.pipelineInputBindings, this.pipelineStepInputBindings);
16640
- }
16819
+ return {
16820
+ [LEAF_BRAND2]: condition,
16821
+ then(outcome, paramsJson) {
16822
+ return {
16823
+ _tag: "rule",
16824
+ mode: "all",
16825
+ conditions: [condition],
16826
+ outcome,
16827
+ ...paramsJson ? { outcomeJson: paramsJson } : {}
16828
+ };
16829
+ }
16830
+ };
16831
+ };
16832
+ return {
16833
+ eq: (v) => leaf("equal", v),
16834
+ ne: (v) => leaf("notEqual", v),
16835
+ gt: (v) => leaf("greaterThan", v),
16836
+ gte: (v) => leaf("greaterThanInclusive", v),
16837
+ lt: (v) => leaf("lessThan", v),
16838
+ lte: (v) => leaf("lessThanInclusive", v),
16839
+ in: (vs) => leaf("in", vs),
16840
+ notIn: (vs) => leaf("notIn", vs),
16841
+ contains: (v) => leaf("contains", v),
16842
+ doesNotContain: (v) => leaf("doesNotContain", v)
16843
+ };
16844
+ }
16845
+ function createCohortLeafFromCondition(condition) {
16846
+ return {
16847
+ [LEAF_BRAND2]: condition,
16848
+ then(outcome, paramsJson) {
16849
+ return {
16850
+ _tag: "rule",
16851
+ mode: "all",
16852
+ conditions: [condition],
16853
+ outcome,
16854
+ ...paramsJson ? { outcomeJson: paramsJson } : {}
16855
+ };
16856
+ }
16857
+ };
16858
+ }
16859
+ function extractCohortCondition(ref) {
16860
+ if (LEAF_BRAND2 in ref)
16861
+ return ref[LEAF_BRAND2];
16862
+ const group = ref[GROUP_BRAND2];
16863
+ return group.mode === "all" ? { _tag: "all", conditions: group.conditions } : { _tag: "any", conditions: group.conditions };
16864
+ }
16865
+ function createCohortGroup(mode, refs) {
16866
+ const conditions = refs.map(extractCohortCondition);
16867
+ return {
16868
+ [GROUP_BRAND2]: { mode, conditions },
16869
+ then(outcome, paramsJson) {
16870
+ return {
16871
+ _tag: "rule",
16872
+ mode,
16873
+ conditions,
16874
+ outcome,
16875
+ ...paramsJson ? { outcomeJson: paramsJson } : {}
16876
+ };
16877
+ }
16878
+ };
16879
+ }
16880
+ function makeKeyedCohortSignalRef(key) {
16881
+ return createCohortSignalRef(key);
16882
+ }
16883
+ function makeAdvanceEachCtx() {
16884
+ return {
16885
+ signal: (key) => makeKeyedCohortSignalRef(key),
16886
+ stepSignals: new Proxy({}, {
16887
+ get(_, key) {
16888
+ if (typeof key === "string")
16889
+ return makeKeyedCohortSignalRef(key);
16890
+ return;
16891
+ }
16892
+ }),
16893
+ all: (...refs) => createCohortGroup("all", refs),
16894
+ any: (...refs) => createCohortGroup("any", refs)
16895
+ };
16896
+ }
16897
+ var branchOutcomeValues = [
16898
+ "continue",
16899
+ "block",
16900
+ "error",
16901
+ "abandoned"
16902
+ ];
16903
+ function summarizeTransformOp(op) {
16904
+ if (op.op === "filter") {
16905
+ return `filter_${op.operator}_${JSON.stringify(op.value)}`;
16906
+ }
16907
+ if (op.op === "sortBy") {
16908
+ return `sortBy_${op.direction}`;
16909
+ }
16910
+ return "unique";
16911
+ }
16912
+ function deriveStepSignalsListKey(ops, reducer) {
16913
+ const pluck = ops.find((op) => op.op === "pluck");
16914
+ const base = `${reducer.op}_${pluck?.signalKey ?? "value"}`;
16915
+ const extras = ops.filter((op) => op.op !== "pluck").map(summarizeTransformOp);
16916
+ const reducerExtra = reducer.op === "join" ? `sep_${reducer.separator}` : null;
16917
+ const suffixParts = [...extras, ...reducerExtra ? [reducerExtra] : []];
16918
+ return suffixParts.length > 0 ? `${base}_${suffixParts.join("_")}` : base;
16919
+ }
16920
+ function createStepSignalsListBuilder(ops) {
16921
+ const withOp = (op) => createStepSignalsListBuilder([...ops, op]);
16922
+ const reduce = (reducer) => {
16923
+ const token = {
16924
+ _tag: "step_signals_list",
16925
+ key: deriveStepSignalsListKey(ops, reducer),
16926
+ ops: [...ops],
16927
+ reducer
16928
+ };
16929
+ return createCohortSignalRef(token);
16930
+ };
16931
+ return {
16932
+ filter: (operator, value) => withOp({ op: "filter", operator, value }),
16933
+ sortBy: (direction = "asc") => withOp({ op: "sortBy", direction }),
16934
+ unique: () => withOp({ op: "unique" }),
16935
+ count: () => reduce({ op: "count" }),
16936
+ sum: () => reduce({ op: "sum" }),
16937
+ avg: () => reduce({ op: "avg" }),
16938
+ min: () => reduce({ op: "min" }),
16939
+ max: () => reduce({ op: "max" }),
16940
+ booleanAll: () => reduce({ op: "booleanAll" }),
16941
+ booleanAny: () => reduce({ op: "booleanAny" }),
16942
+ join: (separator = ",") => reduce({ op: "join", separator }),
16943
+ first: () => reduce({ op: "first" }),
16944
+ last: () => reduce({ op: "last" })
16945
+ };
16946
+ }
16947
+ function makeAdvanceAllCtx() {
16948
+ return {
16949
+ branchOutcomes: {
16950
+ total: () => createCohortSignalRef("branchCount"),
16951
+ count: (outcome) => createCohortSignalRef(`${outcome}Count`),
16952
+ every: (outcome) => createCohortLeafFromCondition({
16953
+ _tag: "signal",
16954
+ signal: `${outcome}Count`,
16955
+ operator: "equal",
16956
+ value: { fact: "branchCount" }
16957
+ }),
16958
+ some: (outcome) => createCohortLeafFromCondition({
16959
+ _tag: "signal",
16960
+ signal: `${outcome}Count`,
16961
+ operator: "greaterThan",
16962
+ value: 0
16963
+ })
16964
+ },
16965
+ stepSignalsList: {
16966
+ pluck: (signalKey) => createStepSignalsListBuilder([{ op: "pluck", signalKey }])
16967
+ },
16968
+ all: (...refs) => createCohortGroup("all", refs),
16969
+ any: (...refs) => createCohortGroup("any", refs)
16970
+ };
16971
+ }
16972
+
16973
+ // src/definitions/pipelines/fan-out-builder.ts
16974
+ function beginFanOut(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings, step, config2) {
16975
+ const baseCtx = makeStepInputCtx(inputSchema);
16976
+ const ctx = {
16977
+ ...baseCtx,
16978
+ item: { source: "fan_out_item" }
16979
+ };
16980
+ const rawInput = config2.input ? config2.input(ctx) : {};
16981
+ const input = mergeStepBindings(pipelineStepInputBindings, normalizeInputMapping(rawInput));
16982
+ const fanOutNodeConfig = {
16983
+ nodeType: "fanOut",
16984
+ fanOutStep: step,
16985
+ overSignalKey: config2.over,
16986
+ ...input ? { input } : {},
16987
+ ...config2.timeout !== undefined ? { timeout: config2.timeout } : {}
16988
+ };
16989
+ const advanceEachCtx = makeAdvanceEachCtx();
16990
+ const advanceEachResult = config2.advance(advanceEachCtx);
16991
+ const advanceEachPolicy = {
16992
+ default: advanceEachResult.default,
16993
+ ...advanceEachResult.rules !== undefined ? { rules: advanceEachResult.rules } : {}
16994
+ };
16995
+ fanOutNodeConfig.advanceEach = advanceEachPolicy;
16996
+ const cohortGateNodeConfig = {
16997
+ nodeType: "cohortGate",
16998
+ nodeKey: `${step.key}__cohortGate`
16999
+ };
17000
+ const advanceAllCtx = makeAdvanceAllCtx();
17001
+ const advanceAllResult = config2.advanceAll(advanceAllCtx);
17002
+ const advanceAllPolicy = {
17003
+ default: advanceAllResult.default,
17004
+ ...advanceAllResult.rules !== undefined ? { rules: advanceAllResult.rules } : {}
17005
+ };
17006
+ cohortGateNodeConfig.advanceAll = advanceAllPolicy;
17007
+ nodes.push(fanOutNodeConfig, cohortGateNodeConfig);
17008
+ return new PipelineStepBuilder(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings);
17009
+ }
17010
+
17011
+ // src/definitions/pipelines/builder.ts
17012
+ function pushStep(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings, step, rawOptions) {
17013
+ const options = rawOptions;
17014
+ const ctx = makeStepInputCtx(inputSchema);
17015
+ const rawInput = options.input ? options.input(ctx) : {};
17016
+ const input = mergeStepBindings(pipelineStepInputBindings, normalizeInputMapping(rawInput));
17017
+ const stepConfig = { step, input };
17018
+ if (options.timeout !== undefined)
17019
+ stepConfig.timeout = options.timeout;
17020
+ const advanceCtx = makeAdvanceCtx();
17021
+ const result = options.advance(advanceCtx);
17022
+ const policy = {
17023
+ defaultOutcome: result.default,
17024
+ ...result.rules !== undefined ? { rules: result.rules } : {}
17025
+ };
17026
+ stepConfig.advancement = policy;
17027
+ nodes.push(stepConfig);
17028
+ return new PipelineStepBuilder(inputSchema, meta3, nodes, pipelineInputBindings, pipelineStepInputBindings);
16641
17029
  }
16642
17030
 
16643
17031
  class PipelineStepBuilder {
16644
17032
  inputSchema;
16645
17033
  meta;
16646
- steps;
17034
+ nodes;
16647
17035
  pipelineInputBindings;
16648
17036
  pipelineStepInputBindings;
16649
- constructor(inputSchema, meta3, steps, pipelineInputBindings = {}, pipelineStepInputBindings = {}) {
17037
+ constructor(inputSchema, meta3, nodes, pipelineInputBindings = {}, pipelineStepInputBindings = {}) {
16650
17038
  this.inputSchema = inputSchema;
16651
17039
  this.meta = meta3;
16652
- this.steps = steps;
17040
+ this.nodes = nodes;
16653
17041
  this.pipelineInputBindings = pipelineInputBindings;
16654
17042
  this.pipelineStepInputBindings = pipelineStepInputBindings;
16655
17043
  }
16656
- step(step, mapper, configFn) {
16657
- const ctx = makeStepInputCtx(this.inputSchema);
16658
- const rawInput = mapper ? mapper(ctx) : {};
16659
- const input = mergeStepBindings(this.pipelineStepInputBindings, normalizeInputMapping(rawInput));
16660
- const stepConfig = { step, input };
16661
- if (configFn) {
16662
- const cfg = {};
16663
- configFn(cfg);
16664
- if (cfg.timeout !== undefined)
16665
- stepConfig.timeout = cfg.timeout;
16666
- }
16667
- this.steps.push(stepConfig);
16668
- return new PipelineStepAdvancementBuilder(this.inputSchema, this.meta, this.steps, this.pipelineInputBindings, this.pipelineStepInputBindings);
17044
+ step(step, options) {
17045
+ return pushStep(this.inputSchema, this.meta, this.nodes, this.pipelineInputBindings, this.pipelineStepInputBindings, step, options);
17046
+ }
17047
+ fanOutStep(step, config2) {
17048
+ return beginFanOut(this.inputSchema, this.meta, this.nodes, this.pipelineInputBindings, this.pipelineStepInputBindings, step, config2);
16669
17049
  }
16670
17050
  build() {
16671
17051
  const config2 = {
@@ -16675,7 +17055,7 @@ class PipelineStepBuilder {
16675
17055
  version: this.meta.version,
16676
17056
  status: this.meta.status,
16677
17057
  input: this.inputSchema,
16678
- steps: this.steps,
17058
+ nodes: this.nodes,
16679
17059
  pipelineInputBindings: this.pipelineInputBindings
16680
17060
  };
16681
17061
  return buildPipelineSpec(config2);
@@ -16685,7 +17065,7 @@ class PipelineStepBuilder {
16685
17065
  class PipelineBuilder {
16686
17066
  inputSchema;
16687
17067
  meta;
16688
- steps = [];
17068
+ nodes = [];
16689
17069
  pipelineInputBindings;
16690
17070
  pipelineStepInputBindings;
16691
17071
  constructor(meta3) {
@@ -16710,19 +17090,8 @@ class PipelineBuilder {
16710
17090
  }
16711
17091
  this.pipelineStepInputBindings = resolveAdditionalStepInputBindings("additionalStepInput", additionalStepInput);
16712
17092
  }
16713
- step(step, mapper, configFn) {
16714
- const ctx = makeStepInputCtx(this.inputSchema);
16715
- const rawInput = mapper ? mapper(ctx) : {};
16716
- const input = mergeStepBindings(this.pipelineStepInputBindings, normalizeInputMapping(rawInput));
16717
- const stepConfig = { step, input };
16718
- if (configFn) {
16719
- const cfg = {};
16720
- configFn(cfg);
16721
- if (cfg.timeout !== undefined)
16722
- stepConfig.timeout = cfg.timeout;
16723
- }
16724
- this.steps.push(stepConfig);
16725
- return new PipelineStepAdvancementBuilder(this.inputSchema, this.meta, this.steps, this.pipelineInputBindings, this.pipelineStepInputBindings);
17093
+ step(step, options) {
17094
+ return pushStep(this.inputSchema, this.meta, this.nodes, this.pipelineInputBindings, this.pipelineStepInputBindings, step, options);
16726
17095
  }
16727
17096
  }
16728
17097
  function pipeline(meta3) {
@@ -16752,23 +17121,35 @@ var buildPipelineDefinitionsClient = (pipelineDefinitions) => {
16752
17121
  stepDefMap.set(s.key, s);
16753
17122
  }
16754
17123
  }
16755
- const stepDefinitions = spec.steps.map((step) => {
16756
- const stepDef = stepDefMap.get(step.stepKey);
17124
+ const nonStepNode = spec.nodeDefinitions.find((node) => node.kind !== "step");
17125
+ if (nonStepNode) {
17126
+ throw new Error(`Pipeline "${spec.key}" contains a "${nonStepNode.kind}" node ("${nonStepNode.nodeKey}"), ` + `but fan-out pipelines cannot be pushed via the current wire contract yet. ` + `Only "step"-only (chain) pipelines can be pushed with \`upsertFromSpec\` today.`);
17127
+ }
17128
+ const ordered = tryOrderChainNodeDefinitions(spec.nodeDefinitions, spec.dependencyEdges);
17129
+ if (ordered === null) {
17130
+ throw new Error(`Pipeline "${spec.key}" has a malformed step graph: its node and ` + `dependency-edge definitions do not form a single connected, ` + `acyclic chain. This should not happen from the \`pipeline()\` ` + `builder \u2014 check for hand-edited or generated pipeline specs.`);
17131
+ }
17132
+ const stepDefinitions = ordered.map((node, index) => {
17133
+ const stepKey = node.stepKey;
17134
+ if (!stepKey) {
17135
+ throw new Error(`Node "${node.nodeKey}" in pipeline "${spec.key}" has no stepKey.`);
17136
+ }
17137
+ const stepDef = stepDefMap.get(stepKey);
16757
17138
  if (!stepDef) {
16758
- throw new Error(`Step "${step.stepKey}" referenced in pipeline "${spec.key}" was not found on the server. ` + `Run \`boboddy steps push\` first to push your step definitions.`);
17139
+ throw new Error(`Step "${stepKey}" referenced in pipeline "${spec.key}" was not found on the server. ` + `Run \`boboddy steps push\` first to push your step definitions.`);
16759
17140
  }
16760
17141
  return {
16761
17142
  stepDefinitionId: stepDef.id,
16762
17143
  stepDefinitionVersion: stepDef.version,
16763
- key: step.stepKey,
16764
- name: step.stepName,
16765
- description: step.stepDescription,
16766
- position: step.position,
16767
- inputBindingsJson: step.inputBindingsJson,
16768
- timeoutSeconds: step.timeoutSeconds,
17144
+ key: node.nodeKey,
17145
+ name: node.stepName ?? "",
17146
+ description: node.stepDescription ?? null,
17147
+ position: index + 1,
17148
+ inputBindingsJson: node.inputBindingsJson ?? {},
17149
+ timeoutSeconds: node.timeoutSeconds ?? null,
16769
17150
  retryPolicyJson: null,
16770
- advancementPolicyDefinition: step.advancementPolicyDefinition,
16771
- computedSignalDefinitions: step.computedSignalDefinitions
17151
+ advancementPolicyDefinition: node.advancementPolicyDefinition,
17152
+ computedSignalDefinitions: node.computedSignalDefinitions ?? []
16772
17153
  };
16773
17154
  });
16774
17155
  const body = {
@@ -16803,7 +17184,12 @@ function makeLeaf(fact, path, operator, value) {
16803
17184
  return {
16804
17185
  _condition: condition,
16805
17186
  then(outcome) {
16806
- return { _tag: "assignment_rule", conditions: [condition], mode: "all", outcome };
17187
+ return {
17188
+ _tag: "assignment_rule",
17189
+ conditions: [condition],
17190
+ mode: "all",
17191
+ outcome
17192
+ };
16807
17193
  }
16808
17194
  };
16809
17195
  }
@@ -16822,7 +17208,7 @@ function makeFieldRef(fact, path) {
16822
17208
  };
16823
17209
  }
16824
17210
  function makeAssign(pipeline2) {
16825
- if (typeof pipeline2 !== "object" || typeof pipeline2["key"] !== "string" || !Array.isArray(pipeline2["steps"])) {
17211
+ if (typeof pipeline2 !== "object" || typeof pipeline2["key"] !== "string" || !Array.isArray(pipeline2["nodeDefinitions"])) {
16826
17212
  throw new Error("assign() requires a pipeline spec produced by pipeline().build(). " + "Pass the default-exported value from a pipeline definition file.");
16827
17213
  }
16828
17214
  return { _tag: "assign", pipeline: pipeline2 };
@@ -16910,7 +17296,7 @@ function serializeDefaultPipelineAssignment(spec) {
16910
17296
  return serializeAssignmentRule(rule);
16911
17297
  });
16912
17298
  return {
16913
- linearPipelineDefinitionKey: primaryKey,
17299
+ pipelineDefinitionKey: primaryKey,
16914
17300
  rulesJson: { rules: serializedRules },
16915
17301
  defaultEventType: defaultType,
16916
17302
  defaultEventParamsJson: defaultParams,
@@ -17275,7 +17661,6 @@ export {
17275
17661
  ProjectIntegrations,
17276
17662
  ProjectContext,
17277
17663
  PipelineStepBuilder,
17278
- PipelineStepAdvancementBuilder,
17279
17664
  PipelineExecutions,
17280
17665
  PipelineDefinitions,
17281
17666
  PipelineBuilder,