@boboddy/sdk 0.1.6-alpha → 0.1.7-alpha

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.
@@ -1,3 +1,50 @@
1
+ /** Aggregation types supported by the runtime for computed signals. */
2
+ export type PipelineStepComputedSignalType = "average" | "weighted_average" | "sum" | "min" | "max" | "count" | "boolean_any" | "boolean_all";
3
+ type Join<T extends readonly string[], D extends string> = T extends readonly [
4
+ infer Head extends string,
5
+ ...infer Rest extends readonly string[]
6
+ ] ? Rest extends readonly [] ? Head : `${Head}${D}${Join<Rest, D>}` : "";
7
+ /**
8
+ * An inline computed-signal token returned by `Computed.X(...)`. Carries the
9
+ * derived `key` (e.g. `"sum_success"`), the aggregation `type`, and the input
10
+ * signal keys it aggregates over. At serialization time, every inline token
11
+ * embedded in a rule's signal position is extracted into the step's
12
+ * `computedSignalDefinitions` and replaced by its bare key string.
13
+ *
14
+ * - `TKey` — the auto-derived key (literal template).
15
+ * - `TInputSignalKeys` — the union of input signal keys; constrained to the
16
+ * step's signals via `Rule.signal` / `Rule.when` typing.
17
+ */
18
+ export type InlineComputedSignal<TKey extends string = string, TInputSignalKeys extends string = string> = {
19
+ readonly _tag: "computed_signal";
20
+ readonly key: TKey;
21
+ readonly type: PipelineStepComputedSignalType;
22
+ readonly inputSignalKeys: ReadonlyArray<TInputSignalKeys>;
23
+ readonly configJson: Record<string, unknown> | null;
24
+ readonly availableWhenResultStatusIn: readonly string[] | null;
25
+ };
26
+ type ComputedOptions = {
27
+ configJson?: Record<string, unknown> | null;
28
+ availableWhenResultStatusIn?: readonly string[] | null;
29
+ };
30
+ /**
31
+ * Factories for inline computed signals. Each call returns a token whose `key`
32
+ * is auto-derived as `${type}_${inputSignalKeys.join("_")}`.
33
+ *
34
+ * @example
35
+ * Rule.when(Computed.sum(["success"]), "greaterThan", 1, "continue")
36
+ * Rule.signal(Computed.average(["score"]), "greaterThanInclusive", 80)
37
+ */
38
+ export declare const Computed: {
39
+ readonly average: <const TInputs extends readonly [string, string, ...string[]]>(inputSignalKeys: TInputs, options?: ComputedOptions) => InlineComputedSignal<`average_${Join<TInputs, "_">}`, TInputs[number]>;
40
+ readonly weightedAverage: <const TInputs extends readonly [string, string, ...string[]]>(inputSignalKeys: TInputs, options?: ComputedOptions) => InlineComputedSignal<`weighted_average_${Join<TInputs, "_">}`, TInputs[number]>;
41
+ readonly sum: <const TInputs extends readonly [string, string, ...string[]]>(inputSignalKeys: TInputs, options?: ComputedOptions) => InlineComputedSignal<`sum_${Join<TInputs, "_">}`, TInputs[number]>;
42
+ readonly min: <const TInputs extends readonly [string, string, ...string[]]>(inputSignalKeys: TInputs, options?: ComputedOptions) => InlineComputedSignal<`min_${Join<TInputs, "_">}`, TInputs[number]>;
43
+ readonly max: <const TInputs extends readonly [string, string, ...string[]]>(inputSignalKeys: TInputs, options?: ComputedOptions) => InlineComputedSignal<`max_${Join<TInputs, "_">}`, TInputs[number]>;
44
+ readonly count: <const TInputs extends readonly [string, string, ...string[]]>(inputSignalKeys: TInputs, options?: ComputedOptions) => InlineComputedSignal<`count_${Join<TInputs, "_">}`, TInputs[number]>;
45
+ readonly booleanAny: <const TInputs extends readonly [string, string, ...string[]]>(inputSignalKeys: TInputs, options?: ComputedOptions) => InlineComputedSignal<`boolean_any_${Join<TInputs, "_">}`, TInputs[number]>;
46
+ readonly booleanAll: <const TInputs extends readonly [string, string, ...string[]]>(inputSignalKeys: TInputs, options?: ComputedOptions) => InlineComputedSignal<`boolean_all_${Join<TInputs, "_">}`, TInputs[number]>;
47
+ };
1
48
  /**
2
49
  * Comparison operators supported by json-rules-engine.
3
50
  * These map directly to the operator names the runtime evaluates against signal values.
@@ -26,11 +73,14 @@ export type AdvancementOutcome = AdvancementEventType | {
26
73
  * by `Rule.when()`.
27
74
  *
28
75
  * `TSignalKeys` is constrained to the declaring step's signal keys, so the
29
- * `signal` field is validated at compile time.
76
+ * `signal` field is validated at compile time. `signal` may be either a step
77
+ * signal key (string) or an inline `Computed.X(...)` token — at serialization
78
+ * time, inline tokens are hoisted into `computedSignalDefinitions` and replaced
79
+ * by their bare key string.
30
80
  */
