@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.
- package/dist/definitions/advancement-policies/define-advancement-policy.d.ts +69 -4
- package/dist/definitions/advancement-policies/index.js +65 -2
- package/dist/definitions/pipelines/define-pipeline.d.ts +11 -26
- package/dist/definitions/pipelines/index.js +65 -9
- package/dist/index.js +64 -8
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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 `
|
|
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 `
|
|
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.
|
|
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.
|
|
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
|