31
81
  export type SignalCondition<TSignalKeys extends string = string> = {
32
82
  readonly _tag: "signal";
33
- signal: TSignalKeys;
83
+ signal: TSignalKeys | InlineComputedSignal<string, TSignalKeys>;
34
84
  operator: ConditionOperator;
35
85
  value: unknown;
36
86
  };
@@ -80,7 +130,7 @@ export type Rule<TSignalKeys extends string = string> = {
80
130
  * Rule.signal("flagged", "equal", false),
81
131
  * ], "continue")
82
132
  */
83
- declare function signal<TSignalKeys extends string>(signal: TSignalKeys, operator: ConditionOperator, value: unknown): SignalCondition<TSignalKeys>;
133
+ declare function signal<TSignalKeys extends string>(signal: TSignalKeys | InlineComputedSignal<string, TSignalKeys>, operator: ConditionOperator, value: unknown): SignalCondition<TSignalKeys>;
84
134
  /**
85
135
  * When called with only `conditions`: returns a nested `AllCondition` group
86
136
  * for use inside another `Rule.all()` or `Rule.any()`.
@@ -136,7 +186,7 @@ declare function any<TSignalKeys extends string>(conditions: RuleCondition<TSign
136
186
  * Rule.when("passed", "equal", true, "continue")
137
187
  * Rule.when("score", "greaterThanInclusive", 80, { outcome: "continue", outcomeJson: { via: "score" } })
138
188
  */
139
- declare function when<TSignalKeys extends string>(signal: TSignalKeys, operator: ConditionOperator, value: unknown, outcome: AdvancementOutcome): Rule<TSignalKeys>;
189
+ declare function when<TSignalKeys extends string>(signal: TSignalKeys | InlineComputedSignal<string, TSignalKeys>, operator: ConditionOperator, value: unknown, outcome: AdvancementOutcome): Rule<TSignalKeys>;
140
190
  /**
141
191
  * All factories for building advancement rules.
142
192
  *
@@ -215,4 +265,19 @@ export type SerializedAdvancementPolicy = {
215
265
  allowedEventTypes: AdvancementEventType[];
216
266
  };
217
267
  export declare function serializeAdvancementPolicy(policy: AdvancementPolicy | undefined): SerializedAdvancementPolicy;
268
+ /** Wire-format computed signal definition emitted on the pipeline step. */
269
+ export type SerializedComputedSignalDefinition = {
270
+ key: string;
271
+ type: PipelineStepComputedSignalType;
272
+ inputSignalKeys: string[];
273
+ configJson: Record<string, unknown> | null;
274
+ availableWhenResultStatusIn: string[] | null;
275
+ };
276
+ /**
277
+ * Walks the rules tree, extracts every inline `Computed.X(...)` token embedded
278
+ * in a `SignalCondition.signal` position, dedupes by key, and returns the
279
+ * resulting computed-signal definitions. Two tokens with the same key but
280
+ * differing definitions are a programming error and throw.
281
+ */
282
+ export declare function extractInlineComputedSignals(policy: AdvancementPolicy | undefined): SerializedComputedSignalDefinition[];
218
283
  export {};
@@ -14,6 +14,27 @@ var __export = (target, all) => {
14
14
  };
15
15
 
16
16
  // src/definitions/advancement-policies/define-advancement-policy.ts
17
+ function makeComputed(type, inputSignalKeys, options) {
18
+ const key = [type, ...inputSignalKeys].join("_");
19
+ return {
20
+ _tag: "computed_signal",
21
+ key,
22
+ type,
23
+ inputSignalKeys,
24
+ configJson: options?.configJson ?? null,
25
+ availableWhenResultStatusIn: options?.availableWhenResultStatusIn ?? null
26
+ };
27
+ }
28
+ var Computed = {
29
+ average: (inputSignalKeys, options) => makeComputed("average", inputSignalKeys, options),
30
+ weightedAverage: (inputSignalKeys, options) => makeComputed("weighted_average", inputSignalKeys, options),
31
+ sum: (inputSignalKeys, options) => makeComputed("sum", inputSignalKeys, options),
32
+ min: (inputSignalKeys, options) => makeComputed("min", inputSignalKeys, options),
33
+ max: (inputSignalKeys, options) => makeComputed("max", inputSignalKeys, options),
34
+ count: (inputSignalKeys, options) => makeComputed("count", inputSignalKeys, options),
35
+ booleanAny: (inputSignalKeys, options) => makeComputed("boolean_any", inputSignalKeys, options),
36
+ booleanAll: (inputSignalKeys, options) => makeComputed("boolean_all", inputSignalKeys, options)
37
+ };
17
38
  function signal(signal2, operator, value) {
18
39
  return { _tag: "signal", signal: signal2, operator, value };
19
40
  }
@@ -47,7 +68,7 @@ function resolveOutcome(outcome) {
47
68
  function serializeCondition(condition) {
48
69
  if (condition._tag === "signal") {
49
70
  return {
50
- fact: condition.signal,
71
+ fact: typeof condition.signal === "string" ? condition.signal : condition.signal.key,
51
72
  operator: condition.operator,
52
73
  value: condition.value
53
74
  };
@@ -89,7 +110,49 @@ function serializeAdvancementPolicy(policy) {
89
110
  allowedEventTypes: [...outcomeSet]
90
111
  };
91
112
  }
113
+ function visitSignalConditions(conditions, visit) {
114
+ for (const c of conditions) {
115
+ if (c._tag === "signal") {
116
+ visit(c);
117
+ } else {
118
+ visitSignalConditions(c.conditions, visit);
119
+ }
120
+ }
121
+ }
122
+ function isSameComputedDefinition(a, b) {
123
+ return a.type === b.type && a.inputSignalKeys.length === b.inputSignalKeys.length && a.inputSignalKeys.every((k, i) => k === b.inputSignalKeys[i]) && JSON.stringify(a.configJson) === JSON.stringify(b.configJson) && JSON.stringify(a.availableWhenResultStatusIn) === JSON.stringify(b.availableWhenResultStatusIn);
124
+ }
125
+ function extractInlineComputedSignals(policy) {
126
+ if (!policy?.rules)
127
+ return [];
128
+ const byKey = new Map;
129
+ for (const rule of policy.rules) {
130
+ visitSignalConditions(rule.conditions, (cond) => {
131
+ if (typeof cond.signal === "string")
132
+ return;
133
+ const inline = cond.signal;
134
+ const def = {
135
+ key: inline.key,
136
+ type: inline.type,
137
+ inputSignalKeys: [...inline.inputSignalKeys],
138
+ configJson: inline.configJson,
139
+ availableWhenResultStatusIn: inline.availableWhenResultStatusIn ? [...inline.availableWhenResultStatusIn] : null
140
+ };
141
+ const existing = byKey.get(def.key);
142
+ if (existing) {
143
+ if (!isSameComputedDefinition(existing, def)) {
144
+ throw new Error(`Conflicting inline computed signal definitions for key "${def.key}"`);
145
+ }
146
+ return;
147
+ }
148
+ byKey.set(def.key, def);
149
+ });
150
+ }
151
+ return [...byKey.values()];
152
+ }
92
153
  export {
93
154
  serializeAdvancementPolicy,
94
- Rule
155
+ extractInlineComputedSignals,
156
+ Rule,
157
+ Computed
95
158
  };
@@ -1,8 +1,8 @@
1
1
  import type { ZodType } from "zod";
2
2
  import type { DotPaths, TypedStepDefinitionSpec } from "../steps/define-step";
3
- import { type AdvancementPolicy, type SerializedAdvancementPolicy } from "../advancement-policies/define-advancement-policy";
4
- export type { AdvancementPolicy } from "../advancement-policies/define-advancement-policy";
5
- export { Rule } from "../advancement-policies/define-advancement-policy";
3
+ import { type AdvancementPolicy, type SerializedAdvancementPolicy, type SerializedComputedSignalDefinition } from "../advancement-policies/define-advancement-policy";
4
+ export type { AdvancementPolicy, PipelineStepComputedSignalType, } from "../advancement-policies/define-advancement-policy";
5
+ export { Computed, Rule, } from "../advancement-policies/define-advancement-policy";
6
6
  type AnyTypedStep = TypedStepDefinitionSpec<any, any, any>;
7
7
  export type PipelineInputBinding = {
8
8
  source: "pipeline_input";
@@ -34,14 +34,6 @@ export declare function fromSignal<TStep extends AnyTypedStep>(step: TStep, sign
34
34
  * For a stable contract, prefer fromSignal() instead.
35
35
  */
36
36
  export declare function stepOutput(step: AnyTypedStep): StepOutputBinding;
37
- export type PipelineStepComputedSignalType = "average" | "weighted_average" | "sum" | "min" | "max" | "count" | "boolean_any" | "boolean_all";
38
- export type PipelineStepComputedSignalSpec<TSignalKey extends string = string> = {
39
- key: string;
40
- type: PipelineStepComputedSignalType;
41
- inputSignalKeys: ReadonlyArray<TSignalKey>;
42
- configJson?: Record<string, unknown> | null;
43
- availableWhenResultStatusIn?: string[] | null;
44
- };
45
37
  export type PipelineStepConfig<TStep extends AnyTypedStep = AnyTypedStep> = {
46
38
  step: TStep;
47
39
  /** Maps each step input field to an input source. Extra keys are ignored at runtime. */
@@ -51,16 +43,13 @@ export type PipelineStepConfig<TStep extends AnyTypedStep = AnyTypedStep> = {
51
43
  timeout?: number | null;
52
44
  /**
53
45
  * Controls when and how this step advances in the pipeline.
54
- * Signal keys in `whenSignal()` rules are type-checked against this step's declared signals.
46
+ * Signal keys in `Rule.signal()` / `Rule.when()` calls are type-checked
47
+ * against the step's declared signals. Inline `Computed.X(...)` tokens can
48
+ * also appear in the signal position; they're hoisted into the step's
49
+ * `computedSignalDefinitions` at serialization time.
55
50
  * Defaults to `{ defaultOutcome: "continue" }` when omitted.
56
51
  */
57
52
  advancement?: AdvancementPolicy<TStep["__signalKeys"]>;
58
- /**
59
- * Aggregations derived from this step's emitted signals (extractor keys plus any
60
- * earlier computed-signal keys in this list). Each entry's `inputSignalKeys` is
61
- * type-checked against the step's declared signal keys.
62
- */
63
- computedSignals?: ReadonlyArray<PipelineStepComputedSignalSpec<TStep["__signalKeys"]>>;
64
53
  };
65
54
  type SerializedBinding = {
66
55
  source: "pipeline_input";
@@ -73,13 +62,6 @@ type SerializedBinding = {
73
62
  source: "step_output";
74
63
  stepKey: string;
75
64
  };
76
- type SerializedComputedSignalDefinition = {
77
- key: string;
78
- type: PipelineStepComputedSignalType;
79
- inputSignalKeys: string[];
80
- configJson: Record<string, unknown> | null;
81
- availableWhenResultStatusIn: string[] | null;
82
- };
83
65
  export type PipelineDefinitionSpec = {
84
66
  key: string;
85
67
  name: string;
@@ -114,7 +96,10 @@ export type DefinePipelineInput = {
114
96
  * Defines a pipeline from an ordered list of step configs.
115
97
  *
116
98
  * Each step's `advancement` policy is typed against that step's declared signal
117
- * keys — passing an unknown signal key to `whenSignal()` is a compile-time error.
99
+ * keys — passing an unknown signal key to `Rule.signal()` / `Rule.when()` is a
100
+ * compile-time error. Inline `Computed.X(...)` tokens can also be used in the
101
+ * signal position; they're walked out of the rules tree at serialization time
102
+ * and emitted as the step's `computedSignalDefinitions`.
118
103
  *
119
104
  * TypeScript achieves per-element signal key checking by constraining `TSteps`
120
105
  * to a tuple of step instances (`AnyTypedStep[]`), not step configs. Each element
@@ -14,6 +14,27 @@ var __export = (target, all) => {
14
14
  };
15
15
 
16
16
  // src/definitions/advancement-policies/define-advancement-policy.ts
17
+ function makeComputed(type, inputSignalKeys, options) {
18
+ const key = [type, ...inputSignalKeys].join("_");
19
+ return {
20
+ _tag: "computed_signal",
21
+ key,
22
+ type,
23
+ inputSignalKeys,
24
+ configJson: options?.configJson ?? null,
25
+ availableWhenResultStatusIn: options?.availableWhenResultStatusIn ?? null
26
+ };
27
+ }
28
+ var Computed = {
29
+ average: (inputSignalKeys, options) => makeComputed("average", inputSignalKeys, options),
30
+ weightedAverage: (inputSignalKeys, options) => makeComputed("weighted_average", inputSignalKeys, options),
31
+ sum: (inputSignalKeys, options) => makeComputed("sum", inputSignalKeys, options),
32
+ min: (inputSignalKeys, options) => makeComputed("min", inputSignalKeys, options),
33
+ max: (inputSignalKeys, options) => makeComputed("max", inputSignalKeys, options),
34
+ count: (inputSignalKeys, options) => makeComputed("count", inputSignalKeys, options),
35
+ booleanAny: (inputSignalKeys, options) => makeComputed("boolean_any", inputSignalKeys, options),
36
+ booleanAll: (inputSignalKeys, options) => makeComputed("boolean_all", inputSignalKeys, options)
37
+ };
17
38
  function signal(signal2, operator, value) {
18
39
  return { _tag: "signal", signal: signal2, operator, value };
19
40
  }
@@ -47,7 +68,7 @@ function resolveOutcome(outcome) {
47
68
  function serializeCondition(condition) {
48
69
  if (condition._tag === "signal") {
49
70
  return {
50
- fact: condition.signal,
71
+ fact: typeof condition.signal === "string" ? condition.signal : condition.signal.key,
51
72
  operator: condition.operator,
52
73
  value: condition.value
53
74
  };
@@ -89,6 +110,46 @@ function serializeAdvancementPolicy(policy) {
89
110
  allowedEventTypes: [...outcomeSet]
90
111
  };
91
112
  }
113
+ function visitSignalConditions(conditions, visit) {
114
+ for (const c of conditions) {
115
+ if (c._tag === "signal") {
116
+ visit(c);
117
+ } else {
118
+ visitSignalConditions(c.conditions, visit);
119
+ }
120
+ }
121
+ }
122
+ function isSameComputedDefinition(a, b) {
123
+ return a.type === b.type && a.inputSignalKeys.length === b.inputSignalKeys.length && a.inputSignalKeys.every((k, i) => k === b.inputSignalKeys[i]) && JSON.stringify(a.configJson) === JSON.stringify(b.configJson) && JSON.stringify(a.availableWhenResultStatusIn) === JSON.stringify(b.availableWhenResultStatusIn);
124
+ }
125
+ function extractInlineComputedSignals(policy) {
126
+ if (!policy?.rules)
127
+ return [];
128
+ const byKey = new Map;
129
+ for (const rule of policy.rules) {
130
+ visitSignalConditions(rule.conditions, (cond) => {
131
+ if (typeof cond.signal === "string")
132
+ return;
133
+ const inline = cond.signal;
134
+ const def = {
135
+ key: inline.key,
136
+ type: inline.type,
137
+ inputSignalKeys: [...inline.inputSignalKeys],
138
+ configJson: inline.configJson,
139
+ availableWhenResultStatusIn: inline.availableWhenResultStatusIn ? [...inline.availableWhenResultStatusIn] : null
140
+ };
141
+ const existing = byKey.get(def.key);
142
+ if (existing) {
143
+ if (!isSameComputedDefinition(existing, def)) {
144
+ throw new Error(`Conflicting inline computed signal definitions for key "${def.key}"`);
145
+ }
146
+ return;
147
+ }
148
+ byKey.set(def.key, def);
149
+ });
150
+ }
151
+ return [...byKey.values()];
152
+ }
92
153
 
93
154
  // src/definitions/pipelines/define-pipeline.ts
94
155
  function fromPipelineInput(_schema, path) {
@@ -129,13 +190,7 @@ function definePipeline(config) {
129
190
  inputBindingsJson: Object.fromEntries(Object.entries(stepConfig.input ?? {}).filter((entry) => entry[1] !== undefined).map(([key, binding]) => [key, serializeBinding(binding)])),
130
191
  timeoutSeconds: stepConfig.timeout ?? null,
131
192
  advancementPolicyDefinition: serializeAdvancementPolicy(stepConfig.advancement),
132
- computedSignalDefinitions: (stepConfig.computedSignals ?? []).map((cs) => ({
133
- key: cs.key,
134
- type: cs.type,
135
- inputSignalKeys: [...cs.inputSignalKeys],
136
- configJson: cs.configJson ?? null,
137
- availableWhenResultStatusIn: cs.availableWhenResultStatusIn ?? null
138
- }))
193
+ computedSignalDefinitions: extractInlineComputedSignals(stepConfig.advancement)
139
194
  }))
140
195
  };
141
196
  }
@@ -186,5 +241,6 @@ export {
186
241
  fromPipelineInput,
187
242
  definePipeline,
188
243
  createPipelineDefinitionsClient,
189
- Rule
244
+ Rule,
245
+ Computed
190
246
  };
package/dist/index.js CHANGED
@@ -15797,6 +15797,27 @@ var Features = {
15797
15797
  })
15798
15798
  };
15799
15799
  // src/definitions/advancement-policies/define-advancement-policy.ts
15800
+ function makeComputed(type, inputSignalKeys, options) {
15801
+ const key = [type, ...inputSignalKeys].join("_");
15802
+ return {
15803
+ _tag: "computed_signal",
15804
+ key,
15805
+ type,
15806
+ inputSignalKeys,
15807
+ configJson: options?.configJson ?? null,
15808
+ availableWhenResultStatusIn: options?.availableWhenResultStatusIn ?? null
15809
+ };
15810
+ }
15811
+ var Computed = {
15812
+ average: (inputSignalKeys, options) => makeComputed("average", inputSignalKeys, options),
15813
+ weightedAverage: (inputSignalKeys, options) => makeComputed("weighted_average", inputSignalKeys, options),
15814
+ sum: (inputSignalKeys, options) => makeComputed("sum", inputSignalKeys, options),
15815
+ min: (inputSignalKeys, options) => makeComputed("min", inputSignalKeys, options),
15816
+ max: (inputSignalKeys, options) => makeComputed("max", inputSignalKeys, options),
15817
+ count: (inputSignalKeys, options) => makeComputed("count", inputSignalKeys, options),
15818
+ booleanAny: (inputSignalKeys, options) => makeComputed("boolean_any", inputSignalKeys, options),
15819
+ booleanAll: (inputSignalKeys, options) => makeComputed("boolean_all", inputSignalKeys, options)
15820
+ };
15800
15821
  function signal(signal2, operator, value) {
15801
15822
  return { _tag: "signal", signal: signal2, operator, value };
15802
15823
  }
@@ -15830,7 +15851,7 @@ function resolveOutcome(outcome) {
15830
15851
  function serializeCondition(condition) {
15831
15852
  if (condition._tag === "signal") {
15832
15853
  return {
15833
- fact: condition.signal,
15854
+ fact: typeof condition.signal === "string" ? condition.signal : condition.signal.key,
15834
15855
  operator: condition.operator,
15835
15856
  value: condition.value
15836
15857
  };
@@ -15872,6 +15893,46 @@ function serializeAdvancementPolicy(policy) {
15872
15893
  allowedEventTypes: [...outcomeSet]
15873
15894
  };
15874
15895
  }
15896
+ function visitSignalConditions(conditions, visit) {
15897
+ for (const c of conditions) {
15898
+ if (c._tag === "signal") {
15899
+ visit(c);
15900
+ } else {
15901
+ visitSignalConditions(c.conditions, visit);
15902
+ }
15903
+ }
15904
+ }
15905
+ function isSameComputedDefinition(a, b) {
15906
+ return a.type === b.type && a.inputSignalKeys.length === b.inputSignalKeys.length && a.inputSignalKeys.every((k, i) => k === b.inputSignalKeys[i]) && JSON.stringify(a.configJson) === JSON.stringify(b.configJson) && JSON.stringify(a.availableWhenResultStatusIn) === JSON.stringify(b.availableWhenResultStatusIn);
15907
+ }
15908
+ function extractInlineComputedSignals(policy) {
15909
+ if (!policy?.rules)
15910
+ return [];
15911
+ const byKey = new Map;
15912
+ for (const rule of policy.rules) {
15913
+ visitSignalConditions(rule.conditions, (cond) => {
15914
+ if (typeof cond.signal === "string")
15915
+ return;
15916
+ const inline = cond.signal;
15917
+ const def = {
15918
+ key: inline.key,
15919
+ type: inline.type,
15920
+ inputSignalKeys: [...inline.inputSignalKeys],
15921
+ configJson: inline.configJson,
15922
+ availableWhenResultStatusIn: inline.availableWhenResultStatusIn ? [...inline.availableWhenResultStatusIn] : null
15923
+ };
15924
+ const existing = byKey.get(def.key);
15925
+ if (existing) {
15926
+ if (!isSameComputedDefinition(existing, def)) {
15927
+ throw new Error(`Conflicting inline computed signal definitions for key "${def.key}"`);
15928
+ }
15929
+ return;
15930
+ }
15931
+ byKey.set(def.key, def);
15932
+ });
15933
+ }
15934
+ return [...byKey.values()];
15935
+ }
15875
15936
 
15876
15937
  // src/definitions/pipelines/define-pipeline.ts
15877
15938
  function fromPipelineInput(_schema, path) {
@@ -15912,13 +15973,7 @@ function definePipeline(config2) {
15912
15973
  inputBindingsJson: Object.fromEntries(Object.entries(stepConfig.input ?? {}).filter((entry) => entry[1] !== undefined).map(([key, binding]) => [key, serializeBinding(binding)])),
15913
15974
  timeoutSeconds: stepConfig.timeout ?? null,
15914
15975
  advancementPolicyDefinition: serializeAdvancementPolicy(stepConfig.advancement),
15915
- computedSignalDefinitions: (stepConfig.computedSignals ?? []).map((cs) => ({
15916
- key: cs.key,
15917
- type: cs.type,
15918
- inputSignalKeys: [...cs.inputSignalKeys],
15919
- configJson: cs.configJson ?? null,
15920
- availableWhenResultStatusIn: cs.availableWhenResultStatusIn ?? null
15921
- }))
15976
+ computedSignalDefinitions: extractInlineComputedSignals(stepConfig.advancement)
15922
15977
  }))
15923
15978
  };
15924
15979
  }
@@ -16633,6 +16688,7 @@ export {
16633
16688
  PipelineDefinitions,
16634
16689
  FeedbackRequests,
16635
16690
  Features,
16691
+ Computed,
16636
16692
  BoboddyClient,
16637
16693
  BOBODDY_CONFIG_RELATIVE_PATH,
16638
16694
  Api
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@boboddy/sdk",
4
- "version": "0.1.6-alpha",
4
+ "version": "0.1.7-alpha",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": {